crocodile2u/validity

此包的最新版本(v1.0.3)没有可用的许可证信息。

v1.0.3 2018-02-10 19:46 UTC

This package is auto-updated.

Last update: 2024-09-14 22:48:16 UTC


README

Validity 是一个简单的 PHP 验证和过滤包。它可以用于验证单个值,如整数和字符串,以及复杂的嵌套结构,使用您能想到的任何复杂的验证逻辑。提供英文和俄文的良好默认错误消息。可以通过自定义语言包轻松扩展,始终可以提供针对每个字段的任何规则的自定义错误消息。

为什么?

目标是简单的:拥有一个合理小巧的验证包,可以轻松满足我的所有需求

  • 验证基本数据类型,无需输入很多,
  • 验证数组,验证复杂逻辑,
  • 根据其他字段的值验证值,
  • 值过滤
  • 国际化,所有情况下的良好错误消息 — 开箱即用
  • 可以为每个案例指定自定义消息

特性

  • 基本字段类型:int,float,bool,string。
  • 更高级的类型:date,datetime,email,phone,enum。
  • 模式验证。
  • 用户提供的回调验证。
  • 验证数组值(例如,复选框或文本输入的数组)。精确的错误消息(能够显示发生错误的确切键)。如果相关,消息内部表示为包含数组键信息的对象。每个消息都导出为 JSON 作为 {text: <string>, "key": <null or string or int>}
  • 验证复合字段(字段是关联数组)。
  • 使用用户提供的回调进行过滤。
  • 轻松设置数字字段、日期/日期时间字段的限制(最小/最大值),为字符串设置最小和最大长度。
  • 将字段标记为必填。您还可以指定在何种条件下某个字段是必填的(例如,当用户选择“大学”作为教育水平时,大学名称字段可以设置为必填)。
  • 开箱即用的英语和俄语可供您使用,包含每种情况的默认错误消息。您可以轻松创建自己的语言类来用于默认消息。至少对于代码的样板版本,这些消息应该可以很好地工作,无需手动编写任何消息。
  • 轻松覆盖每个验证规则的错误消息:如果您没有指定错误消息,则从语言类中选择默认消息。如果为规则提供了消息,则使用该消息。
  • 处理字符串时,不允许潜在的恶意 Unicode 字符,以提高安全性。

示例

一些示例可以在 examples 文件夹中找到。查看它们的最简单方法是让您的 web 服务器提供这些脚本:我简单地将 examples 文件夹符号链接到 localhost 的 $root 下方。

我还会在这里提供一个示例

use \validity\FieldSet, \validity\Field;

$name = Field::pattern("name", "/^[A-Z][a-zA-Z\- ]+$/")->setRequired();
$greeting = Field::enum("greeting", ["mr", "mrs"])->setRequired();
$subscriptions = Field::int("subscriptions")->setMin(1)->expectArray();
$email = Field::email("email")->setRequiredIf(
    function(FieldSet $fieldSet) {
        return (bool) $fieldSet->getFiltered("subscriptions");
    }
);
$dateOfBirth = Field::date("date_of_birth")->setMax("-18years")->setRequired();
$education = Field::string("education")
     ->setMinLength(10)
     ->setMaxLength(100)
     ->expectArray()
     ->setArrayMinLength(0)
     ->setArrayMaxLength(3)
     ->setArraySkipEmpty(true);

$fieldSet = (new FieldSet())
        ->add($name)
        ->add($greeting)
        ->add($subscriptions)
        ->add($email)
        ->add($dateOfBirth)
        ->add($education);

if ($fieldSet->isValid($_POST)) {
    $data = $fieldSet->getFiltered();
    // do something with $data
} else {
    // display errors summary
    echo $fieldSet->getErrors()->toString();
}

在这个代码示例中,没有使用自定义消息。因为为 FieldSet 构造函数没有指定语言,所以默认语言类(英语)将用于提供非常整洁的错误消息。然而,对于每个指定验证规则的调用,您都可以提供自定义消息,并且它将覆盖语言包中的消息。消息可以以模板的形式提供。 {label} 总是替换为字段的 标签

创建字段

字段使用命名构造函数创建

  • Field::int(string $name = null, string $message = null),
  • 字段::float(string $name = null, string $message = null),
  • 字段::bool(string $name = null, string $message = null),
  • 字段::string(string $name = null, string $message = null),
  • 字段::date(string $name = null, string $message = null),
  • 字段::datetime(string $name = null, string $message = null),
  • 字段::enum(string $name = null, array $values, string $message = null),
  • 字段::email(string $name = null, string $message = null),
  • 字段::phone(string $name = null, string $message = null),
  • 字段::pattern(string $name = null, string $pattern, string $message = null),
  • 字段::assoc(string $name = null, FieldSet $innerFieldSet, $message = null, $errorSeparator = "; ").

每个命名构造函数都返回一个对应类型的字段,其中大多数都是相当自解释的,唯一例外的是Assoc,你可以在验证复合值部分了解更多。

在所有情况下,$message用于错误信息,如果输入不能被解释为int、float等。

必填字段

字段可以被标记为必填

Field::string("username")->setRequired("Please enter username");

有时,一个字段只有在其他一些字段已填写(或满足其他条件)时才是必填的。

Field::email("email")->setRequiredIf(
    function(FieldSet $fieldSet) {
        return (bool) $fieldSet->getFiltered("subscriptions");
    }
);

setRequiredIf()接受一个布尔值或一个回调作为参数。在前一种情况下,它只是将字段标记为必填或取消标记。当使用可调用的函数时,它在验证过程中被评估,如果回调返回TRUE,则该字段被视为必填。在上面的例子中,如果用户选择订阅某个邮件列表,则email字段是必填的。

默认值

每个字段都可以分配一个默认值

Field::int("price")->setDefault(100, true, false);

剩下的两个参数是$replaceEmpty$replaceInvalid。如果$replaceEmpty设置为TRUE(默认行为),则在输入中未指定/空值时,将使用默认值作为字段的值。如果$replaceInvalid设置为TRUE(默认为FALSE),则如果输入值未能通过任何验证,它将静默地替换为默认值,并且不会引发错误。

简单约束

数值字段(int & float),以及日期/日期时间字段可以分配最小和最大值

Field::int("price")->setMin(1);
Field::date("date_of_birth")->setMax("-18years");

字符串值可以设置为接受最小和最大字符串长度

Field::string("name")
    ->setMinLength(2)
    ->setMaxLength(100);

如果期望数组,它也可以被限制

Field::string("education")
    ->setMaxLength(100)
    ->expectArray()
    ->setArrayMinLength(0)
    ->setArrayMaxLength(3)

在最后一种情况下,setMaxLength(100)限制education数组中每个字符串的长度,而setArrayMinLength()setArrayMaxLength()设置数组大小的限制(因此我们期望在education中有0到3个条目,每个条目都是一个最大长度为100个字符的字符串)。

回调作为验证器

这是最强大的验证

Field::string("username")
    ->addCallbackRule(
        function($value, FieldSet $fieldSet) {
            return !Users::usernameExists($value);
        }
    );

当调用回调时,它会传递3个参数

  1. $value — 显然,要验证的值;
  2. $fieldSet — FieldSet实例,以便可以获取相邻字段的值;
  3. $key — 如果字段期望一个数组值,则传递数组元素的整数或字符串键(默认为NULL)。

回调应该返回布尔值:如果验证通过,则返回TRUE;如果失败,则返回FALSE。

日期

日期和日期时间字段会将输入值转换为格式化日期,因此当您最终调用 getFiltered() 时,它们将包含字符串日期,格式根据输出格式设置(默认为日期 Y-m-d 和日期时间字段 Y-m-d H:i:s)。您可以通过 setOutputFormat() 更改此格式。默认情况下,日期和日期时间字段期望输入严格遵循由 setInputFormat() 设置的格式,此输入格式也默认为 Y-m-dY-m-d H:i:s。然而,setInputFormat() 接受第二个可选参数——$strict。将其设置为 false 将导致验证器首先尝试精确的输入格式,然后尝试 PHP 的 date_create()。注意使用非严格日期格式,因为它可能会非常令人困惑。例如,“+1year”或“16年前3月1日”这样的值将是有效日期。此外,像“2010-02-31”这样的值显然是无效日期,但会通过验证!在后一种情况下,结果值将是(惊喜!)2010-03-03。更多内容请参阅 PHP 手册 —— 阅读thomas dot ribiere at allgoob dot com的评论。

验证数组

任何字段都可以设置为期望数组值

Field::int("subscriptions")->expectArray();

在这种情况下,字段期望是元素数组,每个元素都经过类型(例如上例中的 int)和您指定的任何规则的验证。可以通过以下方式控制最小和最大数组长度

  • setArrayMinLength(int)
  • setArrayMaxLength(int)

如果某些数组元素验证失败,查看哪些特定元素失败可能会有所帮助。考虑以下示例

Field::int("subscriptions", "{label}: value #{key} is not an integer")
    ->setMin(1, "Subscriptions: value #{key} must be greater then or equal to {min}")
    ->expectArray()
    ->setArrayKeyOffset(1);

假设我们有以下数据集

{
  "subscriptions": [
    1,
    "not an integer",
    -1
  ]
}

那么我们将得到以下错误消息

  • subscriptions: 值 #2 不是一个整数"
  • subscriptions: 值 #3 必须大于或等于 {min}"

消息解析器将用相应的数组键替换 "{key}"。PHP 中的数字数组是零索引的,因此默认情况下,如果第一个数组元素出现错误,您将得到一个错误消息说“value #0 无效”。虽然这可能是期望的行为,但您可能希望将其显示为“value #1 无效”。通过调用 Field::setArrayKeyOffset(1) 可以实现这一点——然后所有键在错误消息中都会增加 1。通常情况下,整数 ID 被用作各种数据的键,因此默认情况下 validity 不会对数字键应用偏移。

验证复合值

Field::assoc() 是一个复合字段,因此 FieldSet 期望值是一个数组,它将使用 $innerFieldSet 进行验证。一个现实生活中的例子:用于创建日期输入的三个字段集合:date[year]date[month]date[day]。假设我们期望 $_POST["date"] 是数组(year: integer, month: integer, day: integer)。在这种情况下,$innerFieldSet 将包含使用 Field::int() 创建的并命名为 yearmonthday 的字段,每个字段都拥有适当的范围验证:setMax()setMin()$message 参数到 Field::assoc() 将仅在 $_POST["date"] 不是一个数组时使用。如果它是一个数组,那么 $innerFieldSet 将负责进一步验证。如果 $innerFieldSet 报告任何错误,它们将被合并成一个字符串,并用作外层 FieldSetdate 字段的错误消息。

技巧与窍门

  • 您在使用 Zend 框架 但仍然想使用 validity 吗?好消息!Zend 验证器是可调用的,所以您可以直接将它们添加为验证规则
Field::string("email")->addCallbakRule(new EmailAddress(), "Email is invalid!");
  • 您在使用 Yii2 但仍然想使用 validity 吗?这比 ZF 稍微复杂一点
Field::string("email")->addCallbakRule(function($value) {
    return (new EmailValidator())->validate($value);
}, "Email is invalid!");

我特意选择了电子邮件验证作为这条技巧。Validity也提供了电子邮件验证功能,但(至少目前)它只是一个简单的正则表达式检查。Zend或Yii2提供了更复杂的方式来验证电子邮件,并且你可以在执行验证流程的同时简单地使用它。

标签

每个字段都必须有一个名称。名称是所有命名构造函数的第一个参数。名称实际上是FieldSet验证的关联数组的键。此外,字段还可以有一个标签。例如,字段名称是date_of_birth,但标签是出生日期。可以使用Field->setLabel(string $label)来设置标签。如果没有设置,则使用字段名称作为标签。