meritum/validation
最新稳定版本:1.0.0
Composer 安装命令:
composer require meritum/validation
包简介
Validation library for the Meritum ecosystem
README 文档
README
Validation library for the Meritum ecosystem. Provides a rule-agnostic engine, a set of 32 default rules, and kernel integration via ValidationModule.
Requirements
- PHP 8.4+
georgeff/kernel^1.6
Installation
composer require meritum/validation
Usage
Inject Validator and call validate() with a schema and input array. The schema maps attribute names to a list of rules. Rules are plain strings; rules with parameters use the attribute name as the key and an array of parameters as the value.
use Meritum\Validation\Validator; $result = $validator->validate( [ 'name' => ['required', 'string', 'lengthMin' => [2], 'lengthMax' => [100]], 'email' => ['required', 'email'], 'age' => ['optional', 'integer', 'min' => [18]], 'password' => ['required', 'string', 'lengthMin' => [8]], 'password_confirmation' => ['required', 'sameAs' => 'password'], ], $input, ); if ($result->passed()) { // proceed } foreach ($result->getErrors() as $attribute => $messages) { // $attribute => 'email', $messages => ['The email must be a valid email address'] }
Optionality and nullability
| Rules | Missing | null |
Present |
|---|---|---|---|
['string'] |
fails | fails | validated |
['required', 'string'] |
fails (stops) | fails (stops) | validated |
['optional', 'string'] |
passes | passes | validated |
['nullable', 'string'] |
fails | passes | validated |
['nullable', 'required', 'string'] |
fails (stops) | passes | validated |
optional— field may be absent or null; if present and non-null, remaining rules runnullable— null is explicitly valid; if the value is null, remaining rules are skippedrequired— field must be present, non-null, and non-emptynullable+requiredexpresses "must be present, but null is acceptable"- Rule order matters —
optionalandnullablemust appear before the rules they gate
Dot notation and wildcards
Nested attributes use dot notation. Wildcards validate each element of an array. Both can be combined and nested arbitrarily.
$result = $validator->validate( [ 'address.city' => ['required', 'string'], 'address.postcode' => ['optional', 'string'], 'items.*.name' => ['required', 'string'], 'items.*.price' => ['required', 'numeric', 'min' => [0]], 'items.*.variants.*.sku' => ['required', 'string'], ], $input, );
Errors for wildcard attributes are keyed by the concrete path — items.1.name, items.0.variants.2.sku, etc. If the parent is absent or not an array, the wildcard path passes silently — combine with a separate rule on the parent attribute to enforce its presence.
Module registration
Register ValidationModule with the kernel to wire up the engine and all default rules.
use Meritum\Validation\ValidationModule; $kernel->addModule(new ValidationModule());
The module binds Validator::class to ValidationEngine via ValidationEngineFactory, and tags all 32 default rules with validation.rules. The factory resolves tagged rules at boot time and spreads them into the engine.
Adding custom rules
Implement RuleInterface and register the class with the kernel tagged as validation.rules. The rule's name() return value is the string used in schemas.
use Meritum\Validation\RuleInterface; final class Slug implements RuleInterface { public function name(): string { return 'slug'; } public function validate(mixed $value, mixed ...$params): bool { return is_string($value) && (bool) preg_match('/^[a-z0-9]+(?:-[a-z0-9]+)*$/', $value); } public function message(string $attribute, mixed ...$params): string { return "The {$attribute} must be a valid slug"; } }
$kernel->define(Slug::class, fn() => new Slug())->tag('validation.rules');
$validator->validate(['handle' => ['required', 'slug']], $input);
Overriding a default rule
Register a new class that returns the same name() as the rule you want to replace. The last registration wins.
final class StrictEmail implements RuleInterface { public function name(): string { return 'email'; // replaces the default Email rule } // ... } $kernel->define(StrictEmail::class, fn() => new StrictEmail())->tag('validation.rules');
Stoppable rules
Implement StoppableRuleInterface to halt validation of remaining rules for an attribute when a condition is met. shouldPropagationStop() is called after validate() and receives the same value and params.
use Meritum\Validation\StoppableRuleInterface; final class Bail implements StoppableRuleInterface { public function name(): string { return 'bail'; } public function validate(mixed $value, mixed ...$params): bool { return true; } public function message(string $attribute, mixed ...$params): string { return ''; } public function shouldPropagationStop(mixed $value, mixed ...$params): bool { return true; // always stop — no further rules run after this } }
Field-referencing rules
Implement FieldReferencingRuleInterface for rules that compare a value against another field in the input. resolveParams() receives the comparison field name (from the schema) and the full input, and returns the params passed to validate() and message().
use Meritum\Validation\FieldReferencingRuleInterface; use Meritum\Validation\Missing; final class GreaterThan implements FieldReferencingRuleInterface { public function name(): string { return 'greaterThan'; } public function resolveParams(string $attribute, array $input): array { return [$input[$attribute] ?? new Missing(), $attribute]; } public function validate(mixed $value, mixed ...$params): bool { if ($params[0] instanceof Missing) { return false; } return is_numeric($value) && is_numeric($params[0]) && $value > $params[0]; } public function message(string $attribute, mixed ...$params): string { $field = is_string($params[1]) ? $params[1] : ''; return "The {$attribute} must be greater than {$field}"; } }
$validator->validate(['end_date' => ['required', 'date', 'greaterThan' => 'start_date']], $input);
Default rules
Presence and flow
| Rule | Schema | Description |
|---|---|---|
required |
'required' |
Must be present, non-null, and non-empty string |
optional |
'optional' |
Absent or null passes; if present and non-null, remaining rules run |
nullable |
'nullable' |
Null passes and remaining rules are skipped |
Type
| Rule | Schema | Description |
|---|---|---|
string |
'string' |
Must be a string |
integer |
'integer' |
Must be an integer |
float |
'float' |
Must be a float (integers do not pass — use numeric for "can be cast to number") |
boolean |
'boolean' |
Must be a boolean |
array |
'array' |
Must be an array |
numeric |
'numeric' |
Must be numeric — accepts integers, floats, and numeric strings |
String
| Rule | Schema | Description |
|---|---|---|
alpha |
'alpha' |
Letters only (a–z, A–Z) |
alphaNum |
'alphaNum' |
Letters and digits only |
email |
'email' |
Valid email address |
url |
'url' |
Valid URL |
uuid |
'uuid' |
Valid UUID (any version) |
ip |
'ip' |
Valid IPv4 or IPv6 address |
ipv4 |
'ipv4' |
Valid IPv4 address |
ipv6 |
'ipv6' |
Valid IPv6 address |
regex |
'regex' => ['/pattern/'] |
Matches the given regular expression |
lengthMin |
'lengthMin' => [4] |
Minimum string length (multibyte-safe) |
lengthMax |
'lengthMax' => [255] |
Maximum string length (multibyte-safe) |
lengthBetween |
'lengthBetween' => [4, 255] |
Length between min and max inclusive |
Numeric
| Rule | Schema | Description |
|---|---|---|
min |
'min' => [0] |
Value must be ≥ min |
max |
'max' => [100] |
Value must be ≤ max |
between |
'between' => [1, 100] |
Value must be between min and max inclusive |
Comparison
| Rule | Schema | Description |
|---|---|---|
equals |
'equals' => ['value'] |
Strict equality against a literal value |
notEquals |
'notEquals' => ['value'] |
Strict inequality against a literal value |
in |
'in' => ['a', 'b', 'c'] |
Value must be in the given list (strict) |
notIn |
'notIn' => ['a', 'b'] |
Value must not be in the given list (strict) |
Field comparison
| Rule | Schema | Description |
|---|---|---|
sameAs |
'sameAs' => 'other_field' |
Must strictly equal another field's value |
differentFrom |
'differentFrom' => 'other_field' |
Must strictly differ from another field's value |
Date
| Rule | Schema | Description |
|---|---|---|
date |
'date' |
Valid calendar date string or DateTimeInterface; rejects relative strings like "next Tuesday" |
dateFormat |
'dateFormat' => ['Y-m-d'] |
Date string matching the given date() format exactly |
License
MIT — see LICENSE.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 7
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-09