跳至内容

验证

简介

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 本地化的更多信息,请查看完整的 本地化文档

exclamation

默认情况下,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 在应用程序的全局中间件栈中包含 TrimStringsConvertEmptyStringsToNull 中间件。因此,如果您不希望验证器将 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 生成的每个表单请求都有两种方法:authorizerules

正如您可能猜到的,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',
];
}
lightbulb

您可以在 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 表示形式

lightbulb

需要将实时表单请求验证添加到您的 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;
}
lightbulb

您可以在 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 的实例。此对象公开了 onlyexceptall 方法以检索已验证数据的子集或已验证数据的整个数组。

$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 本地化的更多信息,请查看完整的 本地化文档

exclamation

默认情况下,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',
],
exclamation

默认情况下,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'
],
],
exclamation

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

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

The credit card number field is required when payment type is credit card.

可用的验证规则

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

已接受

正在验证的字段必须为"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-zA-Z),可以向验证规则提供ascii选项

'username' => 'alpha:ascii',

字母和短划线

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

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

'username' => 'alpha_dash:ascii',

字母数字

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

要将此验证规则限制在 ASCII 范围内的字符(a-zA-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

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

布尔值

正在验证的字段必须能够转换为布尔值。可接受的输入为truefalse10"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之一匹配。在验证字段时,应使用datedate_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

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

尺寸

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

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

可用的约束条件包括:min_widthmax_widthmin_heightmax_heightwidthheightratio

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,...

待验证的字段不得以给定值中的任何一个结尾。

email

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

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

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

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

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

exclamation

dnsspoof 验证器需要 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 规则的 onlyexcept 方法可用于限制哪些枚举情况应被视为有效。

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

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

exclude_if:anotherfield,value

如果 anotherfield 字段等于 value,则待验证的字段将从 validatevalidated 方法返回的请求数据中排除。

如果需要复杂的条件排除逻辑,您可以使用 Rule::excludeIf 方法。此方法接受布尔值或闭包。当给定闭包时,闭包应返回 truefalse 以指示是否应排除待验证的字段。

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,否则待验证的字段将从 validatevalidated 方法返回的请求数据中排除。如果 valuenullexclude_unless:name,null),则除非比较字段为 null 或请求数据中缺少比较字段,否则待验证的字段将被排除。

exclude_with:anotherfield

如果 anotherfield 字段存在,则待验证的字段将从 validatevalidated 方法返回的请求数据中排除。

exclude_without:anotherfield

如果 anotherfield 字段不存在,则待验证的字段将从 validatevalidated 方法返回的请求数据中排除。

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'],
exclamation

您永远不要仅仅依靠验证文件及其用户分配的扩展名。此规则通常应始终与 mimesmimetypes 规则结合使用。

file

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

filled

当字段存在时,待验证的字段不得为空。

gt:field

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

gte:field

待验证的字段必须大于或等于给定的 fieldvalue。这两个字段必须具有相同的类型。字符串、数字、数组和文件使用与 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

待验证的字段必须是整数。

exclamation

此验证规则不验证输入是否为“整数”变量类型,仅验证输入是否为 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'

exclamation

使用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方法。此方法接受布尔值或闭包。当给定闭包时,闭包应返回truefalse以指示是否应禁止正在验证的字段。

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'

exclamation

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

required

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

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

required_if:anotherfield,value,...

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

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

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必须存在于请求数据中,除非valuenull。如果valuenullrequired_unless:name,null),则除非比较字段为null或比较字段缺失于请求数据中,否则正在验证的字段将是必需的。

required_with:foo,bar,...

正在验证的字段只有在任何其他指定字段存在且不为空时才必须存在且不为空。

required_with_all:foo,bar,...

正在验证的字段只有在所有其他指定字段都存在且不为空时才必须存在且不为空。

required_without:foo,bar,...

正在验证的字段只有在任何其他指定字段为空或不存在时才必须存在且不为空。

required_without_all:foo,bar,...

正在验证的字段只有在所有其他指定字段都为空或不存在时才必须存在且不为空。

required_array_keys:foo,bar,...

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

same:field

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

size:value

正在验证的字段的大小必须与给定的value匹配。对于字符串数据,value对应于字符数。对于数字数据,value对应于给定的整数值(属性也必须具有numericinteger规则)。对于数组,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),
],
]);
exclamation

您永远不应将任何用户控制的请求输入传递到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_datedoctor_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数组中时,才会对其进行验证。

lightbulb

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

复杂的条件验证

有时,您可能希望根据更复杂的条件逻辑添加验证规则。例如,您可能希望仅当另一个字段的值大于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;
});
lightbulb

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

复杂的条件数组验证

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

$input = [
'channels' => [
[
'type' => 'email',
'address' => '[email protected]',
],
[
'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',
]);

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

验证嵌套数组输入

验证基于嵌套数组的表单输入字段不必很麻烦。您可以使用“点表示法”来验证数组中的属性。例如,如果传入的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-indexsecond-positionthird-indexthird-position等引用更深层次的嵌套索引和位置。

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

验证文件

Laravel 提供了各种可用于验证上传文件的验证规则,例如mimesimageminmax。虽然您可以自由地在验证文件时单独指定这些规则,但 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)),
],
]);
lightbulb

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

文件大小

为了方便起见,最小和最大文件大小可以指定为带有后缀的字符串,该后缀指示文件大小单位。支持kbmbgbtb后缀。

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
exclamation

“隐式”规则仅暗示属性是必需的。它是否实际使缺少或空的属性无效取决于您。