验证
简介
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 response containing the validation error messages。
为了更好地理解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方法中。不用担心 - 所有可用的验证规则都是documented。同样,如果验证失败,将自动生成正确的响应。如果验证通过,我们的控制器将继续正常执行。
此外,你可以使用validateWithBag方法来验证请求并将任何错误消息存储在named error bag中:
$validated = $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 会自动将用户重定向回之前的位置。此外,所有验证错误和request input 将自动变为flashed to the session。
$errors 变量由Illuminate\View\Middleware\ShareErrorsFromSession 中间件与所有应用程序的视图共享,该中间件由web 中间件组提供。应用此中间件时,$errors 变量将始终在你的视图中可用,从而使你可以方便地假设 $errors 变量始终已定义并且可以安全使用。 $errors 变量将是Illuminate\Support\MessageBag 的实例。有关使用此对象的更多信息,check out its documentation。
因此,在我们的示例中,当验证失败时,用户将被重定向到控制器的 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 本地化的更多信息,请查看完整的localization documentation。
WARNING
默认情况下,Laravel 应用程序框架不包含 lang 目录。如果你想自定义 Laravel 的语言文件,你可以通过 lang:publish Artisan 命令发布它们。
XHR 请求与验证
在此示例中,我们使用传统形式将数据发送到应用程序。然而,许多应用程序从 JavaScript 支持的前端接收 XHR 请求。在 XHR 请求期间使用 validate 方法时,Laravel 将不会生成重定向响应。相反,Laravel 会生成一个JSON response containing all of the validation errors。此 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如果你使用named error bags,则可以将错误袋的名称作为第二个参数传递给@error指令:
<input ... class="@error('title', 'post') is-invalid @enderror">重新填充表单
当 Laravel 由于验证错误而生成重定向响应时,框架会自动flash all of the request's input to the session。这样做是为了你可以在下一个请求期间方便地访问输入并重新填充用户尝试提交的表单。
要检索先前请求中闪现的输入,请在 Illuminate\Http\Request 实例上调用 old 方法。 old方法将从session中提取先前闪烁的输入数据:
$title = $request->old('title');Laravel 还提供了一个全局 old 帮助器。如果你在 Blade template 中显示旧输入,则使用 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'],
];
}INFO
你可以在 rules 方法的签名中键入提示所需的任何依赖项。它们将通过 Laravel service container 自动解析。
那么,验证规则是如何评估的呢?你所需要做的就是在控制器方法上键入提示请求。传入的表单请求在调用控制器方法之前进行验证,这意味着你不需要使用任何验证逻辑来扰乱控制器:
/**
* 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 请求,则将向用户返回带有 422 状态代码的 HTTP 响应,其中包括 JSON representation of the validation errors。
INFO
需要向 Inertia 支持的 Laravel 前端添加实时表单请求验证吗?看看Laravel Precognition。
执行额外验证
有时,你需要在初始验证完成后执行额外的验证。你可以使用表单请求的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 属性添加到请求类中,你可以通知验证器一旦发生单个验证失败,它应该停止验证所有属性:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\StopOnFirstFailure;
use Illuminate\Foundation\Http\FormRequest;
#[StopOnFirstFailure]
class StorePostRequest extends FormRequest
{
// ...
}遇未知字段则失败
通过将 FailOnUnknownFields 属性添加到请求类中,你可以指示 Laravel 拒绝请求验证规则未定义的任何传入字段:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\FailOnUnknownFields;
use Illuminate\Foundation\Http\FormRequest;
#[FailOnUnknownFields]
class StorePostRequest extends FormRequest
{
public function rules(): array
{
return [
'title' => ['required', 'string'],
'body' => ['required', 'string'],
];
}
}你还可以为来自 AppServiceProvider 的所有表单请求全局启用此行为:
use Illuminate\Foundation\Http\FormRequest;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
FormRequest::failOnUnknownFields();
}如果需要,你可以通过将 false 传递给属性来禁用特定请求的此行为:
#[FailOnUnknownFields(false)]
class PublicWebhookRequest extends FormRequest
{
// ...
}拒绝未知字段可以防止意外的输入键更深入地流入应用程序,从而针对批量分配样式问题提供额外的保护。但是,你仍然应该配置模型的 $fillable / $guarded 属性,并且仅保留可信的、经过验证的输入。
自定义重定向位置
当表单请求验证失败时,将生成重定向响应以将用户发送回之前的位置。但是,你可以自由自定义此行为。为此,你可以在表单请求中使用 RedirectTo 属性:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\RedirectTo;
use Illuminate\Foundation\Http\FormRequest;
#[RedirectTo('/dashboard')]
class StorePostRequest extends FormRequest
{
// ...
}或者,如果你想将用户重定向到命名路由,你可以使用 RedirectToRoute 属性:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\RedirectToRoute;
use Illuminate\Foundation\Http\FormRequest;
#[RedirectToRoute('dashboard')]
class StorePostRequest extends FormRequest
{
// ...
}自定义错误袋
当表单请求验证失败时,错误将闪现到default错误袋中。如果你需要将错误存储在不同的named error bag中,你可以在表单请求中使用ErrorBag属性:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\ErrorBag;
use Illuminate\Foundation\Http\FormRequest;
#[ErrorBag('login')]
class LoginRequest extends FormRequest
{
// ...
}授权表单请求
表单请求类还包含authorize 方法。在此方法中,你可以确定经过身份验证的用户是否确实有权更新给定资源。例如,你可以确定用户是否真正拥有他们尝试更新的博客评论。最有可能的是,你将在此方法中与你的authorization gates and policies 进行交互:
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}');因此,如果你的应用程序正在利用route model binding,则通过将解析的模型作为请求的属性进行访问,你的代码可能会变得更加简洁:
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;
}INFO
你可以在 authorize 方法的签名中键入提示所需的任何依赖项。它们将通过 Laravel service container 自动解析。
自定义错误消息
你可以通过重写 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方法,你可以使用Validatorfacade手动创建验证器实例。外观上的 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 array。
在首次验证失败时停止
stopOnFirstFailure 方法将通知验证器,一旦发生单个验证失败,它应该停止验证所有属性:
if ($validator->stopOnFirstFailure()->fails()) {
// ...
}自动重定向
如果你想手动创建验证器实例,但仍然利用 HTTP 请求的 validate 方法提供的自动重定向,则可以在现有验证器实例上调用 validate 方法。如果验证失败,用户将自动被重定向,或者,如果是 XHR 请求,则为 JSON response will be returned:
Validator::make($request->all(), [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
])->validate();如果验证失败,你可以使用validateWithBag方法将错误消息存储在named error bag中:
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']);如果你想以 collection 实例的形式检索经过验证的数据,你可以调用 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 本地化的更多信息,请查看完整的localization documentation。
WARNING
默认情况下,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',
],WARNING
默认情况下,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.你可以通过定义 values 数组在 lang/xx/validation.php 语言文件中指定更用户友好的值表示形式,而不是将 cc 显示为付款类型值:
'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],WARNING
默认情况下,Laravel 应用程序框架不包含 lang 目录。如果你想自定义 Laravel 的语言文件,你可以通过 lang:publish Artisan 命令发布它们。
定义该值后,验证规则将产生以下错误消息:
The credit card number field is required when payment type is credit card.可用验证规则
以下是所有可用验证规则及其功能的列表:
布尔值
字符串
Active URLAlphaAlpha DashAlpha NumericAsciiConfirmedCurrent PasswordDifferentDoesnt Start WithDoesnt End WithEmailEnds WithEnumHex ColorInIP AddressJSONLowercaseMAC AddressMaxMinNot InRegular ExpressionNot Regular ExpressionSameSizeStarts WithStringUppercaseURLULIDUUID
数字
BetweenDecimalDifferentDigitsDigits BetweenGreater ThanGreater Than Or EqualIntegerLess ThanLess Than Or EqualMaxMax DigitsMinMin DigitsMultiple OfNumericSameSize
数组
日期
文件
数据库
工具
Any OfBailExcludeExclude IfExclude UnlessExclude WithExclude WithoutFilledMissingMissing IfMissing UnlessMissing WithMissing With AllNullablePresentPresent IfPresent UnlessPresent WithPresent With AllProhibitedProhibited IfProhibited If AcceptedProhibited If DeclinedProhibited UnlessProhibitsRequiredRequired IfRequired If AcceptedRequired If DeclinedRequired UnlessRequired WithRequired With AllRequired WithoutRequired Without AllRequired Array KeysSometimes
accepted
待验证字段必须是"yes"、"on"、1、"1"、true 或"true"。这对于验证“服务条款”接受或类似字段非常有用。
accepted_if:anotherfield,value,...
如果另一个待验证字段等于指定值,则待验证字段必须是"yes"、"on"、1、"1"、true 或"true"。这对于验证“服务条款”接受或类似字段非常有用。
active_url
根据 dns_get_record PHP 函数,待验证字段必须具有有效的 A 或 AAAA 记录。所提供 URL 的主机名在传递给 dns_get_record 之前使用 parse_url PHP 函数提取。
当测试执行 DNS 查找的验证规则(例如active_url 和email:dns)时,你可以使用Validator::fakeDnsLookups 方法。这会伪造 DNS 查找,同时保留规则的其他验证行为:
use Illuminate\Support\Facades\Validator;
Validator::fakeDnsLookups();after:date
验证字段必须是给定日期之后的值。日期将被传递到 strtotime PHP 函数,以便转换为有效的 DateTime 实例:
'start_date' => ['required', 'date', 'after:tomorrow']你可以指定另一个字段来与日期进行比较,而不是传递要由 strtotime 计算的日期字符串:
'finish_date' => ['required', 'date', 'after:start_date']为了方便起见,可以使用流畅的 date 规则构建器构建基于日期的规则:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->after(today()->addDays(7)),
],afterToday 和 todayOrAfter 方法可用于流畅地表达日期,并且必须分别在今天之后、今天或之后:
'start_date' => [
'required',
Rule::date()->afterToday(),
],after_or_equal:date
待验证字段必须是给定日期之后或等于给定日期的值。有关详细信息,请参阅after 规则。
为了方便起见,可以使用流畅的 date 规则构建器构建基于日期的规则:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->afterOrEqual(today()->addDays(7)),
],anyOf
Rule::anyOf 验证规则允许你指定待验证字段必须满足任何给定的验证规则集。例如,以下规则将验证 username 字段是电子邮件地址还是长度至少为 6 个字符的字母数字字符串(包括破折号):
use Illuminate\Validation\Rule;
'username' => [
'required',
Rule::anyOf([
['string', 'email'],
['string', 'alpha_dash', 'min:6'],
]),
],alpha
要将此验证规则限制为 ASCII 范围内的字符(a-z 和 A-Z),你可以为验证规则提供 ascii 选项:
'username' => ['alpha:ascii'],alpha_dash
要将此验证规则限制为 ASCII 范围内的字符(a-z、A-Z 和 0-9),你可以向验证规则提供 ascii 选项:
'username' => ['alpha_dash:ascii'],alpha_num
要将此验证规则限制为 ASCII 范围内的字符(a-z、A-Z 和 0-9),你可以向验证规则提供 ascii 选项:
'username' => ['alpha_num:ascii'],array
验证字段必须是 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'],
]);一般来说,你应该始终指定数组中允许出现的数组键。
array_keys:foo,bar,...
待验证字段必须是 PHP array,其键全部包含在给定列表中。必须至少提供一把钥匙:
'user' => ['array_keys:name,username'],为了方便起见,你可以使用Rule::arrayKeys方法:
'user' => [Rule::arrayKeys('name', 'username')],ascii
待验证字段必须完全是 7 位 ASCII 字符。
bail
第一次验证失败后,停止运行该字段的验证规则。
bail规则只会在遇到验证失败时停止验证特定字段,而stopOnFirstFailure方法将通知验证器一旦发生单个验证失败就应该停止验证所有属性:
if ($validator->stopOnFirstFailure()->fails()) {
// ...
}before:date
验证字段必须是给定日期之前的值。日期将被传递到 PHP strtotime 函数中,以便转换为有效的 DateTime 实例。此外,与after规则一样,验证中的另一个字段的名称可以作为date的值提供。
为了方便起见,基于日期的规则也可以使用流畅的 date 规则构建器来构建:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->before(today()->subDays(7)),
],beforeToday 和 todayOrBefore 方法可用于流畅地表达日期,并且必须分别在今天之前、今天或之前:
'start_date' => [
'required',
Rule::date()->beforeToday(),
],before_or_equal:date
待验证字段必须是给定日期之前或等于给定日期的值。这些日期将被传递到 PHP strtotime 函数中,以便转换为有效的 DateTime 实例。此外,与after规则一样,验证中的另一个字段的名称可以作为date的值提供。
为了方便起见,基于日期的规则也可以使用流畅的 date 规则构建器来构建:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->beforeOrEqual(today()->subDays(7)),
],between:min,max
验证字段的大小必须介于给定的 min 和 max (含)之间。字符串、数字、数组和文件的计算方式与 size 规则相同。
boolean
验证中的字段必须能够转换为布尔值。接受的输入为true、false、1、0、"1" 和"0"。
你可以使用strict参数仅在其值为true或false时才认为该字段有效:
'foo' => ['boolean:strict']confirmed
待验证字段必须具有匹配字段{field}_confirmation。例如,如果验证字段为password,则输入中必须存在匹配的password_confirmation 字段。
你还可以传递自定义确认字段名称。例如,confirmed:repeat_username 将期望字段repeat_username 与验证中的字段匹配。
contains:foo,bar,...
待验证字段必须是包含所有给定参数值的数组。由于此规则通常要求你 implode 一个数组,因此可以使用 Rule::contains 方法来流畅地构造该规则:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'roles' => [
'required',
'array',
Rule::contains(['admin', 'editor']),
],
]);doesnt_contain:foo,bar,...
待验证字段必须是不包含任何给定参数值的数组。由于此规则通常要求你 implode 一个数组,因此可以使用 Rule::doesntContain 方法来流畅地构造该规则:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'roles' => [
'required',
'array',
Rule::doesntContain(['admin', 'editor']),
],
]);current_password
待验证字段必须与经过身份验证的用户的密码匹配。你可以使用规则的第一个参数指定authentication guard:
'password' => ['current_password:api']date
根据 strtotime PHP 函数,待验证字段必须是有效的非相对日期。
date_equals:date
验证字段必须等于给定日期。这些日期将被传递到 PHP strtotime 函数中,以便转换为有效的 DateTime 实例。
date_format:format,...
验证中的字段必须与给定_格式_之一匹配。验证字段时,你应该使用 **date 或 date_format 之一,而不是同时使用两者。此验证规则支持 PHP 的 DateTime 类支持的所有格式。
为了方便起见,可以使用流畅的 date 规则构建器构建基于日期的规则:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->format('Y-m-d'),
],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']declined
待验证字段必须是"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 之间。
dimensions
正在验证的文件必须是满足规则参数指定的尺寸约束的图像:
'avatar' => ['dimensions:min_width=100,min_height=200']可用约束有:min_width、max_width、min_height、max_height、width、height、ratio、min_ratio、max_ratio。
比率约束应表示为宽度除以高度。这可以通过像3/2这样的分数或像1.5这样的浮点数来指定:
'avatar' => ['dimensions:ratio=3/2']min_ratio 和 max_ratio 约束可用于定义可接受的纵横比范围:
'avatar' => ['dimensions:min_ratio=1/2,max_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),
],
]);你还可以使用 minRatio、maxRatio 和 ratioBetween 方法来流畅地定义比率约束:
Rule::dimensions()->ratioBetween(min: 1 / 2, max: 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,...
待验证字段不得以给定值之一结尾。
email
验证字段的格式必须为电子邮件地址。此验证规则使用egulias/email-validator 包来验证电子邮件地址。默认情况下,应用 RFCValidation 验证器,但你也可以应用其他验证样式:
'email' => ['email:rfc,dns']上面的示例将应用 RFCValidation 和 DNSCheckValidation 验证。以下是你可以应用的验证样式的完整列表:
rfc:RFCValidation- Validate the email address according to supported RFCs.strict:NoRFCWarningsValidation- Validate the email according to supported RFCs, failing when warnings are found (e.g. trailing periods and multiple consecutive periods).dns:DNSCheckValidation- Ensure the email address's domain has a valid MX record.spoof:SpoofCheckValidation- Ensure the email address does not contain homograph or deceptive Unicode characters.filter:FilterEmailValidation- Ensure the email address is valid according to PHP'sfilter_varfunction.filter_unicode:FilterEmailValidation::unicode()- Ensure the email address is valid according to PHP'sfilter_varfunction, allowing some Unicode characters.
为了方便起见,可以使用流畅的规则生成器来构建电子邮件验证规则:
use Illuminate\Validation\Rule;
$request->validate([
'email' => [
'required',
Rule::email()
->rfcCompliant(strict: false)
->validateMxRecord()
->preventSpoofing()
],
]);dns 验证器执行真正的 DNS 查找以确认该地址的域具有有效的 MX 记录。它无法确定单个邮箱是否存在。
由于你的测试不应依赖于实时 DNS 查找,因此你可以使用 Validator::fakeDnsLookups 方法来 fake DNS lookups,同时任何其他请求的验证(例如 rfc)继续运行:
use Illuminate\Support\Facades\Validator;
Validator::fakeDnsLookups();这允许你的应用程序在测试时继续使用其现有的验证规则:
'email' => ['required', 'email:rfc,dns'],WARNING
dns 和 spoof 验证器需要 PHP intl 扩展。
encoding:encoding_type
待验证字段必须与指定的字符编码匹配。该规则使用 PHP 的 mb_check_encoding 函数来验证给定文件或字符串值的编码。为了方便起见,encoding 规则可以使用 Laravel 的流畅文件规则构建器构建:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;
Validator::validate($input, [
'attachment' => [
'required',
File::types(['csv'])
->encoding('utf-8'),
],
]);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或请求数据中缺少比较字段。
如果需要复杂的条件排除逻辑,可以使用Rule::excludeUnless方法。此方法接受布尔值或闭包。当给定一个闭包时,闭包应该返回 true 或 false 以指示是否不应排除待验证字段:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::excludeUnless($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::excludeUnless(fn () => $request->user()->is_admin)],
]);exclude_with:anotherfield
如果存在 anotherfield 字段,则验证中的字段将从 @@0@@ 和 validated 方法返回的请求数据中排除。
exclude_without:anotherfield
如果 anotherfield 字段不存在,则验证中的字段将从 @@0@@ 和 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) {
$query->where('account_id', 1);
}),
],
]);你可以通过将列名作为第二个参数提供给 exists 方法来显式指定 Rule::exists 方法生成的 exists 规则应使用的数据库列名:
'state' => [Rule::exists('states', 'abbreviation')],有时,你可能希望验证数据库中是否存在值数组。你可以通过将 exists 和 array 规则添加到待验证字段来执行此操作:
'states' => ['array', Rule::exists('states', 'abbreviation')],当这两个规则都分配给一个字段时,Laravel 将自动构建一个查询来确定指定表中是否存在所有给定值。
extensions:foo,bar,...
正在验证的文件必须具有与列出的扩展名之一相对应的用户分配的扩展名:
'photo' => ['required', 'extensions:jpg,png'],file
待验证字段必须是已成功上传的文件。
filled
验证字段存在时不得为空。
gt:field
待验证字段必须大于给定的_field_ 或_value_。这两个字段必须属于同一类型。使用与 size 规则相同的约定来评估字符串、数字、数组和文件。
gte:field
待验证字段必须大于或等于给定的_field_ 或_value_。这两个字段必须属于同一类型。使用与 size 规则相同的约定来评估字符串、数字、数组和文件。
hex_color
验证字段必须包含 hexadecimal 格式的有效颜色值。
image
验证的文件必须是图像(jpg、jpeg、png、bmp、gif 或 webp)。
WARNING
默认情况下,由于可能存在 XSS 漏洞,图像规则不允许 SVG 文件。如果你需要允许 SVG 文件,你可以向 image 规则 (image:allow_svg) 提供 allow_svg 指令。
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 的值中。
in_array_keys:value.*
待验证字段必须是一个数组,其中至少有一个给定的_值_作为数组中的键:
'config' => ['array', 'in_array_keys:timezone']integer
待验证字段必须是整数。
你可以使用strict 参数仅在其类型为integer 时才认为该字段有效。具有整数值的字符串将被视为无效:
'age' => ['integer:strict']WARNING
此验证规则不验证输入是否为“整数”变量类型,仅验证输入是否为 PHP 的 FILTER_VALIDATE_INT 规则接受的类型。如果你需要验证输入是否为数字,请将此规则与 the numeric validation rule 结合使用。
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
待验证字段必须小于或等于最大值_值_。字符串、数字、数组和文件的计算方式与 size 规则相同。
max_digits:value
验证中的整数的最大长度必须为_value_。
mimetypes:text/plain,...
正在验证的文件必须与给定的 MIME 类型之一匹配:
'video' => ['mimetypes:video/avi,video/mpeg,video/quicktime'],
'media' => ['mimetypes:image/*,video/*'],为了确定上传文件的 MIME 类型,将读取文件的内容,框架将尝试猜测 MIME 类型,该类型可能与客户端提供的 MIME 类型不同。
mimes:foo,bar,...
正在验证的文件必须具有与列出的扩展名之一相对应的 MIME 类型:
'photo' => ['mimes:jpg,bmp,png']尽管你只需要指定扩展名,但此规则实际上通过读取文件内容并猜测其 MIME 类型来验证文件的 MIME 类型。 MIME 类型及其相应扩展名的完整列表可以在以下位置找到:
MIME 类型与扩展名
此验证规则不会验证 MIME 类型与用户分配给文件的扩展名之间的一致性。例如,mimes:png 验证规则会将包含有效 PNG 内容的文件视为有效的 PNG 图像,即使该文件名为 photo.txt。如果你想验证用户分配的文件扩展名,你可以使用extensions 规则。
min: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']。
nullable
待验证字段可以是null。
numeric
验证字段必须是numeric。
你可以使用 strict 参数仅在其值为整数或浮点类型时才认为该字段有效。数字字符串将被视为无效:
'amount' => ['numeric:strict']present
待验证字段必须存在于输入数据中。
present_if:anotherfield,value,...
如果 anotherfield 字段等于任何_value_,则验证中的字段必须存在。
present_unless:anotherfield,value
除非 anotherfield 字段等于任何_value_,否则验证中的字段必须存在。
present_with:foo,bar,...
仅当任何其他指定字段存在时,验证字段才必须存在。
present_with_all:foo,bar,...
仅当所有其他指定字段都存在时,验证字段才必须存在。
prohibited
待验证字段必须缺失或为空。如果字段满足以下条件之一,则该字段为“空”:
- The value is
null. - The value is an empty string.
- The value is an empty array or empty
Countableobject. - The value is an uploaded file with an empty path.
prohibited_if:anotherfield,value,...
如果 anotherfield 字段等于任何_value_,则验证中的字段必须缺失或为空。如果字段满足以下条件之一,则该字段为“空”:
- The value is
null. - The value is an empty string.
- The value is an empty array or empty
Countableobject. - The value is an uploaded file with an empty path.
如果需要复杂的条件禁止逻辑,可以使用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_if_accepted:anotherfield,...
如果 anotherfield 字段等于 "yes"、"on"、1、"1"、true 或 "true",则验证中的字段必须缺失或为空。
prohibited_if_declined:anotherfield,...
如果 anotherfield 字段等于 "no"、"off"、0、"0"、false 或 "false",则验证中的字段必须缺失或为空。
prohibited_unless:anotherfield,value,...
除非 anotherfield 字段等于任何_value_,否则验证中的字段必须缺失或为空。如果字段满足以下条件之一,则该字段为“空”:
- The value is
null. - The value is an empty string.
- The value is an empty array or empty
Countableobject. - The value is an uploaded file with an empty path.
如果需要复杂的条件禁止逻辑,可以使用Rule::prohibitedUnless方法。此方法接受布尔值或闭包。当给定一个闭包时,该闭包应返回 true 或 false 以指示验证中的字段是否不应被禁止:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::prohibitedUnless($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::prohibitedUnless(fn () => $request->user()->is_admin)],
]);prohibits:anotherfield,...
如果待验证字段不缺失或为空,则 anotherfield 中的所有字段都必须缺失或为空。如果字段满足以下条件之一,则该字段为“空”:
- The value is
null. - The value is an empty string.
- The value is an empty array or empty
Countableobject. - The value is an uploaded file with an empty path.
regex:pattern
待验证字段必须与给定的正则表达式匹配。
在内部,此规则使用 PHP preg_match 函数。指定的模式应遵循 preg_match 所需的相同格式,因此也包含有效的分隔符。例如:'email' => ['regex:/^.+@.+$/i']。
required
验证字段必须存在于输入数据中且不为空。如果字段满足以下条件之一,则该字段为“空”:
- The value is
null. - The value is an empty string.
- The value is an empty array or empty
Countableobject. - The value is an uploaded file with no path.
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_unless规则构造更复杂的条件,可以使用Rule::requiredUnless方法。此方法接受布尔值或闭包。当传递一个闭包时,闭包应该返回 true 或 false 以指示验证中的字段是否不需要:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::requiredUnless($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::requiredUnless(fn () => $request->user()->is_admin)],
]);required_with:foo,bar,...
仅当任何其他指定字段存在且不为空时,验证字段才必须存在且不为空。
required_with_all:foo,bar,...
仅当所有其他指定字段都存在且不为空时,待验证字段才必须存在且不为空。
required_without:foo,bar,...
仅当任何其他指定字段为空或不存在时,验证字段必须存在且不为空。
required_without_all:foo,bar,...
只有当_所有其他指定字段为空或不存在时,验证字段必须存在,而不是empty_only。
required_array_keys:foo,bar,...
待验证字段必须是数组,并且必须至少包含指定的键。
same:field
给定的_field_必须与验证中的字段匹配。
size: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 规则。
为了方便起见,字符串验证规则也可以使用流畅的 Rule::string() 规则构建器来构建:
use Illuminate\Validation\Rule;
'title' => [
'required',
Rule::string()
->min(3)
->max(255)
->alphaDash(ascii: true),
],字符串规则构建器提供了常见字符串约束的方法,包括alpha、alphaDash、alphaNumeric、ascii、between、doesntEndWith、doesntStartWith、endsWith、exactly、lowercase、max、min、startsWith和uppercase。由于规则生成器是有条件的,因此你还可以使用 when 和 unless 方法有条件地应用约束。
timezone
根据 DateTimeZone::listIdentifiers 方法,待验证字段必须是有效的时区标识符。
['DateTimeZone:: listIdentifiers`方法接受的参数] (https://www.php.net/manual/en/datetimezone.listidentifiers.php)也可以提供给此验证规则:
'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']强制 Unique 规则忽略给定 ID:
有时,你可能希望在唯一验证期间忽略给定的 ID。例如,考虑一个“更新个人资料”屏幕,其中包括用户的姓名、电子邮件地址和位置。你可能需要验证电子邮件地址是否唯一。但是,如果用户仅更改名称字段而不更改电子邮件字段,你不希望引发验证错误,因为该用户已经是相关电子邮件地址的所有者。
为了指示验证器忽略用户的 ID,我们将使用 Rule 类来流畅地定义规则。
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 会自动从模型中提取密钥:
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))在 Unique 检查中忽略软删除记录:
默认情况下,唯一规则在确定唯一性时包括软删除记录。要从唯一性检查中排除软删除记录,你可以调用withoutTrashed方法:
Rule::unique('users')->withoutTrashed();如果你的模型对软删除记录使用 deleted_at 以外的列名称,则可以在调用 withoutTrashed 方法时提供列名称:
Rule::unique('users')->withoutTrashed('was_deleted_at');uppercase
验证字段必须为大写。
url
待验证字段必须是有效的 URL。
如果你想指定应被视为有效的 URL 协议,你可以将协议作为验证规则参数传递:
'url' => ['url:http,https'],
'game' => ['url:minecraft,steam'],ulid
验证字段必须是有效的Universally Unique Lexicographically Sortable Identifier (ULID)。
uuid
待验证字段必须是有效的 RFC 9562(版本 1、3、4、5、6、7 或 8)通用唯一标识符 (UUID)。
你还可以验证给定的 UUID 是否与版本的 UUID 规范匹配:
'uuid' => ['uuid:4']有条件地添加规则
字段为特定值时跳过验证
如果另一个字段具有给定值,你有时可能不希望验证给定字段。你可以使用 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 数组中存在时才会被验证。
INFO
如果你尝试验证应始终存在但可能为空的字段,请查看this note on optional fields。
复杂条件验证
有时你可能希望添加基于更复杂的条件逻辑的验证规则。例如,你可能希望仅当另一个字段的值大于 100 时才需要给定字段。或者,仅当存在另一个字段时你可能需要两个字段具有给定值。添加这些验证规则并不一定很痛苦。首先,使用永远不会改变的_静态规则_创建一个Validator实例:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'email' => ['required', 'email'],
'games' => ['required', 'integer', 'min:0'],
]);假设我们的 Web 应用程序是为游戏收藏者设计的。如果游戏收藏家在我们的应用程序中注册并且他们拥有超过 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;
});INFO
传递给闭包的 $input 参数将是 Illuminate\Support\Fluent 的实例,可用于访问你的输入和验证下的文件。
复杂条件数组验证
有时,你可能希望根据同一嵌套数组中你不知道其索引的另一个字段来验证一个字段。在这些情况下,你可以允许闭包接收第二个参数,该参数将是正在验证的数组中的当前单个项目:
$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的实例;否则,它是一个字符串。
验证数组
正如 array validation rule documentation 中所讨论的,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(), [
'users.*.email' => ['email', 'unique:users'],
'users.*.first_name' => ['required_with:users.*.last_name'],
]);同样,在指定 custom validation messages in your language files 时,你可以使用 * 字符,这样就可以轻松地对基于数组的字段使用单个验证消息:
'custom' => [
'users.*.email' => [
'unique' => 'Each user 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),
];
}),
]);错误消息的索引与位置
验证数组时,你可能需要在应用程序显示的错误消息中引用验证失败的特定项目的索引或位置。为此,你可以在custom validation message中包含:index(从0开始)、:position(从1开始)或:ordinal-position(从1st开始)占位符:
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),
],
]);验证文件类型
尽管你只需要在调用 types 方法时指定扩展名,但该方法实际上是通过读取文件内容并猜测其 MIME 类型来验证文件的 MIME 类型。 MIME 类型及其相应扩展名的完整列表可以在以下位置找到:
验证文件大小
为了方便起见,最小和最大文件大小可以指定为带有指示文件大小单位的后缀的字符串。支持 kb、mb、gb 和 tb 后缀:
File::types(['mp3', 'wav'])
->min('1kb')
->max('10mb');验证图片文件
如果你的应用程序接受用户上传的图像,你可以使用File规则的image构造函数来确保验证的文件是图像(jpg、jpeg、png、bmp、gif或webp)。
另外,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)),
],
]);INFO
有关验证图像尺寸的更多信息可以在dimension rule documentation中找到。
WARNING
默认情况下,image 规则不允许 SVG 文件,因为可能存在 XSS 漏洞。如果需要允许 SVG 文件,可以将allowSvg: true 传递给image 规则:File::image(allowSvg: true)。
验证图片尺寸
你还可以验证图像的尺寸。例如,要验证上传的图像至少有 1000 像素宽和 500 像素高,你可以使用 dimensions 规则:
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;
File::image()->dimensions(
Rule::dimensions()
->maxWidth(1000)
->maxHeight(500)
)INFO
有关验证图像尺寸的更多信息可以在dimension rule documentation中找到。
验证密码
为了确保密码具有足够的复杂性,你可以使用 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 most 256 characters...
Password::min(16)->max(256)
// 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-Anonymity 模型来确定密码是否已通过haveibeenpwned.com 服务泄露,而不会牺牲用户的隐私或安全。
默认情况下,如果密码在数据泄露中至少出现一次,则将被视为已泄露。你可以使用uncompromised方法的第一个参数自定义此阈值:
// Ensure the password appears less than 3 times in the same data leak...
Password::min(8)->uncompromised(3);当然,你可以链接上面示例中的所有方法:
Password::min(8)
->max(256)
->letters()
->mixedCase()
->numbers()
->symbols()
->uncompromised()你可以使用 toPasswordRulesString 方法将 Password 规则对象转换为适合 HTML passwordrules 属性的字符串:
<input
type="password"
name="password"
autocomplete="new-password"
passwordrules="{{ Password::defaults()->toPasswordRulesString() }}"
/>定义默认密码规则
你可能会发现在应用程序的单个位置指定密码的默认验证规则很方便。你可以使用 Password::defaults 方法轻松完成此任务,该方法接受闭包。给defaults方法的闭包应该返回密码规则的默认配置。通常,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],
]);翻译验证消息
你也可以提供 translation string key 并指示 Laravel 翻译错误消息,而不是向 $fail 闭包提供文字错误消息:
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 --implicitWARNING
“隐式”规则仅_暗示_该属性是必需的。它是否实际上使缺失或空的属性无效取决于你。