验证器类是一个用于验证数据以及通过 Validator 类获取验证错误消息的简单便捷功能。它在处理由最终用户提交的表单数据时很有用。
在使用模型时,October CMS 提供了一个有用的 验证 trait,它实现了
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, [...]);It is not recommended to use unfiltered
input()values here since it contains GET values that can be used to potentially craft malicious links.
大多数情况下,你会验证通过表单提交的用户输入,如果验证失败,抛出一个 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);
}
}请注意,当验证失败时,我们会将 Validator 实例传递给 Redirect,并使用 withErrors 方法。此方法会将错误消息“闪存”到会话中,以便在下次请求时可用。
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。这对于验证“服务条款”接受很有用。
正在验证的字段必须是一个有效的URL,根据 checkdnsrr PHP 函数。
验证中的字段必须是给定日期之后的值。 这些日期将被传递给 PHP 的 strtotime 函数。
验证字段必须是纯字母字符。
待验证的字段可以包含字母数字字符,以及连字符和下划线。
待验证字段必须完全是字母数字字符。
待验证的字段必须为数组类型。
待验证字段必须是早于给定日期的值。这些日期将被传入 PHP strtotime 函数。
待验证字段的大小必须介于给定的 min 和 max 之间。字符串、数字和文件会以与 size 规则相同的方式进行评估。
待验证的字段必须能够被转换为布尔值。接受的输入包括 true、false、1、0、"1" 和 "0"。
被验证的字段必须具有一个匹配的 foo_confirmation 字段。例如,如果被验证的字段是 password,一个匹配的 password_confirmation 字段必须存在于输入中。
待验证字段必须符合 strtotime PHP 函数的有效日期。
待验证字段必须匹配根据 date_parse_from_format PHP 函数定义的 格式。
给定的字段必须不同于正在验证的字段.
待验证字段必须是数值型,并且长度必须精确为值。
被验证的字段的长度必须介于给定的 最小值 和 最大值 之间。
待验证字段必须是电子邮件地址格式。
待验证字段必须存在于给定的数据库表中。
存在规则的基本用法
'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 模式时,可能需要在数组中指定规则,而不是使用管道分隔符,特别是在正则表达式包含管道字符的情况下。
待验证字段必须存在于输入数据中。
验证字段必须存在,如果 字段 字段等于任何 值。
待验证字段必须存在且不能为空,除非另一个字段等于任何值。
待验证的字段必须存在 仅当 其他任何指定的字段存在时。
待验证字段必须存在 仅当 所有其他指定字段都存在。
待验证字段必须存在 仅当 其他任何指定字段不存在时。
被验证字段必须存在,仅当所有其他指定字段均不存在时。
指定 字段 的值必须匹配待验证字段的值。
待验证字段的大小必须与给定的 值 匹配. 对于字符串数据,值 对应于字符数. 对于数字数据,值 对应于给定的整数值. 对于文件,大小 对应于文件大小(单位为千字节).
待验证的字段必须是字符串类型。
待验证字段必须是根据 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);
}在此示例中,我们创建了一条标记为 uppercase 的规则,并引用了我们的规则类,使其在任何地方都可以作为规则进行指定。
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];
}