验证
介绍
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
{
/**
* 显示创建新博客文章的表单。
*/
public function create(): View
{
return view('post.create');
}
/**
* 存储新的博客文章。
*/
public function store(Request $request): RedirectResponse
{
// 验证并存储博客文章...
$post = /** ... */
return to_route('post.show', ['post' => $post->id]);
}
}
编写验证逻辑
现在我们准备在 store
方法中填写验证新博客文章的逻辑。为此,我们将使用 Illuminate\Http\Request
对象提供的 validate
方法。如果验证规则通过,您的代码将正常执行;然而,如果验证失败,将抛出 Illuminate\Validation\ValidationException
异常,并自动将适当的错误响应发送回用户。
如果在传统 HTTP 请求期间验证失败,将生成重定向响应到上一个 URL。如果传入请求是 XHR 请求,将返回一个包含验证错误消息的 JSON 响应。
为了更好地理解 validate
方法,让我们回到 store
方法:
/**
* 存储新的博客文章。
*/
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// 博客文章是有效的...
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 将自动将用户重定向回其先前的位置。此外,所有验证错误和请求输入将自动闪存到会话。
Illuminate\View\Middleware\ShareErrorsFromSession
中间件通过 web
中间件组与应用程序的所有视图共享一个 $errors
变量。当应用此中间件时,$errors
变量将始终在您的视图中可用,允许您方便地假设 $errors
变量始终定义并可以安全使用。$errors
变量将是 Illuminate\Support\MessageBag
的一个实例。有关使用此对象的更多信息,请查看其文档。
因此,在我们的示例中,当验证失败时,用户将被重定向到我们控制器的 create
方法,允许我们在视图中显示错误消息:
<!-- /resources/views/post/create.blade.php -->
<h1>创建文章</h1>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- 创建文章表单 -->
自定义错误消息
Laravel 的内置验证规则每个都有一个错误消息,位于应用程序的 lang/en/validation.php
文件中。如果您的应用程序没有 lang
目录,您可以使用 lang:publish
Artisan 命令指示 Laravel 创建它。
在 lang/en/validation.php
文件中,您将找到每个验证规则的翻译条目。您可以根据应用程序的需要自由更改或修改这些消息。
此外,您可以将此文件复制到另一个语言目录中,以翻译应用程序语言的消息。要了解有关 Laravel 本地化的更多信息,请查看完整的本地化文档。
WARNING
默认情况下,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">文章标题</label>
<input
id="title"
type="text"
name="title"
class="@error('title') is-invalid @enderror"
/>
@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror
如果您使用命名错误包,可以将错误包的名称作为第二个参数传递给 @error
指令:
<input ... class="@error('title', 'post') is-invalid @enderror">
重新填充表单
当 Laravel 由于验证错误生成重定向响应时,框架将自动闪存请求的所有输入到会话。这样做是为了便于您在下一个请求期间访问输入并重新填充用户尝试提交的表单。
要从上一个请求中检索闪存的输入,请在 Illuminate\Http\Request
的实例上调用 old
方法。old
方法将从会话中提取先前闪存的输入数据:
$title = $request->old('title');
Laravel 还提供了一个全局 old
辅助函数。如果您在Blade 模板中显示旧输入,使用 old
辅助函数重新填充表单更为方便。如果给定字段没有旧输入,将返回 null
:
<input type="text" name="title" value="{{ old('title') }}">
关于可选字段的说明
默认情况下,Laravel 在应用程序的全局中间件堆栈中包含 TrimStrings
和 ConvertEmptyStringsToNull
中间件。因此,如果您不希望验证器将 null
值视为无效,通常需要将“可选”请求字段标记为 nullable
。例如:
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]);
在此示例中,我们指定 publish_at
字段可以是 null
或有效的日期表示。如果未将 nullable
修饰符添加到规则定义中,验证器将视 null
为无效日期。
验证错误响应格式
当您的应用程序抛出 Illuminate\Validation\ValidationException
异常并且传入的 HTTP 请求期望 JSON 响应时,Laravel 将自动为您格式化错误消息并返回 422 Unprocessable Entity
HTTP 响应。
下面,您可以查看验证错误的 JSON 响应格式示例。请注意,嵌套的错误键被展平为“点”符号格式:
{
"message": "团队名称必须是字符串。(还有 4 个错误)",
"errors": {
"team_name": [
"团队名称必须是字符串。",
"团队名称必须至少 1 个字符。"
],
"authorization.role": [
"所选的 authorization.role 无效。"
],
"users.0.email": [
"users.0.email 字段是必需的。"
],
"users.2.email": [
"users.2.email 必须是有效的电子邮件地址。"
]
}
}
表单请求验证
创建表单请求
对于更复杂的验证场景,您可能希望创建一个“表单请求”。表单请求是自定义请求类,封装了自己的验证和授权逻辑。要创建表单请求类,您可以使用 make:request
Artisan CLI 命令:
php artisan make:request StorePostRequest
生成的表单请求类将放置在 app/Http/Requests
目录中。如果此目录不存在,当您运行 make:request
命令时将创建它。Laravel 生成的每个表单请求都有两个方法:authorize
和 rules
。
正如您可能猜到的那样,authorize
方法负责确定当前认证的用户是否可以执行请求所代表的操作,而 rules
方法返回应应用于请求数据的验证规则:
/**
* 获取适用于请求的验证规则。
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
NOTE
您可以在 rules
方法的签名中类型提示您需要的任何依赖项。它们将通过 Laravel 服务容器自动解析。
那么,验证规则是如何评估的呢?您只需在控制器方法中类型提示请求即可。在调用控制器方法之前,将验证传入的表单请求,这意味着您不需要在控制器中混杂任何验证逻辑:
/**
* 存储新的博客文章。
*/
public function store(StorePostRequest $request): RedirectResponse
{
// 传入的请求是有效的...
// 检索验证后的输入数据...
$validated = $request->validated();
// 检索验证输入数据的一部分...
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
// 存储博客文章...
return redirect('/posts');
}
如果验证失败,将生成重定向响应以将用户发送回其先前的位置。错误也将闪存到会话中,以便显示。如果请求是 XHR 请求,将返回包含验证错误的 JSON 表示的 HTTP 响应,状态码为 422。
NOTE
需要将实时表单请求验证添加到您的 Inertia 驱动的 Laravel 前端吗?查看 Laravel Precognition。
在表单请求上执行额外的验证
有时您需要在初始验证完成后执行额外的验证。您可以使用表单请求的 after
方法实现此目的。
after
方法应返回一个可调用或闭包数组,这些将在验证完成后调用。给定的可调用将接收一个 Illuminate\Validation\Validator
实例,允许您在必要时添加额外的错误消息:
use Illuminate\Validation\Validator;
/**
* 获取请求的“后”验证可调用。
*/
public function after(): array
{
return [
function (Validator $validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field',
'此字段有问题!'
);
}
}
];
}
如上所述,after
方法返回的数组还可以包含可调用类。这些类的 __invoke
方法将接收一个 Illuminate\Validation\Validator
实例:
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
use Illuminate\Validation\Validator;
/**
* 获取请求的“后”验证可调用。
*/
public function after(): array
{
return [
new ValidateUserStatus,
new ValidateShippingTime,
function (Validator $validator) {
//
}
];
}
在第一次验证规则失败时停止
通过向请求类添加 stopOnFirstFailure
属性,您可以通知验证器一旦发生单个验证失败,它应停止验证所有属性:
/**
* 指示验证器是否应在第一个规则失败时停止。
*
* @var bool
*/
protected $stopOnFirstFailure = true;
自定义重定向位置
当表单请求验证失败时,将生成重定向响应以将用户发送回其先前的位置。然而,您可以自由自定义此行为。为此,请在表单请求上定义一个 $redirect
属性:
/**
* 如果验证失败,用户应重定向到的 URI。
*
* @var string
*/
protected $redirect = '/dashboard';
或者,如果您希望将用户重定向到命名路由,可以定义一个 $redirectRoute
属性:
/**
* 如果验证失败,用户应重定向到的路由。
*
* @var string
*/
protected $redirectRoute = 'dashboard';
授权表单请求
表单请求类还包含一个 authorize
方法。在此方法中,您可以确定认证用户是否确实有权更新给定资源。例如,您可以确定用户是否确实拥有他们尝试更新的博客评论。您很可能会在此方法中与您的授权门和策略进行交互:
use App\Models\Comment;
/**
* 确定用户是否有权发出此请求。
*/
public function authorize(): bool
{
$comment = Comment::find($this->route('comment'));
return $comment && $this->user()->can('update', $comment);
}
由于所有表单请求都扩展了基本的 Laravel 请求类,我们可以使用 user
方法访问当前认证的用户。此外,请注意上面示例中的 route
方法调用。此方法允许您访问在调用的路由上定义的 URI 参数,例如示例中的 {comment}
参数:
Route::post('/comment/{comment}');
因此,如果您的应用程序利用了路由模型绑定,您的代码可以通过将解析的模型作为请求的属性访问来变得更加简洁:
return $this->user()->can('update', $this->comment);
如果 authorize
方法返回 false
,将自动返回一个状态码为 403 的 HTTP 响应,并且您的控制器方法将不会执行。
如果您计划在应用程序的其他部分处理请求的授权逻辑,可以完全删除 authorize
方法,或者简单地返回 true
:
/**
* 确定用户是否有权发出此请求。
*/
public function authorize(): bool
{
return true;
}
NOTE
您可以在 authorize
方法的签名中类型提示您需要的任何依赖项。它们将通过 Laravel 服务容器自动解析。
自定义错误消息
您可以通过覆盖 messages
方法来自定义表单请求使用的错误消息。此方法应返回一个属性/规则对及其对应错误消息的数组:
/**
* 获取定义的验证规则的错误消息。
*
* @return array<string, string>
*/
public function messages(): array
{
return [
'title.required' => '需要一个标题',
'body.required' => '需要一条消息',
];
}
自定义验证属性
Laravel 的许多内置验证规则错误消息包含一个 :attribute
占位符。如果您希望验证消息的 :attribute
占位符替换为自定义属性名称,可以通过覆盖 attributes
方法指定自定义名称。此方法应返回一个属性/名称对的数组:
/**
* 获取验证器错误的自定义属性。
*
* @return array<string, string>
*/
public function attributes(): array
{
return [
'email' => '电子邮件地址',
];
}
准备输入进行验证
如果您需要在应用验证规则之前准备或清理请求中的任何数据,可以使用 prepareForValidation
方法:
use Illuminate\Support\Str;
/**
* 准备数据进行验证。
*/
protected function prepareForValidation(): void
{
$this->merge([
'slug' => Str::slug($this->slug),
]);
}
同样,如果您需要在验证完成后规范化任何请求数据,可以使用 passedValidation
方法:
/**
* 处理通过的验证尝试。
*/
protected function passedValidation(): void
{
$this->replace(['name' => 'Taylor']);
}
手动创建验证器
如果您不想在请求上使用 validate
方法,可以使用 Validator
facade 手动创建验证器实例。facade 上的 make
方法生成一个新的验证器实例:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
/**
* 存储新的博客文章。
*/
public function store(Request $request): RedirectResponse
{
$validator = Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
if ($validator->fails()) {
return redirect('/post/create')
->withErrors($validator)
.withInput();
}
// 检索验证后的输入...
$validated = $validator->validated();
// 检索验证输入数据的一部分...
$validated = $validator->safe()->only(['name', 'email']);
$validated = $validator->safe()->except(['name', 'email']);
// 存储博客文章...
return redirect('/posts');
}
}
传递给 make
方法的第一个参数是验证的数据。第二个参数是应应用于数据的验证规则数组。
在确定请求验证是否失败后,您可以使用 withErrors
方法将错误消息闪存到会话中。使用此方法时,$errors
变量将在重定向后自动与您的视图共享,允许您轻松地将它们显示给用户。withErrors
方法接受一个验证器、一个 MessageBag
或一个 PHP array
。
在第一次验证失败时停止
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', '此字段有问题!'
);
}
});
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
实例可以像数组一样迭代和访问:
// 验证后的数据可以迭代...
foreach ($request->safe() as $key => $value) {
// ...
}
// 验证后的数据可以作为数组访问...
$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
目录,您可以使用 lang:publish
Artisan 命令指示 Laravel 创建它。
在 lang/en/validation.php
文件中,您将找到每个验证规则的翻译条目。您可以根据应用程序的需要自由更改或修改这些消息。
此外,您可以将此文件复制到另一个语言目录中,以翻译应用程序语言的消息。要了解有关 Laravel 本地化的更多信息,请查看完整的本地化文档。
WARNING
默认情况下,Laravel 应用程序骨架不包含 lang
目录。如果您想自定义 Laravel 的语言文件,可以通过 lang:publish
Artisan 命令发布它们。
特定属性的自定义消息
您可以在应用程序的验证语言文件中为指定的属性和规则组合自定义错误消息。为此,请将您的消息自定义添加到应用程序的 lang/xx/validation.php
语言文件的 custom
数组中:
'custom' => [
'email' => [
'required' => '我们需要知道您的电子邮件地址!',
'max' => '您的电子邮件地址太长了!'
],
],
在语言文件中指定属性
Laravel 的许多内置错误消息包括一个 :attribute
占位符,该占位符将被验证的字段或属性的名称替换。如果您希望验证消息的 :attribute
部分替换为自定义值,可以在 lang/xx/validation.php
语言文件的 attributes
数组中指定自定义属性名称:
'attributes' => [
'email' => '电子邮件地址',
],
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'
]);
如果此验证规则失败,它将生成以下错误消息:
当支付类型为 cc 时,信用卡号字段是必需的。
您可以在 lang/xx/validation.php
语言文件中定义一个 values
数组,指定一个更用户友好的值表示,而不是显示 cc
作为支付类型值:
'values' => [
'payment_type' => [
'cc' => '信用卡'
],
],
WARNING
默认情况下,Laravel 应用程序骨架不包含 lang
目录。如果您想自定义 Laravel 的语言文件,可以通过 lang:publish
Artisan 命令发布它们。
定义此值后,验证规则将生成以下错误消息:
当支付类型为信用卡时,信用卡号字段是必需的。
可用的验证规则
以下是所有可用验证规则及其功能的列表:
布尔值
字符串
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
验证字段必须是 "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 的主机名使用 parse_url
PHP 函数提取,然后传递给 dns_get_record
。
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
验证字段必须完全是 Unicode 字母字符,包含在 \p{L} 和 \p{M} 中。
要将此验证规则限制为 ASCII 范围内的字符(a-z
和 A-Z
),您可以为验证规则提供 ascii
选项:
'username' => 'alpha:ascii',
alpha_dash
验证字段必须完全是 Unicode 字母数字字符,包含在 \p{L}、\p{M}、 \p{N},以及 ASCII 破折号(-
)和 ASCII 下划线(_
)。
要将此验证规则限制为 ASCII 范围内的字符(a-z
、A-Z
和 0-9
),您可以为验证规则提供 ascii
选项:
'username' => 'alpha_dash:ascii',
alpha_num
验证字段必须完全是 Unicode 字母数字字符,包含在 \p{L}、\p{M} 和 \p{N} 中。
要将此验证规则限制为 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',
]);
通常,您应该始终指定允许在数组中存在的数组键。
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"
。
confirmed
验证字段必须有一个匹配的 {field}_confirmation
字段。例如,如果验证字段是 password
,则输入中必须存在一个匹配的 password_confirmation
字段。
您还可以传递自定义确认字段名称。例如,confirmed:repeat_username
将期望字段 repeat_username
与验证字段匹配。
contains:foo,bar,...
验证字段必须是包含所有给定参数值的数组。
current_password
验证字段必须与经过身份验证的用户的密码匹配。您可以使用规则的第一个参数指定身份验证守卫:
'password' => 'current_password:api'
date
验证字段必须是根据 strtotime
PHP 函数的有效非相对日期。
date_equals:date
验证字段必须等于给定日期。日期将传递给 PHP strtotime
函数以转换为有效的 DateTime
实例。
date_format:format,...
验证字段必须匹配给定 formats 之一。验证字段时,您应该使用 either date
或 date_format
。此验证规则支持 PHP 的 DateTime 类支持的所有格式。
为了方便起见,可以使用流畅的 date
规则构建器构建基于日期的规则:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->format('Y-m-d'),
],
decimal:min,max
验证字段必须是数字,并且必须包含指定的小数位数:
// 必须恰好有两位小数(9.99)...
'price' => 'decimal:2'
// 必须有 2 到 4 位小数...
'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。
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'
上面的示例将应用 RFCValidation
和 DNSCheckValidation
验证。以下是您可以应用的验证样式的完整列表:
rfc
:RFCValidation
- 根据 支持的 RFC 标准 验证电子邮件地址。strict
:NoRFCWarningsValidation
- 根据 支持的 RFC 标准 验证电子邮件地址,在发现警告时验证失败(例如末尾的句点或连续多个句点)。dns
:DNSCheckValidation
- 确保电子邮件地址的域具有有效的 MX 记录。spoof
:SpoofCheckValidation
- 确保电子邮件地址不包含同形或欺骗性 Unicode 字符。filter
:FilterEmailValidation
- 确保电子邮件地址根据 PHP 的filter_var
函数有效。filter_unicode
:FilterEmailValidation::unicode()
- 确保电子邮件地址根据 PHP 的filter_var
函数有效,允许某些 Unicode 字符。
为了方便起见,可以使用流畅的规则构建器构建电子邮件验证规则:
use Illuminate\Validation\Rule;
$request->validate([
'email' => [
'required',
Rule::email()
->rfcCompliant(strict: false)
->validateMxRecord()
->preventSpoofing()
],
]);
WARNING
dns
和 spoof
验证器需要 PHP intl
扩展。
ends_with:foo,bar,...
验证字段必须以给定值之一结尾。
enum
Enum
规则是一个基于类的规则,用于验证验证字段是否包含有效的枚举值。Enum
规则接受枚举名称作为其唯一的构造函数参数。在验证原始值时,应将后备枚举提供给 Enum
规则:
use App\Enums\ServerStatus;
use Illuminate\Validation\Rule;
$request->validate([
'status' => [Rule::enum(ServerStatus::class)],
]);
Enum
规则的 only
和 except
方法可用于限制应视为有效的枚举案例:
Rule::enum(ServerStatus::class)
->only([ServerStatus::Pending, ServerStatus::Active]);
Rule::enum(ServerStatus::class)
->except([ServerStatus::Pending, ServerStatus::Active]);
when
方法可用于有条件地修改 Enum
规则:
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;
Rule::enum(ServerStatus::class)
->when(
Auth::user()->isAdmin(),
fn ($rule) => $rule->only(...),
fn ($rule) => $rule->only(...),
);
exclude
验证字段将从 validate
和 validated
方法返回的请求数据中排除。
exclude_if:anotherfield,value
如果 anotherfield 字段等于 value,则验证字段将从 validate
和 validated
方法返回的请求数据中排除。
如果需要复杂的条件排除逻辑,您可以使用 Rule::excludeIf
方法。此方法接受布尔值或闭包。当给定闭包时,闭包应返回 true
或 false
以指示是否应排除验证字段:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => Rule::excludeIf($request->user()->is_admin),
]);
Validator::make($request->all(), [
'role_id' => Rule::excludeIf(fn () => $request->user()->is_admin),
]);
exclude_unless:anotherfield,value
除非 anotherfield 字段等于 value,否则验证字段将从 validate
和 validated
方法返回的请求数据中排除。如果 value 为 null
(exclude_unless:name,null
),则验证字段将被排除,除非比较字段为 null
或请求数据中缺少比较字段。
exclude_with:anotherfield
如果 anotherfield 字段存在,则验证字段将从 validate
和 validated
方法返回的请求数据中排除。
exclude_without:anotherfield
如果 anotherfield 字段不存在,则验证字段将从 validate
和 validated
方法返回的请求数据中排除。
exists:table,column
验证字段必须存在于给定的数据库表中。
Exists 规则的基本用法
'state' => 'exists:states'
如果未指定 column
选项,将使用字段名称。因此,在这种情况下,规则将验证 states
数据库表是否包含与请求的 state
属性值匹配的 state
列值的记录。
指定自定义列名称
您可以通过将其放在数据库表名称之后来显式指定验证规则应使用的数据库列名称:
'state' => 'exists:states,abbreviation'
有时,您可能需要指定特定的数据库连接以用于 exists
查询。您可以通过在表名称前加上连接名称来实现这一点:
'email' => 'exists:connection.staff,email'
您可以指定应使用哪个 Eloquent 模型来确定表名称,而不是直接指定表名称:
'user_id' => 'exists:App\Models\User,id'
如果您想自定义验证规则执行的查询,可以使用 Rule
类流畅地定义规则。在此示例中,我们还将指定验证规则为数组,而不是使用 |
字符来分隔它们:
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::exists('staff')->where(function (Builder $query) {
$query->where('account_id', 1);
}),
],
]);
您可以通过将列名称作为 exists
方法的第二个参数提供,显式指定 exists
规则生成的 Rule::exists
方法应使用的数据库列名称:
'state' => Rule::exists('states', 'abbreviation'),
extensions:foo,bar,...
验证的文件必须具有与列出的扩展名之一对应的用户分配扩展名:
'photo' => ['required', 'extensions:jpg,png'],
file
验证字段必须是成功上传的文件。
filled
验证字段在存在时不得为空。
gt:field
验证字段必须大于给定的 field 或 value。两个字段必须是相同类型的。字符串、数字、数组和文件的评估方式与 size 规则相同。
gte:field
验证字段必须大于或等于给定的 field 或 value。两个字段必须是相同类型的。字符串、数字、数组和文件的评估方式与 size 规则相同。
hex_color
验证字段必须包含有效的 十六进制 格式的颜色值。
image
验证的文件必须是图像(jpg、jpeg、png、bmp、gif 或 webp)。
WARNING
默认情况下,图像规则不允许 SVG 文件,因为可能存在 XSS 漏洞。如果您需要允许 SVG 文件,可以为 image
规则提供 allow_svg
指令(image: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 的值中。
integer
验证字段必须是整数。
WARNING
此验证规则不验证输入是否为“整数”变量类型,仅验证输入是否为 PHP 的 FILTER_VALIDATE_INT
规则接受的类型。如果您需要验证输入为数字,请将此规则与数字验证规则结合使用。
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'
。
WARNING
使用 regex
/ not_regex
模式时,可能需要使用数组而不是 |
分隔符来指定验证规则,尤其是当正则表达式包含 |
字符时。
nullable
验证字段可以为 null
。
numeric
验证字段必须是数字。
present
验证字段必须存在于输入数据中。
present_if:anotherfield,value,...
如果 anotherfield 字段等于任何 value,则验证字段必须存在。
present_unless:anotherfield,value
除非 anotherfield 字段等于任何 value,否则验证字段必须存在。
present_with:foo,bar,...
验证字段必须存在,仅当其他指定字段中的任何一个存在时。
present_with_all:foo,bar,...
验证字段必须存在,仅当所有其他指定字段存在时。
prohibited
验证字段必须丢失或为空。如果字段符合以下条件之一,则该字段为空:
- 值为
null
。 - 值为空字符串。
- 值为空数组或空的
Countable
对象。 - 值是路径为空的上传文件。
prohibited_if:anotherfield,value,...
如果 anotherfield 字段等于任何 value,则验证字段必须丢失或为空。如果字段符合以下条件之一,则该字段为空:
- 值为
null
。 - 值为空字符串。
- 值为空数组或空的
Countable
对象。 - 值是路径为空的上传文件。
如果需要复杂的条件禁止逻辑,您可以使用 Rule::prohibitedIf
方法。此方法接受布尔值或闭包。当给定闭包时,闭包应返回 true
或 false
以指示是否应禁止验证字段:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => Rule::prohibitedIf($request->user()->is_admin),
]);
Validator::make($request->all(), [
'role_id' => Rule::prohibitedIf(fn () => $request->user()->is_admin),
]);
prohibited_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,否则验证字段必须丢失或为空。如果字段符合以下条件之一,则该字段为空:
- 值为
null
。 - 值为空字符串。
- 值为空数组或空的
Countable
对象。 - 值是路径为空的上传文件。
prohibits:anotherfield,...
如果验证字段未丢失或为空,则 anotherfield 中的所有字段必须丢失或为空。如果字段符合以下条件之一,则该字段为空:
- 值为
null
。 - 值为空字符串。
- 值为空数组或空的
Countable
对象。 - 值是路径为空的上传文件。
regex:pattern
验证字段必须与给定的正则表达式匹配。
在内部,此规则使用 PHP preg_match
函数。指定的模式应遵循 preg_match
所需的相同格式,因此还应包括有效的分隔符。例如:'email' => 'regex:/^.+@.+$/i'
。
WARNING
使用 regex
/ not_regex
模式时,可能需要使用数组而不是 |
分隔符来指定规则,尤其是当正则表达式包含 |
字符时。
required
验证字段必须存在于输入数据中且不能为空。如果字段符合以下条件之一,则该字段为空:
- 值为
null
。 - 值为空字符串。
- 值为空数组或空的
Countable
对象。 - 值是路径为空的上传文件。
required_if:anotherfield,value,...
如果 anotherfield 字段等于任何 value,则验证字段必须存在且不能为空。
如果您想为 required_if
规则构建更复杂的条件,可以使用 Rule::requiredIf
方法。此方法接受布尔值或闭包。当传递闭包时,闭包应返回 true
或 false
以指示验证字段是否为必需:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => Rule::requiredIf($request->user()->is_admin),
]);
Validator::make($request->all(), [
'role_id' => Rule::requiredIf(fn () => $request->user()->is_admin),
]);
required_if_accepted:anotherfield,...
如果 anotherfield 字段等于 "yes"
、"on"
、1
、"1"
、true
或 "true"
,则验证字段必须存在且不能为空。
required_if_declined:anotherfield,...
如果 anotherfield 字段等于 "no"
、"off"
、0
、"0"
、false
或 "false"
,则验证字段必须存在且不能为空。
required_unless:anotherfield,value,...
除非 anotherfield 字段等于任何 value,否则验证字段必须存在且不能为空。这也意味着 anotherfield 必须存在于请求数据中,除非 value 为 null
。如果 value 为 null
(required_unless:name,null
),则验证字段将是必需的,除非比较字段为 null
或请求数据中缺少比较字段。
required_with:foo,bar,...
验证字段必须存在且不能为空,仅当其他指定字段中的任何一个存在且不为空时。
required_with_all:foo,bar,...
验证字段必须存在且不能为空,仅当所有其他指定字段存在且不为空时。
required_without:foo,bar,...
验证字段必须存在且不能为空,仅当其他指定字段中的任何一个为空或不存在时。
required_without_all:foo,bar,...
验证字段必须存在且不能为空,仅当所有其他指定字段为空或不存在时。
required_array_keys:foo,bar,...
验证字段必须是数组,并且必须至少包含指定的键。
same:field
给定的 field 必须与验证字段匹配。
size:value
验证字段的大小必须与给定的 value 匹配。对于字符串数据,value 对应于字符数。对于数字数据,value 对应于给定的整数值(属性还必须具有 numeric
或 integer
规则)。对于数组,size 对应于数组的 count
。对于文件,size 对应于文件大小(以千字节为单位)。让我们看一些示例:
// 验证字符串是否恰好为 12 个字符...
'title' => 'size:12';
// 验证提供的整数是否等于 10...
'seats' => 'integer|size:10';
// 验证数组是否恰好有 5 个元素...
'tags' => 'array|size:5';
// 验证上传的文件是否恰好为 512 千字节...
'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),
],
]);
WARNING
您绝不应将任何用户控制的请求输入传递给 ignore
方法。相反,您应该只传递系统生成的唯一 ID,例如 Eloquent 模型实例中的自动递增 ID 或 UUID。否则,您的应用程序将容易受到 SQL 注入攻击。
您可以将整个模型实例传递给 ignore
方法,而不是将模型键的值传递给 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))
在唯一检查中忽略软删除的记录:
默认情况下,唯一规则在确定唯一性时包括软删除的记录。要从唯一性检查中排除软删除的记录,可以调用 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
验证字段必须是有效的通用唯一字母排序标识符 (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',
]);
在上面的示例中,只有在 $data
数组中存在 email
字段时才会对其进行验证。
NOTE
如果您尝试验证一个应该始终存在但可能为空的字段,请查看关于可选字段的说明。
复杂条件验证
有时您可能希望根据更复杂的条件逻辑添加验证规则。例如,您可能希望仅在另一个字段的值大于 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;
});
NOTE
传递给闭包的 $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 验证规则文档中所述,array
规则接受允许的数组键列表。如果数组中存在任何其他键,验证将失败:
use Illuminate\Support\Facades\Validator;
$input = [
'user' => [
'name' => 'Taylor Otwell',
'username' => 'taylorotwell',
'admin' => true,
],
];
Validator::make($input, [
'user' => 'array:name,username',
]);
通常,您应该始终指定允许在数组中存在的数组键。否则,验证器的 validate
和 validated
方法将返回所有经过验证的数据,包括数组及其所有键,即使这些键未通过其他嵌套数组验证规则验证。
验证嵌套数组输入
验证基于嵌套数组的表单输入字段并不困难。您可以使用“点符号”来验证数组中的属性。例如,如果传入的 HTTP 请求包含 photos[profile]
字段,您可以这样验证它:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'photos.profile' => 'required|image',
]);
您还可以验证数组的每个元素。例如,要验证给定数组输入字段中的每个电子邮件是否唯一,您可以执行以下操作:
$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);
同样,您可以在语言文件中指定自定义验证消息时使用 *
字符,使得为基于数组的字段使用单个验证消息变得轻而易举:
'custom' => [
'person.*.email' => [
'unique' => '每个人必须有一个唯一的电子邮件地址',
]
],
访问嵌套数组数据
有时您可能需要在为属性分配验证规则时访问给定嵌套数组元素的值。您可以使用 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' => '请描述照片 #:position。',
]);
根据上面的示例,验证将失败,用户将看到以下错误:“请描述照片 #2。”
如果需要,您可以通过 second-index
、second-position
、third-index
、third-position
等引用更深层次的嵌套索引和位置。
'photos.*.attributes.*.string' => '照片 #: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 类型及其对应扩展名的完整列表:
https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
验证文件大小
为了方便起见,可以将最小和最大文件大小指定为带有指示文件大小单位的后缀的字符串。支持 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)),
],
]);
NOTE
有关验证图像尺寸的更多信息,请参阅尺寸规则文档。
WARNING
默认情况下,由于可能存在 XSS 漏洞,image
规则不允许 SVG 文件。如果您需要允许 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)
)
NOTE
有关验证图像尺寸的更多信息,请参阅尺寸规则文档。
验证密码
为了确保密码具有足够的复杂性,您可以使用 Laravel 的 Password
规则对象:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;
$validator = Validator::make($request->all(), [
'password' => ['required', 'confirmed', Password::min(8)],
]);
Password
规则对象允许您轻松自定义应用程序的密码复杂性要求,例如指定密码至少需要一个字母、数字、符号或混合大小写字符:
// 至少需要 8 个字符...
Password::min(8)
// 至少需要一个字母...
Password::min(8)->letters()
// 至少需要一个大写字母和一个小写字母...
Password::min(8)->mixedCase()
// 至少需要一个数字...
Password::min(8)->numbers()
// 至少需要一个符号...
Password::min(8)->symbols()
此外,您可以使用 uncompromised
方法确保密码未在公共密码数据泄露中被泄露:
Password::min(8)->uncompromised()
在内部,Password
规则对象使用 k-匿名性 模型通过 haveibeenpwned.com 服务确定密码是否已泄露,而不会牺牲用户的隐私或安全性。
默认情况下,如果密码在数据泄露中至少出现一次,则会被视为已泄露。您可以使用 uncompromised
方法的第一个参数自定义此阈值:
// 确保密码在同一数据泄露中出现次数少于 3 次...
Password::min(8)->uncompromised(3);
当然,您可以将上述所有方法链接在一起:
Password::min(8)
->letters()
->mixedCase()
->numbers()
->symbols()
->uncompromised()
定义默认密码规则
您可能会发现方便的是在应用程序的单个位置指定密码的默认验证规则。您可以使用 Password::defaults
方法轻松实现这一点,该方法接受一个闭包。传递给 defaults
方法的闭包应返回 Password 规则的默认配置。通常,defaults
规则应在应用程序的某个服务提供者的 boot
方法中调用:
use Illuminate\Validation\Rules\Password;
/**
* 启动任何应用程序服务。
*/
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
{
/**
* 运行验证规则。
*/
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],
]);
翻译验证消息
您可以提供翻译字符串键并指示 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
{
/**
* 所有正在验证的数据。
*
* @var array<string, mixed>
*/
protected $data = [];
// ...
/**
* 设置正在验证的数据。
*
* @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
{
/**
* 验证器实例。
*
* @var \Illuminate\Validation\Validator
*/
protected $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
要使自定义规则即使在属性为空时也能运行,该规则必须暗示该属性是必需的。要快速生成新的隐式规则对象,您可以使用带有 --implicit
选项的 make:rule
Artisan 命令:
php artisan make:rule Uppercase --implicit
WARNING
“隐式”规则仅_暗示_该属性是必需的。是否实际使缺失或空的属性无效取决于您。