crocodile2u / validity
Requires (Dev)
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个参数
- $value — 显然,要验证的值;
- $fieldSet — FieldSet实例,以便可以获取相邻字段的值;
- $key — 如果字段期望一个数组值,则传递数组元素的整数或字符串键(默认为NULL)。
回调应该返回布尔值:如果验证通过,则返回TRUE;如果失败,则返回FALSE。
日期
日期和日期时间字段会将输入值转换为格式化日期,因此当您最终调用 getFiltered() 时,它们将包含字符串日期,格式根据输出格式设置(默认为日期 Y-m-d 和日期时间字段 Y-m-d H:i:s)。您可以通过 setOutputFormat() 更改此格式。默认情况下,日期和日期时间字段期望输入严格遵循由 setInputFormat() 设置的格式,此输入格式也默认为 Y-m-d 或 Y-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() 创建的并命名为 year、month 和 day 的字段,每个字段都拥有适当的范围验证:setMax() 和 setMin()。$message 参数到 Field::assoc() 将仅在 $_POST["date"] 不是一个数组时使用。如果它是一个数组,那么 $innerFieldSet 将负责进一步验证。如果 $innerFieldSet 报告任何错误,它们将被合并成一个字符串,并用作外层 FieldSet 中 date 字段的错误消息。
技巧与窍门
- 您在使用 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)来设置标签。如果没有设置,则使用字段名称作为标签。