elie29/validator

一个通过执行给定规则来验证上下文(POST、GET等)的库。

v2.0.5 2019-12-06 09:41 UTC

README

Build Status Coverage Status

简介

一个通过执行给定规则来验证上下文(POST、GET等)的库。

安装

运行以下命令通过Composer安装

composer require elie29/validator

入门

Validator 需要一个或多个规则(约束)来验证给定的上下文。

一个使用 $_POST 的基本示例

<?php

use Elie\Validator\Rule\EmailRule;
use Elie\Validator\Rule\MultipleAndRule;
use Elie\Validator\Rule\NumericRule;
use Elie\Validator\Rule\RangeRule;
use Elie\Validator\Rule\StringRule;
use Elie\Validator\Validator;

/**
 * A key could have multiple rules
 *  - name could not be empty (required and minimum 1 character length)
 *  - age could be empty (non existent, null or '') otherwise NumericRule is applied
 *  - age could be empty or among several values
 *  - email is required and should be a valid string email
 */
$rules =[
    ['name', StringRule::class, StringRule::MIN => 1, StringRule::REQUIRED => true],
    ['age', NumericRule::class, NumericRule::MAX => 60],
    ['age', RangeRule::class, RangeRule::RANGE => [30, 40, 50]],
    // Use composition instead of validating the key twice
    ['email', MultipleAndRule::class, MultipleAndRule::REQUIRED => true, MultipleAndRule::RULES => [
        [StringRule::class, StringRule::MAX => 255],
        [EmailRule::class],
    ]],
];

$validator = new Validator($_POST, $rules, true); // stop processing on error.

$validator->validate(); // bool depends on $_POST content

可用规则

  1. 所有规则都接受 requiredtrimmessages 选项。默认情况下,required 为 false,而 trim 为 true。
  2. ArrayRule 接受 minmax 选项。空值将被转换为空数组 []。
  3. BicRule
  4. BooleanRule 接受 cast 选项。
  5. CallableRule 接受 callable 函数。
  6. ChoicesRule 接受 list 选项。
  7. CollectionRule 接受 listjson 选项。
  8. CompareRule 接受 signexpected 选项。默认情况下,signCompareRule::EQexpected 为 null。
  9. DateRule 接受 formatseparator 选项。
  10. EmailRule
  11. IpRule 接受 flag 选项。
  12. JsonRule 接受 decode 选项
  13. MatchRule 需要提供 pattern 选项。
  14. MultipleAndRule 需要提供 rules 选项。
  15. MultipleOrRule 需要提供 rules 选项。
  16. NumericRule 接受 minmaxcast 选项。
  17. RangeRule 接受 range 选项。
  18. StringRule 接受 minmax 选项。
  19. TimeRule
  20. 您的自定义规则

如何添加新规则

您需要实现 RuleInterface 或扩展 AbstractRule

<?php

use Elie\Validator\Rule\AbstractRule;

class MyValueRule extends AbstractRule
{

    public const INVALID_MY_VALUE = 'invalidMyValue';

    protected $my_value = null;

    public function __construct(string $key, $value, array $params = [])
    {
        parent::__construct($key, $value, $params);

        if (isset($params['my_value'])) {
            $this->my_value = $params['my_value'];
        }

        // + in order to add non existent key
        $this->messages += [
            $this::INVALID_MY_VALUE => '%key%: %value% my message %my_value%'
        ];
    }

    public function validate(): int
    {
        $run = parent::validate();

        if ($run !== $this::CHECK) {
            return $run;
        }

        if ($this->value !== $this->my_value) {
            return $this->setAndReturnError($this::INVALID_MY_VALUE, [
                '%my_value%' => $this->stringify($this->my_value)
            ]);
        }

        return $this::VALID;
    }
}

验证上下文

一旦调用验证,我们就可以使用 validatedContext 方法来从原始上下文中检索所有验证值。

默认情况下,所有在规则数组中设置的键都将出现在验证上下文数组中。然而,如果我们不想添加不存在的键,我们应在验证之前调用 appendExistingItemsOnly(true)。

断言集成

您不需要逐个使用断言键,而是可以验证整个上下文,然后使用以下方法使用 AssertionAssert

<?php

use Assert\Assertion;
use Elie\Validator\Rule\EmailRule;
use Elie\Validator\Rule\NumericRule;
use Elie\Validator\Rule\StringRule;
use Elie\Validator\Validator;
use Webmozart\Assert\Assert;

$rules =[
    ['age', NumericRule::class, NumericRule::MAX => 60],
    ['name', StringRule::class, StringRule::MIN => 1, StringRule::REQUIRED => true],
    ['email', EmailRule::class, EmailRule::REQUIRED => true],
];

$validator = new Validator($_POST, $rules);

Assert::true($validator->validate(), $validator->getImplodedErrors());

// OR

Assertion::true($validator->validate(), $validator->getImplodedErrors());

部分验证

有时我们需要对上下文进行部分验证,尤其是当我们有相互依赖的Json项或键时。

以下是一个示例,其中上下文(例如 $_POST)应包含Json用户数据

$rules = [
    ['user', JsonRule::class, JsonRule::REQUIRED => true],
];

$validator = new Validator($_POST, $rules);

Assertion::true($validator->validate()); // this assertion validates that the user is in Json format

$validatedPost = $validator->getValidatedContext();

// But we need to validate user data as well (suppose it should contain name and age):

$rules = [
    ['name', MatchRule::class, MatchRule::PATTERN => '/^[a-z]{1,20}$/i'],
    ['age', NumericRule::class, NumericRule::MAX => 80],
];
$validator->setRules($rules);

// Decode user as it is a valid JSON
$user = json_decode($validatedPost['user'], true);
$validator->setContext($user); // new context is now user data

Assertion::true($validator->validate()); // this assertion validates user data

/*
Validate accepts a boolean argument - mergedValidatedContext - which is false by default. If set to true
$validator->getValidatedContext() would return:

array:4 [▼
  "email" => "elie29@gmail.com"
  "user" => "{"name": "John", "age": 25}"
  "name" => "John"
  "age" => 25
]
*/

使用多维数组的部分验证

通常,使用JsonRule,我们可以期待一个多维数组。在这种情况下,验证过程将类似于部分验证,但不合并数据

$rules = [
    // With Json decode, validated value will be decoded into array
    ['users', JsonRule::class, JsonRule::REQUIRED => true, JsonRule::DECODE => true],
];

$validator = new Validator([
    'users' => '[{"name":"John","age":25},{"name":"Brad","age":42}]'
], $rules);

Assertion::true($validator->validate()); // this validate that users is a valid Json format

// But we need to validate all user data as well (suppose it should contain name and age):
$validator->setRules([
    ['name', MatchRule::class, MatchRule::PATTERN => '/^[a-z]{1,20}$/i'],
    ['age', NumericRule::class, NumericRule::MAX => 80],
]);

$validatedContext = $validator->getValidatedContext();

$users = $validatedContext['users'];

Assertion::isArray($users);

foreach ($users as $user) {
    // each user is a new context
    $validator->setContext($user);
    // do not merge data !!
    Assertion::true($validator->validate()); // we could validate all users and determine which ones are invalid!
}

已添加新的 CollectionRule,用于验证集合数据(数组或json),如下所示

$rules = [
    ['users', CollectionRule::class, CollectionRule::JSON => true, CollectionRule::RULES => [
        ['name', MatchRule::class, MatchRule::PATTERN => '/^[a-z]{1,20}$/i'],
        ['age', NumericRule::class, NumericRule::MAX => 80],
    ]],
];

$data = [
    'users' => '[{"name":"John","age":25},{"name":"Brad","age":42}]'
];

$validator = new Validator($data, $rules);

assertThat($validator->validate(), is(true));

$users = $validator->getValidatedContext()['users'];

assertThat($users, arrayWithSize(2));

开发先决条件

文本文件编码

  • UTF-8

代码样式格式化器

  • Zend Framework编码标准

Composer命令

  • clean:清理所有生成的文件
  • test:启动单元测试
  • test-coverage:启动单元测试,并生成clover.xml文件
  • cs-check:进行代码嗅探检查
  • cs-fix:进行代码嗅探修复
  • phpstan:启动PHP静态分析工具
  • check:启动cleancs-checktestphpstan