tobento / service-validation
轻松验证数据。
Requires
- php: >=8.0
- psr/container: ^2.0
- psr/log: ^1.1 || ^2.0 || ^3.0
- tobento/service-autowire: ^1.0
- tobento/service-collection: ^1.0
- tobento/service-dater: ^1.0
- tobento/service-message: ^1.0
Requires (Dev)
- monolog/monolog: ^2.3
- phpunit/phpunit: ^9.5
- tobento/service-container: ^1.0
- tobento/service-translation: ^1.0
- vimeo/psalm: ^4.0
Suggests
- tobento/service-translation: Support for translating messages
README
验证服务提供了一种轻松验证数据的方法。
目录
入门
运行以下命令添加验证服务的最新版本。
composer require tobento/service-validation
要求
- PHP 8.0 或更高版本
亮点
- 框架无关,与任何项目兼容
- 解耦设计
文档
验证
单值
轻松验证单值。
use Tobento\Service\Validation\Validator; use Tobento\Service\Validation\ValidatorInterface; use Tobento\Service\Validation\ValidationInterface; $validator = new Validator(); var_dump($validator instanceof ValidatorInterface); // bool(true) $validation = $validator->validating( value: 'foo', rules: 'alphaStrict|minLen:2', data: [], key: null ); var_dump($validation instanceof ValidationInterface); // bool(true)
查看验证器了解有关验证器的更多信息。
查看验证了解有关ValidationInterface的更多信息。
参数说明
多值
验证多个值。
use Tobento\Service\Validation\Validator; use Tobento\Service\Validation\ValidatorInterface; use Tobento\Service\Validation\ValidationInterface; $validator = new Validator(); var_dump($validator instanceof ValidatorInterface); // bool(true) $validation = $validator->validate( data: [ 'title' => 'Product', 'color' => 'blue', ], rules: [ 'title' => 'alpha', 'color' => 'in:blue:red:green', ] ); var_dump($validation instanceof ValidationInterface); // bool(true)
查看验证器了解有关验证器的更多信息。
查看验证了解有关ValidationInterface的更多信息。
参数说明
嵌套值
如果传入的值包含“嵌套”数据,您可以在规则中使用“点”语法指定这些属性
use Tobento\Service\Validation\Validator; use Tobento\Service\Validation\ValidatorInterface; use Tobento\Service\Validation\ValidationInterface; $validator = new Validator(); var_dump($validator instanceof ValidatorInterface); // bool(true) $validation = $validator->validate( data: [ 'title' => 'Product', 'meta' => [ 'color' => 'blue', ], ], rules: [ 'title' => 'alpha', 'meta.color' => 'required|in:blue:red:green', ] ); var_dump($validation instanceof ValidationInterface); // bool(true)
查看验证器了解有关验证器的更多信息。
查看验证了解有关ValidationInterface的更多信息。
参数说明
规则定义
默认规则解析器支持以下规则定义。
您还可以查看默认规则以了解它提供的规则。
如果您添加具有依赖关系的“懒”规则,您将需要使用AutowiringRuleFactory来解决,请参阅默认规则。
字符串定义
use Tobento\Service\Validation\Validator; $validation = (new Validator())->validate( data: [ 'title' => 'Product', ], rules: [ 'title' => 'minLen:2|alpha', ] );
具有字符串规则的数组定义
如果您需要定义额外的规则参数或自定义错误消息,请将规则包装在数组中
use Tobento\Service\Validation\Validator; $validation = (new Validator())->validate( data: [ 'title' => 'Product', ], rules: [ 'title' => [ // single or multiple rules 'required|alpha', // using array with string rule and custom parameters. ['minLen:3', 'error' => 'Custom error message'], // using array with string rule but seperate rule parameters and custom parameters. ['minLen', [3], 'error' => 'Custom error message'], ], ] );
对象规则
您可以通过实现规则接口来定义对象规则
use Tobento\Service\Validation\Validator; use Tobento\Service\Validation\Rule\Same; $validation = (new Validator())->validate( data: [ 'title' => 'Product', ], rules: [ 'title' => [ // single or multiple rules 'required|minLen:2', new Same(), // using array for custom parameters: [new Same(), 'error' => 'Custom error message'], // using array for lazy rule: [[Rule::class], [3], 'error' => 'Custom error message'], // lazy rule with unresolvable class params: // [[Rule::class, ['name' => 'value']], [3], 'error' => 'Custom error message'], ], ] );
具有不同验证方法的对象规则
您可以通过定义具有不同验证方法的对象规则
use Tobento\Service\Validation\Validator; use Tobento\Service\Validation\Rule\Length; $validation = (new Validator())->validate( data: [ 'title' => 'Product', ], rules: [ 'title' => [ // single or multiple rules 'required|alpha', // calls the min method for validation: [[new Length(), 'min'], [3], 'error' => 'Custom error message'], // lazy rule [[Length::class, 'min'], [3], 'error' => 'Custom error message'], // lazy rule with unresolvable class params: [[Length::class, 'min', ['name' => 'value']], [3], 'error' => 'Custom error message'], // lazy rule with unresolvable class params without method to call: // [[Rule::class, ['name' => 'value']], [3], 'error' => 'Custom error message'], ], ] );
参数
对于每个规则,您可以定义自定义参数。
use Tobento\Service\Validation\Validator; use Tobento\Service\Validation\Rule\Length; $validation = (new Validator())->validate( data: [ 'title' => 'Product', ], rules: [ 'title' => [ [ 'minLen:3', 'error' => ':attribute must at least contain :parameters[0] chars', // you might want a custom value for the attribute: ':attribute' => 'The TITLE', // you might need a custom value: ':parameters[0]' => 3, // global modifier parameters: 'limit_length' => 100, ], ], ] );
全局参数
有时您可能需要为所有规则自定义参数。
use Tobento\Service\Validation\Validator; use Tobento\Service\Validation\Rule\Length; $validation = (new Validator())->validate( data: [ 'title' => 'Product', ], rules: [ 'title' => [ // single or multiple rules 'required|alpha', // calls the min method for validation: [[new Length(), 'min'], [3]], // global error message: 'error' => 'Error message', // global replacement parameters for messages: ':attribute' => 'The TITLE', // global modifier parameters: 'limit_length' => 100, ], ] );
验证器
创建验证器
use Tobento\Service\Validation\Validator; use Tobento\Service\Validation\ValidatorInterface; use Tobento\Service\Validation\RulesInterface; use Tobento\Service\Validation\RulesParserInterface; use Tobento\Service\Validation\RulesAware; use Tobento\Service\Message\MessagesFactoryInterface; $validator = new Validator( rules: null, // null|RulesInterface rulesParser: null, // null|RulesParserInterface messagesFactory: null // null|MessagesFactoryInterface ); var_dump($validator instanceof ValidatorInterface); // bool(true) var_dump($validator instanceof RulesAware); // bool(true)
参数说明
验证器接口
use Tobento\Service\Validation\ValidatorInterface; use Tobento\Service\Validation\ValidationInterface; use Tobento\Service\Collection\Collection; interface ValidatorInterface { public function validating( mixed $value, string|array $rules, array|Collection $data = [], null|string $key = null ): ValidationInterface; public function validate(mixed $data, array $rules): ValidationInterface; }
查看验证以了解有关方法的更多信息。
查看Collection Service以了解更多信息。
规则感知
use Tobento\Service\Validation\RulesInterface; interface RulesAware { public function rules(): RulesInterface; }
查看规则接口以了解有关RulesInterface的更多信息。
验证
验证接口
use Tobento\Service\Validation\ValidationInterface; use Tobento\Service\Validation\RuleInterface; use Tobento\Service\Message\MessagesInterface; use Tobento\Service\Collection\Collection; interface ValidationInterface { public function isValid(): bool; public function errors(): MessagesInterface; public function data(): Collection; public function valid(): Collection; public function invalid(): Collection; public function rule(): null|RuleInterface; }
方法说明
错误信息
默认情况下,当在错误消息中定义时,规则键用作:attribute 参数。
出于翻译原因,不建议编写像“:attribute 必须……”这样的消息,更好的做法是将“title”添加到:attribute 参数中,因为“the”可能因属性名称而异。
use Tobento\Service\Validation\Validator; use Tobento\Service\Message\MessagesInterface; $validation = (new Validator())->validate( data: [ 'title' => 'Pr', 'color' => 'green', ], rules: [ 'title' => 'minLen:3|alpha', 'color' => 'in:blue:red', ] ); $errors = $validation->errors(); var_dump($errors instanceof MessagesInterface); // bool(true)
获取数据键的第一个错误消息
use Tobento\Service\Message\MessageInterface; $errors = $validation->errors(); $error = $errors->key('title')->first(); var_dump($error instanceof MessageInterface); // bool(true) echo $error; // The title must at least contain 3 chars.
查看消息服务以了解有关消息的更多信息。
检索所有数据键的所有错误消息
use Tobento\Service\Message\MessageInterface; $errors = $validation->errors(); foreach($errors->key('title')->all() as $error) { var_dump($error instanceof MessageInterface); // bool(true) }
查看消息服务以了解有关消息的更多信息。
确定是否存在某个数据键的消息
$errors = $validation->errors(); var_dump($errors->key('title')->has()); // bool(true)
查看消息服务以了解有关消息的更多信息。
自定义错误消息
use Tobento\Service\Validation\Validator; $validation = (new Validator())->validate( data: [ 'title' => 'Pr', 'color' => 'green', ], rules: [ 'title' => [ 'alpha', ['minLen', [3], 'error' => ':attribute must contain at least :parameters[0] chars!'] ], 'color' => 'in:blue:red', ] ); $errors = $validation->errors(); echo $errors->key('title')->first(); // The title must contain at least 3 chars!
自定义错误消息参数
use Tobento\Service\Validation\Validator; $validation = (new Validator())->validate( data: [ 'title' => 'Pr', 'color' => 'green', ], rules: [ 'title' => [ 'alpha', [ 'minLen', [3], ':attribute' => 'The TITLE', ':parameters[0]' => 3, 'error' => ':attribute must contain at least :parameters[0] chars!' ] ], 'color' => 'in:blue:red', ] ); $errors = $validation->errors(); echo $errors->key('title')->first(); // The TITLE must contain at least 3 chars!
全局自定义错误消息参数
您可能需要定义所有规则的全局消息参数
use Tobento\Service\Validation\Validator; $validation = (new Validator())->validate( data: [ 'title' => 'Pr', 'color' => 'green', ], rules: [ 'title' => [ 'minLen:3|alpha', ':attribute' => 'The TITLE', // you might even set a global message for all rules. 'error' => ':attribute is invalid', ], 'color' => 'in:blue:red', ] ); $errors = $validation->errors(); echo $errors->key('title')->first(); // The TITLE is invalid.
跳过第一个参数
您可能需要通过将其声明为 :parameters[-1] 来跳过参数的第一个值。
use Tobento\Service\Validation\Validator; $validation = (new Validator())->validate( data: [ 'title' => '', 'color' => 'green', ], rules: [ 'title' => [ 'required_ifIn:color:green:red', 'error' => ':attribute is required as :parameters[0] is in list :parameters[-1].', ], 'color' => 'in:blue:red', ] ); $errors = $validation->errors(); echo $errors->key('title')->first(); // The title is required as color is in list green, red.
已验证数据
use Tobento\Service\Validation\Validator; use Tobento\Service\Collection\Collection; $validation = (new Validator())->validate( data: [ 'title' => 'Pr', 'color' => 'green', ], rules: [ 'title' => 'minLen:3|alpha', 'color' => 'in:blue:red', ] ); // all validated data: var_dump($validation->data() instanceof Collection); // bool(true) // all valid data: var_dump($validation->valid() instanceof Collection); // bool(true) // all invalid data: var_dump($validation->invalid() instanceof Collection); // bool(true)
查看集合服务以了解有关集合的更多信息。
规则
规则接口
use Tobento\Service\Validation\RulesInterface; use Tobento\Service\Validation\RuleInterface; use Tobento\Service\Validation\RuleNotFoundException; use Tobento\Service\Validation\InvalidRuleException; /** * RulesInterface */ interface RulesInterface { /** * Add a rule. * * @param string $name * @param mixed $rule * @return static $this */ public function add(string $name, mixed $rule): static; /** * Returns the rule based on the specified rule. * * @param mixed $rule * @return RuleInterface * * @throws RuleNotFoundException * @throws InvalidRuleException */ public function get(mixed $rule): RuleInterface; }
默认规则
use Tobento\Service\Validation\DefaultRules; use Tobento\Service\Validation\RulesInterface; use Tobento\Service\Validation\RuleFactoryInterface; $rules = new DefaultRules( ruleFactory: null, //null|RuleFactoryInterface ); var_dump($rules instanceof RulesInterface); // bool(true)
使用自动装配规则工厂
如果您使用依赖关系定义或添加“延迟”规则,则需要自动装配规则工厂。
use Tobento\Service\Validation\DefaultRules; use Tobento\Service\Validation\AutowiringRuleFactory; // Any PSR-11 container $container = new \Tobento\Service\Container\Container(); $rules = new DefaultRules( ruleFactory: new AutowiringRuleFactory($container); );
可用规则
以下规则是默认可用的
添加规则
您可以通过以下方式添加额外的规则。如果您添加具有依赖关系的“延迟”规则,则将需要使用自动装配规则工厂进行解析。
use Tobento\Service\Validation\DefaultRules; use Tobento\Service\Validation\RulesInterface; use Tobento\Service\Validation\AutowiringRuleFactory; use Tobento\Service\Validation\Rule\Same; use Tobento\Service\Validation\Rule\Type; // Any PSR-11 container $container = new \Tobento\Service\Container\Container(); $rules = new DefaultRules( ruleFactory: new AutowiringRuleFactory($container); ); $rules = new DefaultRules(); $rules->add('same', new Same()); // Lazy: $rules->add('same', Same::class); // Custom method: $rules->add('bool', [new Type(), 'bool']); // Lazy custom method: $rules->add('bool', [Type::class, 'bool']); // Lazy custom method with unresolvable parameters: // $rules->add('rule', [Rule::class, 'bool', ['name' => 'value']]); // Lazy with unresolvable parameters: // $rules->add('rule', [Rule::class, ['name' => 'value']]);
自定义规则
您可以编写自己的规则类或调整默认规则以满足您的需求。
use Tobento\Service\Validation\DefaultRules; class CustomDefaultRules extends DefaultRules { protected function getDefaultRules(): array { $rules = parent::getDefaultRules(); // adding or overwriting rules. $rules['bool'] = [\Tobento\Service\Validation\Rule\Type::class, 'bool']; return $rules; } } $rules = new CustomDefaultRules();
规则
规则接口
use Tobento\Service\Validation\RuleInterface; /** * RuleInterface */ interface RuleInterface { /** * Skips validation depending on value and rule method. * * @param mixed $value The value to validate. * @param string $method * @return bool Returns true if skip validation, otherwise false. */ public function skipValidation(mixed $value, string $method = 'passes'): bool; /** * Determine if the validation rule passes. * * @param mixed $value The value to validate. * @param array $parameters Any parameters used for the validation. * @return bool */ public function passes(mixed $value, array $parameters = []): bool; /** * Returns the validation error messages. * * @return array */ public function messages(): array; }
通过规则
使用Passes规则可以创建任何自定义规则。
use Tobento\Service\Validation\Rule\Passes; $validation = $validator->validating( value: 'foo', rules: [ // rule does pass: new Passes(passes: true), // rule does not pass: new Passes(passes: false), // rule does pass: new Passes(passes: fn (mixed $value): bool => $value === 'foo'), // using static new method: Passes::new(passes: true), ], );
Passes参数
以下参数可用
use Tobento\Service\Validation\Rule\Passes; use Tobento\Service\Validation\ValidatorInterface; use Tobento\Service\Validation\ValidationInterface; $rule = new Passes(passes: function( mixed $value, array $parameters, ValidatorInterface $validator, ValidationInterface $validation): bool { return true; });
如果您使用自动装配规则工厂设置了验证器,则 passes
和 skipValidation
可调用项将被自动装配
use Tobento\Service\Validation\Rule\Passes; $rule = new Passes(passes: function(mixed $value, SomeService $service): bool { return true; });
确保声明闭包类型
默认情况下,声明类型为 $value
参数的闭包将自动验证。如果不匹配输入值类型,则规则将不会通过,并且闭包将永远不会执行。
use Tobento\Service\Validation\Rule\Passes; $rule = new Passes(passes: fn (string|int $value): bool { return true; }); // you may deactivate it, but then you will need to declare the value type as mixed: $rule = new Passes( passes: fn (mixed $value): bool { return true; }, verifyDeclaredType: false, );
自定义错误消息
您可以指定自定义错误消息
use Tobento\Service\Validation\Rule\Passes; $rule = new Passes( passes: true, errorMessage: 'Custom error message', );
跳过验证
您可以使用 skipValidation 参数在特定条件下跳过验证
$validation = $validator->validating( value: 'foo', rules: [ // skips validation: new Passes(passes: true, skipValidation: true), // does not skip validation: new Passes(passes: true, skipValidation: false), // skips validation: new Passes(passes: true, skipValidation: fn (mixed $value): bool => $value === 'foo'), ], );
自定义规则
use Tobento\Service\Validation\Rule; class ListRule extends Rule { /** * The error messages. */ public const MESSAGES = [ 'passes' => ':attribute must be in list :parameters', ]; /** * Determine if the validation rule passes. * * @param mixed $value The value to validate. * @param array $parameters Any parameters used for the validation. * @return bool */ public function passes(mixed $value, array $parameters = []): bool { return in_array($value, $parameters); } }
使用多个验证方法
查看Rule\Strings的示例。
需要验证进行验证
查看Rule\Arr的示例。
需要验证器进行验证
查看Rule\Arr的示例。
在Passes时跳过验证
查看规则示例。
规则解析器
规则解析器的角色是解析规则定义。
默认规则解析器
有关更多详细信息,请参阅规则定义。
自定义规则解析器
您可以根据需要实现以下接口来编写自己的解析器。
use Tobento\Service\Validation\RulesParserInterface; use Tobento\Service\Validation\ParsedRule; use Tobento\Service\Validation\RulesParserException; interface RulesParserInterface { /** * Parses the rules. * * @param string|array $rules * @return array<int, ParsedRule> * * @throws RulesParserException */ public function parse(string|array $rules): array; }
消息
消息用于验证错误消息。
查看消息服务以了解有关消息的更多信息。
消息工厂
使用消息工厂,您可以完全控制消息的创建和修改。
use Tobento\Service\Validation\Message\MessagesFactory; use Tobento\Service\Message\MessagesFactoryInterface; use Tobento\Service\Message\MessageFactoryInterface; use Tobento\Service\Message\ModifiersInterface; use Psr\Log\LoggerInterface; $messagesFactory = new MessagesFactory( messageFactory: null, // null|MessageFactoryInterface modifiers: null, // null|ModifiersInterface logger: null, // null|LoggerInterface ); var_dump($messagesFactory instanceof MessagesFactoryInterface); // bool(true) $modifiers = $messagesFactory->modifiers(); var_dump($modifiers instanceof ModifiersInterface); // bool(true)
参数说明
默认修饰符
如果您未在工厂上设置修饰符,则会添加以下修饰符
use Tobento\Service\Message\Modifiers; use Tobento\Service\Validation\Message\RuleParametersModifier; use Tobento\Service\Message\Modifier\ParameterReplacer; $modifiers = new Modifiers( // maps :attribute, :value, :parameters // based on the rule parameters new RuleParametersModifier(), // Default parameter replacer new ParameterReplacer(), );
消息翻译
如果您想翻译消息,则可以使用翻译修饰符
但是,您首先需要安装翻译服务。
use Tobento\Service\Validation\Validator; use Tobento\Service\Validation\Message\MessagesFactory; use Tobento\Service\Validation\Message\RuleParametersModifier; use Tobento\Service\Translation; use Tobento\Service\Message\Modifier\Translator; use Tobento\Service\Message\Modifier\ParameterTranslator; use Tobento\Service\Message\Modifiers; use Tobento\Service\Message\Modifier\ParameterReplacer; $translator = new Translation\Translator( new Translation\Resources( new Translation\Resource('*', 'de', [ 'The :attribute must only contain letters [a-zA-Z]' => ':attribute muss aus Buchstaben [a-zA-Z] bestehen.', 'title' => 'Titel', ]), ), new Translation\Modifiers(), new Translation\MissingTranslationHandler(), 'de', ); $messagesFactory = new MessagesFactory( modifiers: new Modifiers( new Translator(translator: $translator, src: '*'), new RuleParametersModifier(), new ParameterTranslator( parameters: [':attribute'], translator: $translator, src: '*' ), new ParameterReplacer(), ) ); $validator = new Validator(messagesFactory: $messagesFactory); $validation = $validator->validate( data: [ 'title' => 'P3', ], rules: [ 'title' => 'alpha', ] ); $errors = $validation->errors(); var_dump($errors->key('title')->first()->message()); // string(44) "Titel muss aus Buchstaben [a-zA-Z] bestehen."