The package provides data validation capabilities.
- Could be used with any object.
- Skip further validation if an error occurred for the same field.
- Skip validation of empty value.
- Error message translations.
- Conditional validation.
- Could pass context to validation rule.
- Common rules bundled.
Library could be used in two ways: validating a single value and validating a set of data.
use Yiisoft\Validator\Rules;
use Yiisoft\Validator\Rule\Required;
use Yiisoft\Validator\Rule\Number;
use Yiisoft\Validator\Result;
$rules = new Rules([
new Required(),
(new Number())->min(10),
static function ($value): Result {
$result = new Result();
if ($value !== 42) {
$result->addError('Value should be 42!');
}
return $result;
}
]);
$result = $rules->validate(41);
if ($result->isValid() === false) {
foreach ($result->getErrors() as $error) {
// ...
}
}
use Yiisoft\Validator\DataSetInterface;
use Yiisoft\Validator\Validator;
use Yiisoft\Validator\Rule\Number;
use Yiisoft\Validator\Result;
final class MoneyTransfer implements DataSetInterface
{
private $amount;
public function __construct($amount) {
$this->amount = $amount;
}
public function getAttributeValue(string $key){
if (!isset($this->$key)) {
throw new \InvalidArgumentException("There is no \"$key\" in MoneyTransfer.");
}
return $this->$key;
}
}
$moneyTransfer = new MoneyTransfer(142);
$validator = new Validator([
'amount' => [
(new Number())->integer()->max(100),
static function ($value): Result {
$result = new Result();
if ($value === 13) {
$result->addError('Value should not be 13!');
}
return $result;
}
],
]);
$results = $validator->validate($moneyTransfer);
foreach ($results as $attribute => $result) {
if ($result->isValid() === false) {
foreach ($result->getErrors() as $error) {
// ...
}
}
}
By default, if an error occurred during validation of an attribute, further rules for this attribute are skipped.
To change this behavior use skipOnError(false)
when configuring rules:
(new Number())->integer()->max(100)->skipOnError(false)
By default, empty values are validated. That is undesirable if you need to allow not specifying a field.
To change this behavior use skipOnEmpty(true)
:
(new Number())->integer()->max(100)->skipOnEmpty(true)
In some cases there is a need to apply rule conditionally. It could be performed by using when()
:
(new Number())->integer()->min(100)->when(static function ($value, DataSetInterface $dataSet) {
return $dataSet->getAttributeValue('country') === Country::USA;
});
If callable returns true
rule is applied, when the value returned is false
, rule is skipped.
To create your own validation rule you should extend Rule
class:
namespace MyVendor\Rules;
use Yiisoft\Validator\DataSetInterface;
use Yiisoft\Validator\Result;
use Yiisoft\Validator\Rule;
final class Pi extends Rule
{
protected function validateValue($value, DataSetInterface $dataSet = null): Result
{
$result = new Result();
if ($value != M_PI) {
$result->addError('Value is not PI');
}
return $result;
}
}
Note that validateValue()
second argument is an instance of DataSetInterface
so you can use it if you need
whole data set context. For example, implementation might be the following if you need to validate "company"
property only if "hasCompany" is true:
namespace MyVendor\Rules;
use Yiisoft\Validator\DataSetInterface;
use Yiisoft\Validator\Result;
use Yiisoft\Validator\Rule;
final class CompanyName extends Rule
{
protected function validateValue($value, DataSetInterface $dataSet = null): Result
{
$result = new Result();
$hasCompany = $dataSet !== null && $dataSet->getAttributeValue('hasCompany') === true;
if ($hasCompany && $this->isCompanyNameValid($value) === false) {
$result->addError('Company name is not valid');
}
return $result;
}
private function isCompanyNameValid(string $value): bool
{
// check company name
}
}
To reuse multiple validation rules it is advised to group rules like the following:
use Yiisoft\Validator\Rules;
use Yiisoft\Validator\Rule\HasLength;
use Yiisoft\Validator\Rule\MatchRegularExpression;
use \Yiisoft\Validator\Rule\GroupRule;
final class UsernameRule extends GroupRule
{
public function getRules(): Rules
{
return new Rules([
(new HasLength())->min(2)->max(20),
new MatchRegularExpression('~[a-z_\-]~i')
]);
}
}
Then it could be used like the following:
use Yiisoft\Validator\Validator;
use Yiisoft\Validator\Rule\Email;
$validator = new Validator([
'username' => new UsernameRule(),
'email' => [new Email()]
]);
$results = $validator->validate($user);
foreach ($results as $attribute => $result) {
if ($result->isValid() === false) {
foreach ($result->getErrors() as $error) {
// ...
}
}
}
The package is tested with PHPUnit. To run tests:
./vendor/bin/phpunit
The package tests are checked with Infection mutation framework. To run it:
./vendor/bin/infection
The code is statically analyzed with Psalm. To run static analysis:
./vendor/bin/psalm
The Yii Validator is free software. It is released under the terms of the BSD License.
Please see LICENSE
for more information.
Maintained by Yii Software.