验证器类是一个简单、方便的工具,用于验证数据并通过 Validator 类检索验证错误消息。当处理最终用户提交的表单数据时,它会很有用。
在使用模型时,October CMS 提供了一个实用的验证特性,它实现了
Validator类并支持相同的规则定义。
下方是所有可用验证规则的列表:
在大多数情况下,您应该首先捕获用户输入并将其传递给 make 方法(第一个参数),并包含应用于数据的验证规则(第二个参数)。在以下示例中,我们使用 post() 辅助函数捕获回发的用户输入。
$data = post();
$validator = Validator::make($data, [
'name' => 'required|min:5'
]);多条规则可以使用“管道”字符分隔,或作为数组的独立元素。
$validator = Validator::make($data, [
'name' => ['required', 'min:5']
]);要验证多个字段,只需将它们添加到数组中。
$data = [
'name' => 'Joe',
'password' => 'lamepassword',
'email' => 'email@example.tld'
];
$validator = Validator::make($data, [
'name' => 'required',
'password' => 'required|min:8',
'email' => 'required|email|unique:users'
]);一旦 Validator 实例被创建,便可以使用 fails(或 passes)方法来执行验证。
if ($validator->fails()) {
// The given data did not pass validation
}如果验证失败,您可以从验证器获取错误信息。
$messages = $validator->messages();您还可以访问一个包含失败验证规则的数组,不包含消息。为此,请使用 failed 方法:
$failed = $validator->failed();Validator 类提供了一些验证文件的规则, 例如 size, mimes, 等. 验证文件时, 您可以简单地将它们与您的其他数据一同传入验证器.
$data = files() + post();
$validator = Validator::make($data, [...]);不建议在此处使用未经过滤的
input()值,因为它包含 GET 值,这些值可能被用于构造恶意链接。
在大多数情况下,你将验证通过表单提交的用户输入,并且如果验证失败,抛出 ValidationException 是一个兼容的操作。作为验证表单的更简洁方式,你可以直接使用 validate 方法。
$data = Validator::validate($data, $rules);
validate方法返回过滤后的用户数据,即已通过验证的属性和值。
上述方法实现的功能与以下代码等效。它还演示了如何将验证器实例直接传递给 验证异常 (第一个参数)。
$validation = Validator::make($data, $rules);
if ($validation->fails()) {
throw new ValidationException($validation);
}另一种选择是使用 Request 门面来对所有用户输入执行验证。这消除了提供数据的需要,因此您只需提供规则(第一个参数)。 validate 方法返回过滤后的用户数据,即经过验证的属性和值。
$data = Request::validate($rules);validate 的返回值会根据验证规则进行筛选. 如果字段未在规则中定义,则不会包含在此数据中.
在 Validator 实例上调用 messages 方法后,您将收到一个 Illuminate\Support\MessageBag 实例,该实例具有多种便捷方法,用于处理错误消息。
echo $messages->first('email');foreach ($messages->get('email') as $message) {
//
}foreach ($messages->all() as $message) {
//
}if ($messages->has('email')) {
//
}echo $messages->first('email', '<p>:message</p>');注意:默认情况下,消息使用 Bootstrap 兼容语法进行格式化。
foreach ($messages->all('<li>:message</li>') as $message) {
//
}一旦你执行了验证,你需要一种简便的方法将错误消息返回到你的视图中。October CMS 提供了便捷的处理方式。请看以下 AJAX 处理器作为示例:
public function onRegister()
{
$rules = [];
$validator = Validator::make(input(), $rules);
if ($validator->fails()) {
return Redirect::to('register')->withErrors($validator);
}
}请注意,当验证失败时,我们使用 withErrors 方法将 Validator 实例传递给 Redirect。这个方法会将错误消息闪存到会话中,以便它们在下一次请求时可用。
October CMS 始终会检查会话数据中的错误,如果存在,则会自动将其绑定到视图。因此,请务必注意,一个 errors 变量将始终在你的所有页面上,在每个请求中都可用,这样你就可以方便地假设 errors 变量始终已定义并且可以安全使用。该 errors 变量将是 MessageBag 的一个实例。
因此,重定向后,您可以在您的视图中利用自动绑定的 errors 变量:
{{ errors.first('email') }}如果您的单个页面上有多个表单,您可能希望命名错误的 MessageBag。这将允许您检索特定表单的错误消息。只需将一个名称作为第二个参数传递给 withErrors。
return Redirect::to('register')->withErrors($validator, 'login');之后,您可以从 $errors 变量中访问命名为 MessageBag 的实例:
{{ errors.login.first('email') }}以下是所有可用的验证规则及其功能。
验证中的字段必须是 yes, on, 或 1. 这对于验证 "服务条款" 的接受很有用.
待验证字段必须是符合 checkdnsrr PHP 函数的有效 URL。
验证字段必须是给定日期之后的值。这些日期将被传递到 PHP strtotime 函数。
待验证字段必须全部是字母字符。
待验证字段可以包含字母数字字符,以及连字符和下划线。
待验证字段必须只包含字母数字字符。
待验证字段必须是数组类型。
验证字段的值必须早于给定日期. 这些日期将被传入 PHP 的 strtotime 函数.
待验证字段的大小必须介于给定的 min 和 max 之间。字符串, 数字, 和文件会采用与 size 规则相同的方式进行评估。
待验证字段必须可以转换为布尔值。接受的输入包括 true, false, 1, 0, "1" and "0"。
待验证字段必须有一个匹配的 foo_confirmation 字段。例如,如果待验证字段是 password,一个匹配的 password_confirmation 字段必须存在于输入中。
日期待验证字段必须是根据PHP strtotime 函数的有效日期。
待验证字段必须匹配根据 date_parse_from_format PHP 函数定义的格式。
给定 字段 必须不同于正在验证的字段。
待验证字段必须是数值型且长度必须精确为值。
待验证字段的长度必须介于给定的最小值和最大值之间。
待验证字段必须格式化为电子邮件地址。
待验证字段必须在给定的数据库表中存在。
exists 规则的基本用法
'state' => 'exists:states'指定自定义列名
'state' => 'exists:states,abbreviation'你还可以指定更多条件,这些条件将作为“where”子句添加到查询中:
'email' => 'exists:staff,email,account_id,1'传递 NULL 作为 "where" 子句值,将添加一个检查,以查找 NULL 数据库值:
'email' => 'exists:staff,email,deleted_at,NULL'待验证的文件必须是一个图像文件 (jpeg, png, bmp, 或 gif)
待验证字段必须包含在给定值列表内。
待验证字段必须是整数值。
待验证字段必须格式化为 IP 地址。
待验证字段必须小于或等于一个最大值。字符串、数字和文件的评估方式与 size 规则相同。
待验证的文件必须具有与列出的扩展名之一对应的 MIME 类型。
'photo' => 'mimes:jpeg,bmp,png'待验证字段必须具有一个最小值。字符串、数字和文件以与 size 规则相同的方式进行评估。
待验证字段不得包含在给定的值列表中。
待验证字段可能为null。这在验证可以包含null值的原始类型(例如字符串和整数)时特别有用。
待验证字段必须为数值。
待验证字段必须匹配给定的正则表达式。
**注意:**当使用 regex 模式时,可能需要在一个数组中指定规则,而不是使用管道分隔符,特别是当正则表达式包含管道字符时。
验证字段必须存在于输入数据中。
待验证字段必须存在,如果 字段 字段等于任何 值。
待验证字段必须存在且不为空,除非 anotherfield 字段等于任何值。
被验证字段必须存在,仅当任何其他指定字段存在时。
待验证字段必须存在 仅当 所有其他指定字段都存在时.
待验证字段必须存在 仅当 任何其他指定字段不存在时。
待验证字段必须存在 仅当 所有其他指定字段均不存在时。
指定的 字段 值必须匹配正在验证的字段的值。
待验证字段的大小必须与给定的 值 匹配。对于字符串数据,值 对应于字符数。对于数字数据,值 对应于给定的整数值。对于文件,大小 对应于以千字节为单位的文件大小。
验证中的字段必须是字符串类型。
待验证字段必须是符合 timezone_identifiers_list PHP 函数规定的有效时区标识符。
被验证的字段在给定的数据库表中必须是唯一的。如果未指定 column 选项,将使用字段名。
唯一规则的基本用法
'email' => 'unique:users'指定自定义列名。
'email' => 'unique:users,email_address'强制唯一规则忽略给定ID。
'email' => 'unique:users,email_address,10'添加额外的 where 子句。
你还可以指定更多条件将作为“where”子句添加到查询中:
'email' => 'unique:users,email_address,NULL,id,account_id,1'在上述规则中,只有 account_id 为 1 的行才会被包含在唯一性检查中。
验证字段在相同的站点上下文中必须是唯一的。其定义与unique规则相同。
'email' => 'unique_site:users'待验证字段必须是 URL 格式。
此函数使用 PHP 的
filter_var方法。
在某些情况下,你可能希望仅当某个字段存在于输入数组中时,才对该字段运行验证检查。为快速实现此目的,将 sometimes 规则添加到你的规则列表中:
$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);在上面的示例中,email 字段将仅在它存在于 $data 数组中时进行验证。
有时你可能希望仅当另一个字段的值大于 100 时才要求给定字段。或者你可能需要仅当另一个字段存在时才使两个字段具有给定值。添加这些验证规则不必很麻烦。首先,创建一个 Validator 实例,并附带你的 静态规则,这些规则永不改变:
$v = Validator::make($data, [
'email' => 'required|email',
'games' => 'required|numeric',
]);假设我们的 Web 应用程序是面向游戏收藏家的. 如果一位游戏收藏家注册了我们的应用程序, 并且他们拥有超过 100 款游戏, 我们希望他们解释为什么拥有如此多的游戏. 例如, 也许他们经营一家游戏转售店, 或者他们只是喜欢收藏. 为了有条件地添加此要求, 我们可以使用 Validator 实例上的 sometimes 方法.
$v->sometimes('reason', 'required|max:500', function($input) {
return $input->games >= 100;
});传递给 sometimes 方法的第一个参数是我们正在有条件地验证的字段名称。第二个参数是我们想要添加的规则。如果作为第三个参数传递的 Closure 返回 true,则规则将被添加。这个方法使构建复杂的条件验证变得轻而易举。你甚至可以同时为多个字段添加条件验证:
$v->sometimes(['reason', 'cost'], 'required', function($input) {
return $input->games >= 100;
});传递给你的
Closure的$input参数将是Illuminate\Support\Fluent的一个实例,并可用作一个对象来访问你的输入和文件。
验证基于数组的表单输入字段不必很麻烦。您可以使用 "点式表示法" 来验证数组中的属性。例如,如果传入的 HTTP 请求包含一个 photos[profile] 字段,您可以像这样验证它:
$validator = Validator::make(input(), [
'photos.profile' => 'required|image',
]);你还可以验证数组的每个元素。例如,要验证给定数组输入字段中的每个电子邮件都是唯一的,你可以这样做:
$validator = Validator::make(input(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);同样,你可以在你的语言文件中指定验证消息时使用 * 字符,使得为基于数组的字段使用单个验证消息变得轻而易举:
'custom' => [
'person.*.email' => [
'unique' => 'Each person must have a unique e-mail address',
]
],您也可以在您的验证规则中使用"数组表示法",如果您愿意的话。这些规则将在验证时自动转换为"点表示法"。
$validator = Validator::make(input(), [
'photos[profile]' => 'required|image',
'person[][email]' => 'email|unique:users',
]);如果需要,您可以使用自定义错误消息进行验证,而不是默认消息。有几种方法可以指定自定义消息。以下显示了如何将自定义消息传递给验证器实例。
$messages = [
'required' => 'The :attribute field is required.',
];
$validator = Validator::make($input, $rules, $messages);该:attribute占位符将被替换为实际的验证字段名称。你也可以在验证消息中使用其他占位符。以下展示了一些你可能会遇到的其他验证占位符。
$messages = [
'same' => 'The :attribute and :other must match.',
'size' => 'The :attribute must be exactly :size.',
'between' => 'The :attribute must be between :min - :max.',
'in' => 'The :attribute must be one of the following types: :values',
];有时你可能希望仅针对特定字段指定自定义错误消息。以下内容将为 email 属性在使用 required 规则时指定自定义消息。
$messages = [
'email.required' => 'We need to know your e-mail address!',
];在某些情况下,您可能希望在语言文件中指定您的自定义消息,而不是直接将其传递给 Validator。 为此,请将您的消息添加到您的插件的 lang/xx/validation.php 语言文件中的一个数组里。
return [
'required' => 'We need to know your e-mail address!',
'email.required' => 'We need to know your e-mail address!',
];然后在你对 Validator::make 的调用中 使用 Lang:get 来使用你的自定义文件。
Validator::make($formValues, $validations, Lang::get('acme.blog::validation'));验证器的默认消息字符串位于 modules/system/lang/xx/validation.php 文件中。我们建议打开此文件以查找所有可用的消息。
文件包含一个消息数组,用于每个验证规则。有一个 custom 属性用于自定义错误消息,采用 "attribute.rule" 命名约定,还有一个 attributes 属性用于存储自定义属性名称。
return [
'required' => 'The :attribute field is required!',
// ...
'custom' => [
// ...
],
'attributes' => [
// ...
]
];您可以通过在 app 目录中创建一个新文件来修改这些值中的任何一个,例如,对于 en 语言环境,创建一个名为 app/lang/system/en/validation.php。此文件中的值将覆盖默认值,您只需包含想要修改的值即可。
return [
'required' => 'Sorry, we need that field (:attribute) you gave!',
'attributes' => [
'email' => 'email address'
],
];存在多种有用的验证规则,然而,您可能希望指定一些您自己的规则。首先,您应该决定您的规则是应该全局注册,还是使用局部规则对象。
一个全局注册的规则可以通过使用标签和规则类注册,从而在整个应用程序中共享。这通常在 插件注册文件 的 register 方法中,使用 registerValidationRule 辅助方法完成。
public function register()
{
$this->registerValidationRule('uppercase', UppercaseRule::class);
}在这个例子中,我们创建了一个标记为大写的规则,并引用了我们的规则类,使其在任何地方都可以被指定为规则。
Validator::make($data, [
'shoutout' => 'required|uppercase',
]);一个全局规则类代表用于你模型的单个可复用验证规则。至少,规则类必须提供一个 validate 方法,用于判断验证规则是否通过。你也可以指定一个可选的 message 方法,以返回自定义错误消息。
class UppercaseRule
{
/**
* validate determines if the validation rule passes.
* @param string $attribute
* @param mixed $value
* @param array $params
* @return bool
*/
public function validate($attribute, $value, $params)
{
return strtoupper($value) === $value;
}
/**
* message gets the validation error message.
* @return string
*/
public function message()
{
return 'The :attribute must be uppercase.';
}
}全局规则可以支持在定义时一并传递参数。例如,一个名为 betwixt 的规则可能需要两个值。参数可以通过冒号 (:) 分隔的方式传递给规则,且每个参数之间用逗号 (,) 分隔。
$v = Validator::make($data, [
'name' => 'betwixt:1,6',
]);这些参数随后被传递给 validate 方法并变得可用。错误消息也可以通过定义一个 replace 方法来处理。
class BetwixtRule
{
/**
* validate between start and end parameters.
*/
public function validate($attribute, $value, $params)
{
[$start, $end] = $params;
return strlen($value) > $start && strlen($value) < $end;
}
/**
* message gets the validation error message.
* @return string
*/
public function message()
{
return 'The :attribute must be between :start and :end.';
}
/**
* replace defines custom placeholder replacements.
* @return string
*/
public function replace($message, $attribute, $rule, $params)
{
[$start, $end] = $params;
$message = str_replace(':start', $start, $message);
$message = str_replace(':end', $end, $message);
return $message;
}
}Laravel 规则对象文档 更详细地描述了如何定义一个规则类。具体来说,该规则必须实现 Illuminate\Contracts\Validation\Rule 契约,其中需要定义一个 passes 方法。
class LowercaseRule implements \Illuminate\Contracts\Validation\Rule
{
/**
* passes checks if the rule is successful
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
return strtolower($value) === $value;
}
/**
* message gets the validation error message.
* @return string
*/
public function message()
{
return 'The :attribute must be lowercase.';
}
}一旦定义了规则,它就可以作为一个实例传递给 Validator 服务。
$v = Validator::make($data, [
'name' => ['required', new LowercaseRule],
]);您还可以使用 beforeValidate 方法覆盖在模型中实现规则对象。
public function beforeValidate()
{
$this->rules['name'] = ['required', new LowercaseRule];
}