Skip to content

验证

介绍

Laravel 提供了几种不同的方法来验证应用程序的传入数据。最常见的方法是使用所有传入 HTTP 请求上可用的 validate 方法。但是,我们还将讨论其他验证方法。

Laravel 包含各种方便的验证规则,您可以将其应用于数据,甚至可以验证值在给定数据库表中是否唯一。我们将详细介绍这些验证规则中的每一个,以便您熟悉 Laravel 的所有验证功能。

验证快速入门

要了解 Laravel 强大的验证功能,让我们看一个验证表单并将错误消息显示回给用户的完整示例。通过阅读此高级概述,您将能够对如何使用 Laravel 验证传入的请求数据有一个很好的总体了解:

定义路由

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

php
    use App\Http\Controllers\PostController;
    
    Route::get('/post/create', [PostController::class, 'create']);
    Route::post('/post', [PostController::class, 'store']);

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

创建控制器

接下来,让我们看一下一个简单的控制器,它处理对这些路由的传入请求。我们现在将 store 方法留空:

php
    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Illuminate\View\View;
    
    class PostController extends Controller
    {
        /**
         * 显示表单以创建新的博客文章
         */
        public function create(): View
        {
            return view('post.create');
        }
    
        /**
         * 存储新的博客文章
         */
        public function store(Request $request): RedirectResponse
        {
            // 验证并存储博客文章...
    
            $post = /** ... */
    
            return to_route('post.show', ['post' => $post->id]);
        }
    }

编写验证逻辑

现在我们准备好用逻辑填充我们的 store 方法来验证新的博客文章。为此,我们将使用 Illuminate\Http\Request 对象提供的 validate 方法。如果验证规则通过,您的代码将继续正常执行;但是,如果验证失败,将引发异常 Illuminate\Validation\ValidationException ,并且将自动将正确的错误响应发送回用户。

如果在传统 HTTP 请求期间验证失败,将生成对上一个 URL 的重定向响应。如果传入请求是 XHR 请求,则将返回包含验证错误消息的 JSON 响应

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

php
    /**
     * Store a new blog post.
     */
    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);
    
        // 博文有效...
    
        return redirect('/posts');
    }

如您所见,验证规则被传递到 validate 方法中。别担心 - 所有可用的验证规则都已记录在案。同样,如果验证失败,将自动生成正确的响应。如果验证通过,我们的控制器将继续正常执行。

或者,可以将验证规则指定为规则数组,而不是单个 | 分隔字符串:

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

此外,您可以使用 validateWithBag 方法来验证请求并将任何错误消息存储在命名的错误包中:

php
    $validatedData = $request->validateWithBag('post', [
        'title' => ['required', 'unique:posts', 'max:255'],
        'body' => ['required'],
    ]);

首次验证失败时停止

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

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

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

关于嵌套属性的说明

如果传入的 HTTP 请求包含 “nested” 字段数据,您可以使用 “dot” 语法在验证规则中指定这些字段:

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

另一方面,如果您的字段名称包含文字句点,则可以通过使用反斜杠转义句点来显式防止将其解释为 “点” 语法:

php
    $request->validate([
        'title' => 'required|unique:posts|max:255',
        'v1\.0' => 'required',
    ]);

显示验证错误

那么,如果传入的请求字段没有通过给定的验证规则怎么办?如前所述,Laravel 会自动将用户重定向回他们之前的位置。此外,所有验证错误和request input都将自动flashed to the session

$errors 变量由 Illuminate\View\Middleware\ShareErrorsFromSession 中间件与应用程序的所有视图共享,中间件由 Web 中间件组提供。应用此中间件后,$errors 变量将始终在您的视图中可用,从而允许您方便地假设 $errors 变量始终已定义并且可以安全地使用。$errors 变量将是 Illuminate\Support\MessageBag 的实例。有关使用此对象的更多信息,请查看其文档

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

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

<h1>Create Post</h1>

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

<!-- Create Post Form -->

自定义错误消息

Laravel 的内置验证规则每个都有一条错误消息,位于应用程序的 lang/en/validation.php 文件中。如果您的应用程序没有 lang 目录,您可以指示 Laravel 使用 lang:publish Artisan 命令创建它。

lang/en/validation.php 文件中,您将找到每个验证规则的翻译条目。您可以根据应用程序的需要自由更改或修改这些消息。

此外,您可以将此文件复制到另一个语言目录,以翻译应用程序语言的消息。要了解有关 Laravel 本地化的更多信息,请查看完整的本地化文档

WARNING

默认情况下,Laravel 应用程序框架不包括 lang 目录。如果你想自定义 Laravel 的语言文件,你可以通过 lang:publish Artisan 命令发布它们。

XHR 请求和验证

在此示例中,我们使用传统表单将数据发送到应用程序。但是,许多应用程序从 JavaScript 支持的前端接收 XHR 请求。在 XHR 请求期间使用 validate 方法时,Laravel 不会生成重定向响应。相反,Laravel 会生成包含所有验证错误的 JSON 响应。此 JSON 响应将与 422 HTTP 状态代码一起发送。

@error 指令

您可以使用 @errorBlade 指令快速确定给定属性是否存在验证错误消息。在 @error 指令中,您可以回显 $message 变量以显示错误消息:

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

<label for="title">Post Title</label>

<input id="title"
    type="text"
    name="title"
    class="@error('title') is-invalid @enderror">

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

如果你正在使用命名错误,你可以将错误袋的名称作为第二个参数传递给 @error 指令:

blade
<input ... class="@error('title', 'post') is-invalid @enderror">

重新填充表单

当 Laravel 由于验证错误而生成重定向响应时,框架会自动将所有请求的输入刷入会话。这样做是为了让您可以在下一个请求期间方便地访问输入,并重新填充用户尝试提交的表单。

要从上一个请求中检索闪现的输入,请在 Illuminate\Http\Request 的实例上调用old方法。old方法将从 session 中提取之前闪现的 input 数据:

$title = $request->old('title');

Laravel 还提供了一个 全局 old 帮助函数。如果要在 Blade 模板中显示旧输入,则使用old帮助程序重新填充表单会更方便。如果给定字段不存在旧输入,则将返回 null

blade
<input type="text" name="title" value="{{ old('title') }}">

关于可选字段的说明

默认情况下,Laravel 在应用程序的全局中间件堆栈中包含 TrimStringsConvertEmptyStringsToNull 中间件。因此,如果您不希望验证程序将 null 值视为无效,则通常需要将 “optional” 请求字段标记为nullable。例如:

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

在此示例中,我们指定 publish_at 字段可以是 null 或有效日期表示形式。如果未将 nullable 修饰符添加到规则定义中,则验证程序会将 null 视为无效日期。

验证错误响应格式

当您的应用程序引发 Illuminate\Validation\ValidationException 异常并且传入的 HTTP 请求需要 JSON 响应时,Laravel 将自动为您格式化错误消息并返回 422 Unprocessable Entity HTTP 响应。

下面,您可以查看验证错误的 JSON 响应格式示例。请注意,嵌套的错误键被扁平化为 “dot” 表示法格式:

json
{
    "message": "The team name must be a string. (and 4 more errors)",
    "errors": {
        "team_name": [
            "The team name must be a string.",
            "The team name must be at least 1 characters."
        ],
        "authorization.role": [
            "The selected authorization.role is invalid."
        ],
        "users.0.email": [
            "The users.0.email field is required."
        ],
        "users.2.email": [
            "The users.2.email must be a valid email address."
        ]
    }
}

表单请求验证

创建表单请求

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

shell
php artisan make:request StorePostRequest

生成的表单请求类将放置在 app/Http/Requests 目录中。如果此目录不存在,则会在运行 make:request 命令时创建该目录。Laravel 生成的每个表单请求都有两种方法:authorizerules

您可能已经猜到了,authorize 方法负责确定当前经过身份验证的用户是否可以执行请求所表示的操作,而 rules 方法返回应应用于请求数据的验证规则:

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

NOTE

您可以在 rules 方法的签名中键入所需的任何依赖项。它们将通过 Laravel 服务容器自动解析。

那么,如何评估验证规则呢?您需要做的就是在 controller 方法上对请求进行类型提示。传入的表单请求在调用 controller 方法之前进行验证,这意味着你不需要用任何验证逻辑来弄乱你的控制器:

php
    /**
     * 存储新的博客文章
     */
    public function store(StorePostRequest $request): RedirectResponse
    {
        //  传入请求有效...
    
        //  检索已验证的输入数据...
        $validated = $request->validated();
    
        //  检索已验证输入数据的一部分...
        $validated = $request->safe()->only(['name', 'email']);
        $validated = $request->safe()->except(['name', 'email']);
    
        // 存储博客文章...
    
        return redirect('/posts');
    }

如果验证失败,将生成重定向响应以将用户发送回其之前的位置。错误也将闪存到会话中,以便它们可供显示。如果请求是 XHR 请求,则将向用户返回带有 422 状态代码的 HTTP 响应,包括验证错误的 JSON 表示形式。

NOTE

需要将实时表单请求验证添加到您的 Inertia 驱动的 Laravel 前端吗?查看 Laravel Precognition

执行其他验证

有时,您需要在初始验证完成后执行其他验证。您可以使用表单请求的 after 方法完成此操作。

after 方法应返回一个可调用对象或闭包数组,该数组将在验证完成后调用。给定的可调用对象将接收一个 Illuminate\Validation\Validator 实例,允许你在必要时引发额外的错误消息:

php
    use Illuminate\Validation\Validator;
    
    /**
     * 获取请求的 “after” 验证可调用对象。
     */
    public function after(): array
    {
        return [
            function (Validator $validator) {
                if ($this->somethingElseIsInvalid()) {
                    $validator->errors()->add(
                        'field',
                        'Something is wrong with this field!'
                    );
                }
            }
        ];
    }

如前所述,after 方法返回的数组也可能包含可调用的类。这些类的 __invoke 方法将接收一个 Illuminate\Validation\Validator 实例:

php
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
use Illuminate\Validation\Validator;

/**
 * 获取请求的 “after” 验证可调用对象
 */
public function after(): array
{
    return [
        new ValidateUserStatus,
        new ValidateShippingTime,
        function (Validator $validator) {
            //
        }
    ];
}

在第一次验证失败时停止

通过将 stopOnFirstFailure 属性添加到您的请求类中,您可以通知验证器在发生单个验证失败后应停止验证所有属性:

php
    /**
     * 指示验证器是否应在第一次规则失败时停止。
     *
     * @var bool
     */
    protected $stopOnFirstFailure = true;

自定义重定向位置

如前所述,当表单请求验证失败时,将生成重定向响应以将用户发送回其先前的位置。但是,您可以自由自定义此行为。为此,请在表单请求中定义 $redirect 属性:

php
    /**
     * 验证失败时应将用户重定向到的 URI。
     *
     * @var string
     */
    protected $redirect = '/dashboard';

或者,如果你想将用户重定向到命名路由,你可以定义一个 $redirectRoute 属性:

php
    /**
     * 验证失败时应将用户重定向到的路由。
     *
     * @var string
     */
    protected $redirectRoute = 'dashboard';

授权表单请求

表单请求类还包含一个 authorize 方法。在此方法中,您可以确定经过身份验证的用户是否真的有权更新给定资源。例如,您可以确定用户是否实际拥有他们尝试更新的博客评论。最有可能的是,您将在此方法中与您的授权和策略进行交互:

php
    use App\Models\Comment;
    
    /**
     * 确定用户是否有权发出此请求。
     */
    public function authorize(): bool
    {
        $comment = Comment::find($this->route('comment'));
    
        return $comment && $this->user()->can('update', $comment);
    }

由于所有表单请求都扩展了 Laravel 请求的基本类,因此我们可以使用 user 方法来访问当前经过身份验证的用户。另外,请注意上面示例中对 route 方法的调用。此方法授予您访问在被调用的路由上定义的 URI 参数的权限,例如以下示例中的 {comment} 参数:

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

因此,如果您的应用程序正在利用路由模型绑定,则可以通过将解析的模型作为请求的属性进行访问来使您的代码更加简洁:

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

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

如果您计划在应用程序的另一部分处理请求的授权逻辑,则可以完全删除 authorize 方法,或者直接返回 true

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

NOTE

您可以在 authorize 方法的签名中键入 type-hint 所需的任何依赖项。它们将通过 Laravel 服务容器自动解析。

自定义错误消息

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

php
    /**
     * 获取已定义验证规则的错误消息。
     *
     * @return array<string, string>
     */
    public function messages(): array
    {
        return [
            'title.required' => 'A title is required',
            'body.required' => 'A message is required',
        ];
    }

自定义验证属性

许多 Laravel 的内置验证规则错误消息都包含 :attribute 占位符。如果您希望将验证消息的 :attribute 占位符替换为自定义属性名称,则可以通过覆盖 attributes 方法来指定自定义名称。此方法应返回一个属性/名称对数组:

php
    /**
     * 获取验证器错误的自定义属性
     *
     * @return array<string, string>
     */
    public function attributes(): array
    {
        return [
            'email' => 'email address',
        ];
    }

准备用于验证的输入

如果您需要在应用验证规则之前准备或清理请求中的任何数据,则可以使用 prepareForValidation 方法:

php
    use Illuminate\Support\Str;
    
    /**
     * 准备用于验证的数据。
     */
    protected function prepareForValidation(): void
    {
        $this->merge([
            'slug' => Str::slug($this->slug),
        ]);
    }

同样,如果你需要在验证完成后规范化任何请求数据,你可以使用 passedValidation 方法:

php
    /**
     * 处理通过的验证尝试
     */
    protected function passedValidation(): void
    {
        $this->replace(['name' => 'Taylor']);
    }

手动创建 Validator

如果您不想在请求中使用 validate 方法,则可以使用 Validator facade手动创建 validator 实例。Facade 上的 make 方法会生成一个新的 validator 实例:

php
    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\RedirectResponse;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Validator;
    
    class PostController extends Controller
    {
        /**
         * 存储新的博客文章。
         */
        public function store(Request $request): RedirectResponse
        {
            $validator = Validator::make($request->all(), [
                'title' => 'required|unique:posts|max:255',
                'body' => 'required',
            ]);
    
            if ($validator->fails()) {
                return redirect('/post/create')
                            ->withErrors($validator)
                            ->withInput();
            }
    
            //  检索已验证的输入...
            $validated = $validator->validated();
    
            //  检索已验证输入的一部分...
            $validated = $validator->safe()->only(['name', 'email']);
            $validated = $validator->safe()->except(['name', 'email']);
    
            // 存储博客文章...
    
            return redirect('/posts');
        }
    }

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

在确定请求验证是否失败后,你可以使用 withErrors 方法将错误消息发送到 session 中。使用此方法时,$errors 变量将在重定向后自动与您的视图共享,以便您轻松地将它们显示回给用户。withErrors 方法接受验证器、MessageBag 或 PHP 数组

首次验证失败时停止

stopOnFirstFailure 方法将通知验证器,一旦发生单个验证失败,它应该停止验证所有属性:

php
    if ($validator->stopOnFirstFailure()->fails()) {
        // ...
    }

自动重定向

如果您想手动创建验证程序实例,但仍利用 HTTP 请求的 validate 方法提供的自动重定向,则可以在现有验证程序实例上调用 validate 方法。如果验证失败,用户将自动重定向,或者在 XHR 请求的情况下,将返回 JSON 响应

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

如果验证失败,您可以使用 validateWithBag 方法将错误消息存储在命名的错误包中:

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

命名错误组

如果单个页面上有多个表单,您可能希望命名包含验证错误的 MessageBag,以便您检索特定表单的错误消息。为此,请将 name 作为第二个参数传递给 withErrors

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

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

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

自定义错误消息

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

php
    $validator = Validator::make($input, $rules, $messages = [
        'required' => 'The :attribute field is required.',
    ]);

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

php
    $messages = [
        'same' => 'The :attribute and :other must match.',
        'size' => 'The :attribute must be exactly :size.',
        'between' => 'The :attribute value :input is not between :min - :max.',
        'in' => 'The :attribute must be one of the following types: :values',
    ];

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

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

php
    $messages = [
        'email.required' => 'We need to know your email address!',
    ];

指定自定义属性值

Laravel 的许多内置错误消息都包含一个 :attribute 占位符,该占位符替换为正在验证的字段或属性的名称。要自定义用于替换特定字段的这些占位符的值,您可以将自定义属性数组作为第四个参数传递给 Validator::make 方法:

php
    $validator = Validator::make($input, $rules, $messages, [
        'email' => 'email address',
    ]);

执行其他验证

有时,您需要在初始验证完成后执行其他验证。您可以使用 validator 的 after 方法完成此操作。after 方法接受一个闭包或一个可调用对象数组,这些将在验证完成后调用。给定的可调用对象将接收一个 Illuminate\Validation\Validator 实例,允许你在必要时引发额外的错误消息:

php
    use Illuminate\Support\Facades\Validator;
    
    $validator = Validator::make(/* ... */);
    
    $validator->after(function ($validator) {
        if ($this->somethingElseIsInvalid()) {
            $validator->errors()->add(
                'field', 'Something is wrong with this field!'
            );
        }
    });
    
    if ($validator->fails()) {
        // ...
    }

如前所述,after 方法还接受一个可调用数组,如果您的 “after validation” 逻辑封装在可调用类中,这将特别方便,这些类将通过其 __invoke 方法接收一个 Illuminate\Validation\Validator 实例:

php
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;

$validator->after([
    new ValidateUserStatus,
    new ValidateShippingTime,
    function ($validator) {
        // ...
    },
]);

使用经过验证的输入

使用表单请求或手动创建的验证器实例验证传入请求数据后,您可能希望检索实际经过验证的传入请求数据。这可以通过多种方式实现。首先,您可以在表单请求或验证程序实例上调用 validated 方法。此方法返回已验证的数据数组:

php
    $validated = $request->validated();
    
    $validated = $validator->validated();

或者,您可以在表单请求或验证器实例上调用 safe 方法。此方法返回 Illuminate\Support\ValidatedInput 的实例。此对象公开 exceptall 方法来检索已验证数据的子集或整个已验证数据数组:

php
    $validated = $request->safe()->only(['name', 'email']);
    
    $validated = $request->safe()->except(['name', 'email']);
    
    $validated = $request->safe()->all();

此外, Illuminate\Support\ValidatedInput 可以像数组一样迭代和访问实例:

php
    // 经过验证的数据可能会迭代...
    foreach ($request->safe() as $key => $value) {
        // ...
    }
    
    // 经过验证的数据可以作为数组访问...
    $validated = $request->safe();
    
    $email = $validated['email'];

如果您想向已验证的数据添加其他字段,您可以调用 merge 方法:

php
    $validated = $request->safe()->merge(['name' => 'Taylor Otwell']);

如果您想将经过验证的数据作为集合实例检索,您可以调用 collect 方法:

php
    $collection = $request->safe()->collect();

使用错误消息

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')) {
        // ...
    }

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

Laravel 的内置验证规则每个都有一条错误消息,位于应用程序的 lang/en/validation.php 文件中。如果您的应用程序没有 lang 目录,您可以指示 Laravel 使用 lang:publish Artisan 命令创建它。

lang/en/validation.php 文件中,您将找到每个验证规则的翻译条目。您可以根据应用程序的需要自由更改或修改这些消息。

此外,您可以将此文件复制到另一个语言目录,以翻译应用程序语言的消息。要了解有关 Laravel 本地化的更多信息,请查看完整的本地化文档

WARNING

默认情况下,Laravel 应用程序框架不包括 lang 目录。如果你想自定义 Laravel 的语言文件,你可以通过 lang:publish Artisan 命令发布它们。

特定属性的自定义消息

您可以自定义用于应用程序验证语言文件中指定属性和规则组合的错误消息。为此,请将您的消息自定义添加到应用程序的 lang/xx/validation.php 语言文件的自定义数组中:

php
    'custom' => [
        'email' => [
            'required' => 'We need to know your email address!',
            'max' => 'Your email address is too long!'
        ],
    ],

在语言文件中指定属性

Laravel 的许多内置错误消息都包含一个 :attribute 占位符,该占位符替换为正在验证的字段或属性的名称。如果您希望将验证消息的 :attribute 部分替换为自定义值,则可以在 lang/xx/validation.php 语言文件的 attributes 数组中指定自定义属性名称:

php
    'attributes' => [
        'email' => 'email address',
    ],

WARNING

默认情况下,Laravel 应用程序框架不包括 lang 目录。如果你想自定义 Laravel 的语言文件,你可以通过 lang:publish Artisan 命令发布它们。

在语言文件中指定值

一些 Laravel 的内置验证规则错误消息包含一个 :value 占位符,该占位符替换为 request 属性的当前值。但是,您可能偶尔需要将验证消息的 :value 部分替换为值的自定义表示形式。例如,请考虑以下规则,该规则指定如果 payment_type 的值为 cc,则需要信用卡号:

php
    Validator::make($request->all(), [
        'credit_card_number' => 'required_if:payment_type,cc'
    ]);

如果此验证规则失败,它将生成以下错误消息:

php
当付款类型为 cc 时,信用卡号字段为必填项

您可以通过定义 values 数组在 lang/xx/validation.php 语言文件中指定更用户友好的值表示形式,而不是将 cc 显示为付款类型值:

php
    'values' => [
        'payment_type' => [
            'cc' => 'credit card'
        ],
    ],

WARNING

默认情况下,Laravel 应用程序框架不包括 lang 目录。如果你想自定义 Laravel 的语言文件,你可以通过 lang:publish Artisan 命令发布它们。

定义此值后,验证规则将生成以下错误消息:

php
当付款类型为 credit card 时,信用卡号字段为必填项

可用的验证规则

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

accepted

正在验证的字段必须为 “yes”、“``on”1“1”true“true”。这对于验证 “Terms of Service” 接受或类似字段非常有用。

accepted_if:anotherfield,value,...

如果另一个正在验证的字段等于指定值,则正在验证的字段必须为 “yes”、“``on”1“1”true“true”。这对于验证 “Terms of Service” 接受或类似字段非常有用。

active_url

根据 PHP 函数,正在验证的字段必须具有有效的 A 或 AAAA dns_get_record记录。在将所提供 URL 的主机名传递给 dns_get_record 之前,将使用 parse_url PHP 函数提取该 URL。

after:date

正在验证的字段必须是给定日期之后的值。日期将被传递到 strtotime PHP 函数中,以便转换为有效的 DateTime 实例:

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

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

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

after_or_equal:date

正在验证的字段必须是晚于或等于给定日期的值。有关更多信息,请参阅 after 规则。

alpha

正在验证的字段必须完全是 \p{L}\p{M} 中包含的 Unicode 字母字符。

要将此验证规则限制为 ASCII 范围(a-zA-Z)中的字符,您可以为验证规则提供 ascii 选项:

php
'username' => 'alpha:ascii',

alpha_dash

正在验证的字段必须完全是 \p{L}\p{M}\p{N} 中包含的 Unicode 字母数字字符,以及 ASCII 破折号 (-) 和 ASCII 下划线 (_)。

要将此验证规则限制为 ASCII 范围(a-zA-Z)中的字符,您可以为验证规则提供 ascii 选项:

php
'username' => 'alpha_dash:ascii',

alpha_num

正在验证的字段必须完全是 \p{L}\p{M}\p{N} 中包含的 Unicode 字母数字字符。

要将此验证规则限制为 ASCII 范围(a-zA-Z)中的字符,您可以为验证规则提供 ascii 选项:

php
'username' => 'alpha_num:ascii',

array

正在验证的字段必须是 PHP 数组

当向数组规则提供其他值时,输入数组中的每个键都必须存在于提供给规则的值列表中。在以下示例中,输入数组中的 admin 键无效,因为它不包含在提供给数组规则的值列表中:

php
    use Illuminate\Support\Facades\Validator;
    
    $input = [
        'user' => [
            'name' => 'Taylor Otwell',
            'username' => 'taylorotwell',
            'admin' => true,
        ],
    ];
    
    Validator::make($input, [
        'user' => 'array:name,username',
    ]);

通常,您应该始终指定允许存在于数组中的数组键。

ascii

正在验证的字段必须完全是 7 位 ASCII 字符。

bail

在第一次验证失败后停止运行字段的验证规则。

虽然bail规则仅在遇到验证失败时停止验证特定字段,但 stopOnFirstFailure 方法将通知验证程序,一旦发生单个验证失败,它就应该停止验证所有属性:

php
    if ($validator->stopOnFirstFailure()->fails()) {
        // ...
    }

before:date

正在验证的字段必须是给定日期之前的值。日期将被传递到 PHP strtotime 函数中,以便转换为有效的 DateTime 实例。此外,与 after 规则一样,正在验证的另一个字段的名称可以作为 date 的值提供。

before_or_equal:date

正在验证的字段必须是早于或等于给定日期的值。日期将被传递到 PHP strtotime 函数中,以便转换为有效的 DateTime 实例。此外,与 after 规则一样,正在验证的另一个字段的名称可以作为 date 的值提供。

between:min,max

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

boolean

正在验证的字段必须能够强制转换为布尔值。接受的输入包括 truefalse10“1”“0”。

confirmed

正在验证的字段必须具有匹配字段 {field}_confirmation。例如,如果正在验证的字段是 password,则输入中必须存在匹配的 password_confirmation 字段。

contains:foo,bar,...

正在验证的字段必须是包含所有给定参数值的数组。

current_password

验证下的字段必须与经过身份验证的用户的密码匹配。您可以使用规则的第一个参数指定身份验证守卫

php
    'password' => 'current_password:api'

date

根据 strtotime PHP 函数,正在验证的字段必须是有效的非相对日期。

date_equals:date

正在验证的字段必须等于给定的日期。日期将被传递到 PHP strtotime 函数中,以便转换为有效的 DateTime 实例。

date_format:format,...

正在验证的字段必须与给定格式之一匹配。验证字段时,应使用datedate_format,而不是同时使用两者。此验证规则支持 PHP 的 DateTime 类支持的所有格式。

decimal:min,max

验证的字段必须是数字,并且必须包含指定的小数位数:

php
    // Must have exactly two decimal places (9.99)...
    'price' => 'decimal:2'
    
    // Must have between 2 and 4 decimal places...
    'price' => 'decimal:2,4'

declined

正在验证的字段必须为 “no”、“``off”0“0”false“false”。

declined_if:anotherfield,value,...

如果另一个正在验证的字段等于指定值,则正在验证的字段必须为 “no”、“``off”0“0”false“false”。

different:field

正在验证的 field 的值必须与 field 不同。

digits:value

正在验证的整数必须具有确切的 value 长度。

digits_between:min,max

整数验证的长度必须介于给定的 minmax 之间。

dimensions

正在验证的文件必须是满足规则参数指定的尺寸约束的图像:

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

可用约束包括:min_width, max_width, min_height, max_height, width, height, ratio.

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

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

由于这条规则需要几个参数,你可以使用 Rule::dimensions 方法流畅地构造规则:

php
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rule;
    
    Validator::make($data, [
        'avatar' => [
            'required',
            Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),
        ],
    ]);

distinct

验证数组时,正在验证的字段不得有任何重复值:

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

默认情况下,Distinct 使用松散变量比较。要使用严格比较,您可以将 strict 参数添加到验证规则定义中:

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

您可以向验证规则的参数添加ignore_case,以使规则忽略大小写差异:

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

doesnt_start_with:foo,bar,...

正在验证的字段不得以给定值之一开头。

doesnt_end_with:foo,bar,...

正在验证的字段不得以给定值之一结尾。

email

验证下的字段必须格式化为电子邮件地址。此验证规则利用 egulias/email-validator 包来验证电子邮件地址。默认情况下,将应用 RFCValidation 验证器,但您也可以应用其他验证样式:

php
    'email' => 'email:rfc,dns'

上面的示例将应用 RFCValidationDNSCheckValidation 验证。以下是您可以应用的验证样式的完整列表:

  • rfc: RFCValidation
  • strict: NoRFCWarningsValidation
  • dns: DNSCheckValidation
  • spoof: SpoofCheckValidation
  • filter: FilterEmailValidation
  • filter_unicode: FilterEmailValidation::unicode()

过滤器验证器使用 PHP 的 filter_var 函数,随 Laravel 一起提供,是 Laravel 5.8 版之前的 Laravel 默认电子邮件验证行为。

WARNING

dnsspoof 验证程序需要 PHP intl 扩展。

ends_with:foo,bar,...

正在验证的字段必须以给定值之一结尾。

enum

Enum 规则是基于类的规则,用于验证所验证的字段是否包含有效的枚举值。Enum 规则接受 enum 的名称作为其唯一的构造函数参数。在验证原始值时,应为 Enum 规则提供一个支持的 Enum

php
    use App\Enums\ServerStatus;
    use Illuminate\Validation\Rule;
    
    $request->validate([
        'status' => [Rule::enum(ServerStatus::class)],
    ]);

Enum 规则的 onlyexcept 方法可用于限制哪些枚举情况应被视为有效:

php
    Rule::enum(ServerStatus::class)
        ->only([ServerStatus::Pending, ServerStatus::Active]);
    
    Rule::enum(ServerStatus::class)
        ->except([ServerStatus::Pending, ServerStatus::Active]);

when 方法可用于有条件地修改 Enum 规则:

php
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;

Rule::enum(ServerStatus::class)
    ->when(
        Auth::user()->isAdmin(),
        fn ($rule) => $rule->only(...),
        fn ($rule) => $rule->only(...),
    );

exclude

正在验证的字段将从 validatevalidated 方法返回的请求数据中排除。

exclude_if:anotherfield,value

如果 anotherfield 字段等于 value,则 validate 和 validated 方法返回的请求数据中将排除 validation 下的字段。

如果需要复杂的条件排除逻辑,则可以使用 Rule::excludeIf 方法。此方法接受 boolean 或 closure。当给定一个闭包时,闭包应该返回 truefalse,以指示是否应该排除正在验证的字段:

php
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rule;
    
    Validator::make($request->all(), [
        'role_id' => Rule::excludeIf($request->user()->is_admin),
    ]);
    
    Validator::make($request->all(), [
        'role_id' => Rule::excludeIf(fn () => $request->user()->is_admin),
    ]);

exclude_unless:anotherfield,value

除非 anotherfield 的字段等于 value,否则 validate 和 validated 方法返回的请求数据中将排除正在验证的字段。如果 valuenullexclude_unless:name,null),则除非比较字段为 null 或请求数据中缺少比较字段,否则将排除正在验证的字段。

exclude_with:anotherfield

如果存在 anotherfield 字段,则 validate 和 validated 方法返回的请求数据中将排除 validation 下的字段。

exclude_without:anotherfield

如果 anotherfield 字段不存在,则 validate 和 validated 方法返回的请求数据中将排除 another field

exists:table,column

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

Exists 规则的基本用法

php
    'state' => 'exists:states'

如果未指定 column 选项,则将使用字段名称。因此,在这种情况下,规则将验证 states 数据库表是否包含一条记录,其 state 列值与请求的 state 属性值匹配。

指定自定义列名称

您可以通过将 数据表列名放在表名之后来显式指定验证规则应该使用的列名:

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

有时,您可能需要指定要用于 exists 查询的特定数据库连接。您可以通过在 table name 前面加上连接名称来实现此目的:

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

除了直接指定表名,您还可以指定 Eloquent 模型,该模型应该用于确定表名:

php
    'user_id' => 'exists:App\Models\User,id'

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

php
    use Illuminate\Database\Query\Builder;
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rule;
    
    Validator::make($data, [
        'email' => [
            'required',
            Rule::exists('staff')->where(function (Builder $query) {
                return $query->where('account_id', 1);
            }),
        ],
    ]);

您可以通过提供列名作为 exists 方法的第二个参数来显式指定 Rule::exists 方法生成的 exists 规则应使用的数据库列名:

php
    'state' => Rule::exists('states', 'abbreviation'),

extensions:foo,bar,...

正在验证的文件必须具有与列出的扩展名之一对应的用户分配的扩展名:

php
    'photo' => ['required', 'extensions:jpg,png'],

WARNING

您绝不应仅依赖通过用户分配的扩展名来验证文件。此规则通常应始终与 mimesmimetypes 规则结合使用。

file

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

filled

正在验证的字段在存在时不能为空。

gt:field

正在验证的字段必须大于给定的字段。这两个字段的类型必须相同。字符串、数字、数组和文件使用与 size 规则相同的约定进行评估。

gte:field

正在验证的字段必须大于或等于给定的字段。这两个字段的类型必须相同。字符串、数字、数组和文件使用与 size 规则相同的约定进行评估。

hex_color

正在验证的字段必须包含十六进制格式的有效颜色值。

image

正在验证的文件必须是图像(jpg、jpeg、png、bmp、gif、svg 或 webp)。

in:foo,bar,...

正在验证的字段必须包含在给定的值列表中。由于此规则通常要求您内爆数组,因此可以使用 Rule::in 方法流畅地构造规则:

php
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rule;
    
    Validator::make($data, [
        'zones' => [
            'required',
            Rule::in(['first-zone', 'second-zone']),
        ],
    ]);

in 规则与 array 规则结合使用时,输入数组中的每个值都必须存在于提供给 in 规则的值列表中。在以下示例中,输入数组中的 LAS 机场代码无效,因为它不包含在提供给 in 规则的机场列表中:

php
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rule;
    
    $input = [
        'airports' => ['NYC', 'LAS'],
    ];
    
    Validator::make($input, [
        'airports' => [
            'required',
            'array',
        ],
        'airports.*' => Rule::in(['NYC', 'LIT']),
    ]);

in_array:anotherfield.*

正在验证的字段必须存在于另一个字段的值中。

integer

正在验证的字段必须为整数。

WARNING

此验证规则不验证输入是否为 “integer” 变量类型,只验证输入是否为 PHP 的 FILTER_VALIDATE_INT 规则接受的类型。如果您需要将输入验证为数字,请将此规则与数字验证规则结合使用。

ip

正在验证的字段必须是 IP 地址。

ipv4

正在验证的字段必须是 IPv4 地址。

ipv6

正在验证的字段必须是 IPv6 地址。

json

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

lt:field

正在验证的字段必须小于给定的字段。这两个字段的类型必须相同。字符串、数字、数组和文件使用与 size 规则相同的约定进行评估。

lte:field

正在验证的字段必须小于或等于给定字段。这两个字段的类型必须相同。字符串、数字、数组和文件使用与 size 规则相同的约定进行评估。

lowercase

正在验证的字段必须为小写。

list

正在验证的字段必须是列表数组。如果数组的键由从 0 到 count($array) - 1 的连续数字组成,则数组被视为列表。

mac_address

正在验证的字段必须是 MAC 地址。

max:value

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

max_digits:value

正在验证的整数必须具有最大长度

mimetypes:text/plain,...

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

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

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

mimes:foo,bar,...

正在验证的文件必须具有与列出的扩展名之一对应的 MIME 类型:

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

即使您只需要指定扩展名,此规则实际上也会通过读取文件的内容并猜测其 MIME 类型来验证文件的 MIME 类型。MIME 类型及其相应扩展名的完整列表可在以下位置找到:

https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

MIME Types and Extensions

此验证规则不验证 MIME 类型与用户分配给文件的扩展名之间的一致性。例如,mimes:png 验证规则会将包含有效 PNG 内容的文件视为有效的 PNG 图像,即使该文件名为 photo.txt。如果要验证用户分配的文件扩展名,可以使用 extensions 规则。

min:value

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

min_digits:value

正在验证的整数必须具有最小长度

multiple_of:value

正在验证的字段必须是值的倍数。

missing

输入数据中不得存在正在验证的字段。

missing_if:anotherfield,value,...

如果 anotherfield 字段等于任何,则 validation 中的字段不得存在。

missing_unless:anotherfield,value

除非 anotherfield 字段等于任何,否则 validation 中的字段不得存在。

missing_with:foo,bar,...

仅当存在任何其他指定字段,才不得存在正在验证的字段。

missing_with_all:foo,bar,...

仅当所有其他指定字段都存在,验证下的字段才不得存在。

not_in:foo,bar,...

正在验证的字段不得包含在给定的值列表中。Rule::notIn 方法可用于流畅地构造规则:

php
    use Illuminate\Validation\Rule;
    
    Validator::make($data, [
        'toppings' => [
            'required',
            Rule::notIn(['sprinkles', 'cherries']),
        ],
    ]);

not_regex:pattern

正在验证的字段不得与给定的正则表达式匹配。

在内部,此规则使用 PHP preg_match 函数。指定的模式应遵循 preg_match 要求的相同格式,因此还包括有效的分隔符。例如: 'email' => 'not_regex:/^.+$/i' .

WARNING

使用正则表达式 / not_regex模式时,可能需要使用数组而不是 |分隔符来指定验证规则,尤其是在正则表达式包含 | 字符时。

nullable

正在验证的字段可能为 null

numeric

正在验证的字段必须是数字

present

正在验证的字段必须存在于输入数据中。

present_if:anotherfield,value,...

如果 anotherfield 字段等于任何,则 validing 中的字段必须存在。

present_unless:anotherfield,value

除非 anotherfield 字段等于任何,否则必须存在正在验证的字段。

present_with:foo,bar,...

仅当存在任何其他指定字段,才能存在正在验证的字段。

present_with_all:foo,bar,...

仅当所有其他指定字段都存在,验证中的字段必须存在。

prohibited

正在验证的字段必须缺失或为空。如果字段满足以下条件之一,则该字段为“空”:

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

prohibited_if:anotherfield,value,...

如果 anotherfield 字段等于任何,则 validation 下的字段必须缺失或为空。如果字段满足以下条件之一,则该字段为“空”:

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

如果需要复杂的条件禁止逻辑,您可以使用 Rule::p rohibitedIf 方法。此方法接受 boolean 或 closure。当给定一个闭包时,闭包应该返回 truefalse,以指示是否应该禁止正在验证的字段:

php
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rule;
    
    Validator::make($request->all(), [
        'role_id' => Rule::prohibitedIf($request->user()->is_admin),
    ]);
    
    Validator::make($request->all(), [
        'role_id' => Rule::prohibitedIf(fn () => $request->user()->is_admin),
    ]);

prohibited_unless:anotherfield,value,...

除非 anotherfield 字段等于任何,否则正在验证的字段必须缺失或为空。如果字段满足以下条件之一,则该字段为“空”:

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

prohibits:anotherfield,...

如果验证中的字段未缺失或为空,则 anotherfield 中的所有字段都必须缺失或为空。如果字段满足以下条件之一,则该字段为“空”:

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

regex:pattern

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

在内部,此规则使用 PHP preg_match 函数。指定的模式应遵循 preg_match 所需的相同格式,因此还包括有效的分隔符。例如:'email' => 'regex:/^.+@.+$/i'

WARNING

使用正则表达式 / not_regex模式时,可能需要在数组中指定规则,而不是使用 | 分隔符,尤其是在正则表达式包含 | 字符时。

required

正在验证的字段必须存在于输入数据中,并且不能为空。如果字段满足以下条件之一,则该字段为“空”:

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

required_if:anotherfield,value,...

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

如果您想为 required_if 规则构建更复杂的条件,您可以使用 Rule::requiredIf 方法。此方法接受 boolean 或 closure。当传递一个闭包时,闭包应该返回 truefalse,以指示正在验证的字段是否是必需的:

php
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rule;
    
    Validator::make($request->all(), [
        'role_id' => Rule::requiredIf($request->user()->is_admin),
    ]);
    
    Validator::make($request->all(), [
        'role_id' => Rule::requiredIf(fn () => $request->user()->is_admin),
    ]);

required_if_accepted:anotherfield,...

如果 anotherfield 字段等于 “yes”、“``on”1“1”true“true”,则正在验证的字段必须存在且不为空。

required_if_declined:anotherfield,...

如果 anotherfield 字段等于 “no”、“``off”0“0”、false“false”,则正在验证的字段必须存在且不``为空。

required_unless:anotherfield,value,...

正在验证的字段必须存在且不能为空,除非 anotherfield 字段等于任何。这也意味着请求数据中必须存在另一个字段,除非 valuenull。如果 valuenullrequired_unless:name,null),则除非比较字段为 null 或请求数据中缺少比较字段,否则将需要验证的字段。

required_with:foo,bar,...

正在验证的字段必须存在,并且仅当任何其他指定字段存在且不为空,该字段才不为空。

required_with_all:foo,bar,...

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

required_without:foo,bar,...

正在验证的字段必须存在,并且仅当任何其他指定字段为空或不存在才为空。

required_without_all:foo,bar,...

正在验证的字段必须存在,并且仅当所有其他指定字段为空或不存在才不为空。

required_array_keys:foo,bar,...

正在验证的字段必须是一个数组,并且必须至少包含指定的键。

same:field

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

size:value

正在验证的字段的大小必须与给定匹配。对于字符串数据,value 对应于字符数。对于数字数据,value 对应于给定的整数值(该属性还必须具有 numericinteger 规则)。对于数组,size 对应于数组的计数。对于文件,大小对应于文件大小(以 KB 为单位)。让我们看一些例子:

php
    // 验证字符串的长度是否正好为 12 个字符...
    'title' => 'size:12';
    
    // 验证提供的整数是否等于 10...
    'seats' => 'integer|size:10';
    
    // 验证数组是否恰好有 5 个元素...
    'tags' => 'array|size:5';
    
    // 验证上传的文件是否正好是 512 KB...
    'image' => 'file|size:512';

starts_with:foo,bar,...

正在验证的字段必须以给定值之一开头。

string

正在验证的字段必须为字符串。如果要允许字段也为 null,则应将可为 null 的规则分配给该字段。

timezone

根据 DateTimeZone::listIdentifiers 方法,正在验证的字段必须是有效的时区标识符。

DateTimeZone::listIdentifiers 方法接受 的参数也可以提供给此验证规则:

php
    'timezone' => 'required|timezone:all';
    
    'timezone' => 'required|timezone:Africa';
    
    'timezone' => 'required|timezone:per_country,US';

unique:table,column

正在验证的字段不得存在于给定的数据库表中。

Specifying a Custom Table / Column Name:

除了直接指定表名,您还可以指定 Eloquent 模型,该模型应该用于确定表名:

php
    'email' => 'unique:App\Models\User,email_address'

column 选项可用于指定字段的相应数据库列。如果未指定 column 选项,则将使用正在验证的字段的名称。

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

Specifying a Custom Database Connection

有时,您可能需要为 Validator 进行的数据库查询设置自定义连接。为此,您可以在表名前面加上连接名称:

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

Forcing a Unique Rule to Ignore a Given ID:

有时,您可能希望在唯一验证期间忽略给定的 ID。例如,考虑一个包含用户姓名、电子邮件地址和位置的 “update profile” 屏幕。您可能需要验证电子邮件地址是否唯一。但是,如果用户只更改 name 字段而不更改 email 字段,则您不希望引发验证错误,因为该用户已经是相关电子邮件地址的所有者。

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

php
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rule;
    
    Validator::make($data, [
        'email' => [
            'required',
            Rule::unique('users')->ignore($user->id),
        ],
    ]);

WARNING

您永远不应将任何用户控制的请求输入传递到 ignore 方法中。相反,您应该只传递系统生成的唯一 ID,例如来自 Eloquent 模型实例的自动递增 ID 或 UUID。否则,您的应用程序将容易受到 SQL 注入攻击。

除了将模型键的值传递给 ignore 方法外,你还可以传递整个模型实例。Laravel 会自动从模型中提取 key:

php
    Rule::unique('users')->ignore($user)

如果你的表使用了 id 以外的主键列名,你可以在调用 ignore 方法时指定列名:

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

默认情况下,unique规则将检查与正在验证的属性的名称匹配的列的唯一性。但是,您可以将不同的列名作为第二个参数传递给 unique 方法:

php
    Rule::unique('users', 'email_address')->ignore($user->id)

Adding Additional Where Clauses:

您可以通过使用 where 方法自定义查询来指定其他查询条件。例如,让我们添加一个查询条件,将查询范围限定为仅搜索 account_id 列值为 1 的记录:

php
    'email' => Rule::unique('users')->where(fn (Builder $query) => $query->where('account_id', 1))

uppercase

验证下的字段必须为大写。

url

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

如果您想指定应被视为有效的 URL 协议,您可以将协议作为验证规则参数传递:

php
'url' => 'url:http,https',

'game' => 'url:minecraft,steam',

ulid

正在验证的字段必须是有效的通用唯一字典排序标识符 (ULID)。

uuid

正在验证的字段必须是有效的 RFC 4122(版本 1、3、4 或 5)通用唯一标识符 (UUID)。

有条件地添加规则

当字段具有特定值时跳过验证

如果另一个字段具有给定值,则有时可能希望不验证给定字段。您可以使用 exclude_if 验证规则来完成此操作。在此示例中,如果 has_appointment 字段的值为 false,则不会验证 appointment_date 和 doctor_name 字段:

php
    use Illuminate\Support\Facades\Validator;
    
    $validator = Validator::make($data, [
        'has_appointment' => 'required|boolean',
        'appointment_date' => 'exclude_if:has_appointment,false|required|date',
        'doctor_name' => 'exclude_if:has_appointment,false|required|string',
    ]);

或者,您可以使用 exclude_unless 规则不验证给定字段,除非另一个字段具有给定值:

php
    $validator = Validator::make($data, [
        'has_appointment' => 'required|boolean',
        'appointment_date' => 'exclude_unless:has_appointment,true|required|date',
        'doctor_name' => 'exclude_unless:has_appointment,true|required|string',
    ]);

在存在时进行验证

在某些情况下,您可能希望仅在正在验证的数据中存在该字段时才对该字段运行验证检查。要快速完成此操作,请将 sometimes 规则添加到您的规则列表中:

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

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

NOTE

如果您尝试验证一个应该始终存在但可能为空的字段,请查看此 可选字段说明

复杂条件验证

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

php
    use Illuminate\Support\Facades\Validator;
    
    $validator = Validator::make($request->all(), [
        'email' => 'required|email',
        'games' => 'required|numeric',
    ]);

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

php
    use Illuminate\Support\Fluent;
    
    $validator->sometimes('reason', 'required|max:500', function (Fluent $input) {
        return $input->games >= 100;
    });

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

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

NOTE

传递给你的 Closure$input 参数将是 Illuminate\Support\Fluent 的实例,可用于访问你的输入和正在验证的文件。

复杂条件数组验证

有时,您可能希望基于您不知道其索引的同一嵌套数组中的另一个字段来验证字段。在这些情况下,你可以允许你的闭包接收第二个参数,该参数将是正在验证的数组中的当前单个项目:

php
    $input = [
        'channels' => [
            [
                'type' => 'email',
                'address' => 'abigail@example.com',
            ],
            [
                'type' => 'url',
                'address' => 'https://example.com',
            ],
        ],
    ];
    
    $validator->sometimes('channels.*.address', 'email', function (Fluent $input, Fluent $item) {
        return $item->type === 'email';
    });
    
    $validator->sometimes('channels.*.address', 'url', function (Fluent $input, Fluent $item) {
        return $item->type !== 'email';
    });

与传递给闭包的 $input 参数一样,当属性数据为数组时,$item 参数是 Illuminate\Support\Fluent 的实例;否则,它是一个字符串。

验证数组

数组 验证规则文档中所述,数组规则接受允许的数组键列表。如果数组中存在任何其他键,则验证将失败:

php
    use Illuminate\Support\Facades\Validator;
    
    $input = [
        'user' => [
            'name' => 'Taylor Otwell',
            'username' => 'taylorotwell',
            'admin' => true,
        ],
    ];
    
    Validator::make($input, [
        'user' => 'array:name,username',
    ]);

通常,您应该始终指定允许存在于数组中的数组键。否则,验证器的 validatevalidated 方法将返回所有已验证的数据,包括数组及其所有键,即使这些键未由其他嵌套数组验证规则验证。

验证嵌套数组输入

验证基于嵌套数组的表单输入字段并不一定很痛苦。您可以使用 “点表示法” 来验证数组中的属性。例如,如果传入的 HTTP 请求包含 photos[profile] 字段,您可以像这样验证它:

php
    use Illuminate\Support\Facades\Validator;
    
    $validator = Validator::make($request->all(), [
        'photos.profile' => 'required|image',
    ]);

您还可以验证数组的每个元素。例如,要验证给定数组输入字段中的每封电子邮件是否唯一,您可以执行以下操作:

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

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

php
    'custom' => [
        'person.*.email' => [
            'unique' => 'Each person must have a unique email address',
        ]
    ],

访问嵌套数组数据

有时,在为属性分配验证规则时,您可能需要访问给定嵌套数组元素的值。您可以使用 Rule::forEach 方法完成此操作。forEach 方法接受一个闭包,该闭包将在验证中为 array 属性的每次迭代调用,并将接收该属性的值和显式的、完全扩展的属性名称。闭包应返回一个规则数组以分配给数组元素:

php
    use App\Rules\HasPermission;
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rule;
    
    $validator = Validator::make($request->all(), [
        'companies.*.id' => Rule::forEach(function (string|null $value, string $attribute) {
            return [
                Rule::exists(Company::class, 'id'),
                new HasPermission('manage-company', $value),
            ];
        }),
    ]);

错误消息索引和位置

验证数组时,您可能希望在应用程序显示的错误消息中引用验证失败的特定项目的索引或位置。为此,您可以在自定义验证消息中包含 :index(从 0 开始)和 :p osition(从 1 开始)占位符:

php
    use Illuminate\Support\Facades\Validator;
    
    $input = [
        'photos' => [
            [
                'name' => 'BeachVacation.jpg',
                'description' => 'A photo of my beach vacation!',
            ],
            [
                'name' => 'GrandCanyon.jpg',
                'description' => '',
            ],
        ],
    ];
    
    Validator::validate($input, [
        'photos.*.description' => 'required',
    ], [
        'photos.*.description.required' => 'Please describe photo #:position.',
    ]);

鉴于上面的示例,验证将失败,并且用户将看到以下错误“请描述照片 #2”

如有必要,您可以通过 second-indexsecond-positionthird-indexthird-position 等方式引用嵌套更深的索引和位置。

php
    'photos.*.attributes.*.string' => 'Invalid attribute for photo #:second-position.',

验证文件

Laravel 提供了多种可用于验证上传文件的验证规则,例如 mimesimageminmax。虽然您可以在验证文件时自由地单独指定这些规则,但 Laravel 还提供了一个 Fluent 文件验证规则构建器,您可能会觉得很方便:

php
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rules\File;
    
    Validator::validate($input, [
        'attachment' => [
            'required',
            File::types(['mp3', 'wav'])
                ->min(1024)
                ->max(12 * 1024),
        ],
    ]);

如果您的应用程序接受用户上传的图像,则可以使用 File 规则的 image 构造函数方法来指示上传的文件应为图像。此外,dimensions 规则可用于限制图像的尺寸:

php
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rule;
    use Illuminate\Validation\Rules\File;
    
    Validator::validate($input, [
        'photo' => [
            'required',
            File::image()
                ->min(1024)
                ->max(12 * 1024)
                ->dimensions(Rule::dimensions()->maxWidth(1000)->maxHeight(500)),
        ],
    ]);

NOTE

有关验证图像尺寸的更多信息,请参阅尺寸规则文档

文件大小

为方便起见,可以将最小和最大文件大小指定为字符串,后缀表示文件大小单位。支持 kbmbgbtb 后缀:

php
File::image()
    ->min('1kb')
    ->max('10mb')

文件类型

尽管您只需要在调用 types 方法时指定扩展名,但此方法实际上通过读取文件的内容并猜测其 MIME 类型来验证文件的 MIME 类型。MIME 类型及其相应扩展名的完整列表可在以下位置找到:

https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

验证密码

为了确保密码具有足够的复杂程度,你可以使用 Laravel 的 Password 规则对象:

php
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Validation\Rules\Password;
    
    $validator = Validator::make($request->all(), [
        'password' => ['required', 'confirmed', Password::min(8)],
    ]);

Password 规则对象允许您轻松自定义应用程序的密码复杂性要求,例如指定密码至少需要一个字母、数字、符号或混合大小写的字符

php
    // 至少需要 8 个字符...
    Password::min(8)
    
    //  至少需要一个字母...
    Password::min(8)->letters()
    
    // 至少需要一个大写字母和一个小写字母...
    Password::min(8)->mixedCase()
    
    // 至少需要一个数字...
    Password::min(8)->numbers()
    
    // 至少需要一个symbol...
    Password::min(8)->symbols()

此外,您可以使用未泄露的方法确保密码未在公共密码数据泄露中泄露:

php
    Password::min(8)->uncompromised()

在内部,Password 规则对象使用 k-Anonymity 模型来确定密码是否已通过 haveibeenpwned.com 服务泄露,而不会牺牲用户的隐私或安全性。

默认情况下,如果密码在数据泄露中至少出现一次,则视为已泄露。您可以使用 uncompromised 方法的第一个参数自定义此阈值:

php
    // 确保密码在同一数据泄漏中出现的次数少于 3 次...
    Password::min(8)->uncompromised(3);

当然,你可以链接上面示例中的所有方法:

php
    Password::min(8)
        ->letters()
        ->mixedCase()
        ->numbers()
        ->symbols()
        ->uncompromised()

定义默认密码规则

您可能会发现在应用程序的单个位置为密码指定默认验证规则很方便。您可以使用 Password::d efaults 方法轻松完成此操作,该方法接受闭包。为 defaults 方法提供的闭包应返回 Password 规则的默认配置。通常,应在应用程序的某个服务提供商的 boot 方法中调用 defaults 规则:

php
use Illuminate\Validation\Rules\Password;

/**
 * 引导任何应用程序服务
 */
public function boot(): void
{
    Password::defaults(function () {
        $rule = Password::min(8);

        return $this->app->isProduction()
                    ? $rule->mixedCase()->uncompromised()
                    : $rule;
    });
}

然后,当你想将 default 规则应用于正在验证的特定密码时,你可以调用不带参数的 defaults 方法:

php
    'password' => ['required', Password::defaults()],

有时,您可能希望将其他验证规则附加到默认密码验证规则。您可以使用 rules 方法完成此操作:

php
    use App\Rules\ZxcvbnRule;
    
    Password::defaults(function () {
        $rule = Password::min(8)->rules([new ZxcvbnRule]);
    
        // ...
    });

自定义验证规则

使用规则对象

Laravel 提供了各种有用的验证规则;但是,您可能希望指定一些自己的。注册自定义验证规则的一种方法是使用规则对象。要生成新的规则对象,您可以使用 make:rule Artisan 命令。让我们使用此命令生成一个规则,以验证字符串是否为大写。Laravel 会将新规则放在 app/Rules 目录中。如果此目录不存在,Laravel 将在您执行 Artisan 命令创建规则时创建它:

shell
php artisan make:rule Uppercase

创建规则后,我们就可以定义其行为了。规则对象包含一个方法:validate。此方法接收属性名称、其值和应在失败时调用的回调,并显示验证错误消息:

php
    <?php
    
    namespace App\Rules;
    
    use Closure;
    use Illuminate\Contracts\Validation\ValidationRule;
    
    class Uppercase implements ValidationRule
    {
        /**
         * 运行验证规则
         */
        public function validate(string $attribute, mixed $value, Closure $fail): void
        {
            if (strtoupper($value) !== $value) {
                $fail('The :attribute must be uppercase.');
            }
        }
    }

定义规则后,您可以通过将 rule 对象的实例与其他验证规则一起传递给验证器,将其附加到验证器:

php
    use App\Rules\Uppercase;
    
    $request->validate([
        'name' => ['required', 'string', new Uppercase],
    ]);

翻译验证消息

除了向 $fail 闭包提供文字错误消息外,您还可以提供翻译字符串 key 并指示 Laravel 翻译错误消息:

php
    if (strtoupper($value) !== $value) {
        $fail('validation.uppercase')->translate();
    }

如有必要,你可以提供占位符替换和首选语言作为 translate 方法的第一个和第二个参数:

php
    $fail('validation.location')->translate([
        'value' => $this->value,
    ], 'fr')

访问其他数据

如果您的自定义验证规则类需要访问所有其他正在验证的数据,则您的规则类可以实现该 Illuminate\Contracts\Validation\DataAwareRule 接口。此接口要求您的类定义 setData 方法。Laravel 将自动调用此方法(在验证继续之前),所有数据都在验证中:

php
    <?php
    
    namespace App\Rules;
    
    use Illuminate\Contracts\Validation\DataAwareRule;
    use Illuminate\Contracts\Validation\ValidationRule;
    
    class Uppercase implements DataAwareRule, ValidationRule
    {
        /**
         * 所有数据都在验证中
         *
         * @var array<string, mixed>
         */
        protected $data = [];
    
        // ...
    
        /**
         * 设置验证数据
         *
         * @param  array<string, mixed>  $data
         */
        public function setData(array $data): static
        {
            $this->data = $data;
    
            return $this;
        }
    }

或者,如果你的验证规则需要访问执行验证的验证者实例,你可以实现 ValidatorAwareRule 接口:

php
    <?php
    
    namespace App\Rules;
    
    use Illuminate\Contracts\Validation\ValidationRule;
    use Illuminate\Contracts\Validation\ValidatorAwareRule;
    use Illuminate\Validation\Validator;
    
    class Uppercase implements ValidationRule, ValidatorAwareRule
    {
        /**
         * 验证实例
         *
         * @var \Illuminate\Validation\Validator
         */
        protected $validator;
    
        // ...
    
        /**
         * 设置当前验证
         */
        public function setValidator(Validator $validator): static
        {
            $this->validator = $validator;
    
            return $this;
        }
    }

使用闭包

如果在整个应用程序中只需要一次自定义规则的功能,则可以使用闭包而不是 rule 对象。闭包接收属性的名称、属性的值以及验证失败时应调用的 $fail 回调:

php
    use Illuminate\Support\Facades\Validator;
    use Closure;
    
    $validator = Validator::make($request->all(), [
        'title' => [
            'required',
            'max:255',
            function (string $attribute, mixed $value, Closure $fail) {
                if ($value === 'foo') {
                    $fail("The {$attribute} is invalid.");
                }
            },
        ],
    ]);

隐式规则

默认情况下,当正在验证的属性不存在或包含空字符串时,不会运行常规验证规则(包括自定义规则)。例如,唯一规则不会针对空字符串运行:

php
    use Illuminate\Support\Facades\Validator;
    
    $rules = ['name' => 'unique:users,name'];
    
    $input = ['name' => ''];
    
    Validator::make($input, $rules)->passes(); // true

要使自定义规则即使在属性为空时也运行,该规则必须暗示该属性是必需的。要快速生成新的隐式规则对象,您可以使用带有 --implicit 选项的 make:rule Artisan 命令:

shell
php artisan make:rule Uppercase --implicit

WARNING

“隐式”规则仅表示该属性是必需的。它是否真的使缺失或空的属性无效取决于您。