Skip to content

Commit 960ca39

Browse files
AZabolotnikovclaude
andcommitted
docs: document validation rules and the BaseValidationRule structure
Add documentation/rules.md covering the three custom validation rules (unique_except_of_authorized_user, list_exists, db_type_range) and how they plug into BaseValidationRule (validate/ruleName/fromParameters), so a future contributor knows how to add a new rule. Link it from the readme and the iterators doc's nav footer. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 30dd0a9 commit 960ca39

3 files changed

Lines changed: 91 additions & 0 deletions

File tree

documentation/iterators.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,7 @@ foreach($iterator->getGenerator() as $category) {
5555
```
5656

5757
[<< Services][1]
58+
[Rules >>][2]
5859

5960
[1]:services.md
61+
[2]:rules.md

documentation/rules.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
[<< Iterators][1]
2+
3+
# Validation rules
4+
5+
`ValidationServiceProvider` registers a set of custom validation rules on boot. If your app relies on Laravel's
6+
package auto-discovery, this happens automatically. Otherwise you need to add
7+
`RonasIT\Support\ValidationServiceProvider::class` to `config/app.php` yourself (see the
8+
[3.9 migration note][2] for details).
9+
10+
Every rule below can be used either with Laravel's string syntax (`'field' => 'rule_name:param1,param2'`) or with
11+
the object syntax (`'field' => [new SomeRule(...)]`).
12+
13+
## unique_except_of_authorized_user
14+
15+
`RonasIT\Support\Rules\UniqueExceptOfAuthorizedUserRule`
16+
17+
Fails if any other row (any row except the currently authorized user's own) already has the given value(s) in the
18+
checked column. Useful for "unique, but ignore my own record" checks, e.g. when a user updates their own email.
19+
20+
```
21+
'email' => 'unique_except_of_authorized_user:users,id'
22+
```
23+
24+
* `table` (optional, default `users`) - table to check.
25+
* `keyField` (optional, default `id`) - primary key column excluded for the currently authorized user (via
26+
`Auth::id()`).
27+
28+
## list_exists
29+
30+
`RonasIT\Support\Rules\ListExistsRule`
31+
32+
Fails unless every value passed in an array field exists in the given table's column. Accepts either a flat array
33+
of values, or an array of objects/collections, in which case the third parameter tells the rule which field to
34+
pluck values from.
35+
36+
```
37+
'ids' => 'list_exists:clients,id'
38+
39+
// or, for a collection of objects:
40+
'items' => 'list_exists:clients,id,id'
41+
```
42+
43+
* `table` (required) - table to check against.
44+
* `keyField` (optional, default `id`) - column to check against.
45+
* `fieldName` (optional) - required when the field value is an array of objects/collections; the field to pluck
46+
from each item before checking.
47+
48+
## db_type_range
49+
50+
`RonasIT\Support\Rules\DBTypeRangeRule`
51+
52+
Fails unless the value fits the numeric or string range of the given database column type. Useful for validating
53+
request input before it hits a database insert/update, so out-of-range values fail with a clear message instead of
54+
a database error.
55+
56+
```
57+
'age' => 'db_type_range:smallint'
58+
```
59+
60+
* `type` (required) - one of `smallint`, `integer`, `bigint`, `smallserial`, `serial`, `bigserial`, `real`,
61+
`double`, `varchar`. The ranges are resolved via the `DBTypeResolverContract` binding (`PostgresDBTypeResolver`
62+
by default).
63+
64+
## Adding a new rule
65+
66+
Every rule class extends the abstract `RonasIT\Support\Rules\BaseValidationRule`, which implements
67+
`Illuminate\Contracts\Validation\ValidationRule` and provides the bridge between Laravel's string-syntax
68+
`Validator::extend()` API and the rule's own `validate()` method. A new rule only needs to implement three things:
69+
70+
* `validate(string $attribute, mixed $value, Closure $fail): void` - the actual validation logic, same as any
71+
other Laravel `ValidationRule`.
72+
* `ruleName(): string` - the string name the rule is registered under (used to attach the failure message via
73+
`addReplacer()`).
74+
* `fromParameters(array $parameters, string $attribute): static` - builds a rule instance from the string-syntax
75+
parameters (`'rule_name:param1,param2'`); this is also the right place to throw
76+
`InvalidValidationRuleUsageException` for misuse (e.g. a missing required parameter).
77+
78+
Then register it in `ValidationServiceProvider::extendValidator()`:
79+
80+
```php
81+
Validator::extend('my_rule', MyRule::extend(...));
82+
```
83+
84+
[<< Iterators][1]
85+
86+
[1]:iterators.md
87+
[2]:migration.md#3.9

readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Versioning is a mechanism to keep your API applications in a workable state for
2929
- [Traits][2]
3030
- [Services][3]
3131
- [Iterators][4]
32+
- [Validation rules][9]
3233

3334
## Migration guids
3435
- [1.1][5]
@@ -43,3 +44,4 @@ Versioning is a mechanism to keep your API applications in a workable state for
4344
[6]:./documentation/migration.md#2.0.0
4445
[7]:./documentation/migration.md#2.0.8
4546
[8]:./documentation/versioning.md
47+
[9]:./documentation/rules.md

0 commit comments

Comments
 (0)