轻量级的独立验证库

v4.1.0 2022-02-06 08:19 UTC

README

  __ _ _ __ ___  ___
 / _` | '__/ _ \/ __|
| (_| | | |  __/\__ \
 \__,_|_|  \___||___/

Ares 是一个轻量级的独立验证库。

Codacy Badge Latest Stable Version Total Downloads Minimum PHP Version Build Status Coverage Status

目录

安装

通过 composer 安装库

composer require bus-factor/ares

基本用法

<?php

use Ares\Ares;

// atomic types
$ares = new Ares(['type' => 'string']);
$valid = $ares->validate('John Doe');
$errors = $ares->getValidationErrors();

// complex/nested types
$ares = new Ares([
    'type' => 'map',
    'schema' => [
        'firstName' => ['type' => 'string', 'required' => true],
        'lastName' => ['type' => 'string', 'required' => true],
    ],
]);
$valid = $ares->validate(['firstName' => 'John', 'lastName' => 'Doe']);
$errors = $ares->getValidationErrors();

验证错误

validate() 方法返回 true 如果提供的数据有效,否则返回 false

getValidationErrors() 方法返回一个 Ares\Validation\Error\ErrorCollection 对象,该对象包含在最后的数据验证过程中收集的 Ares\Validation\Error\Error 实例列表。每次调用 validate() 时,验证错误列表都会重置。

每个 Ares\Validation\Error\Error 对象实现 JsonSerializable 接口并包含有关错误的详细信息。

Ares\Validation\Error\ErrorCollection 对象是可迭代的,但也提供了两个便利方法

  • ::toArrayJsonApiStyle() - 返回一个数组,该数组反映了 json:api 规范
  • ::toArrayNested - 返回一个嵌套数组,其中错误信息与其嵌套结构匹配输入数据的结构

验证选项

验证选项可以在验证时传递

$schema = [];
$options = [];
$ares = new Ares($schema, $options);

默认验证选项是

Validator::OPTIONS_DEFAULTS = [
    'allBlankable'      => false,
    'allNullable'       => false,
    'allRequired'       => true,
    'allUnknownAllowed' => false,
]

allBlankable

此选项仅适用于 string 类型。如果设置为 true,则空白值被视为有效。如果设置为 false,则空白值被视为无效。

$schema = [
    'type' => 'map',
    'schema' => [
        'name' => ['type' => 'string'],
    ],
];

$ares = new Ares($schema);

$ares->validate(['name' => ''], ['allBlankable' => true]); // -> true
$ares->validate(['name' => ''], ['allBlankable' => false]); // -> false

可以使用 blankable 规则按字段覆盖此选项

$schema = [
    'type' => 'map',
    'schema' => [
        'name' => ['type' => 'string'],
        'email' => ['type' => 'string', 'blankable' => true],
    ],
];

$ares->validate(['name' => 'John Doe', 'email' => ''], ['allBlankable' => false]); // -> true

allNullable

如果设置为 true,则 null 被视为有效值。如果设置为 false,则 null 不被视为有效值。

$schema = [
    'type' => 'map',
    'schema' => [
        'name' => ['type' => 'string'],
    ],
];

$ares->validate(['name' => null], ['allNullable' => true]); // -> true
$ares->validate(['name' => null], ['allNullable' => false]); // -> false

可以使用 nullable 规则按字段覆盖此选项

$schema = [
    'type' => 'map',
    'schema' => [
        'name' => ['type' => 'string'],
        'email' => ['type' => 'string', 'nullable' => true],
    ],
];

$ares->validate(['name' => 'John Doe', 'email' => null], ['allNullable' => false]); // -> true

allRequired

如果设置为 true(默认)字段在模式中定义但不在输入中,则被视为无效。如果设置为 false,则字段在模式中定义但不在输入中,则被视为有效。

$schema = [
    'type' => 'map',
    'schema' => [
        'name' => ['type' => 'string'],
    ],
];

$ares = new Ares($schema);
$ares->validate([], ['allRequired' => true]); // -> false
$ares->validate([], ['allRequired' => false]); // -> true

可以使用 required 规则按字段覆盖此选项

$schema = [
    'type' => 'map',
    'schema' => [
        'name' => ['type' => 'string'],
        'email' => ['type' => 'string', 'required' => false],
    ],
];

$ares = new Ares($schema);
$ares->validate(['name' => 'John Doe'], ['allRequired' => true]); // -> true

allUnknownAllowed

此选项仅适用于 map 类型。如果设置为 true,则在输入数据中出现但未在模式中定义的字段被视为无效。如果设置为 false,则这些字段被视为有效。

$schema = [
    'type' => 'map',
    'schema' => [
        'name' => ['type' => 'string'],
    ],
];

$ares = new Ares($schema);
$ares->validate(['name' => 'John Doe', 'initials' => 'JD'], ['allUnknownAllowed' => false]); // -> false
$ares->validate(['name' => 'John Doe', 'initials' => 'JD'], ['allUnknownAllowed' => true]); // -> true

验证规则

allowed

allowed 验证规则检查值是否在给定的允许值集合(枚举)中。

示例

$ares = new Ares(['type' => 'string', 'allowed' => ['small', 'large']]);
$ares->validate('medium'); // -> false
$ares->validate('small'); // -> true

《允许》验证规则与《禁止》验证规则相反。

可空白

《可空白》规则仅适用于《字符串》类型的数据。如果设置为《true》,空白字符串被视为有效。如果设置为《false》,空白字符串被视为无效(默认)。

示例

$ares = new Ares(['type' => 'string', 'blankable' => false]);
$ares->validate(''); // -> false
$ares->validate('   '); // -> false
$ares->validate('John Doe'); // -> true

$ares = new Ares(['type' => 'string', 'blankable' => true]);
$ares->validate('   '); // -> true

《可空白》验证规则可以与《全部可空白》验证选项一起使用。

日期时间

《日期时间》验证规则仅适用于《字符串》类型的数据。如果设置为《true》,任何可解析的日期时间字符串被视为有效。如果设置为《false》,将不会进行日期时间的验证。如果设置特定的日期时间格式字符串,则还会检查给定的值是否与该格式匹配。有关格式字符串的详细信息,请参阅DateTime::createFromFormat()

示例

$ares = new Ares(['type' => 'string', 'datetime' => true]);
$ares->validate('foo'); // -> false
$ares->validate('2018-03-23'); // -> true

$ares = new Ares(['type' => 'string', 'datetime' => 'd.m.Y H:i']);
$ares->validate('2018-03-23'); // -> false
$ares->validate('23.03.2019 00:20'); // -> true

目录

《目录》验证规则检查给定的字符串值是否包含指向现有目录的路径。如果设置为《true》,只有指向现有目录的路径被视为有效。如果设置为《false》,所有输入都被视为有效(不进行验证)。

示例

$ares = new Ares(['type' => 'string', 'directory' => true]);
$ares->validate(''); // -> false
$ares->validate(__FILE__); // -> false
$ares->validate(__DIR__); // -> true

电子邮件

《电子邮件》验证规则检查值是否为有效的电子邮件地址。如果设置为《true》,只有有效的电子邮件地址被视为有效。如果设置为《false》,所有输入都被视为有效(不进行验证)。

示例

$ares = new Ares(['type' => 'string', 'email' => true]);
$ares->validate('John Doe'); // -> false
$ares->validate('john.doe@example.com'); // -> true

文件

《文件》验证规则检查给定的字符串值是否包含指向现有文件的路径。如果设置为《true》,只有指向现有文件的路径被视为有效。如果设置为《false》,所有输入都被视为有效(不进行验证)。

示例

$ares = new Ares(['type' => 'string', 'file' => true]);
$ares->validate(''); // -> false
$ares->validate(__DIR__); // -> false
$ares->validate(__FILE__); // -> true

禁止

《禁止》验证规则检查值是否在给定的禁止值集合(枚举)中。

示例

$ares = new Ares(['type' => 'string', 'forbidden' => ['small', 'medium']]);
$ares->validate('medium'); // -> false
$ares->validate('large'); // -> true

《禁止》验证规则与《允许》验证规则相反。

长度

《长度》验证规则适用于《字符串》和《列表》类型的数据。《长度》验证规则检查字符串或列表是否具有指定的确切长度。

示例

$ares = new Ares(['type' => 'string', 'length' => 3]);
$ares->validate('foobar'); // -> false
$ares->validate('foo'); // -> true

$ares = new Ares([
    'type' => 'list',
    'length' => 3,
    'schema' => [
        'type' => 'integer'
    ],
])
$ares->validate([1, 2]); // -> false
$ares->validate([1, 2, 3]); // -> true

最大值

《最大值》验证规则仅适用于《浮点数》和《整数》类型的数据。《最大值》验证规则检查值是否等于或小于指定的最大值。

示例

$ares = new Ares(['type' => 'integer', 'max' => 5]);
$ares->validate(6); // -> false
$ares->validate(2); // -> true

注意当与不支持的数据类型一起使用时,此验证规则将抛出《Ares\Exception\InapplicableValidationRuleException》异常。

最大长度

《最大长度》验证规则适用于《字符串》和《列表》类型的数据。《最大长度》验证规则检查字符串或列表是否不超出指定的最大长度。

示例

$ares = new Ares(['type' => 'string', 'maxlength' => 5]);
$ares->validate('foobar'); // -> false
$ares->validate('foo'); // -> true

$ares = new Ares([
    'type' => 'list',
    'maxlength' => 3,
    'schema' => [
        'type' => 'integer'
    ],
])
$ares->validate([1, 2, 3, 4]); // -> false
$ares->validate([1, 2, 3]); // -> true

最小值

《最小值》验证规则仅适用于《浮点数》和《整数》类型的数据。《最小值》验证规则检查值是否等于或大于指定的最小值。

示例

$ares = new Ares(['type' => 'integer', 'min' => 5]);
$ares->validate(4); // -> false
$ares->validate(8); // -> true

注意当与不支持的数据类型一起使用时,此验证规则将抛出《Ares\Exception\InapplicableValidationRuleException》异常。

最小长度

《最小长度》验证规则适用于《字符串》和《列表》类型的数据。《最小长度》验证规则检查字符串或列表是否不短于指定的最小长度。

示例

$ares = new Ares(['type' => 'string', 'minlength' => 5]);
$ares->validate('foo'); // -> false
$ares->validate('foobar'); // -> true

$ares = new Ares([
    'type' => 'list',
    'minlength' => 3,
    'schema' => [
        'type' => 'integer'
    ],
])
$ares->validate([1, 2]); // -> false
$ares->validate([1, 2, 3]); // -> true

可空

如果设置为《true》,《null》被视为有效值。如果设置为《false》,《null》被视为无效值(默认)。

示例

$ares = new Ares(['type' => 'string', 'nullable' => false]);
$ares->validate(null); // -> false
$ares->validate('John Doe'); // -> true

$ares = new Ares(['type' => 'string', 'nullable' => true]);
$ares->validate(null); // -> true

《可空》验证规则可以与《全部可空》验证选项一起使用。

正则表达式

正则表达式验证规则仅适用于 string 类型的值。正则表达式验证规则检查一个字符串是否与正则表达式匹配。

示例

$ares = new Ares([
    'type' => 'map',
    'schema' => [
        'key' => [
            'type' => 'string',
            'regex' => '/^[A-Z]{3}$/',
        ],
    ],
]);

$ares->validate(['key' => 'foobar']); // -> false
$ares->validate(['key' => 'FOO']); // -> true

必填

使用 required 规则来强制值的存在。如果设置为 true,则空字段被视为无效。如果设置为 false(默认值),则空字段被视为有效。

示例

$ares = new Ares([
    'type' => 'map',
    'schema' => [
        'name' => ['type' => 'string', 'required' => true],
    ],
]);

$ares->validate([]); // -> false
$ares->validate(['name' => 'John Doe']); // -> true

required 验证规则可以与 allRequired 验证选项结合使用。

模式

当使用类型 listmaptuple 时,schema 规则是必需的。

模式(列表)

验证器期望模式定义列表项的验证规则。

示例

$ares = new Ares([
    'type' => 'list',
    'schema' => [
        'type' => 'integer',
    ],
]);

$ares->validate(['foo', 'bar']); // -> false
$ares->validate([1, 2, 3]); // -> true

模式(映射)

验证器期望模式为关联数组输入定义每个字段的验证规则。

示例

$ares = new Ares([
    'type' => 'map',
    'schema' => [
        'email' => ['type' => 'string', 'required' => true],
        'password' => ['type' => 'string', 'required' => true],
    ],
]);

$ares->validate(['email' => 'john.doe@example.com']); // -> false
$ares->validate(['email' => 'john.doe@example.com', 'password' => 'j4n3:)']); // -> true

模式(元组)

验证器期望模式为输入数组元素定义验证规则。在验证过程中,输入数组元素应从 0 开始的连续索引(0, 1, 2, ...)。

示例

$ares = new Ares([
    'type' => 'tuple',
    'schema' => [
        ['type' => 'string', 'email' => true],
        ['type' => 'integer'],
    ],
]);

$ares->validate(['john.doe@example.com']); // -> false
$ares->validate([1 => 'john.doe@example.com', 2 => 23]); // -> false
$ares->validate(['john.doe@example.com', 23]); // -> true

在内部,元组的所有 schema 元素都是必需的,并且不能通过模式声明为可选。

类型

type 规则是必需的,并定义了预期/允许的值类型。支持的类型有:

  • 布尔型
  • 浮点型
  • 整型
  • numericfloatinteger
  • 字符串
  • 映射
  • 列表
  • 元组

示例

$ares = new Ares(['type' => 'float']);
$ares->validate(5); // -> false
$ares->validate('John Doe'); // -> false

请参阅自定义类型部分,了解如何定义和重用您自己的类型。

unknownAllowed

unknownAllowed 验证规则检查一个 map 是否包含在模式中未定义的字段。如果设置为 true,则模式中未定义的字段被视为有效。如果设置为 false,则模式中未定义的字段被视为无效。

示例

$ares = new Ares([
    'type' => 'map',
    'schema' => [
        'name' => ['type' => 'string'],
    ],
    'unknownAllowed' => false,
]);

$ares->validate(['name' => 'John Doe', 'email' => 'john.doe@example.com']); // -> false
$ares->validate(['name' => 'John Doe']); // -> true

url

url 验证规则检查值是否是有效的 URL。

示例

$ares = new Ares(['type' => 'string', 'url' => true]);
$ares->validate('example'); // -> false
$ares->validate('https://example.com'); // -> true

uuid

uuid 验证规则检查值是否是有效的 UUID。

示例

$ares = new Ares(['type' => 'string', 'uuid' => true]);
$ares->validate('example'); // -> false
$ares->validate('609de7b6-0ef5-11ea-8d71-362b9e155667'); // -> true

自定义类型

基本上,自定义类型是用户定义的模式,它存储在并从注册表中检索。以下是一个示例,说明它是如何工作的

use Ares\Ares;
use Ares\Schema\TypeRegistry;

TypeRegistry::register('GermanDateString', [
    'type' => 'string',
    ['datetime' => 'd.m.Y', 'message' => 'Invalid date format, try something like "24.02.2019"'],
]);

TypeRegistry::register('ListOfHobbies', [
    'type' => 'list',
    'schema' => [
        'type' => 'string',
        'allowed' => ['Reading', 'Biking'],
    ],
]);

TypeRegistry::register('Student', [
    'type' => 'map',
    'schema' => [
        'birthDate' => ['type' => 'GermanDateString'],
        'hobbies' => ['type' => 'ListOfHobbies', 'minlength' => 1],
    ],
]);

$schema = ['type' => 'Student'];

$ares = new Ares($schema);

$ares->validate(['birthDate' => '1998-06-14', 'hobbies' => []]); // false
$ares->validate(['birthDate' => '14.06.1998', 'hobbies' => ['Reading']]); // true

使用 TypeRegistry::unregister() 注销先前注册的类型。使用 TypeRegistry::unregisterAll() 一次性注销所有先前注册的类型。还可以定义递归类型。

自定义验证错误消息

更改单个规则的验证错误消息

以下示例展示了如何自定义验证错误消息

// validation rule without custom message (default)
$ares = new Ares([
    'type' => 'integer',
]);

// validation rule with custom message
$ares = new Ares([
    ['type' => 'integer', 'message' => 'Pleaser provide an integer value']
]);

只需将您的规则(键值)包装在一个数组中,并添加一个 'message' 键。

验证错误消息本地化

所有内置验证规则都使用 Ares\Error\ErrorMessageRendererInterface 来渲染消息。如果没有指定,则创建一个 Ares\Error\ErrorMessageRenderer 实例并将其传递给验证过程。如果需要,可以将自定义错误消息渲染器传递给验证器

use Ares\Ares;
use Ares\Validation\Error\ErrorMessageRendererInterface;

class MyErrorMessageRenderer implements ErrorMessageRendererInterface
{
    // ...
}

// ...

$ares = new Ares($schema);

$ares->getValidator()->setErrorMessageRenderer(new MyErrorMessageRenderer());

$valid = $ares->validate($data);

自定义验证规则

以下简单示例展示了如何实现和集成自定义验证规则

use Ares\Ares;
use Ares\Schema\Type;
use Ares\Validation\Context;
use Ares\Validation\RuleRegistry;
use Ares\Validation\Rule\AbstractRule;

class ZipCodeRule extends AbstractRule
{
    public const ID = 'zipcode';
    public const ERROR_MESSAGE = 'Invalid ZIP code';

    /**
     * Returns all supported value types.
     *
     * @return array
     */
    public function getSupportedTypes(): array
    {
        return [
            Type::STRING,
        ];
    }

    /**
     * Perform the value validation.
     *
     * @param mixed   $args    Validation rule arguments.
     * @param mixed   $data    Data being validated.
     * @param Context $context Validation context.
     * @return bool
     */
    public function performValidation($args, $data, Context $context): bool
    {
        // implement validation ...

        // add error if the validation fails
        $context->addError(self::ID, self::ERROR_MESSAGE);

        // TRUE  - skip all following validation rules for the current field
        // FALSE - run all following validation rules for the current field
        return false; 
    }
}

RuleRegistry::register(ZipCodeRule::ID, new ZipCodeRule());

$schema = [
    'type' => 'string',
    'zipcode' => true,
];

$ares = new Ares($schema);

清理

以下示例展示了如何清理数据

$schema = [
    'type' => 'map',
    'schema' => [
        'name' => ['type' => 'string'],
        'age' => ['type' => 'integer'],
        'active' => ['type' => 'boolean'],
    ],
];

$ares = new Ares($schema);

$data = [
    'name' => ' John Doe   ',
    'age' => '23',
    'active' => '1',
    'hobby' => 'Reading',
];

$sanitizedData = $ares->sanitize($data);

// Result:
// [
//     'name' => 'John Doe',
//     'age' => 23,
//     'active' => true,
// ]

如示例所示,默认情况下清理会进行以下调整:

  • 修剪字符串
  • 将数字字符串转换为整数或字符串值
  • 将非空数字字符串转换为布尔值
  • 从输入数据中删除未知字段

清理选项

trimStrings

如果设置为 true(默认值),则从字符串中删除周围的空白。如果设置为 false,则保留周围的空白。

purgeUnknown

如果设置为 true(默认值),则从输入数据中删除未知字段(在模式中未定义的字段/索引)。如果设置为 false,则保留未知字段。