验证
简介
Laravel 提供了几种不同的方法来验证应用程序的传入数据。最常见的是使用所有传入 HTTP 请求中可用的 validate
方法。但是,我们也将讨论其他验证方法。
Laravel 包含各种方便的验证规则,你可以应用于数据,甚至可以验证值在给定数据库表中是否唯一。我们将详细介绍每个验证规则,以便你熟悉 Laravel 的所有验证功能。
验证快速入门
要了解 Laravel 强大的验证功能,让我们看一个验证表单并向用户显示错误消息的完整示例。通过阅读此高级概述,你将能够很好地理解如何使用 Laravel 验证传入的请求数据。
定义路由
首先,让我们假设我们在 routes/web.php
文件中定义了以下路由。
use App\Http\Controllers\PostController; Route::get('/post/create', [PostController::class, 'create']);Route::post('/post', [PostController::class, 'store']);
GET
路由将显示一个表单,供用户创建新的博客文章,而 POST
路由将新的博客文章存储到数据库中。
创建控制器
接下来,让我们看一下处理这些路由的传入请求的简单控制器。我们现在将 store
方法留空。
<?php namespace App\Http\Controllers; use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request;use Illuminate\View\View; class PostController extends Controller{ /** * Show the form to create a new blog post. */ public function create(): View { return view('post.create'); } /** * Store a new blog post. */ public function store(Request $request): RedirectResponse { // Validate and store the blog post... $post = /** ... */ return to_route('post.show', ['post' => $post->id]); }}
编写验证逻辑
现在我们准备用验证新博客文章的逻辑填充 store
方法。为此,我们将使用 Illuminate\Http\Request
对象提供的 validate
方法。如果验证规则通过,你的代码将继续正常执行;但是,如果验证失败,将抛出 Illuminate\Validation\ValidationException
异常,并且将自动向用户发送正确的错误响应。
如果在传统的 HTTP 请求期间验证失败,则会生成一个重定向响应到上一个 URL。如果传入的请求是 XHR 请求,则将返回一个 包含验证错误消息的 JSON 响应。
为了更好地理解 validate
方法,让我们回到 store
方法。
/** * Store a new blog post. */public function store(Request $request): RedirectResponse{ $validated = $request->validate([ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]); // The blog post is valid... return redirect('/posts');}
如你所见,验证规则传递给 validate
方法。不用担心 - 所有可用的验证规则都已 记录。同样,如果验证失败,将自动生成正确的响应。如果验证通过,我们的控制器将继续正常执行。
或者,验证规则可以指定为规则数组,而不是单个用 |
分隔的字符串。
$validatedData = $request->validate([ 'title' => ['required', 'unique:posts', 'max:255'], 'body' => ['required'],]);
此外,你可以使用 validateWithBag
方法验证请求并将任何错误消息存储到 命名错误包 中。
$validatedData = $request->validateWithBag('post', [ 'title' => ['required', 'unique:posts', 'max:255'], 'body' => ['required'],]);
在第一次验证失败时停止
有时你可能希望在第一次验证失败后停止对属性运行验证规则。为此,将 bail
规则分配给属性。
$request->validate([ 'title' => 'bail|required|unique:posts|max:255', 'body' => 'required',]);
在此示例中,如果 title
属性上的 unique
规则失败,则不会检查 max
规则。规则将按分配的顺序进行验证。
关于嵌套属性的说明
如果传入的 HTTP 请求包含“嵌套”字段数据,则可以使用“点”语法在验证规则中指定这些字段。
$request->validate([ 'title' => 'required|unique:posts|max:255', 'author.name' => 'required', 'author.description' => 'required',]);
另一方面,如果你的字段名称包含文字句点,则可以通过使用反斜杠转义句点来明确防止将其解释为“点”语法。
$request->validate([ 'title' => 'required|unique:posts|max:255', 'v1\.0' => 'required',]);
显示验证错误
那么,如果传入的请求字段未通过给定的验证规则会发生什么?如前所述,Laravel 将自动将用户重定向到他们之前的位置。此外,所有验证错误和 请求输入 将自动 闪存到会话 中。
$errors
变量由 Illuminate\View\Middleware\ShareErrorsFromSession
中间件与应用程序的所有视图共享,该中间件由 web
中间件组提供。当应用此中间件时,$errors
变量将始终在你的视图中可用,允许你方便地假设 $errors
变量始终已定义并且可以安全使用。$errors
变量将是 Illuminate\Support\MessageBag
的实例。有关使用此对象的更多信息,请 查看其文档。
因此,在我们的示例中,当验证失败时,用户将被重定向到控制器的 create
方法,允许我们在视图中显示错误消息。
<!-- /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 本地化的更多信息,请查看完整的 本地化文档。
默认情况下,Laravel 应用程序骨架不包含 lang
目录。如果你想自定义 Laravel 的语言文件,可以通过 lang:publish
Artisan 命令发布它们。
XHR 请求和验证
在此示例中,我们使用传统表单将数据发送到应用程序。但是,许多应用程序从 JavaScript 驱动的前端接收 XHR 请求。在 XHR 请求期间使用 validate
方法时,Laravel 不会生成重定向响应。相反,Laravel 生成一个 包含所有验证错误的 JSON 响应。此 JSON 响应将发送带有 422 HTTP 状态代码。
@error
指令
你可以使用 @error
Blade 指令快速确定给定属性是否存在验证错误消息。在 @error
指令中,你可以回显 $message
变量以显示错误消息。
<!-- /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
指令。
<input ... class="@error('title', 'post') is-invalid @enderror">
重新填充表单
当 Laravel 由于验证错误生成重定向响应时,框架将自动 将所有请求的输入闪存到会话 中。这样做是为了让你能够在下一个请求期间方便地访问输入并重新填充用户尝试提交的表单。
要从上一个请求中检索闪存的输入,请在 Illuminate\Http\Request
的实例上调用 old
方法。old
方法将从 会话 中提取之前闪存的输入数据。
$title = $request->old('title');
Laravel 还提供了一个全局的 old
辅助函数。如果您在 Blade 模板 中显示旧输入,使用 old
辅助函数重新填充表单会更加方便。如果给定字段不存在旧输入,则会返回 null
。
<input type="text" name="title" value="{{ old('title') }}">
关于可选字段的说明
默认情况下,Laravel 在应用程序的全局中间件栈中包含 TrimStrings
和 ConvertEmptyStringsToNull
中间件。因此,如果您不希望验证器将 null
值视为无效值,则通常需要将“可选”请求字段标记为 nullable
。例如:
$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 响应格式示例。请注意,嵌套错误键会展平为“点”表示法格式。
{ "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 命令。
php artisan make:request StorePostRequest
生成的表单请求类将放置在 app/Http/Requests
目录中。如果此目录不存在,则在运行 make:request
命令时会创建它。Laravel 生成的每个表单请求都有两种方法:authorize
和 rules
。
正如您可能猜到的,authorize
方法负责确定当前已认证的用户是否可以执行请求表示的操作,而 rules
方法返回应应用于请求数据的验证规则。
/** * Get the validation rules that apply to the request. * * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string> */public function rules(): array{ return [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ];}
您可以在 rules
方法的签名中类型提示您需要的任何依赖项。它们将通过 Laravel 服务容器 自动解析。
那么,验证规则是如何评估的呢?您只需在控制器方法中类型提示请求即可。在调用控制器方法之前会验证传入的表单请求,这意味着您无需在控制器中添加任何验证逻辑。
/** * Store a new blog post. */public function store(StorePostRequest $request): RedirectResponse{ // The incoming request is valid... // Retrieve the validated input data... $validated = $request->validated(); // Retrieve a portion of the validated input data... $validated = $request->safe()->only(['name', 'email']); $validated = $request->safe()->except(['name', 'email']); // Store the blog post... return redirect('/posts');}
如果验证失败,将生成重定向响应以将用户发送回其先前的位置。错误也将闪存到会话中,以便可以显示它们。如果请求是 XHR 请求,则会向用户返回 HTTP 响应,状态代码为 422,其中包含 验证错误的 JSON 表示形式。
需要将实时表单请求验证添加到您的 Inertia 驱动的 Laravel 前端?查看 Laravel 预知。
执行其他验证
有时您需要在初始验证完成后执行其他验证。您可以使用表单请求的 after
方法来实现此目的。
after
方法应返回一个可调用对象或闭包数组,这些对象或闭包将在验证完成后被调用。给定的可调用对象将接收一个 Illuminate\Validation\Validator
实例,允许您在必要时引发其他错误消息。
use Illuminate\Validation\Validator; /** * Get the "after" validation callables for the request. */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
实例。
use App\Validation\ValidateShippingTime;use App\Validation\ValidateUserStatus;use Illuminate\Validation\Validator; /** * Get the "after" validation callables for the request. */public function after(): array{ return [ new ValidateUserStatus, new ValidateShippingTime, function (Validator $validator) { // } ];}
在第一个验证失败时停止
通过向您的请求类添加 stopOnFirstFailure
属性,您可以告知验证器,一旦发生单个验证失败,它应该停止验证所有属性。
/** * Indicates if the validator should stop on the first rule failure. * * @var bool */protected $stopOnFirstFailure = true;
自定义重定向位置
如前所述,当表单请求验证失败时,将生成重定向响应以将用户发送回其先前的位置。但是,您可以自由自定义此行为。为此,请在您的表单请求中定义一个 $redirect
属性。
/** * The URI that users should be redirected to if validation fails. * * @var string */protected $redirect = '/dashboard';
或者,如果您希望将用户重定向到命名路由,则可以改为定义 $redirectRoute
属性。
/** * The route that users should be redirected to if validation fails. * * @var string */protected $redirectRoute = 'dashboard';
授权表单请求
表单请求类还包含一个 authorize
方法。在此方法中,您可以确定已认证的用户是否真正有权更新给定的资源。例如,您可以确定用户是否真正拥有他们尝试更新的博客评论。最有可能的是,您将在此方法中与您的 授权门和策略 进行交互。
use App\Models\Comment; /** * Determine if the user is authorized to make this request. */public function authorize(): bool{ $comment = Comment::find($this->route('comment')); return $comment && $this->user()->can('update', $comment);}
由于所有表单请求都扩展了基本的 Laravel 请求类,因此我们可以使用 user
方法访问当前已认证的用户。另外,请注意上面示例中对 route
方法的调用。此方法允许您访问正在调用的路由上定义的 URI 参数,例如以下示例中的 {comment}
参数。
Route::post('/comment/{comment}');
因此,如果您的应用程序正在利用 路由模型绑定,则可以通过将解析的模型作为请求的属性来访问,从而使您的代码更加简洁。
return $this->user()->can('update', $this->comment);
如果 authorize
方法返回 false
,则会自动返回状态代码为 403 的 HTTP 响应,并且您的控制器方法不会执行。
如果您计划在应用程序的其他部分处理请求的授权逻辑,则可以完全删除 authorize
方法,或者只返回 true
。
/** * Determine if the user is authorized to make this request. */public function authorize(): bool{ return true;}
您可以在 authorize
方法的签名中类型提示您需要的任何依赖项。它们将通过 Laravel 服务容器 自动解析。
自定义错误消息
您可以通过覆盖 messages
方法来自定义表单请求使用的错误消息。此方法应返回属性/规则对及其对应的错误消息数组。
/** * Get the error messages for the defined validation rules. * * @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
方法来指定自定义名称。此方法应返回属性/名称对数组。
/** * Get custom attributes for validator errors. * * @return array<string, string> */public function attributes(): array{ return [ 'email' => 'email address', ];}
准备输入以进行验证
如果您需要在应用验证规则之前准备或清理请求中的任何数据,则可以使用 prepareForValidation
方法。
use Illuminate\Support\Str; /** * Prepare the data for validation. */protected function prepareForValidation(): void{ $this->merge([ 'slug' => Str::slug($this->slug), ]);}
同样,如果您需要在验证完成后规范化任何请求数据,则可以使用 passedValidation
方法。
/** * Handle a passed validation attempt. */protected function passedValidation(): void{ $this->replace(['name' => 'Taylor']);}
手动创建验证器
如果您不想在请求上使用 validate
方法,则可以使用 Validator
外观 手动创建验证器实例。外观上的 make
方法生成一个新的验证器实例。
<?php namespace App\Http\Controllers; use Illuminate\Http\RedirectResponse;use Illuminate\Http\Request;use Illuminate\Support\Facades\Validator; class PostController extends Controller{ /** * Store a new blog post. */ 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(); } // Retrieve the validated input... $validated = $validator->validated(); // Retrieve a portion of the validated input... $validated = $validator->safe()->only(['name', 'email']); $validated = $validator->safe()->except(['name', 'email']); // Store the blog post... return redirect('/posts'); }}
传递给 make
方法的第一个参数是要验证的数据。第二个参数是要应用于数据的验证规则数组。
在确定请求验证是否失败后,您可以使用 withErrors
方法将错误消息闪存到会话中。使用此方法时,$errors
变量会在重定向后自动与您的视图共享,使您可以轻松地将它们显示回用户。withErrors
方法接受验证器、MessageBag
或 PHP 数组
。
在第一次验证失败时停止
stopOnFirstFailure
方法将告知验证器,一旦发生单个验证失败,它应该停止验证所有属性。
if ($validator->stopOnFirstFailure()->fails()) { // ...}
自动重定向
如果您想手动创建验证器实例,但仍想利用 HTTP 请求的 validate
方法提供的自动重定向功能,则可以在现有的验证器实例上调用 validate
方法。如果验证失败,用户将自动被重定向,或者在 XHR 请求的情况下,将返回 JSON 响应。
Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required',])->validate();
您可以使用 validateWithBag
方法将错误消息存储在 命名错误包 中(如果验证失败)。
Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required',])->validateWithBag('post');
命名错误包
如果在一个页面上有多个表单,您可能希望命名包含验证错误的 MessageBag
,以便您可以检索特定表单的错误消息。要实现此目的,请将名称作为第二个参数传递给 withErrors
。
return redirect('/register')->withErrors($validator, 'login');
然后,您可以从 $errors
变量中访问命名 MessageBag
实例。
{{ $errors->login->first('email') }}
自定义错误消息
如果需要,您可以提供验证器实例应使用的自定义错误消息,而不是 Laravel 提供的默认错误消息。有几种方法可以指定自定义消息。首先,您可以将自定义消息作为第三个参数传递给 Validator::make
方法。
$validator = Validator::make($input, $rules, $messages = [ 'required' => 'The :attribute field is required.',]);
在此示例中,:attribute
占位符将被正在验证的字段的实际名称替换。您也可以在验证消息中使用其他占位符。例如:
$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',];
为给定属性指定自定义消息
有时您可能希望仅为特定属性指定自定义错误消息。您可以使用“点”表示法来做到这一点。首先指定属性的名称,然后指定规则。
$messages = [ 'email.required' => 'We need to know your email address!',];
指定自定义属性值
Laravel 的许多内置错误消息都包含一个 :attribute
占位符,该占位符将替换为正在验证的字段或属性的名称。要自定义用于替换特定字段的这些占位符的值,您可以将自定义属性数组作为第四个参数传递给 Validator::make
方法。
$validator = Validator::make($input, $rules, $messages, [ 'email' => 'email address',]);
执行其他验证
有时您需要在初始验证完成后执行其他验证。您可以使用验证器的 after
方法来实现此目的。after
方法接受一个闭包或可调用对象数组,这些对象或闭包将在验证完成后被调用。给定的可调用对象将接收一个 Illuminate\Validation\Validator
实例,允许您在必要时引发其他错误消息。
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
方法还接受可调用对象数组,如果您将“验证后”逻辑封装在可调用类中,这尤其方便,这些类将通过其 __invoke
方法接收 Illuminate\Validation\Validator
实例。
use App\Validation\ValidateShippingTime;use App\Validation\ValidateUserStatus; $validator->after([ new ValidateUserStatus, new ValidateShippingTime, function ($validator) { // ... },]);
使用已验证的输入
使用表单请求或手动创建的验证器实例验证传入的请求数据后,您可能希望检索实际经过验证的传入请求数据。这可以通过多种方式实现。首先,您可以在表单请求或验证器实例上调用 validated
方法。此方法返回已验证数据的数组。
$validated = $request->validated(); $validated = $validator->validated();
或者,您可以在表单请求或验证器实例上调用 safe
方法。此方法返回 Illuminate\Support\ValidatedInput
的实例。此对象公开了 only
、except
和 all
方法以检索已验证数据的子集或已验证数据的整个数组。
$validated = $request->safe()->only(['name', 'email']); $validated = $request->safe()->except(['name', 'email']); $validated = $request->safe()->all();
此外,可以像数组一样迭代和访问 Illuminate\Support\ValidatedInput
实例。
// Validated data may be iterated...foreach ($request->safe() as $key => $value) { // ...} // Validated data may be accessed as an array...$validated = $request->safe(); $email = $validated['email'];
如果您想将其他字段添加到已验证的数据中,则可以调用 merge
方法。
$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);
如果您想将已验证的数据作为 集合 实例检索,则可以调用 collect
方法。
$collection = $request->safe()->collect();
使用错误消息
在 Validator
实例上调用 errors
方法后,您将收到一个 Illuminate\Support\MessageBag
实例,该实例具有多种用于处理错误消息的便捷方法。自动提供给所有视图的 $errors
变量也是 MessageBag
类的实例。
检索字段的第一个错误消息
要检索给定字段的第一个错误消息,请使用first
方法
$errors = $validator->errors(); echo $errors->first('email');
检索字段的所有错误消息
如果需要检索给定字段的所有消息的数组,请使用get
方法
foreach ($errors->get('email') as $message) { // ...}
如果正在验证数组表单字段,可以使用*
字符检索每个数组元素的所有消息
foreach ($errors->get('attachments.*') as $message) { // ...}
检索所有字段的所有错误消息
要检索所有字段的所有消息的数组,请使用all
方法
foreach ($errors->all() as $message) { // ...}
确定字段是否存在消息
可以使用has
方法确定给定字段是否存在任何错误消息
if ($errors->has('email')) { // ...}
在语言文件中指定自定义消息
Laravel 的内置验证规则每个都有一个错误消息,该消息位于应用程序的 lang/en/validation.php
文件中。如果你的应用程序没有 lang
目录,则可以指示 Laravel 使用 lang:publish
Artisan 命令创建它。
在 lang/en/validation.php
文件中,你会找到每个验证规则的翻译条目。你可以根据应用程序的需要自由更改或修改这些消息。
此外,你可以将此文件复制到另一个语言目录以翻译应用程序语言的消息。要了解有关 Laravel 本地化的更多信息,请查看完整的 本地化文档。
默认情况下,Laravel 应用程序骨架不包含 lang
目录。如果你想自定义 Laravel 的语言文件,可以通过 lang:publish
Artisan 命令发布它们。
特定属性的自定义消息
可以在应用程序的验证语言文件中自定义用于指定属性和规则组合的错误消息。为此,请将您的消息自定义添加到应用程序lang/xx/validation.php
语言文件的custom
数组中
'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
数组中指定自定义属性名称
'attributes' => [ 'email' => 'email address',],
默认情况下,Laravel 应用程序骨架不包含 lang
目录。如果你想自定义 Laravel 的语言文件,可以通过 lang:publish
Artisan 命令发布它们。
在语言文件中指定值
Laravel 的一些内置验证规则错误消息包含一个:value
占位符,该占位符将替换为请求属性的当前值。但是,您可能偶尔需要将验证消息的:value
部分替换为值的自定义表示形式。例如,考虑以下规则,该规则指定如果payment_type
的值为cc
,则需要信用卡号
Validator::make($request->all(), [ 'credit_card_number' => 'required_if:payment_type,cc']);
如果此验证规则失败,它将产生以下错误消息
The credit card number field is required when payment type is cc.
而不是将cc
显示为支付类型值,可以在lang/xx/validation.php
语言文件中定义一个values
数组,以指定更友好的值表示形式
'values' => [ 'payment_type' => [ 'cc' => 'credit card' ],],
默认情况下,Laravel 应用程序骨架不包含 lang
目录。如果你想自定义 Laravel 的语言文件,可以通过 lang:publish
Artisan 命令发布它们。
定义此值后,验证规则将产生以下错误消息
The credit card number field is required when payment type is credit card.
可用的验证规则
以下是所有可用验证规则及其功能的列表
已接受 如果已接受 有效网址 之后(日期) 之后或等于(日期) 字母 字母和短划线 字母数字 数组 ASCII 终止 之前(日期) 之前或等于(日期) 介于之间 布尔值 已确认 包含 当前密码 日期 日期相等 日期格式 小数 已拒绝 如果已拒绝 不同 位数 位数介于之间 尺寸(图像文件) 唯一 不以开头 不以结尾 电子邮件 以结尾 枚举 排除 如果排除 除非排除 与排除 无排除 存在(数据库) 扩展名 文件 已填写 大于 大于或等于 十六进制颜色 图像(文件) 在…中 在数组中 整数 IP地址 JSON 小于 小于或等于 列表 小写 MAC地址 最大值 最大位数 MIME类型 根据文件扩展名获取MIME类型 最小值 最小位数 缺失 如果缺失 除非缺失 与缺失 与所有缺失 的倍数 不在…中 非正则表达式 可为空 数值 存在 如果存在 除非存在 与存在 与所有存在 禁止 如果禁止 除非禁止 禁止 正则表达式 必填 如果必填 如果已接受则必填 如果已拒绝则必填 除非必填 与必填 与所有必填 无必填 与所有无必填 必填数组键 相同 大小 有时 以开头 字符串 时区 唯一(数据库) 大写 网址 ULID UUID
已接受
正在验证的字段必须为"yes"
、"on"
、1
、"1"
、true
或"true"
。这对于验证“服务条款”接受或类似字段很有用。
accepted_if:anotherfield,value,...
如果正在验证的另一个字段等于指定值,则正在验证的字段必须为"yes"
、"on"
、1
、"1"
、true
或"true"
。这对于验证“服务条款”接受或类似字段很有用。
有效网址
根据dns_get_record
PHP 函数,正在验证的字段必须具有有效的 A 或 AAAA 记录。提供的 URL 的主机名在传递给dns_get_record
之前,使用parse_url
PHP 函数提取。
after:date
正在验证的字段必须是给定日期之后的值。日期将传递给strtotime
PHP 函数,以便转换为有效的DateTime
实例
'start_date' => 'required|date|after:tomorrow'
可以指定另一个字段来与日期进行比较,而不是传递要由strtotime
评估的日期字符串
'finish_date' => 'required|date|after:start_date'
after_or_equal:date
正在验证的字段必须是给定日期之后或等于给定日期的值。有关更多信息,请参阅after规则。
字母
正在验证的字段必须完全是包含在\p{L}
和\p{M}
中的 Unicode 字母字符。
要将此验证规则限制在 ASCII 范围内的字符(a-z
和A-Z
),可以向验证规则提供ascii
选项
'username' => 'alpha:ascii',
字母和短划线
正在验证的字段必须完全是包含在\p{L}
、\p{M}
、\p{N}
中的 Unicode 字母数字字符,以及 ASCII 短划线(-
)和 ASCII 下划线(_
)。
要将此验证规则限制在 ASCII 范围内的字符(a-z
和A-Z
),可以向验证规则提供ascii
选项
'username' => 'alpha_dash:ascii',
字母数字
正在验证的字段必须完全是包含在\p{L}
、\p{M}
和\p{N}
中的 Unicode 字母数字字符。
要将此验证规则限制在 ASCII 范围内的字符(a-z
和A-Z
),可以向验证规则提供ascii
选项
'username' => 'alpha_num:ascii',
数组
正在验证的字段必须是 PHP array
。
当向array
规则提供其他值时,输入数组中的每个键都必须存在于提供给规则的值列表中。在以下示例中,输入数组中的admin
键无效,因为它不包含在提供给array
规则的值列表中
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
规则仅在遇到验证失败时才会停止验证特定字段,但stopOnFirstFailure
方法将通知验证器,一旦发生单个验证失败,它应该停止验证所有属性
if ($validator->stopOnFirstFailure()->fails()) { // ...}
before:date
正在验证的字段必须是给定日期之前的值。日期将传递给 PHP strtotime
函数,以便转换为有效的DateTime
实例。此外,与after
规则一样,可以将正在验证的另一个字段的名称作为date
的值提供。
before_or_equal:date
正在验证的字段必须是给定日期之前或等于给定日期的值。日期将传递给 PHP strtotime
函数,以便转换为有效的DateTime
实例。此外,与after
规则一样,可以将正在验证的另一个字段的名称作为date
的值提供。
between:min,max
正在验证的字段的大小必须介于给定的min和max(包含)之间。字符串、数字、数组和文件以与size
规则相同的方式进行评估。
布尔值
正在验证的字段必须能够转换为布尔值。可接受的输入为true
、false
、1
、0
、"1"
和"0"
。
已确认
正在验证的字段必须具有匹配的{field}_confirmation
字段。例如,如果正在验证的字段为password
,则输入中必须存在匹配的password_confirmation
字段。
也可以传递自定义确认字段名称。例如,confirmed:repeat_username
将期望字段repeat_username
与正在验证的字段匹配。
contains:foo,bar,...
正在验证的字段必须是包含所有给定参数值的数组。
当前密码
正在验证的字段必须与已认证用户的密码匹配。可以使用规则的第一个参数指定身份验证守卫
'password' => 'current_password:api'
日期
正在验证的字段必须是根据strtotime
PHP 函数的有效非相对日期。
date_equals:date
正在验证的字段必须等于给定日期。日期将传递给 PHP strtotime
函数,以便转换为有效的DateTime
实例。
date_format:format,...
正在验证的字段必须与给定的format之一匹配。在验证字段时,应使用或date
或date_format
,而不是同时使用两者。此验证规则支持 PHP 的DateTime类支持的所有格式。
decimal:min,max
正在验证的字段必须是数字,并且必须包含指定的小数位数
// Must have exactly two decimal places (9.99)...'price' => 'decimal:2' // Must have between 2 and 4 decimal places...'price' => 'decimal:2,4'
已拒绝
正在验证的字段必须为"no"
、"off"
、0
、"0"
、false
或"false"
。
declined_if:anotherfield,value,...
如果正在验证的另一个字段等于指定值,则正在验证的字段必须为"no"
、"off"
、0
、"0"
、false
或"false"
。
different:field
正在验证的字段必须与field的值不同。
digits:value
待验证的整数必须具有精确长度 value。
digits_between:min,max
整数验证的长度必须介于给定的 min 和 max 之间。
尺寸
待验证的文件必须是符合规则参数指定的尺寸约束的图像。
'avatar' => 'dimensions:min_width=100,min_height=200'
可用的约束条件包括:min_width、max_width、min_height、max_height、width、height、ratio。
ratio 约束应表示为宽度除以高度。这可以通过分数(例如 3/2
)或浮点数(例如 1.5
)来指定。
'avatar' => 'dimensions:ratio=3/2'
由于此规则需要多个参数,您可以使用 Rule::dimensions
方法流畅地构建规则。
use Illuminate\Support\Facades\Validator;use Illuminate\Validation\Rule; Validator::make($data, [ 'avatar' => [ 'required', Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2), ],]);
distinct
验证数组时,待验证的字段不得包含任何重复值。
'foo.*.id' => 'distinct'
Distinct 默认使用宽松的变量比较。要使用严格比较,您可以将 strict
参数添加到验证规则定义中。
'foo.*.id' => 'distinct:strict'
您可以将 ignore_case
添加到验证规则的参数中,以使规则忽略大小写差异。
'foo.*.id' => 'distinct:ignore_case'
doesnt_start_with:foo,bar,...
待验证的字段不得以给定值中的任何一个开头。
doesnt_end_with:foo,bar,...
待验证的字段不得以给定值中的任何一个结尾。
待验证的字段必须格式化为电子邮件地址。此验证规则利用 egulias/email-validator
包来验证电子邮件地址。默认情况下,应用 RFCValidation
验证器,但您也可以应用其他验证样式。
'email' => 'email:rfc,dns'
上面的示例将应用 RFCValidation
和 DNSCheckValidation
验证。以下是您可以应用的完整验证样式列表。
-
rfc
:RFCValidation
-
strict
:NoRFCWarningsValidation
-
dns
:DNSCheckValidation
-
spoof
:SpoofCheckValidation
-
filter
:FilterEmailValidation
-
filter_unicode
:FilterEmailValidation::unicode()
filter
验证器使用 PHP 的 filter_var
函数,随 Laravel 一起提供,并且是 Laravel 5.8 版本之前 Laravel 的默认电子邮件验证行为。
dns
和 spoof
验证器需要 PHP 的 intl
扩展。
ends_with:foo,bar,...
待验证的字段必须以给定值中的任何一个结尾。
enum
Enum
规则是一个基于类的规则,用于验证待验证的字段是否包含有效的枚举值。Enum
规则接受枚举名称作为其唯一的构造函数参数。验证原始值时,应向 Enum
规则提供一个支持的枚举。
use App\Enums\ServerStatus;use Illuminate\Validation\Rule; $request->validate([ 'status' => [Rule::enum(ServerStatus::class)],]);
Enum
规则的 only
和 except
方法可用于限制哪些枚举情况应被视为有效。
Rule::enum(ServerStatus::class) ->only([ServerStatus::Pending, ServerStatus::Active]); Rule::enum(ServerStatus::class) ->except([ServerStatus::Pending, ServerStatus::Active]);
when
方法可用于有条件地修改 Enum
规则。
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
待验证的字段将从 validate
和 validated
方法返回的请求数据中排除。
exclude_if:anotherfield,value
如果 anotherfield 字段等于 value,则待验证的字段将从 validate
和 validated
方法返回的请求数据中排除。
如果需要复杂的条件排除逻辑,您可以使用 Rule::excludeIf
方法。此方法接受布尔值或闭包。当给定闭包时,闭包应返回 true
或 false
以指示是否应排除待验证的字段。
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
方法返回的请求数据中排除。如果 value 为 null
(exclude_unless:name,null
),则除非比较字段为 null
或请求数据中缺少比较字段,否则待验证的字段将被排除。
exclude_with:anotherfield
如果 anotherfield 字段存在,则待验证的字段将从 validate
和 validated
方法返回的请求数据中排除。
exclude_without:anotherfield
如果 anotherfield 字段不存在,则待验证的字段将从 validate
和 validated
方法返回的请求数据中排除。
exists:table,column
待验证的字段必须存在于给定的数据库表中。
Exists 规则的基本用法
'state' => 'exists:states'
如果未指定 column
选项,则将使用字段名称。因此,在这种情况下,规则将验证 states
数据库表是否包含一条记录,其 state
列值与请求的 state
属性值匹配。
指定自定义列名
您可以通过将数据库表名称放在数据库表名称之后来显式指定验证规则应使用的数据库列名。
'state' => 'exists:states,abbreviation'
有时,您可能需要指定要用于 exists
查询的特定数据库连接。您可以通过在表名前添加连接名称来实现此目的。
'email' => 'exists:connection.staff,email'
您可以指定应用于确定表名的 Eloquent 模型,而不是直接指定表名。
'user_id' => 'exists:App\Models\User,id'
如果您想自定义验证规则执行的查询,您可以使用 Rule
类流畅地定义规则。在此示例中,我们还将验证规则作为数组指定,而不是使用 |
字符分隔它们。
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
规则应使用的数据库列名。
'state' => Rule::exists('states', 'abbreviation'),
extensions:foo,bar,...
待验证的文件必须具有与列出的扩展名之一相对应的用户分配的扩展名。
'photo' => ['required', 'extensions:jpg,png'],
file
待验证的字段必须是成功上传的文件。
filled
当字段存在时,待验证的字段不得为空。
gt:field
待验证的字段必须大于给定的 field 或 value。这两个字段必须具有相同的类型。字符串、数字、数组和文件使用与 size
规则相同的约定进行评估。
gte:field
待验证的字段必须大于或等于给定的 field 或 value。这两个字段必须具有相同的类型。字符串、数字、数组和文件使用与 size
规则相同的约定进行评估。
hex_color
待验证的字段必须包含 十六进制 格式的有效颜色值。
image
待验证的文件必须是图像(jpg、jpeg、png、bmp、gif、svg 或 webp)。
in:foo,bar,...
待验证的字段必须包含在给定的值列表中。由于此规则通常需要您 implode
数组,因此可以使用 Rule::in
方法流畅地构建规则。
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
规则的机场列表中。
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.*
待验证的字段必须存在于 anotherfield 的值中。
integer
待验证的字段必须是整数。
此验证规则不验证输入是否为“整数”变量类型,仅验证输入是否为 PHP 的 FILTER_VALIDATE_INT
规则接受的类型。如果您需要验证输入是否为数字,请将此规则与 numeric
验证规则 结合使用。
ip
待验证的字段必须是 IP 地址。
ipv4
待验证的字段必须是 IPv4 地址。
ipv6
待验证的字段必须是 IPv6 地址。
json
待验证的字段必须是有效的 JSON 字符串。
lt:field
待验证的字段必须小于给定的 field。这两个字段必须具有相同的类型。字符串、数字、数组和文件使用与 size
规则相同的约定进行评估。
lte:field
待验证的字段必须小于或等于给定的 field。这两个字段必须具有相同的类型。字符串、数字、数组和文件使用与 size
规则相同的约定进行评估。
lowercase
待验证的字段必须是小写。
list
待验证的字段必须是数组列表。如果数组的键包含从 0 到 count($array) - 1
的连续数字,则该数组被视为列表。
mac_address
待验证的字段必须是 MAC 地址。
max:value
待验证的字段必须小于或等于最大 value。字符串、数字、数组和文件以与 size
规则相同的方式进行评估。
max_digits:value
待验证的整数必须具有最大长度 value。
mimetypes:text/plain,...
待验证的文件必须与给定的 MIME 类型之一匹配。
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'
要确定上传文件的 MIME 类型,将读取文件的内容,并且框架将尝试猜测 MIME 类型,这可能与客户端提供的 MIME 类型不同。
mimes:foo,bar,...
待验证的文件必须具有与列出的扩展名之一相对应的 MIME 类型。
'photo' => 'mimes:jpg,bmp,png'
即使您只需要指定扩展名,此规则实际上也会通过读取文件的内容并猜测其 MIME 类型来验证文件的 MIME 类型。可以在以下位置找到 MIME 类型及其对应扩展名的完整列表。
https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
MIME 类型和扩展名
此验证规则不验证 MIME 类型与用户分配给文件的扩展名之间的一致性。例如,mimes:png
验证规则会将包含有效 PNG 内容的文件视为有效的 PNG 图像,即使该文件名为 photo.txt
。如果您想验证文件的用户分配的扩展名,可以使用 extensions
规则。
min:value
待验证的字段必须具有最小 value。字符串、数字、数组和文件以与 size
规则相同的方式进行评估。
min_digits:value
待验证的整数必须具有最小长度 value。
multiple_of:value
待验证的字段必须是 value 的倍数。
missing
待验证的字段不得出现在输入数据中。
missing_if:anotherfield,value,...
如果 anotherfield 字段等于任何 value,则待验证的字段不得存在。
missing_unless:anotherfield,value
除非 anotherfield 字段等于任何 value,否则待验证的字段不得存在。
missing_with:foo,bar,...
仅当其他指定的字段中的任何一个存在时,待验证的字段不得存在。
missing_with_all:foo,bar,...
正在验证的字段只有在所有其他指定字段都存在时才不能存在。
not_in:foo,bar,...
正在验证的字段不得包含在给定的值列表中。可以使用Rule::notIn
方法流畅地构建规则。
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'
。
使用regex
/ not_regex
模式时,可能需要使用数组而不是使用|
分隔符来指定验证规则,尤其是在正则表达式包含|
字符时。
nullable
正在验证的字段可以为null
。
numeric
正在验证的字段必须是数值型。
present
正在验证的字段必须存在于输入数据中。
present_if:anotherfield,value,...
如果anotherfield字段等于任何value,则正在验证的字段必须存在。
present_unless:anotherfield,value
除非anotherfield字段等于任何value,否则正在验证的字段必须存在。
present_with:foo,bar,...
正在验证的字段只有在任何其他指定字段存在时才必须存在。
present_with_all:foo,bar,...
正在验证的字段只有在所有其他指定字段都存在时才必须存在。
prohibited
正在验证的字段必须缺失或为空。如果字段满足以下条件之一,则为“空”
- 值为
null
。 - 值为空字符串。
- 值为空数组或空
Countable
对象。 - 值是具有空路径的上传文件。
prohibited_if:anotherfield,value,...
如果anotherfield字段等于任何value,则正在验证的字段必须缺失或为空。如果字段满足以下条件之一,则为“空”
- 值为
null
。 - 值为空字符串。
- 值为空数组或空
Countable
对象。 - 值是具有空路径的上传文件。
如果需要复杂的条件禁止逻辑,您可以使用Rule::prohibitedIf
方法。此方法接受布尔值或闭包。当给定闭包时,闭包应返回true
或false
以指示是否应禁止正在验证的字段。
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字段等于任何value,否则正在验证的字段必须缺失或为空。如果字段满足以下条件之一,则为“空”
- 值为
null
。 - 值为空字符串。
- 值为空数组或空
Countable
对象。 - 值是具有空路径的上传文件。
prohibits:anotherfield,...
如果正在验证的字段不缺失或为空,则anotherfield中的所有字段都必须缺失或为空。如果字段满足以下条件之一,则为“空”
- 值为
null
。 - 值为空字符串。
- 值为空数组或空
Countable
对象。 - 值是具有空路径的上传文件。
regex:pattern
正在验证的字段必须与给定的正则表达式匹配。
在内部,此规则使用PHP preg_match
函数。指定的模式应遵守preg_match
所需的相同格式,因此还应包含有效的定界符。例如:'email' => 'regex:/^.+@.+$/i'
。
使用regex
/ not_regex
模式时,可能需要在数组中指定规则,而不是使用|
分隔符,尤其是在正则表达式包含|
字符时。
required
正在验证的字段必须存在于输入数据中且不为空。如果字段满足以下条件之一,则为“空”
- 值为
null
。 - 值为空字符串。
- 值为空数组或空
Countable
对象。 - 值为一个没有路径的上传文件。
required_if:anotherfield,value,...
如果anotherfield字段等于任何value,则正在验证的字段必须存在且不为空。
如果您想为required_if
规则构建更复杂的条件,可以使用Rule::requiredIf
方法。此方法接受布尔值或闭包。当传递闭包时,闭包应返回true
或false
以指示是否需要正在验证的字段。
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字段等于任何value,否则正在验证的字段必须存在且不为空。这也意味着anotherfield必须存在于请求数据中,除非value为null
。如果value为null
(required_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
给定的field必须与正在验证的字段匹配。
size:value
正在验证的字段的大小必须与给定的value匹配。对于字符串数据,value对应于字符数。对于数字数据,value对应于给定的整数值(属性也必须具有numeric
或integer
规则)。对于数组,size对应于数组的count
。对于文件,size对应于以千字节为单位的文件大小。让我们看一些例子。
// Validate that a string is exactly 12 characters long...'title' => 'size:12'; // Validate that a provided integer equals 10...'seats' => 'integer|size:10'; // Validate that an array has exactly 5 elements...'tags' => 'array|size:5'; // Validate that an uploaded file is exactly 512 kilobytes...'image' => 'file|size:512';
starts_with:foo,bar,...
正在验证的字段必须以给定值之一开头。
string
正在验证的字段必须是字符串。如果您希望允许字段也为null
,则应将nullable
规则分配给该字段。
timezone
正在验证的字段必须是根据DateTimeZone::listIdentifiers
方法的有效时区标识符。
也可以将DateTimeZone::listIdentifiers
方法接受的参数提供给此验证规则。
'timezone' => 'required|timezone:all'; 'timezone' => 'required|timezone:Africa'; 'timezone' => 'required|timezone:per_country,US';
unique:table,column
正在验证的字段不得存在于给定的数据库表中。
指定自定义表/列名
您可以指定应用于确定表名的 Eloquent 模型,而不是直接指定表名。
'email' => 'unique:App\Models\User,email_address'
可以使用column
选项指定字段对应的数据库列。如果未指定column
选项,则将使用正在验证的字段的名称。
'email' => 'unique:users,email_address'
指定自定义数据库连接
有时,您可能需要为验证器执行的数据库查询设置自定义连接。要实现此目的,您可以将连接名称添加到表名前。
'email' => 'unique:connection.users,email_address'
强制唯一规则忽略给定的ID
有时,您可能希望在唯一验证期间忽略给定的ID。例如,考虑一个“更新个人资料”屏幕,其中包含用户的姓名、电子邮件地址和位置。您可能希望验证电子邮件地址是否唯一。但是,如果用户只更改姓名字段而不更改电子邮件字段,则不希望抛出验证错误,因为用户已经是所讨论电子邮件地址的所有者。
为了指示验证器忽略用户的ID,我们将使用Rule
类来流畅地定义规则。在此示例中,我们还将验证规则指定为数组,而不是使用|
字符来分隔规则。
use Illuminate\Support\Facades\Validator;use Illuminate\Validation\Rule; Validator::make($data, [ 'email' => [ 'required', Rule::unique('users')->ignore($user->id), ],]);
您永远不应将任何用户控制的请求输入传递到ignore
方法中。相反,您应该只传递系统生成的唯一ID,例如来自Eloquent模型实例的自增ID或UUID。否则,您的应用程序将容易受到SQL注入攻击。
您可以传递整个模型实例,而不是将模型键的值传递给ignore
方法。Laravel将自动从模型中提取键。
Rule::unique('users')->ignore($user)
如果您的表使用除id
之外的主键列名,则可以在调用ignore
方法时指定列的名称。
Rule::unique('users')->ignore($user->id, 'user_id')
默认情况下,unique
规则将检查与正在验证的属性名称匹配的列的唯一性。但是,您可以将不同的列名作为第二个参数传递给unique
方法。
Rule::unique('users', 'email_address')->ignore($user->id)
添加其他Where子句
您可以通过使用where
方法自定义查询来指定其他查询条件。例如,让我们添加一个查询条件,该条件将查询范围限定为仅搜索account_id
列值为1
的记录。
'email' => Rule::unique('users')->where(fn (Builder $query) => $query->where('account_id', 1))
uppercase
正在验证的字段必须是大写。
url
正在验证的字段必须是有效的URL。
如果您想指定应视为有效的URL协议,可以将协议作为验证规则参数传递。
'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
字段。
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
规则,除非另一个字段具有给定值,否则不验证给定字段。
$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
规则添加到您的规则列表中。
$validator = Validator::make($data, [ 'email' => 'sometimes|required|email',]);
在上面的示例中,只有当email
字段存在于$data
数组中时,才会对其进行验证。
如果您尝试验证一个应该始终存在但可能为空的字段,请查看关于可选字段的说明。
复杂的条件验证
有时,您可能希望根据更复杂的条件逻辑添加验证规则。例如,您可能希望仅当另一个字段的值大于100时才要求给定字段。或者,您可能需要两个字段只有在另一个字段存在时才具有给定值。添加这些验证规则不必很麻烦。首先,使用静态规则创建Validator
实例,这些规则永远不会更改。
use Illuminate\Support\Facades\Validator; $validator = Validator::make($request->all(), [ 'email' => 'required|email', 'games' => 'required|numeric',]);
假设我们的网络应用程序是针对游戏收藏家的。如果游戏收藏家在我们应用程序中注册,并且他们拥有超过100款游戏,我们希望他们解释为什么拥有这么多游戏。例如,也许他们经营游戏转售商店,或者也许他们只是喜欢收藏游戏。为了有条件地添加此要求,我们可以在Validator
实例上使用sometimes
方法。
use Illuminate\Support\Fluent; $validator->sometimes('reason', 'required|max:500', function (Fluent $input) { return $input->games >= 100;});
传递给sometimes
方法的第一个参数是我们要进行条件验证的字段的名称。第二个参数是我们想要添加的规则列表。如果作为第三个参数传递的闭包返回true
,则会添加这些规则。此方法使构建复杂的条件验证变得轻而易举。您甚至可以同时为多个字段添加条件验证。
$validator->sometimes(['reason', 'cost'], 'required', function (Fluent $input) { return $input->games >= 100;});
传递给闭包的$input
参数将是Illuminate\Support\Fluent
的一个实例,可用于访问正在验证的输入和文件。
复杂的条件数组验证
有时您可能希望根据同一嵌套数组中另一个字段进行字段验证,而您不知道该字段的索引。在这些情况下,您可以允许您的闭包接收第二个参数,该参数将是正在验证的数组中的当前单个项目。
$input = [ 'channels' => [ [ 'type' => 'email', ], [ '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
的一个实例;否则,它是一个字符串。
验证数组
如array
验证规则文档中所述,array
规则接受允许的数组键列表。如果数组中存在任何其他键,则验证将失败。
use Illuminate\Support\Facades\Validator; $input = [ 'user' => [ 'name' => 'Taylor Otwell', 'username' => 'taylorotwell', 'admin' => true, ],]; Validator::make($input, [ 'user' => 'array:name,username',]);
通常,您应该始终指定允许在数组中存在的数组键。否则,验证器的validate
和validated
方法将返回所有已验证的数据,包括数组及其所有键,即使这些键未由其他嵌套数组验证规则验证。
验证嵌套数组输入
验证基于嵌套数组的表单输入字段不必很麻烦。您可以使用“点表示法”来验证数组中的属性。例如,如果传入的HTTP请求包含一个photos[profile]
字段,您可以像这样验证它。
use Illuminate\Support\Facades\Validator; $validator = Validator::make($request->all(), [ 'photos.profile' => 'required|image',]);
您还可以验证数组的每个元素。例如,要验证给定数组输入字段中的每个电子邮件是否唯一,您可以执行以下操作。
$validator = Validator::make($request->all(), [ 'person.*.email' => 'email|unique:users', 'person.*.first_name' => 'required_with:person.*.last_name',]);
同样,您可以在指定语言文件中的自定义验证消息时使用*
字符,从而可以轻松地对基于数组的字段使用单个验证消息。
'custom' => [ 'person.*.email' => [ 'unique' => 'Each person must have a unique email address', ]],
访问嵌套数组数据
有时您可能需要在为属性分配验证规则时访问给定嵌套数组元素的值。您可以使用Rule::forEach
方法来实现这一点。forEach
方法接受一个闭包,该闭包将在验证期间的数组属性的每次迭代时调用,并接收属性的值和明确的、完全扩展的属性名称。闭包应返回要分配给数组元素的规则数组。
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
开始)和:position
(从1
开始)占位符。
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-index
、second-position
、third-index
、third-position
等引用更深层次的嵌套索引和位置。
'photos.*.attributes.*.string' => 'Invalid attribute for photo #:second-position.',
验证文件
Laravel 提供了各种可用于验证上传文件的验证规则,例如mimes
、image
、min
和max
。虽然您可以自由地在验证文件时单独指定这些规则,但 Laravel 还提供了一个流畅的文件验证规则构建器,您可能会发现它很方便。
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
规则可用于限制图像的尺寸。
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)), ],]);
有关验证图像尺寸的更多信息,请参阅尺寸规则文档。
文件大小
为了方便起见,最小和最大文件大小可以指定为带有后缀的字符串,该后缀指示文件大小单位。支持kb
、mb
、gb
和tb
后缀。
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
规则对象。
use Illuminate\Support\Facades\Validator;use Illuminate\Validation\Rules\Password; $validator = Validator::make($request->all(), [ 'password' => ['required', 'confirmed', Password::min(8)],]);
Password
规则对象允许您轻松自定义应用程序的密码复杂度要求,例如指定密码至少需要一个字母、数字、符号或混合大小写的字符。
// Require at least 8 characters...Password::min(8) // Require at least one letter...Password::min(8)->letters() // Require at least one uppercase and one lowercase letter...Password::min(8)->mixedCase() // Require at least one number...Password::min(8)->numbers() // Require at least one symbol...Password::min(8)->symbols()
此外,您可以使用uncompromised
方法确保密码未在公共密码数据泄露中泄露。
Password::min(8)->uncompromised()
在内部,Password
规则对象使用k-匿名性模型来确定密码是否通过haveibeenpwned.com服务泄露,而不会牺牲用户的隐私或安全。
默认情况下,如果密码在数据泄露中至少出现一次,则会被视为已泄露。您可以使用uncompromised
方法的第一个参数自定义此阈值。
// Ensure the password appears less than 3 times in the same data leak...Password::min(8)->uncompromised(3);
当然,您可以将上面示例中的所有方法链接起来。
Password::min(8) ->letters() ->mixedCase() ->numbers() ->symbols() ->uncompromised()
定义默认密码规则
您可能会发现,在应用程序的单个位置指定密码的默认验证规则很方便。您可以使用Password::defaults
方法轻松实现这一点,该方法接受一个闭包。传递给defaults
方法的闭包应返回 Password 规则的默认配置。通常,defaults
规则应在应用程序服务提供程序之一的boot
方法中调用。
use Illuminate\Validation\Rules\Password; /** * Bootstrap any application services. */public function boot(): void{ Password::defaults(function () { $rule = Password::min(8); return $this->app->isProduction() ? $rule->mixedCase()->uncompromised() : $rule; });}
然后,当您希望将默认规则应用于正在进行验证的特定密码时,您可以不带任何参数调用defaults
方法。
'password' => ['required', Password::defaults()],
有时,您可能希望将其他验证规则附加到默认密码验证规则。您可以使用rules
方法来实现这一点。
use App\Rules\ZxcvbnRule; Password::defaults(function () { $rule = Password::min(8)->rules([new ZxcvbnRule]); // ...});
自定义验证规则
使用规则对象
Laravel 提供了各种有用的验证规则;但是,您可能希望指定一些自己的规则。注册自定义验证规则的一种方法是使用规则对象。要生成新的规则对象,您可以使用make:rule
Artisan 命令。让我们使用此命令生成一个验证字符串是否为大写的规则。Laravel 将把新规则放在app/Rules
目录中。如果此目录不存在,Laravel 在您执行创建规则的 Artisan 命令时将创建它。
php artisan make:rule Uppercase
创建规则后,我们就可以定义它的行为。规则对象包含一个方法:validate
。此方法接收属性名称、其值以及一个回调函数,该回调函数应在验证失败时使用验证错误消息调用。
<?php namespace App\Rules; use Closure;use Illuminate\Contracts\Validation\ValidationRule; class Uppercase implements ValidationRule{ /** * Run the validation rule. */ public function validate(string $attribute, mixed $value, Closure $fail): void { if (strtoupper($value) !== $value) { $fail('The :attribute must be uppercase.'); } }}
定义规则后,您可以通过将规则对象的实例与其他验证规则一起传递来将其附加到验证器。
use App\Rules\Uppercase; $request->validate([ 'name' => ['required', 'string', new Uppercase],]);
翻译验证消息
除了向$fail
闭包提供文字错误消息外,您还可以提供翻译字符串键并指示 Laravel 翻译错误消息。
if (strtoupper($value) !== $value) { $fail('validation.uppercase')->translate();}
如有必要,您可以将占位符替换和首选语言作为第一个和第二个参数传递给translate
方法。
$fail('validation.location')->translate([ 'value' => $this->value,], 'fr')
访问其他数据
如果您的自定义验证规则类需要访问所有正在进行验证的其他数据,则您的规则类可以实现Illuminate\Contracts\Validation\DataAwareRule
接口。此接口要求您的类定义一个setData
方法。此方法将由 Laravel 自动调用(在验证进行之前),并传递所有正在验证的数据。
<?php namespace App\Rules; use Illuminate\Contracts\Validation\DataAwareRule;use Illuminate\Contracts\Validation\ValidationRule; class Uppercase implements DataAwareRule, ValidationRule{ /** * All of the data under validation. * * @var array<string, mixed> */ protected $data = []; // ... /** * Set the data under validation. * * @param array<string, mixed> $data */ public function setData(array $data): static { $this->data = $data; return $this; }}
或者,如果您的验证规则需要访问执行验证的验证器实例,则可以实现ValidatorAwareRule
接口。
<?php namespace App\Rules; use Illuminate\Contracts\Validation\ValidationRule;use Illuminate\Contracts\Validation\ValidatorAwareRule;use Illuminate\Validation\Validator; class Uppercase implements ValidationRule, ValidatorAwareRule{ /** * The validator instance. * * @var \Illuminate\Validation\Validator */ protected $validator; // ... /** * Set the current validator. */ public function setValidator(Validator $validator): static { $this->validator = $validator; return $this; }}
使用闭包
如果您只需要在整个应用程序中使用一次自定义规则的功能,则可以使用闭包而不是规则对象。闭包接收属性的名称、属性的值以及一个$fail
回调函数,如果验证失败,则应调用此回调函数。
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."); } }, ],]);
隐式规则
默认情况下,当正在验证的属性不存在或包含空字符串时,不会运行正常的验证规则,包括自定义规则。例如,unique
规则不会对空字符串运行。
use Illuminate\Support\Facades\Validator; $rules = ['name' => 'unique:users,name']; $input = ['name' => '']; Validator::make($input, $rules)->passes(); // true
为了使自定义规则即使在属性为空时也运行,该规则必须暗示属性是必需的。要快速生成新的隐式规则对象,您可以使用make:rule
Artisan 命令并加上--implicit
选项。
php artisan make:rule Uppercase --implicit
“隐式”规则仅暗示属性是必需的。它是否实际使缺少或空的属性无效取决于您。