Skip to content

Latest commit

 

History

History
258 lines (196 loc) · 7.27 KB

File metadata and controls

258 lines (196 loc) · 7.27 KB

Using validator

Validator allows to check data in any format. Here are some of the most common use cases.

Data

Single value

In the simplest case, the validator can be used to check a single value:

use Yiisoft\Validator\Rule\Length;
use Yiisoft\Validator\Rule\Regex;
use Yiisoft\Validator\Validator;

$value = 'mrX';
$rules = [
    new Length(min: 4, max: 20),
    new Regex('~^[a-z_\-]*$~i'),
];
$result = (new Validator())->validate($value, $rules);

Note: Use Each rule to validate multiple values of the same type.

Array

It's possible to validate an array both as a whole and by individual items. For example:

use Yiisoft\Validator\Rule\FilledAtLeast;
use Yiisoft\Validator\Rule\Count;
use Yiisoft\Validator\Rule\Email;
use Yiisoft\Validator\Rule\Length;
use Yiisoft\Validator\Rule\Number;
use Yiisoft\Validator\Rule\Required;
use Yiisoft\Validator\Validator;

$data = [
    'name' => 'John',
    'age' => 17,
    'email' => 'john@example.com',
    'phone' => null,
];
$rules = [
    // The rules that are not related to a specific property

    // At least one of the properties ("email" and "phone") must be passed and have non-empty value.  
    new FilledAtLeast(['email', 'phone']),

    // The rules related to a specific property.

    'name' => [
        // The name is required (must be passed and have non-empty value).
        new Required(),
        // The name's length must be no less than 2 characters.
        new Length(min: 2),
    ],  
    'age' => new Number(min: 21), // The age must be at least 21 years.  
    'email' => new Email(), // Email must be a valid email address.  
];
$result = (new Validator())->validate($data, $rules);

Note: Use Nested rule to validate nested arrays and Each rule to validate multiple arrays.

Object

Similar to arrays, it's possible to validate an object both as a whole and by individual properties.

For objects there is an additional option to configure validation with PHP attributes which allows to not pass the rules separately in explicit way (passing just the object itself is enough). For example:

use Yiisoft\Validator\Rule\FilledAtLeast;
use Yiisoft\Validator\Rule\Email;
use Yiisoft\Validator\Rule\Length;
use Yiisoft\Validator\Rule\Number;
use Yiisoft\Validator\Rule\Required;
use Yiisoft\Validator\Validator;

#[FilledAtLeast(['email', 'phone'])]
final class Person
{
    public function __construct(
        #[Required]
        #[Length(min: 2)]
        public readonly ?string $name = null,

        #[Number(min: 21)]
        public readonly ?int $age = null,

        #[Email]
        public readonly ?string $email = null,

        public readonly ?string $phone = null,
    ) {
    }
}

$person = new Person(name: 'John', age: 17, email: 'john@example.com', phone: null);
$result = (new Validator())->validate($person);

Note: readonly properties are supported only starting from PHP 8.1.

Note: Use Nested rule to validate related objects and Each rule to validate multiple objects.

Custom data set

Most of the time creating a custom data set is not needed because of built-in data sets and automatic normalization of all types during validation. However, this can be useful, for example, to change a default value for certain properties:

use Yiisoft\Validator\DataSetInterface;
use Yiisoft\Validator\Rule\Length;
use Yiisoft\Validator\Rule\Number;
use Yiisoft\Validator\Validator;

final class MyArrayDataSet implements DataSetInterface
{
    public function __construct(private array $data = [],) 
    {
    }

    public function getPropertyValue(string $property): mixed
    {
        if ($this->hasProperty($property)) {
            return $this->data[$property];
        }

        return $property === 'name' ? '' : null;
    }

    public function getData(): array
    {
        return $this->data;
    }

    public function hasProperty(string $property): bool
    {
        return array_key_exists($property, $this->data);
    }
}

$data = new MyArrayDataSet([]);
$rules = ['name' => new Length(min: 2), 'age' => new Number(min: 21)];
$result = (new Validator())->validate($data, $rules);

Rules

Passing single rule

For a single rule, there is an option to omit the array:

use Yiisoft\Validator\Rule\Number;
use Yiisoft\Validator\Validator;

$value = 7;
$rule = new Number(min: 42);
$result = (new Validator())->validate($value, $rule);

Providing rules via dedicated object

Could help reuse the same set of rules across different places. Two ways are possible - using PHP attributes and specifying explicitly via interface method implementation.

Using PHP attributes

In this case, the rules will be automatically parsed, no need to additionally do anything.

use Yiisoft\Validator\Rule\Length;
use Yiisoft\Validator\Rule\Number;
use Yiisoft\Validator\Validator;

final class PersonRulesProvider
{
    #[Length(min: 2)]
    public string $name;

    #[Number(min: 21)]
    public int $age;
}

$data = ['name' => 'John', 'age' => 18];
$rulesProvider = new PersonRulesProvider();
$result = (new Validator())->validate($data, $rulesProvider);

Using interface method implementation

When an object implementing RulesProviderInterface is passed as the $rules argument (second argument of validate()), only the rules from getRules() are used. PHP attributes on the object are not parsed in this case.

use Yiisoft\Validator\Rule\Length;
use Yiisoft\Validator\Rule\Number;
use Yiisoft\Validator\RulesProviderInterface;
use Yiisoft\Validator\Validator;

final class PersonRulesProvider implements RulesProviderInterface
{
    #[Length(min: 2)] // Ignored because the object is passed as the $rules argument.
    public string $name;

    #[Number(min: 21)] // Ignored because the object is passed as the $rules argument.
    public int $age;

    public function getRules(): iterable
    {
        return ['name' => new Length(min: 2), 'age' => new Number(min: 21)];
    }
}

$data = ['name' => 'John', 'age' => 18];
$rulesProvider = new PersonRulesProvider();
$result = (new Validator())->validate($data, $rulesProvider);

Providing rules via the data object

In this way, rules are provided in addition to data in the same object. Both PHP attributes and getRules() method are supported — their rules are merged (attribute rules are applied first). Note that the rules argument is null in the validate() method call.

use Yiisoft\Validator\Rule\Length;
use Yiisoft\Validator\Rule\Number;
use Yiisoft\Validator\RulesProviderInterface;
use Yiisoft\Validator\Validator;

final class Person implements RulesProviderInterface
{
    public function __construct(
        #[Length(min: 2)] // Merged with rules from getRules(). Attribute rules are applied first.
        public string $name = '',
        #[Number(min: 21)] // Merged with rules from getRules(). Attribute rules are applied first.
        public int $age = 0,
    ) {
    }

    public function getRules(): iterable
    {
        return ['name' => new Length(min: 2), 'age' => new Number(min: 21)];
    }
}

$data = new Person(name: 'John', age: 18);
$result = (new Validator())->validate($data);