Skip to content

Commit 2e460b2

Browse files
committed
Update English documentation to match current API (2.0.0–2.5.2)
1 parent c399079 commit 2e460b2

12 files changed

+342
-64
lines changed

docs/guide/en/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
- [Built-in rules](built-in-rules.md)
1313
- [Callback](built-in-rules-callback.md)
14+
- [Compare](built-in-rules-compare.md)
1415
- [Composite](built-in-rules-composite.md)
1516
- [Each](built-in-rules-each.md)
1617
- [Nested](built-in-rules-nested.md)

docs/guide/en/built-in-rules-compare.md

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,46 @@
11
# `Compare` - comparing validated value with target value
22

3+
The `Compare` rule and its shortcut classes validate a value by comparing it with a target value or another property.
4+
5+
Available shortcut classes:
6+
7+
- `Equal` (`==`)
8+
- `NotEqual` (`!=`)
9+
- `GreaterThan` (`>`)
10+
- `GreaterThanOrEqual` (`>=`)
11+
- `LessThan` (`<`)
12+
- `LessThanOrEqual` (`<=`)
13+
14+
## Comparison types
15+
16+
The `type` parameter controls how values are compared:
17+
18+
- `CompareType::NUMBER` — values are compared as numbers (default).
19+
- `CompareType::STRING` — values are compared as strings, byte by byte.
20+
- `CompareType::ORIGINAL` — values are compared as-is, without type casting. Required for `DateTime` objects.
21+
22+
## Comparing with a target value
23+
24+
```php
25+
use Yiisoft\Validator\Rule\GreaterThanOrEqual;
26+
27+
$rules = [
28+
'age' => new GreaterThanOrEqual(18),
29+
];
30+
```
31+
32+
## Comparing with another property
33+
34+
Use the `targetProperty` parameter to compare against another property in the same data set:
35+
36+
```php
37+
use Yiisoft\Validator\Rule\Equal;
38+
39+
$rules = [
40+
'password_repeat' => new Equal(targetProperty: 'password'),
41+
];
42+
```
43+
344
## Using with `DateTime` objects
445

546
### Basic usage
@@ -17,11 +58,11 @@ $rules = [
1758
### Dynamic range
1859

1960
```php
61+
use DateInterval;
2062
use DateTime;
21-
use Yiisoft\Validator\Rule\Callback;
2263
use Yiisoft\Validator\Rule\CompareType;
23-
use Yiisoft\Validator\Rule\GreaterThanOrEqual;
24-
use Yiisoft\Validator\Rule\LessThanOrEqual;
64+
use Yiisoft\Validator\Rule\GreaterThan;
65+
use Yiisoft\Validator\Rule\LessThan;
2566

2667
$rules = [
2768
'shipping_datetime' => [
@@ -34,7 +75,7 @@ $rules = [
3475
(new DateTime('now'))
3576
->add(DateInterval::createFromDateString('1 week')),
3677
type: CompareType::ORIGINAL,
37-
),
78+
),
3879
],
3980
];
4081
```

docs/guide/en/built-in-rules-composite.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ final class CoordinatesRuleSet extends Composite
5959
public function getRules(): array
6060
{
6161
return [
62-
new Nested(
62+
new Nested([
6363
'latitude' => new Number(min: -90, max: 90),
6464
'longitude' => new Number(min: -90, max: 90),
65-
),
65+
]),
6666
];
6767
}
6868
}

docs/guide/en/built-in-rules-each.md

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,37 @@ $rules = [
3030
];
3131
```
3232

33-
Validated data items are not limited to only "simple" values - `Each` can be used both within a `Nested` and contain
33+
## Stopping on first error
34+
35+
By default, `Each` validates all items in the set and collects all errors. To stop validation at the first item
36+
that produces an error, use the `stopOnError` parameter:
37+
38+
```php
39+
use Yiisoft\Validator\Rule\Each;
40+
use Yiisoft\Validator\Rule\Integer;
41+
42+
new Each(
43+
rules: [new Integer(min: 0, max: 255)],
44+
stopOnError: true,
45+
);
46+
```
47+
48+
## Accessing the current key
49+
50+
During validation of each item, the current iteration key is available through the validation context
51+
parameter `Each::PARAMETER_EACH_KEY`. This can be useful in `when` callbacks or custom rule handlers:
52+
53+
```php
54+
use Yiisoft\Validator\Rule\Each;
55+
use Yiisoft\Validator\ValidationContext;
56+
57+
// Inside a when callback or custom rule handler:
58+
$currentKey = $context->getParameter(Each::PARAMETER_EACH_KEY);
59+
```
60+
61+
## Using with `Nested`
62+
63+
Validated data items are not limited to only "simple" values — `Each` can be used both within a `Nested` and contain
3464
`Nested` rule covering one-to-many and many-to-many relations:
3565

3666
```php
@@ -48,10 +78,10 @@ $rule = new Nested([
4878
'x' => [new Number(min: -10, max: 10)],
4979
'y' => [new Number(min: -10, max: 10)],
5080
]),
51-
'rgb' => new Each([
81+
'rgb' => [
5282
new Count(3),
53-
new Number(min: 0, max: 255),
54-
]),
83+
new Each([new Number(min: 0, max: 255)]),
84+
],
5585
]),
5686
]),
5787
]),

docs/guide/en/built-in-rules-nested.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,44 @@ attributes] section.
388388
- For more information about possible data / rules combinations passed for validation, refer to the [Using validator]
389389
section.
390390

391+
### Conditional validation within nested structures
392+
393+
When using `when` callbacks inside `Nested`, the validation context provides access to sibling properties — other
394+
properties at the same nesting level. Use `$context->getDataSet()->getPropertyValue()` to read them.
395+
396+
For example, to require `content` only when `isEnabled` is `true`:
397+
398+
```php
399+
use Yiisoft\Validator\Rule\BooleanValue;
400+
use Yiisoft\Validator\Rule\Nested;
401+
use Yiisoft\Validator\Rule\Required;
402+
use Yiisoft\Validator\ValidationContext;
403+
use Yiisoft\Validator\Validator;
404+
405+
$data = [
406+
'push' => [
407+
'isEnabled' => true,
408+
'content' => null,
409+
],
410+
];
411+
$rules = new Nested([
412+
'push' => new Nested([
413+
'isEnabled' => [new BooleanValue()],
414+
'content' => [
415+
new Required(
416+
when: static function (mixed $value, ValidationContext $context): bool {
417+
return (bool) $context->getDataSet()->getPropertyValue('isEnabled');
418+
},
419+
),
420+
],
421+
]),
422+
]);
423+
$result = (new Validator())->validate($data, $rules);
424+
```
425+
426+
This works at any depth, including when combined with `Each`. For more details and examples, see the
427+
[Conditional validation] guide.
428+
391429
### Using keys containing separator / shortcut
392430

393431
If a key contains the separator (`.`), or `Each` shortcut (`*`), it must be escaped with backslash (`\`) in
@@ -462,5 +500,6 @@ $data = [
462500
[Result]: result.md
463501
[Basic usage]: #basic-usage-one-to-one-relation
464502
[JSFiddle]: https://jsfiddle.net/fys8uadr/
503+
[Conditional validation]: conditional-validation.md
465504
[Configuring rules via PHP attributes]: configuring-rules-via-php-attributes.md
466505
[Using validator]: using-validator.md

docs/guide/en/built-in-rules.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ Here is a list of all available built-in rules, divided by category.
2020
- [Ip](../../../src/Rule/Ip.php)
2121
- [Json](../../../src/Rule/Json.php)
2222
- [Url](../../../src/Rule/Url.php)
23+
- [Uuid](../../../src/Rule/Uuid.php)
2324

2425
### Boolean rules
2526

26-
- [Boolean](../../../src/Rule/BooleanValue.php)
27-
- [IsTrue](../../../src/Rule/TrueValue.php)
27+
- [BooleanValue](../../../src/Rule/BooleanValue.php)
28+
- [TrueValue](../../../src/Rule/TrueValue.php)
2829

2930
### Number rules
3031

docs/guide/en/conditional-validation.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,83 @@ $rules = [
266266
$result = (new Validator())->validate($data, $rules);
267267
```
268268

269+
### `when` within nested structures
270+
271+
`$context->getDataSet()->getPropertyValue()` also works within nested validation, giving access to sibling properties
272+
at the same nesting level.
273+
274+
In this example `content` is only required when its sibling property `isEnabled` is `true`:
275+
276+
```php
277+
use Yiisoft\Validator\Rule\BooleanValue;
278+
use Yiisoft\Validator\Rule\Nested;
279+
use Yiisoft\Validator\Rule\Required;
280+
use Yiisoft\Validator\ValidationContext;
281+
use Yiisoft\Validator\Validator;
282+
283+
$data = [
284+
'push' => [
285+
'isEnabled' => true,
286+
'content' => null,
287+
],
288+
];
289+
$rules = new Nested([
290+
'push' => new Nested([
291+
'isEnabled' => [new BooleanValue()],
292+
'content' => [
293+
new Required(
294+
when: static function (mixed $value, ValidationContext $context): bool {
295+
return (bool) $context->getDataSet()->getPropertyValue('isEnabled');
296+
},
297+
),
298+
],
299+
]),
300+
]);
301+
$result = (new Validator())->validate($data, $rules);
302+
```
303+
304+
Since `isEnabled` is `true`, the `Required` rule is applied and `content` fails validation because it is `null`.
305+
Setting `isEnabled` to `false` would skip the `Required` rule entirely.
306+
307+
This approach works at any depth, including inside `Each`:
308+
309+
```php
310+
use Yiisoft\Validator\Rule\BooleanValue;
311+
use Yiisoft\Validator\Rule\Each;
312+
use Yiisoft\Validator\Rule\Nested;
313+
use Yiisoft\Validator\Rule\Required;
314+
use Yiisoft\Validator\ValidationContext;
315+
use Yiisoft\Validator\Validator;
316+
317+
$data = [
318+
'tasks' => [
319+
[
320+
'push' => [
321+
'isEnabled' => false,
322+
'content' => null,
323+
],
324+
],
325+
],
326+
];
327+
$rules = new Nested([
328+
'tasks' => new Each(
329+
new Nested([
330+
'push' => new Nested([
331+
'isEnabled' => [new BooleanValue()],
332+
'content' => [
333+
new Required(
334+
when: static function (mixed $value, ValidationContext $context): bool {
335+
return (bool) $context->getDataSet()->getPropertyValue('isEnabled');
336+
},
337+
),
338+
],
339+
]),
340+
]),
341+
),
342+
]);
343+
$result = (new Validator())->validate($data, $rules);
344+
```
345+
269346
As an alternative to functions, callable classes can be used instead. This approach has the advantage of code reusability.
270347
See the [Skip on empty] section for an example.
271348

docs/guide/en/configuring-rules-via-php-attributes.md

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ final class User
7171
}
7272
```
7373

74-
> **Note:** [readonly properties] are supported only starting from PHP 8.1.
75-
7674
Error messages may include `{property}` placeholder that is replaced with the name of the property. To capitalize the
7775
first letter, you can use the `{Property}` placeholder. If you would like the name to be replaced with a custom value,
7876
you can specify it using the `Label` attribute:
@@ -91,8 +89,6 @@ final class User
9189
}
9290
```
9391

94-
> **Note:** [readonly properties] are supported only starting from PHP 8.1.
95-
9692
## Configuring for multiple entities / models with relations
9793

9894
An example of rule set for a blog post configured via arrays only:
@@ -150,7 +146,6 @@ final class Post
150146
#[Nested]
151147
public Author|null $author = null;
152148

153-
// Passing instances is available only since PHP 8.1.
154149
#[Each(new Nested(File::class))]
155150
public array $files = [];
156151

@@ -330,15 +325,9 @@ final class Yaml implements RuleInterface
330325

331326
## Limitations and workarounds
332327

333-
### Instances
334-
335-
Passing instances in the scope of attributes is only possible as of PHP 8.1. This means using attributes for complex
336-
rules such as `Composite`, `Each` and `Nested` or rules that take instances as arguments, can be problematic with PHP 8.0.
337-
338-
The first workaround is to upgrade to PHP 8.1 - this is fairly simple since it is a minor version. Tools like
339-
[Rector] can ease the process of upgrading the code base by automating routine tasks.
328+
### Alternative approaches for complex rules
340329

341-
If this is not an option, you can use other ways of providing rules, such as rule providers:
330+
For complex rules involving relations (`Nested`, `Each`), you can use rule providers as an alternative to attributes:
342331

343332
```php
344333
use Yiisoft\Validator\Rule\Integer;
@@ -452,6 +441,15 @@ method for validation - use a `Callback` rule with [method reference]. Otherwise
452441
- Use `Composite` or rules provider described in the [Instances] section.
453442
- Create a [custom rule].
454443

444+
## Combining attributes with `RulesProviderInterface`
445+
446+
When a data object has rules declared via PHP attributes and also implements `RulesProviderInterface`, rules from both
447+
sources are merged. Rules from PHP attributes are applied first, followed by rules from `getRules()`. If the same
448+
property has rules in both sources, they are combined.
449+
450+
> **Note:** This merging only applies when the object is passed as the data (first argument of `validate()`). When
451+
> passed as the rules argument (second argument), only `getRules()` is used — see [Using validator] for details.
452+
455453
## Using rules
456454

457455
Well, the rules are configured. What's next? We can either:
@@ -565,7 +563,7 @@ $dataSet = new ObjectDataSet(
565563
$result = (new Validator())->validate($dataSet);
566564
```
567565

568-
Some edge cases, like skipping DTO's static properties, require using of `AttributeRulesProvider`. After initializing it
566+
Some edge cases, like skipping DTO's static properties, require using of `AttributesRulesProvider`. After initializing it
569567
can be passed for validation right away - no need to extract rules manually beforehand.
570568

571569
```php
@@ -625,6 +623,7 @@ $options = RulesDumper::asArray($rules);
625623
[Rector]: https://github.com/rectorphp/rector
626624
[when]: conditional-validation.md#when
627625
[conditional validation]: conditional-validation.md
628-
[Instances]: #instances
626+
[Instances]: #alternative-approaches-for-complex-rules
627+
[Using validator]: using-validator.md
629628
[custom rule]: creating-custom-rules.md
630629
[method reference]: built-in-rules-callback.md#for-property

0 commit comments

Comments
 (0)