one234ru / form-validator
HTML 表单验证工具,客户端和服务器端(PHP)
Requires
- php: >=7.3
This package is auto-updated.
Last update: 2024-09-20 01:11:38 UTC
README
检查的结果是一个错误数据数组,用于发送到浏览器。
客户端部分描述见此处。
错误数组的形式
[ { "name": "имя поля (атрибут name в HTML-коде)", "value": "значение", "messages": [ "текст ошибки", "текст другой ошибки" ] }, { ... } ]
如果表单填写正确,数组为空。
检查基于特殊的配置和 HTTP 请求参数。
require 'Validator.php'; $config = [...]; $values = $_GET; $obj = new One234ru\FormValidator($config, $values); $obj->validate($values); // $obj->errors будет содержать массив ошибок
标准检查
假设表单中有三个字段——姓名、电话和电子邮件,分别对应 name
、phone
和 email
。那么检查配置的形式如下
$config = [ 'name' => ..., // здесь инструкции для проверки 'phone' => ..., 'email' => ... ];
数组键必须与 HTML 代码中字段的 name
属性值相匹配。
简单的填充检查
这个检查的唯一参数是错误文本,如果字段未填写或完全不存在于 HTTP 请求参数中,将显示给用户。如果字段的值是 0
而不是空字符串,则检查将不会通过。在检查之前会删除前后空格。
存在两种声明检查的方式:简短形式——字符串形式,和完整形式——键为 *
的数组形式。
假设我们要求填写姓名和电话,而电子邮件是可选的。
在下面的例子中,name
字段使用简短形式,而 phone
使用完整形式
$config = [ 'name' => 'Укажите имя.', 'phone' => [ '*' => 'Укажите телефон.' ], 'email' => [] ];
在这个例子中,没有为 email
字段指定检查指令,因此其内容不会影响检查结果。
看看如果发送空 HTTP 请求进行检查会发生什么
$obj = new One234ru\FormValidator($config); $values = []; // имитируем пустой запрос $obj->validate($values); echo json_encode($obj->errors, JSON_UNESCAPED_UNICODE);
结果(格式化以便于阅读)
[ { "name": "name", "value": null, "messages": [ "Укажите имя." ] }, { "name": "phone", "value": null, "messages": [ "Укажите телефон." ] } ]
可以看到,每个字段都有一个错误信息列表的数组。在所有情况下,value
都包含 null
,因为 HTTP 请求中不存在相应的元素。
简短形式和完整形式的记录作用完全相同。通常如果没有其他检查,使用简短形式更方便。
使用正则表达式检查内容
现在假设我们不仅想要检查字段是否填写,而且要确保它们包含格式正确的值。例如,电话必须严格由十个数字组成,而电子邮件必须符合特定的格式。
这可以通过正则表达式检查来实现。为了设置这样的检查,需要在检查数组中添加一个元素,其键是正则表达式(分隔符为 /
),其值是错误文本
$config = [ // проверку name здесь и далее опустим 'phone' => [ '*' => 'Укажите телефон.', '/^\d{10}$/' => 'Телефон следует указывать в виде 10 цифр.', ], 'email' => [ '/^[\.\-\w]+@(\w+\-)*\.[A-z]{2}$/' => '"{*value*}" не является адресом электронной почты.', ] ];
错误文本中的 {*value*}
标记将被字段值(通过 htmlspecialchars()
编码)替换。
看看错误将如何显示
$values = [ 'phone' => '1234', 'email' => 'somebody@', ];
[ { "name": "phone", "value": "1234", "messages": [ "Телефон следует указывать в виде 10 цифр." ] }, { "name": "email", "value": "somebody@", "messages": [ "\"somebody@\" не является адресом электронной почты." ] } ]
正则表达式检查仅在通过填充检查的情况下执行。这很容易验证
$values = [];
[ { "name": "phone", "value": null, "messages": [ "Укажите телефон." ] } ]
因此,email
字段仍然是可选的,并且只有在它包含非空值时才会进行检查。
使用任意函数的检查
这种检查分为两种类型——初级 和 二级。
二级 检查仅在成功通过该字段的全部其他检查后执行。
假设需要检查表单中输入的电话号码是否在某个数据库中。
'phone' => [ '*' => 'Укажите телефон.', '/^\d{10}$/' => 'Телефон следует указывать в виде 10 цифр.', function($value) { $found = ...; // тут ищем в базе данных return (!$found) ? "Телефон $value не значится в наших списках." : ""; // Т.к. телефон уже проверялся регулярным выражением, // обрабатывать его htmlspecialchars() // перед вставкой в текст ошибки ни к чему. } ]
从例子中可以看出,函数的参数是字段值。函数应该返回错误信息字符串,如果没有错误则返回空值。
$values = [ 'phone' => '1234567890' ];
[ { "name": "phone", "value": "1234567890", "messages": [ "Телефон 1234567890 не значится в наших списках." ] } ]
初级检查总是执行,无论字段是否填写和是否有其他检查。
它们的声明仅有一点不同,即在数组中使用 '*'
代替无名称键元素。还有简化的记录形式
// вторичная проверка 'phone' => [ function($value) {...} ] // первичная проверка, полная форма 'phone' => [ '*' => function($value) {...} ] // первичная проверка, сокращенная форма 'phone' => function($value) {...}
在完整形式中,初级检查可以与其他检查结合。
假设我们决定在一个函数内部本地化所有电话检查。以下是它的样子
'phone' => function($value) { if (empty($value)) { $message = "Укажите телефон."; } elseif (!preg_match('/^\d{10}$/', $value)) { $message = "Телефон следует указывать в виде 10 цифр."; } elseif (!($found = ...)) { $message = "Телефон $value не значится в наших списках."; } else { $message = ""; } return $message; }
检查结果的数据格式保持不变。它也不依赖于记录形式——简短或完整。
汇总检查
可以根据多个字段的值构建检查。
使用将函数放在配置顶级无名称元素内部的函数来声明这些检查。这些函数接受完整的HTTP请求参数数组作为参数。
此函数的结果是发现错误列表。列表中的每个错误都以以下元素表示的数组形式出现
name
—— 字段名称value
—— 字段值message
—— 错误信息文本
假设在我们的示例中,某个数据库中的每个电话号码都对应一个特定的电子邮件地址,并且当填写表单时需要检查这种对应关系。以下是如何进行此类检查的示例
$config = [ ... [ function ($query) { if (...) { // тут проверяем телефон и email $errors[] = [ 'name' => 'email', 'value' => $query['email'], 'message' => "К телефону $query[phone] привязан другой email." ]; } return $errors ?? []; } ] ]; $values = [ 'phone' => '1234567890', 'email' => 'someone@somewhere.ru', ];
结果
[ { "name": "email", "value": "someone@somewhere.ru", "message": "К телефону 1234567890 привязан другой email." } ]
与单个字段的检查类似,总检查也有初级和次级:初级总是执行,次级仅在所有其他检查成功完成后执行。
它们的声明与单个字段的情况一样:初级以键 '*'
声明,次级以无名称数字键声明
$config = [ ..., [ '*' => function($query) { ... }, // первичная проверка function($query) { ... }, // вторичная проверка function($query) { ... }, // еще одна вторичная проверка ] ]
可以有多个包含汇总检查的元素
$config = [ ..., [ '*' => function($query) { ... }, function($query) { ... }, ], [ '*' => function($query) { ... }, function($query) { ... }, ], ... ]
与特定字段无关的错误
在某些情况下,错误与特定字段无关(例如,在调用某些外部系统失败的情况下)。
可以使用通用检查将它们添加到列表中,不指定 name
和 value
或根本返回字符串——错误文本——代替数组。
$config = [ ..., function($query) { if (...) { // Полная форма: return [ [ 'message' => "Произошёл сбой связи с внешней системой." ] ]; // Краткая форма, вложенность на ДВА уровня ниже return "Произошёл сбой связи с внешней системой."; } } ];
以这种形式格式化错误将影响其在客户端的显示:它将位于表单的某个通用区域(通常在发送按钮旁边),而不是特定字段。
将通用错误添加到列表的另一种方法是调用 addError()
方法,见下文。
同类型字段的检查 —— []
同类型是指具有相同 name
属性的字段,其末尾包含 []
,每个字段都遵循相同的检查逻辑。
此类字段的好例子是促销代码,用户可以在表单中随意输入。对于每个促销代码,表单中都会有一个名为 promo_codes[]
的文本字段,用户可以通过“输入更多促销代码”类型的按钮自行添加新的促销代码字段。
在HTTP请求中,这些字段将与包含字符串数组的键 promo_codes
相对应
$values = [ 'promo_codes' => [ "ABC", "", // могут быть и пустые поля "123" ] ] ];
使用键 []
指定同类型字段的检查
$config = [ 'promo_codes' => [ '[]' => [ '/^[A-z]+$/' => 'Промо-коды могут состоять только из латинских букв.', function ($value) { if (...) { return "Промо-код $value не распознан."; } } ] ] ]
结果
[ { "name": "promo_codes[]", "value": "abc", "messages": [ "Промо-код abc не распознан." ] }, { "name": "promo_codes[]", "value": "134", "messages": [ "Промо-коды могут состоять только из латинских букв." ] } ]
指定在键 []
中的检查遵循与单个字段检查相同的规则
以下缩写形式的记录与完整形式
'[]' => function() {...}
相对应
'[]' => [ '*' => function() {...} ]
除了 []
之外,还可以对请求中是否存在字段进行通用检查。它需要与 []
位于同一级别
$config = [ 'promo_codes' => [ '*' => 'Нужно указать хотя бы один промо-код', '[]' => ... ] ]
如果在这种情况下请求中不存在键 promo_codes
或它只包含空值(有关详细信息,请参阅以下内容),则结果将是错误消息
$values = [ 'promo_codes' => [ "", "" ] ];
[ { "name": "promo_codes", "value": [], "messages": [ "Нужно ввести хотя бы один промо-код." ] } ]
请注意,在此情况下 name
不包含末尾的 []
,因为检查是在HTTP请求通用键级别进行的,而不是在单独字段级别。这将很重要,因为放置错误在客户端。
请注意,在检查之前,HTTP请求的内容会从空同类型字段中清除(预先删除边缘的空格)。数组中的空值将被排除。
将检查配置作为子配置连接 —— children
有时,一个表单可以作为子表单嵌入到一个更大的表单中,同时保留所有字段填写的规则。
例如,在网店中,客户个人信息编辑表单可能作为客户字段部分嵌入到订单表单中。此时,字段名称将进行修改,以确保在HTTP请求中,它们的值不是在顶层,而是在某个键的内部。例如,<input name="phone">
可能变成<input name="client[phone]">
,<input name="email">
变成<input name="client[email]">
等等。
为了继续使用现有的字段检查配置,需要使用children
键。
$clients_config = [ 'name' => 'Укажите имя.', 'phone' => 'Укажите телефон.', ]; $full_config = [ 'client' => [ 'chlidren' => $clients_config ] ]; // Пример HTTP-запроса из формы с незаполненными полями $http_query = [ 'client' => [ 'name' => '', 'phone' => '' ] ]; $obj = new One234ru\FormValidator($full_config); $obj->validate($http_query);
结果
[ { "name": "client[name]", "value": "", "messages": [ "Укажите имя." ] }, { "name": "client[phone]", "value": "", "messages": [ "Укажите телефон." ] } ]
子配置没有功能限制,可以包含上述描述的任何类型的检查。
addError()
- 手动添加错误列表
此方法允许绕过总体检查逻辑手动添加列表。
这可能在与外部系统交互时需要,例如,当请求基于表单数据构建时。在发送请求之前,需要确保数据的正确性,因此检查在发送请求之前进行。然而,请求结果也可能包含错误消息,在这种情况下,需要将它们包含在列表中。这正是addError()
的作用。
它接受参数,顺序如下
- 错误消息文本或错误列表数组
- 字段名称(可选)
- 值(可选)
示例
$obj = new One234ru\FormValidator($config); $obj->addError('Какая-то ошибка с телефоном', 'phone'); $obj->addError('И с email тоже ошибка', 'email');
结果看起来与常规检查相同
[ { "name": "phone", "messages": [ "Какая-то ошибка с телефоном" ] }, { "name": "email", "messages": [ "И с email тоже ошибка" ] } ]
addError()
的参数顺序使得添加通用错误特别方便,允许仅以单个参数指定错误文本
$obj->addError('Произошёл сбой связи с внешней системой.');
[ { "messages": [ "Произошёл сбой связи с внешней системой." ] } ]
更改检查配置,清除错误列表
可以使用setConfigTo()
方法在对象中加载另一个用于检查的配置。
如果之后运行检查,新发现的错误将替换现有的错误。为了避免这种情况,需要在传递给getErrors()
方法的第二个参数中指定false
。
// Проверяем какие-то внешние условия и добавляем в список // выявленные ошибки в качестве общих. $some_errors = ...; $obj = new One234ru\FormValidator([]); $obj->addError($some_errors); // Теперь генерируем конфигурацию для проверки $config = ...; $obj->setConfigTo($config); $obj->validate($http_query, false);
如果检查配置是动态生成的,并且在确定某些错误时并不完全明确,这可能会很有用。
其他功能
在检查完成后,可以按字段名称确定字段是否填写正确
$obj->validate($http_query, false); ... $obj->isFieldValid('email');