Skip to content

Latest commit

 

History

History
380 lines (272 loc) · 10.4 KB

File metadata and controls

380 lines (272 loc) · 10.4 KB

Result

The validation result is an object containing errors that occurred during validation.

Is validation successful?

To just check the status of validation (whether a data is valid as a whole), use the following Result API call:

use Yiisoft\Validator\Result;

/** @var Result $result */
$result->isValid();

It can be narrowed down to a specific property:

use Yiisoft\Validator\Result;

/** @var Result $result */
$result->isPropertyValid('name');

Errors

Most of the time telling only the status of validation is not enough. There are multiple methods to get detailed errors list with their data from the result. The difference between them is in the grouping, filtering, and representation of every error. Choose one to fit your needs depending on the situation.

Flat list of error messages

One of the simplest cases is getting a flat list of all error messages. Use the following Result API call:

use Yiisoft\Validator\Result;

/** @var Result $result */
$result->getErrorMessages();

An example of output with age and email properties:

[
    'Value must be no less than 21.',
    'This value is not a valid email address.',
    'A custom error message.',
];

It's easy to display and iterate, however, with a bigger amount of properties and depending on a message, it can be problematic to understand which property an error belongs to.

Error messages not bound to a specific property

Sometimes error messages are not related to a specific property. It can happen during the validation of multiple properties depending on each other for example. Use the following Result API call:

$result->getCommonErrorMessages();

The output for example above:

[
    'A custom error message.',
];

Filtering by a specific property

This list can be also filtered by a specific property. Only top-level attributes are supported.

$result->getPropertyErrorMessages('email');

The output for example above:

[
    'This value is not a valid email address.',
];

Filtering by a specific path

This list of error messages can be filtered by a specific path to property.

$result->getPropertyErrorMessagesByPath(['person', 'first_name']);

Error messages indexed by property

To group error messages by property, use the following Result API call:

use Yiisoft\Validator\Result;

/** @var Result $result */
$result->getErrorMessagesIndexedByProperty();

An example of output:

[
    'name' => [
        'Value cannot be blank.',
        'This value must contain at least 4 characters.',
    ],
    'email' => ['This value is not a valid email address.'],
    // Error messages not bound to specific property are grouped under empty string key.
    '' => ['A custom error message.'],
];

Note that the result is always a 2-dimensional array with property names as keys at the first nesting level. This means that further nesting of properties is not supported (but could be achieved by using getErrorMessagesIndexedByPath()). Returning to the previous example, when name and email belong to a user property, the output will be:

[
    'user' => [
        'Value cannot be blank.',
        'This value must contain at least 4 characters.',
        'This value is not a valid email address.'
    ],
    // Error messages not bound to specific property are grouped under empty string key.
    '' => ['A custom error message.'],
];

Also keep in mind that property names must be strings, even when used with Each:

$rule = new Each([new Number(min: 21)]);

With input containing non-string keys for top level properties, for example, [21, 22, 23, 20], InvalidArgumentException will be thrown.

Even array ['1' => 21, '2' => 22, '3' => 23, '4' => 20] will cause an error, because PHP will cast keys to the int type.

But if given array with string keys ['1a' => 21, '2b' => 22, '3c' => 23, '4d' => 20], the output will be:

[
    '4d' => [
        0 => 'Value must be no less than 21.'
    ]
]

First error messages indexed by property

To get only the first error message for each property (useful for displaying a single error per field), use:

use Yiisoft\Validator\Result;

/** @var Result $result */
$result->getFirstErrorMessagesIndexedByProperty();

An example of output:

[
    'name' => 'Value cannot be blank.',
    'email' => 'This value is not a valid email address.',
    '' => 'A custom error message.',
];

Note that unlike getErrorMessagesIndexedByProperty(), each value is a single string, not an array.

Error messages indexed by path

This is probably the most advanced representation offered by built-in methods. The grouping is done by path - a concatenated property sequence showing the location of errored value within a data structure. A separator is customizable, dot notation is set as the default one. Use the following Result API call:

use Yiisoft\Validator\Result;

/** @var Result $result */
$result->getErrorMessagesIndexedByPath();

An example of output:

[
    'user.firstName' => ['Value cannot be blank.'],
    'user.lastName' => ['This value must contain at least 4 characters.'],
    'email' => ['This value is not a valid email address.'],
    // Error messages not bound to specific property are grouped under empty string key.
    '' => ['A custom error message.'],
];

A path can contain integer elements too (when using the Each rule for example):

[
    'charts.0.points.0.coordinates.y' => ['Value must be no greater than 10.'],
];

First error messages indexed by path

To get only the first error message for each path (useful for displaying a single error per field), use:

use Yiisoft\Validator\Result;

/** @var Result $result */
$result->getFirstErrorMessagesIndexedByPath();

An example of output:

[
    'user.firstName' => 'Value cannot be blank.',
    'user.lastName' => 'This value must contain at least 4 characters.',
    'email' => 'This value is not a valid email address.',
    '' => 'A custom error message.',
];

Note that unlike getErrorMessagesIndexedByPath(), each value is a single string, not an array.

Resolving special characters collision in property names

When the property name in the error messages list contains a path separator (dot . by default), it is automatically escaped using a backslash (\):

[
    'country\.code' => ['Value cannot be blank.'],
],

In case of using a single property per rule set, any additional modifications of attribute names in the rules configuration are not required, so they must stay as is:

use Yiisoft\Validator\Rule\In;
use Yiisoft\Validator\Rule\Required;

$rules = [
    'country.code' => [
        new Required();
        new In(['ru', 'en'], skipOnError: true),
    ],
];

However, when using the Nested rule with multiple properties per rule set, special characters need to be escaped with a backslash (\) for value paths to be correct and to be possible to reverse them back from string to individual items. See the Using keys containing separator / shortcut section for more details.

This can be used as an alternative to using a custom separator.

Filtering by a specific property

This list can be also filtered by a specific property. Only top-level properties are supported.

use Yiisoft\Validator\Result;

/** @var Result $result */
$result->getPropertyErrorMessagesIndexedByPath('user');

The output for example above:

[
    'firstName' => ['Value cannot be blank.'],
    'lastName' => ['This value must contain at least 4 characters.'],
];

Error objects list

When even these representations are not enough, an initial unmodified list of error objects can be accessed via this method:

use Yiisoft\Validator\Result;

/** @var Result $result */
$result->getErrors();

Each error stores the following data:

  • Message. Either a simple message like This value is wrong. or a template with placeholders enclosed in curly braces ({}), for example: Value must be no less than {min}.. The actual formatting is done in Validator depending on the configured translator.
  • Template parameters for substitution during formatting, for example: ['min' => 7].
  • A path to a value within a checked data structure, for example: ['user', 'name', 'firstName'].

An example of an application

What this can be useful for? For example, to build a nested tree of error messages indexed by property names:

[
    'user' => [
        'name' => [
            'firstName' => ['Value cannot be blank.'],
            'lastName' => ['This value must contain at least 4 characters.'],
        ],
    ],
    'email' => ['This value is not a valid email address.'],    
];

It's intentionally not provided out of the box due to the complexity of iteration. However, this can be useful for dumping as JSON and storing in logs for example.

Debugging original error objects is also more convenient.

Filtering by a specific property

This list can be also filtered by a specific property. Only top-level properties are supported.

use Yiisoft\Validator\Result;

/** @var Result $result */
$result->getPropertyErrors('email');

Adding errors

When writing custom rule handlers, errors are added to a Result object. There are three methods available, each with different post-processing behavior:

  • addError() — message is translated and formatted (default behavior).
  • addErrorWithFormatOnly() — message is formatted (parameter substitution) but not translated.
  • addErrorWithoutPostProcessing() — message is used as-is, with no formatting or translation.
use Yiisoft\Validator\Result;

$result = new Result();
$result->addError('Value must be no less than {min}.', ['min' => 7]);
$result->addErrorWithFormatOnly('Already formatted: {value}.', ['value' => 42]);
$result->addErrorWithoutPostProcessing('This message is used exactly as written.');

Merging results

To merge other validation results into the current one, use the add() method:

use Yiisoft\Validator\Result;

$result1 = new Result();
$result1->addError('Error 1.');

$result2 = new Result();
$result2->addError('Error 2.');

$result1->add($result2);
$result1->getErrorMessages(); // ['Error 1.', 'Error 2.']