phpixie / validate
PHPixie 验证库
3.4.1
2018-02-16 00:11 UTC
Requires (Dev)
- phpixie/test: 3.*@dev
README
PHPixie 验证库
大多数 PHP 验证库都存在一个很大的缺陷 - 它们只适用于扁平数组,并且主要针对表单验证。这种做法已经过时,因为当开发 API 和 RESTful 服务时,我们经常需要处理具有复杂结构的请求文档。PHPixie Validate 设计用于提供一种简单的方法来验证这些文档。它不需要任何依赖项,因此即使您不使用 PHPixie,它也可以在您的项目中派上用场。
让我们先从一个简单的扁平数组示例开始
$validate = new \PHPixie\Validate(); //Or if you are using PHPixie $validate = $builder->components()->validate(); // The data we will be validating $data = array( 'name' => 'Pixie', 'home' => 'Oak', 'age' => 200, 'type' => 'fairy' ); // There are multiple syntaxes supported // for building a validator // The standard approach $validator = $validate->validator(); // A flat file is just a document $document = $validator->rule()->addDocument(); // A required field with filters $document->valueField('name') ->required() ->addFilter() ->alpha() ->minLength(3) // Add custom error message if this set of filters fails ->message('Name is too short') // Or define a custom error type ->customError('name_short', 'Name is too short'); // You can also add filters as array $document->valueField('home') ->required() ->addFilter() ->filters(array( 'alpha', 'minLength' => array(3) )); // Or a shorthand $document->valueField('home') ->required() ->filter(array( 'alpha', 'minLength' => array(3) ), "Home must consist of letters and be longer than 3 characters"); // A shorthand approach $document->valueField('age') ->required() // Define filter and message ->filter('numeric', 'Age must be a number'); // Pass your own callback $document->valueField('type') ->required() // More flexible callback with // access to result object ->callback(function($result, $value) { if(!in_array($value, array('fairy', 'pixie'))) { // If is not valid add an error to the result $result->addMessageError("Type can be either 'fairy' or 'pixie'"); //Or you can just return an error message to be added return "Type can be either 'fairy' or 'pixie'"; } }); // By default validator will only allow // fields that have rules attached to them // If you wish to allow extra fields: $document->allowExtraFields(); // Custom validator function $validator->rule()->callback(function($result, $value) { if($value['type'] === 'fairy' && $value['home'] !== 'Oak') { $result->addMessageError("Fairies live only inside oaks"); } });
可用过滤器的完整列表可以在此处找到 这里。这些注册类中的每个公共方法都是一个可用过滤器
您也可以使用简写回调语法构建验证器
$validator = $validate->validator(function($value) { $value->document(function($document) { $document ->allowExtraFields() ->field('name', function($name) { $name ->required() ->filter(function($filter) { $filter ->alpha() ->minLength(3); }); }) ->field('home', function($home) { $home ->required() ->filter(array( 'alpha', 'minLength' => array(3) )); }) ->field('age', function($age) { $age ->required() ->filter('numeric'); }) ->field('type', function($home) { $home ->required() ->callback(function($result, $value) { if(!in_array($value, array('fairy', 'pixie'))) { $result->addMessageError("Type can be either 'fairy' or 'pixie'"); } }); }); }) ->callback(function($result, $value) { if($value['type'] === 'fairy' && $value['home'] !== 'Oak') { $result->addMessageError("Fairies live only inside oaks"); } }); });
现在我们来尝试进行验证
$result = $validator->validate($data); var_dump($result->isValid()); // Add some errors $data['name'] = 'Pi'; $data['home'] = 'Maple'; $result = $validator->validate($data); var_dump($result->isValid()); // Print errors foreach($result->errors() as $error) { echo $error."\n"; } foreach($result->invalidFields() as $fieldResult) { echo $fieldResult->path().":\n"; foreach($fieldResult->errors() as $error) { echo $error."\n"; } } /* bool(true) bool(false) Fairies live only inside oaks name: Value did not pass filter 'minLength' */
处理结果
如上图所示,Result 对象包含附加到其上的错误以及所有字段的输出结果。虽然错误看起来像是字符串,但实际上它们也是实现了 __toString()
方法以便于调试的类。当处理表单时,您可能想使用自己的错误消息。为此,从错误类中获取类型和参数信息并相应地格式化,例如
if($error->type() === 'filter') { if($error->filter() === 'minLength') { $params = $error->parameters(); echo "Please enter at least {$params[0]} characters"; } }
这样,您就可以通过简单的辅助类来定制所有错误消息供您的用户使用。
数据结构
现在我们来尝试一个结构化示例
$data = array( 'name' => 'Pixie', // 'home' is just a subdocument 'home' => array( 'location' => 'forest', 'name' => 'Oak' ), // 'spells' is an array of documents of a particular type // and a string key (also has to be validated) // of the same type 'spells' => array( 'charm' => array( 'name' => 'Charm Person', 'type' => 'illusion' ), 'blast' => array( 'name' => 'Fire Blast', 'type' => 'evocation' ), // .... ) ); $validator = $validate->validator(); $document = $validator->rule()->addDocument(); $document->valueField('name') ->required() ->addFilter() ->alpha() ->minLength(3); // Subdocument $homeDocument = $document->valueField('home') ->required() ->addDocument(); $homeDocument->valueField('location') ->required() ->addFilter() ->in(array('forest', 'meadow')); $homeDocument->valueField('name') ->required() ->addFilter() ->alpha(); // Array of subdocuments $spellsArray = $document->valueField('spells') ->required() ->addArrayOf() ->minCount(1); // Rule for the array key $spellDocument = $spellsArray ->valueKey() ->filter('alpha'); // Rule for the array element $spellDocument = $spellsArray ->valueItem() ->addDocument(); $spellDocument->valueField('name') ->required() ->addFilter() ->minLength(3); $spellDocument->valueField('type') ->required() ->addFilter() ->alpha();
使用替代语法时看起来会更好,因为它遵循您数据的结构
$validator = $validate->validator(function($value) { $value->document(function($document) { $document ->field('name', function($name) { $name ->required() ->filter(array( 'alpha', 'minLength' => array(3) )); }) ->field('home', function($home) { $home ->required() ->document(function($home) { $home->field('location', function($location) { $location ->required() ->addFilter() ->in(array('forest', 'meadow')); }); $home->field('name', function($name) { $name ->required() ->filter('alpha'); }); }); }) ->field('spells', function($spells) { $spells->required()->arrayOf(function($spells){ $spells ->minCount(1) ->key(function($key) { $key->filter('alpha'); }) ->item(function($spell) { $spell->required()->document(function($spell) { $spell->field('name', function($name) { $name ->required() ->addFilter() ->minLength(3); }); $spell->field('type', function($type) { $type ->required() ->filter('alpha'); }); }); }); }); }); }); });
现在我们来尝试使用它
$result = $validator->validate($data); var_dump($result->isValid()); //bool(true) // Add some errors $data['name'] = ''; $data['spells']['charm']['name'] = '1'; // Invalid key (should be string) $data['spells'][3] = $data['spells']['blast']; $result = $validator->validate($data); var_dump($result->isValid()); //bool(false) // Recursive function for error printing function printErrors($result) { foreach($result->errors() as $error) { echo $result->path().': '.$error."\n"; } foreach($result->invalidFields() as $result) { printErrors($result); } } printErrors($result); /* name: Value is empty spells.charm.name: Value did not pass filter 'minLength' spells.3: Value did not pass filter 'alpha' */
试试看
要启动此演示,只需运行
git clone https://github.com/phpixie/validate
cd validate/examples
php composer.phar install
php simple.php
php document.php