Skip to content

验证

介绍

Laravel 提供了几种不同的方法来验证应用程序的传入数据。默认情况下,Laravel 的基础控制器类使用 ValidatesRequests trait,它提供了一种方便的方法来使用各种强大的验证规则验证传入的 HTTP 请求。

验证快速入门

为了了解 Laravel 强大的验证功能,让我们看一个完整的示例,验证一个表单并将错误消息显示给用户。

定义路由

首先,假设我们在 routes/web.php 文件中定义了以下路由:

php
Route::get('post/create', 'PostController@create');

Route::post('post', 'PostController@store');

当然,GET 路由将显示一个表单,供用户创建新的博客文章,而 POST 路由将把新的博客文章存储到数据库中。

创建控制器

接下来,让我们看看一个简单的控制器,它处理这些路由。我们将暂时留空 store 方法:

php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PostController extends Controller
{
    /**
     * 显示创建新博客文章的表单。
     *
     * @return Response
     */
    public function create()
    {
        return view('post.create');
    }

    /**
     * 存储新的博客文章。
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        // 验证并存储博客文章...
    }
}

编写验证逻辑

现在我们准备在 store 方法中填写验证新博客文章的逻辑。如果您检查应用程序的基础控制器 (App\Http\Controllers\Controller) 类,您会看到该类使用了 ValidatesRequests trait。此 trait 为所有控制器提供了一个方便的 validate 方法。

validate 方法接受传入的 HTTP 请求和一组验证规则。如果验证规则通过,您的代码将正常执行;但是,如果验证失败,将抛出异常,并自动将适当的错误响应发送回用户。在传统的 HTTP 请求的情况下,将生成重定向响应,而对于 AJAX 请求,将发送 JSON 响应。

为了更好地理解 validate 方法,让我们回到 store 方法:

php
/**
 * 存储新的博客文章。
 *
 * @param  Request  $request
 * @return Response
 */
public function store(Request $request)
{
    $this->validate($request, [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

    // 博客文章有效,存储到数据库...
}

如您所见,我们只需将传入的 HTTP 请求和所需的验证规则传递给 validate 方法。再次强调,如果验证失败,将自动生成适当的响应。如果验证通过,我们的控制器将继续正常执行。

在第一次验证失败时停止

有时您可能希望在属性的第一次验证失败后停止运行验证规则。为此,请为属性分配 bail 规则:

php
$this->validate($request, [
    'title' => 'bail|required|unique:posts|max:255',
    'body' => 'required',
]);

在此示例中,如果 title 属性上的 required 规则失败,则不会检查 unique 规则。规则将按照分配的顺序进行验证。

嵌套属性的注意事项

如果您的 HTTP 请求包含“嵌套”参数,您可以使用“点”语法在验证规则中指定它们:

php
$this->validate($request, [
    'title' => 'required|unique:posts|max:255',
    'author.name' => 'required',
    'author.description' => 'required',
]);

显示验证错误

那么,如果传入的请求参数未通过给定的验证规则怎么办?如前所述,Laravel 将自动将用户重定向回其先前的位置。此外,所有验证错误将自动 闪存到会话

再次注意,我们不必在 GET 路由中显式绑定错误消息到视图。这是因为 Laravel 将检查会话数据中的错误,并在可用时自动将它们绑定到视图。$errors 变量将是 Illuminate\Support\MessageBag 的一个实例。有关使用此对象的更多信息,请 查看其文档

lightbulb

$errors 变量由 Illuminate\View\Middleware\ShareErrorsFromSession 中间件绑定到视图,该中间件由 web 中间件组提供。当应用此中间件时,您的视图中将始终可用 $errors 变量,允许您方便地假设 $errors 变量始终已定义并且可以安全使用。

因此,在我们的示例中,当验证失败时,用户将被重定向到控制器的 create 方法,允许我们在视图中显示错误消息:

php
<!-- /resources/views/post/create.blade.php -->

<h1>创建文章</h1>

@if (count($errors) > 0)
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<!-- 创建文章表单 -->

自定义闪存错误格式

如果您希望自定义验证失败时闪存到会话的验证错误的格式,请在基础控制器上重写 formatValidationErrors。不要忘记在文件顶部导入 Illuminate\Contracts\Validation\Validator 类:

php
<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;

abstract class Controller extends BaseController
{
    use DispatchesJobs, ValidatesRequests;

    /**
     * {@inheritdoc}
     */
    protected function formatValidationErrors(Validator $validator)
    {
        return $validator->errors()->all();
    }
}

AJAX 请求与验证

在此示例中,我们使用传统表单将数据发送到应用程序。然而,许多应用程序使用 AJAX 请求。在 AJAX 请求期间使用 validate 方法时,Laravel 不会生成重定向响应。相反,Laravel 会生成一个包含所有验证错误的 JSON 响应。此 JSON 响应将以 422 HTTP 状态码发送。

表单请求验证

创建表单请求

对于更复杂的验证场景,您可能希望创建一个“表单请求”。表单请求是包含验证逻辑的自定义请求类。要创建表单请求类,请使用 make:request Artisan CLI 命令:

php
php artisan make:request StoreBlogPost

生成的类将放置在 app/Http/Requests 目录中。如果此目录不存在,当您运行 make:request 命令时将创建它。让我们在 rules 方法中添加一些验证规则:

php
/**
 * 获取适用于请求的验证规则。
 *
 * @return array
 */
public function rules()
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}

那么,如何评估验证规则?您只需在控制器方法中对请求进行类型提示即可。在调用控制器方法之前,将验证传入的表单请求,这意味着您不需要在控制器中混杂任何验证逻辑:

php
/**
 * 存储传入的博客文章。
 *
 * @param  StoreBlogPost  $request
 * @return Response
 */
public function store(StoreBlogPost $request)
{
    // 传入的请求有效...
}

如果验证失败,将生成重定向响应以将用户发送回其先前的位置。错误也将闪存到会话中,以便显示。如果请求是 AJAX 请求,将返回一个包含 422 状态码的 HTTP 响应,其中包括验证错误的 JSON 表示。

授权表单请求

表单请求类还包含一个 authorize 方法。在此方法中,您可以检查经过身份验证的用户是否确实有权更新给定资源。例如,您可以确定用户是否确实拥有他们尝试更新的博客评论:

php
/**
 * 确定用户是否有权发出此请求。
 *
 * @return bool
 */
public function authorize()
{
    $comment = Comment::find($this->route('comment'));

    return $comment && $this->user()->can('update', $comment);
}

由于所有表单请求都扩展了基础 Laravel 请求类,我们可以使用 user 方法访问当前经过身份验证的用户。还要注意上面示例中的 route 方法调用。此方法允许您访问正在调用的路由上定义的 URI 参数,例如示例中的 {comment} 参数:

php
Route::post('comment/{comment}');

如果 authorize 方法返回 false,将自动返回一个 403 状态码的 HTTP 响应,并且您的控制器方法将不会执行。

如果您计划在应用程序的其他部分中进行授权逻辑,只需从 authorize 方法返回 true

php
/**
 * 确定用户是否有权发出此请求。
 *
 * @return bool
 */
public function authorize()
{
    return true;
}

自定义错误格式

如果您希望自定义验证失败时闪存到会话的验证错误的格式,请在基础请求 (App\Http\Requests\Request) 上重写 formatErrors。不要忘记在文件顶部导入 Illuminate\Contracts\Validation\Validator 类:

php
/**
 * {@inheritdoc}
 */
protected function formatErrors(Validator $validator)
{
    return $validator->errors()->all();
}

自定义错误消息

您可以通过重写 messages 方法来自定义表单请求使用的错误消息。此方法应返回一个属性/规则对及其相应错误消息的数组:

php
/**
 * 获取定义的验证规则的错误消息。
 *
 * @return array
 */
public function messages()
{
    return [
        'title.required' => '需要一个标题',
        'body.required'  => '需要一条消息',
    ];
}

手动创建验证器

如果您不想使用 ValidatesRequests trait 的 validate 方法,您可以使用 Validator facade 手动创建一个验证器实例。make 方法在 facade 上生成一个新的验证器实例:

php
<?php

namespace App\Http\Controllers;

use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PostController extends Controller
{
    /**
     * 存储新的博客文章。
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);

        if ($validator->fails()) {
            return redirect('post/create')
                        ->withErrors($validator)
                        ->withInput();
        }

        // 存储博客文章...
    }
}

传递给 make 方法的第一个参数是验证的数据。第二个参数是应应用于数据的验证规则。

在检查请求验证失败后,您可以使用 withErrors 方法将错误消息闪存到会话中。使用此方法时,$errors 变量将在重定向后自动与您的视图共享,允许您轻松地将它们显示给用户。withErrors 方法接受一个验证器、一个 MessageBag 或一个 PHP array

自动重定向

如果您希望手动创建验证器实例,但仍然利用 ValidatesRequest trait 提供的自动重定向,您可以在现有验证器实例上调用 validate 方法。如果验证失败,用户将自动重定向,或者在 AJAX 请求的情况下,将返回 JSON 响应:

php
Validator::make($request->all(), [
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
])->validate();

命名错误包

如果您在单个页面上有多个表单,您可能希望命名错误消息的 MessageBag,以便您可以检索特定表单的错误消息。只需将名称作为第二个参数传递给 withErrors

php
return redirect('register')
            ->withErrors($validator, 'login');

然后,您可以从 $errors 变量中访问命名的 MessageBag 实例:

php
{{ $errors->login->first('email') }}

验证后钩子

验证器还允许您附加回调,以便在验证完成后运行。这使您可以轻松地执行进一步的验证,甚至将更多的错误消息添加到消息集合中。要开始,请在验证器实例上使用 after 方法:

php
$validator = Validator::make(...);

$validator->after(function ($validator) {
    if ($this->somethingElseIsInvalid()) {
        $validator->errors()->add('field', '此字段有问题!');
    }
});

if ($validator->fails()) {
    //
}

处理错误消息

Validator 实例上调用 errors 方法后,您将收到一个 Illuminate\Support\MessageBag 实例,该实例具有多种方便的方法来处理错误消息。自动提供给所有视图的 $errors 变量也是 MessageBag 类的一个实例。

检索字段的第一个错误消息

要检索给定字段的第一个错误消息,请使用 first 方法:

php
$errors = $validator->errors();

echo $errors->first('email');

检索字段的所有错误消息

如果您需要检索给定字段的所有消息数组,请使用 get 方法:

php
foreach ($errors->get('email') as $message) {
    //
}

如果您正在验证数组表单字段,您可以使用 * 字符检索每个数组元素的所有消息:

php
foreach ($errors->get('attachments.*') as $message) {
    //
}

检索所有字段的所有错误消息

要检索所有字段的所有消息数组,请使用 all 方法:

php
foreach ($errors->all() as $message) {
    //
}

确定字段是否存在消息

has 方法可用于确定给定字段是否存在任何错误消息:

php
if ($errors->has('email')) {
    //
}

自定义错误消息

如果需要,您可以为验证使用自定义错误消息,而不是默认消息。有几种方法可以指定自定义消息。首先,您可以将自定义消息作为第三个参数传递给 Validator::make 方法:

php
$messages = [
    'required' => '需要 :attribute 字段。',
];

$validator = Validator::make($input, $rules, $messages);

在此示例中,:attribute 占位符将被替换为正在验证的字段的实际名称。您还可以在验证消息中使用其他占位符。例如:

php
$messages = [
    'same'    => ':attribute 和 :other 必须匹配。',
    'size'    => ':attribute 必须正好是 :size。',
    'between' => ':attribute 必须介于 :min - :max 之间。',
    'in'      => ':attribute 必须是以下类型之一::values',
];

为给定属性指定自定义消息

有时您可能希望仅为特定字段指定自定义错误消息。您可以使用“点”符号来实现。首先指定属性的名称,然后是规则:

php
$messages = [
    'email.required' => '我们需要知道您的电子邮件地址!',
];

在语言文件中指定自定义消息

在大多数情况下,您可能会在语言文件中指定自定义消息,而不是直接传递给 Validator。为此,请将您的消息添加到 resources/lang/xx/validation.php 语言文件中的 custom 数组中。

php
'custom' => [
    'email' => [
        'required' => '我们需要知道您的电子邮件地址!',
    ],
],

在语言文件中指定自定义属性

如果您希望验证消息中的 :attribute 部分替换为自定义属性名称,您可以在 resources/lang/xx/validation.php 语言文件的 attributes 数组中指定自定义名称:

php
'attributes' => [
    'email' => '电子邮件地址',
],

可用的验证规则

以下是所有可用验证规则及其功能的列表:

accepted

验证字段必须是 yeson1true。这对于验证“服务条款”接受非常有用。

active_url

验证字段必须具有有效的 A 或 AAAA 记录,根据 dns_get_record PHP 函数。

after:date

验证字段必须是给定日期之后的值。日期将传递给 strtotime PHP 函数:

php
'start_date' => 'required|date|after:tomorrow'

您可以指定另一个字段来与日期进行比较,而不是传递一个日期字符串给 strtotime 进行评估:

php
'finish_date' => 'required|date|after:start_date'

alpha

验证字段必须完全是字母字符。

alpha_dash

验证字段可以包含字母数字字符,以及破折号和下划线。

alpha_num

验证字段必须完全是字母数字字符。

array

验证字段必须是 PHP array

before:date

验证字段必须是给定日期之前的值。日期将传递给 PHP strtotime 函数。

between:min,max

验证字段的大小必须在给定的 minmax 之间。字符串、数字和文件的评估方式与 size 规则相同。

boolean

验证字段必须能够被转换为布尔值。接受的输入有 truefalse10"1""0"

confirmed

验证字段必须有一个匹配的 foo_confirmation 字段。例如,如果验证字段是 password,则必须在输入中存在一个匹配的 password_confirmation 字段。

date

验证字段必须是一个有效的日期,根据 strtotime PHP 函数。

date_format:format

验证字段必须匹配给定的 format。在验证字段时,您应该使用 either datedate_format,而不是两者。

different:field

验证字段的值必须与 field 不同。

digits:value

验证字段必须是 numeric,并且必须具有 value 的确切长度。

digits_between:min,max

验证字段的长度必须在给定的 minmax 之间。

dimensions

验证的文件必须是符合规则参数指定的尺寸约束的图像:

php
'avatar' => 'dimensions:min_width=100,min_height=200'

可用的约束有:min_widthmax_widthmin_heightmax_heightwidthheightratio

ratio 约束应表示为宽度除以高度。可以通过 3/2 这样的语句或 1.5 这样的浮点数来指定:

php
'avatar' => 'dimensions:ratio=3/2'

distinct

在处理数组时,验证字段不得有任何重复值。

php
'foo.*.id' => 'distinct'

email

验证字段必须格式化为电子邮件地址。

exists:table,column

验证字段必须存在于给定的数据库表中。

Exists 规则的基本用法

php
'state' => 'exists:states'

指定自定义列名

php
'state' => 'exists:states,abbreviation'

有时,您可能需要指定用于 exists 查询的特定数据库连接。您可以通过使用“点”语法将连接名称添加到表名来实现:

php
'email' => 'exists:connection.staff,email'

如果您希望自定义验证规则执行的查询,可以使用 Rule 类来流畅地定义规则。在此示例中,我们还将指定验证规则为数组,而不是使用 | 字符来分隔它们:

php
use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::exists('staff')->where(function ($query) {
            $query->where('account_id', 1);
        }),
    ],
]);

file

验证字段必须是成功上传的文件。

filled

验证字段在存在时不得为空。

image

验证的文件必须是图像(jpeg、png、bmp、gif 或 svg)

in:foo,bar,...

验证字段必须包含在给定的值列表中。

in_array:anotherfield

验证字段必须存在于 anotherfield 的值中。

integer

验证字段必须是整数。

ip

验证字段必须是 IP 地址。

json

验证字段必须是有效的 JSON 字符串。

max:value

验证字段必须小于或等于最大 value。字符串、数字和文件的评估方式与 size 规则相同。

mimetypes:text/plain,...

验证的文件必须匹配给定的 MIME 类型之一:

php
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'

为了确定上传文件的 MIME 类型,将读取文件的内容,框架将尝试猜测 MIME 类型,这可能与客户端提供的 MIME 类型不同。

mimes:foo,bar,...

验证的文件必须具有与列出的扩展名对应的 MIME 类型。

MIME 规则的基本用法

php
'photo' => 'mimes:jpeg,bmp,png'

即使您只需要指定扩展名,此规则实际上是通过读取文件的内容并猜测其 MIME 类型来验证文件的 MIME 类型。

MIME 类型及其对应扩展名的完整列表可以在以下位置找到:https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

min:value

验证字段必须具有最小 value。字符串、数字和文件的评估方式与 size 规则相同。

nullable

验证字段可以为 null。这在验证可以包含 null 值的字符串和整数等原始类型时特别有用。

not_in:foo,bar,...

验证字段不得包含在给定的值列表中。

numeric

验证字段必须是数字。

present

验证字段必须存在于输入数据中,但可以为空。

regex:pattern

验证字段必须匹配给定的正则表达式。

注意: 使用 regex 模式时,可能需要在数组中指定规则,而不是使用管道分隔符,特别是当正则表达式包含管道字符时。

required

验证字段必须存在于输入数据中且不为空。如果以下条件之一为真,则字段被视为“空”:

  • 值为 null
  • 值为空字符串。
  • 值为空数组或空 Countable 对象。
  • 值是没有路径的上传文件。

required_if:anotherfield,value,...

如果 anotherfield 字段等于任何 value,则验证字段必须存在且不为空。

required_unless:anotherfield,value,...

除非 anotherfield 字段等于任何 value,否则验证字段必须存在且不为空。

required_with:foo,bar,...

验证字段必须存在且不为空,仅当 其他指定字段中的任何一个存在时。

required_with_all:foo,bar,...

验证字段必须存在且不为空,仅当 所有其他指定字段都存在时。

required_without:foo,bar,...

验证字段必须存在且不为空,仅当 其他指定字段中的任何一个不存在时。

required_without_all:foo,bar,...

验证字段必须存在且不为空,仅当 所有其他指定字段都不存在时。

same:field

给定的 field 必须与验证字段匹配。

size:value

验证字段的大小必须与给定的 value 匹配。对于字符串数据,value 对应于字符数。对于数字数据,value 对应于给定的整数值。对于数组,size 对应于数组的 count。对于文件,size 对应于文件大小(以千字节为单位)。

string

验证字段必须是字符串。如果您希望字段也可以为 null,您应该为字段分配 nullable 规则。

timezone

验证字段必须是根据 timezone_identifiers_list PHP 函数的有效时区标识符。

unique:table,column,except,idColumn

验证字段在给定的数据库表中必须是唯一的。如果未指定 column 选项,将使用字段名称。

指定自定义列名:

php
'email' => 'unique:users,email_address'

自定义数据库连接

有时,您可能需要为验证器进行的数据库查询设置自定义连接。如上所示,设置 unique:users 作为验证规则将使用默认数据库连接查询数据库。要覆盖此设置,请使用“点”语法指定连接和表名:

php
'email' => 'unique:connection.users,email_address'

强制唯一规则忽略给定 ID:

有时,您可能希望在唯一检查期间忽略给定的 ID。例如,考虑一个包含用户姓名、电子邮件地址和位置的“更新个人资料”屏幕。当然,您将希望验证电子邮件地址是唯一的。但是,如果用户仅更改名称字段而不更改电子邮件字段,您不希望抛出验证错误,因为用户已经是电子邮件地址的所有者。

要指示验证器忽略用户的 ID,我们将使用 Rule 类来流畅地定义规则。在此示例中,我们还将指定验证规则为数组,而不是使用 | 字符来分隔规则:

php
use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::unique('users')->ignore($user->id),
    ],
]);

如果您的表使用的主键列名不是 id,您可以在调用 ignore 方法时指定列的名称:

php
'email' => Rule::unique('users')->ignore($user->id, 'user_id')

添加额外的 Where 子句:

您还可以通过使用 where 方法自定义查询来指定额外的查询约束。例如,让我们添加一个约束,验证 account_id1

php
'email' => Rule::unique('users')->where(function ($query) {
    $query->where('account_id', 1);
})

url

验证字段必须是有效的 URL。

有条件地添加规则

当存在时进行验证

在某些情况下,您可能希望仅在输入数组中存在该字段时对其进行验证检查。要快速实现此目的,请将 sometimes 规则添加到您的规则列表中:

php
$v = Validator::make($data, [
    'email' => 'sometimes|required|email',
]);

在上面的示例中,只有在 $data 数组中存在 email 字段时才会对其进行验证。

复杂的条件验证

有时,您可能希望根据更复杂的条件逻辑添加验证规则。例如,您可能希望仅在另一个字段的值大于 100 时才要求给定字段。或者,您可能需要两个字段仅在另一个字段存在时才具有给定值。添加这些验证规则不必是痛苦的。首先,使用您的 static rules 创建一个 Validator 实例,这些规则永远不会改变:

php
$v = Validator::make($data, [
    'email' => 'required|email',
    'games' => 'required|numeric',
]);

假设我们的 Web 应用程序是为游戏收藏家设计的。如果游戏收藏家注册我们的应用程序并且他们拥有超过 100 个游戏,我们希望他们解释为什么他们拥有这么多游戏。例如,也许他们经营一个游戏转售商店,或者他们只是喜欢收藏。要有条件地添加此要求,我们可以在 Validator 实例上使用 sometimes 方法。

php
$v->sometimes('reason', 'required|max:500', function ($input) {
    return $input->games >= 100;
});

传递给 sometimes 方法的第一个参数是我们有条件验证的字段名称。第二个参数是我们要添加的规则。如果作为第三个参数传递的 Closure 返回 true,则将添加规则。此方法使构建复杂的条件验证变得轻而易举。您甚至可以一次为多个字段添加条件验证:

php
$v->sometimes(['reason', 'cost'], 'required', function ($input) {
    return $input->games >= 100;
});
lightbulb

传递给您的 Closure$input 参数将是 Illuminate\Support\Fluent 的一个实例,可以用于访问您的输入和文件。

验证数组

验证基于数组的表单输入字段不必是痛苦的。例如,要验证给定数组输入字段中的每个电子邮件是否唯一,您可以执行以下操作:

php
$validator = Validator::make($request->all(), [
    'person.*.email' => 'email|unique:users',
    'person.*.first_name' => 'required_with:person.*.last_name',
]);

同样,您可以在语言文件中指定验证消息时使用 * 字符,使得为基于数组的字段使用单个验证消息变得轻而易举:

php
'custom' => [
    'person.*.email' => [
        'unique' => '每个人必须有一个唯一的电子邮件地址',
    ]
],

自定义验证规则

Laravel 提供了多种有用的验证规则;然而,您可能希望指定一些自己的规则。注册自定义验证规则的一种方法是使用 Validator facade 上的 extend 方法。让我们在 service provider 中使用此方法注册自定义验证规则:

php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;

class AppServiceProvider extends ServiceProvider
{
    /**
     * 启动任何应用程序服务。
     *
     * @return void
     */
    public function boot()
    {
        Validator::extend('foo', function ($attribute, $value, $parameters, $validator) {
            return $value == 'foo';
        });
    }

    /**
     * 注册服务提供者。
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

自定义验证器闭包接收四个参数:正在验证的 $attribute 的名称、属性的 $value、传递给规则的 $parameters 数组和 Validator 实例。

您还可以将类和方法传递给 extend 方法,而不是闭包:

php
Validator::extend('foo', 'FooValidator@validate');

定义错误消息

您还需要为自定义规则定义错误消息。您可以使用内联自定义消息数组或通过在验证语言文件中添加条目来实现。此消息应放置在数组的第一级,而不是在 custom 数组中,该数组仅用于特定属性的错误消息:

php
"foo" => "您的输入无效!",

"accepted" => ":attribute 必须被接受。",

// 其余的验证错误消息...

在创建自定义验证规则时,您可能有时需要为错误消息定义自定义占位符替换。您可以通过创建自定义验证器(如上所述),然后调用 Validator facade 上的 replacer 方法来实现。您可以在 service providerboot 方法中执行此操作:

php
/**
 * 启动任何应用程序服务。
 *
 * @return void
 */
public function boot()
{
    Validator::extend(...);

    Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) {
        return str_replace(...);
    });
}

隐式扩展

默认情况下,当正在验证的属性不存在或包含由 required 规则定义的空值时,正常的验证规则(包括自定义扩展)不会运行。例如,unique 规则不会对 null 值运行:

php
$rules = ['name' => 'unique'];

$input = ['name' => null];

Validator::make($input, $rules)->passes(); // true

要使规则即使在属性为空时也能运行,该规则必须暗示该属性是必需的。要创建这样的“隐式”扩展,请使用 Validator::extendImplicit() 方法:

php
Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
    return $value == 'foo';
});
exclamation

“隐式”扩展仅 暗示 属性是必需的。是否实际使缺失或空的属性无效取决于您。