主题
表单验证
简介
Laravel 提供了多种不同的方法来验证应用程序的传入数据。最常见的是使用所有传入 HTTP 请求上可用的 validate 方法。不过,我们也会讨论其他验证方法。
Laravel 包含了各种方便的验证规则,你可以将它们应用于数据,甚至提供了验证值在给定数据库表中是否唯一的能力。我们将详细介绍每个验证规则,以便你熟悉 Laravel 的所有验证功能。
验证快速入门
为了了解 Laravel 强大的验证功能,让我们看一个验证表单并将错误消息显示给用户的完整示例。通过阅读这个高层概述,你将能够很好地了解如何使用 Laravel 验证传入的请求数据:
定义路由
首先,假设我们在 routes/web.php 文件中定义了以下路由:
php
use App\Http\Controllers\PostController;
Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);GET 路由将显示一个供用户创建新博客文章的表单,而 POST 路由将新博客文章存储到数据库中。
创建控制器
接下来,让我们看一个处理这些路由传入请求的简单控制器。我们暂时将 store 方法留空:
php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class PostController extends Controller
{
/**
* 显示创建新博客文章的表单。
*/
public function create(): View
{
return view('post.create');
}
/**
* 存储新博客文章。
*/
public function store(Request $request): RedirectResponse
{
// 验证并存储博客文章...
$post = /** ... */
return to_route('post.show', ['post' => $post->id]);
}
}编写验证逻辑
现在我们准备在 store 方法中填写验证新博客文章的逻辑。为此,我们将使用 Illuminate\Http\Request 对象提供的 validate 方法。如果验证规则通过,你的代码将继续正常执行;但如果验证失败,将抛出 Illuminate\Validation\ValidationException 异常,并自动将适当的错误响应发送回用户。
如果在传统 HTTP 请求期间验证失败,将生成重定向到先前 URL 的响应。如果传入请求是 XHR 请求,将返回包含验证错误消息的 JSON 响应。
为了更好地理解 validate 方法,让我们回到 store 方法:
php
/**
* 存储新博客文章。
*/
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
// 博客文章有效...
return redirect('/posts');
}如你所见,验证规则被传递到 validate 方法中。不用担心 - 所有可用的验证规则都有文档记录。同样,如果验证失败,将自动生成适当的响应。如果验证通过,我们的控制器将继续正常执行。
此外,你可以使用 validateWithBag 方法来验证请求并将任何错误消息存储在命名错误包中:
php
$validated = $request->validateWithBag('post', [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);在第一次验证失败时停止
有时你可能希望在第一次验证失败后停止对属性运行验证规则。为此,将 bail 规则分配给该属性:
php
$request->validate([
'title' => ['bail', 'required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);在此示例中,如果 title 属性上的 unique 规则失败,则不会检查 max 规则。规则将按照分配的顺序进行验证。
关于嵌套属性的说明
如果传入的 HTTP 请求包含"嵌套"字段数据,你可以使用"点"语法在验证规则中指定这些字段:
php
$request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'author.name' => ['required'],
'author.description' => ['required'],
]);另一方面,如果你的字段名称包含字面句点,你可以通过使用反斜杠转义句点来明确防止其被解释为"点"语法:
php
$request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'v1\.0' => ['required'],
]);显示验证错误
那么,如果传入的请求字段未通过给定的验证规则会怎样?如前所述,Laravel 将自动将用户重定向回其先前位置。此外,所有验证错误和请求输入将自动闪存到 session。
Illuminate\View\Middleware\ShareErrorsFromSession middleware(由 web middleware 组提供)会与你应用程序的所有视图共享一个 $errors 变量。当应用了此 middleware 时,$errors 变量将始终在你的视图中可用,让你可以方便地假定 $errors 变量始终已定义并可安全使用。$errors 变量将是 Illuminate\Support\MessageBag 的实例。有关使用此对象的更多信息,请查看其文档。
因此,在我们的示例中,当验证失败时,用户将被重定向到控制器的 create 方法,允许我们在视图中显示错误消息:
blade
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- 创建博客文章的表单 -->自定义错误消息
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 变量来显示错误消息:
blade
<!-- /resources/views/post/create.blade.php -->
<label for="title">Post Title</label>
<input
id="title"
type="text"
name="title"
class="@error('title') is-invalid @enderror"
/>
@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror如果你使用命名错误包,你可以将错误包的名称作为 @error 指令的第二个参数传递:
blade
<input ... class="@error('title', 'post') is-invalid @enderror">重新填充表单
当 Laravel 由于验证错误生成重定向响应时,框架会自动将所有请求输入闪存到 session。这样做是为了你可以在下一个请求期间方便地访问输入并重新填充用户尝试提交的表单。
要从上一个请求中检索闪存的输入,请在 Illuminate\Http\Request 实例上调用 old 方法。old 方法将从 session 中提取先前闪存的输入数据:
php
$title = $request->old('title');Laravel 还提供了一个全局 old 辅助函数。如果你在 Blade 模板中显示旧输入,使用 old 辅助函数来重新填充表单更方便。如果给定字段不存在旧输入,将返回 null:
blade
<input type="text" name="title" value="{{ old('title') }}">关于可选字段的说明
默认情况下,Laravel 在应用程序的全局 middleware 栈中包含 TrimStrings 和 ConvertEmptyStringsToNull middleware。因此,如果你不希望验证器将 null 值视为无效,则经常需要将"可选"请求字段标记为 nullable。例如:
php
$request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
'publish_at' => ['nullable', 'date'],
]);在此示例中,我们指定 publish_at 字段可以是 null 或有效的日期表示。如果未将 nullable 修饰符添加到规则定义中,验证器将认为 null 是无效日期。
验证错误响应格式
当你的应用程序抛出 Illuminate\Validation\ValidationException 异常且传入的 HTTP 请求期望 JSON 响应时,Laravel 将自动为你格式化错误消息并返回 422 Unprocessable Entity HTTP 响应。
下面,你可以查看验证错误的 JSON 响应格式示例。请注意,嵌套的错误键被扁平化为"点"表示法格式:
json
{
"message": "The team name field must be a string. (and 4 more errors)",
"errors": {
"team_name": [
"The team name field must be a string.",
"The team name field 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 field must be a valid email address."
]
}
}表单请求验证
创建表单请求
对于更复杂的验证场景,你可能希望创建一个"表单请求"。表单请求是封装了自己的验证和授权逻辑的自定义请求类。要创建表单请求类,可以使用 make:request Artisan CLI 命令:
shell
php artisan make:request StorePostRequest生成的表单请求类将放置在 app/Http/Requests 目录中。如果此目录不存在,运行 make:request 命令时将创建它。Laravel 生成的每个表单请求都有两个方法:authorize 和 rules。
你可能已经猜到了,authorize 方法负责确定当前认证的用户是否可以执行请求所代表的操作,而 rules 方法返回应该应用于请求数据的验证规则:
php
/**
* 获取适用于请求的验证规则。
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
];
}NOTE
你可以在 rules 方法的签名中类型提示你需要的任何依赖。它们将通过 Laravel 服务容器自动解析。
那么,验证规则是如何被评估的呢?你只需要在控制器方法上类型提示该请求。传入的表单请求在控制器方法被调用之前就已经被验证了,这意味着你不需要在控制器中堆积任何验证逻辑:
php
/**
* 存储新博客文章。
*/
public function store(StorePostRequest $request): RedirectResponse
{
// 传入的请求有效...
// 检索验证过的输入数据...
$validated = $request->validated();
// 检索验证过的输入数据的一部分...
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
// 存储博客文章...
return redirect('/posts');
}如果验证失败,将生成重定向响应以将用户送回其先前位置。错误也将闪存到 session 中以便显示。如果请求是 XHR 请求,将向用户返回带有 422 状态码的 HTTP 响应,其中包含验证错误的 JSON 表示。
NOTE
需要为你的 Inertia 驱动的 Laravel 前端添加实时表单请求验证?请查看 Laravel Precognition。
执行额外验证
有时你需要在初始验证完成后执行额外的验证。你可以使用表单请求的 after 方法来完成此操作。
after 方法应返回一个可调用对象或闭包的数组,这些将在验证完成后被调用。给定的可调用对象将接收一个 Illuminate\Validation\Validator 实例,允许你在必要时引发额外的错误消息:
php
use Illuminate\Validation\Validator;
/**
* 获取请求的 "after" 验证可调用对象。
*/
public function after(): array
{
return [
function (Validator $validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field',
'Something is wrong with this field!'
);
}
}
];
}如前所述,after 方法返回的数组也可以包含可调用类。这些类的 __invoke 方法将接收一个 Illuminate\Validation\Validator 实例:
php
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
use Illuminate\Validation\Validator;
/**
* 获取请求的 "after" 验证可调用对象。
*/
public function after(): array
{
return [
new ValidateUserStatus,
new ValidateShippingTime,
function (Validator $validator) {
//
}
];
}在第一次验证失败时停止
通过向请求类添加 StopOnFirstFailure 属性,你可以通知验证器一旦发生单个验证失败就应停止验证所有属性:
php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\StopOnFirstFailure;
use Illuminate\Foundation\Http\FormRequest;
#[StopOnFirstFailure]
class StorePostRequest extends FormRequest
{
// ...
}未知字段时报错
通过向请求类添加 FailOnUnknownFields 属性,你可以指示 Laravel 拒绝任何未在请求验证规则中定义的传入字段:
php
<?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 中为所有表单请求全局启用此行为:
php
use Illuminate\Foundation\Http\FormRequest;
/**
* 引导所有应用服务。
*/
public function boot(): void
{
FormRequest::failOnUnknownFields();
}如有需要,你可以通过向该属性传递 false 为特定请求关闭此行为:
php
#[FailOnUnknownFields(false)]
class PublicWebhookRequest extends FormRequest
{
// ...
}拒绝未知字段可以通过阻止意外输入键继续流入应用更深层逻辑,为类似 mass-assignment 的问题提供额外保护。同时,你仍应正确配置模型的 $fillable / $guarded 属性,并且只持久化可信且已验证的输入。
自定义重定向位置
当表单请求验证失败时,将生成重定向响应以将用户送回其先前位置。但是,你可以自由自定义此行为。为此,你可以在表单请求上使用 RedirectTo 属性:
php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\RedirectTo;
use Illuminate\Foundation\Http\FormRequest;
#[RedirectTo('/dashboard')]
class StorePostRequest extends FormRequest
{
// ...
}或者,如果你想将用户重定向到命名路由,可以使用 RedirectToRoute 属性:
php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\RedirectToRoute;
use Illuminate\Foundation\Http\FormRequest;
#[RedirectToRoute('dashboard')]
class StorePostRequest extends FormRequest
{
// ...
}自定义错误包
当表单请求验证失败时,错误将闪存到 default 错误包。如果你需要将错误存储在不同的命名错误包中,可以在表单请求上使用 ErrorBag 属性:
php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\Attributes\ErrorBag;
use Illuminate\Foundation\Http\FormRequest;
#[ErrorBag('login')]
class LoginRequest extends FormRequest
{
// ...
}授权表单请求
表单请求类还包含一个 authorize 方法。在此方法中,你可以确定经过认证的用户是否实际有权更新给定资源。例如,你可以确定用户是否实际拥有他们尝试更新的博客评论。最有可能的是,你将在此方法中与授权门和策略交互:
php
use App\Models\Comment;
/**
* 确定用户是否有权发出此请求。
*/
public function authorize(): bool
{
$comment = Comment::find($this->route('comment'));
return $comment && $this->user()->can('update', $comment);
}由于所有表单请求都扩展了基础 Laravel 请求类,我们可以使用 user 方法来访问当前认证的用户。另外,请注意上面示例中对 route 方法的调用。此方法允许你访问在被调用路由上定义的 URI 参数,例如下面示例中的 {comment} 参数:
php
Route::post('/comment/{comment}');因此,如果你的应用程序利用了路由模型绑定,通过将解析的模型作为请求的属性访问,你的代码可以更加简洁:
php
return $this->user()->can('update', $this->comment);如果 authorize 方法返回 false,将自动返回带有 403 状态码的 HTTP 响应,并且你的控制器方法将不会执行。
如果你计划在应用程序的其他部分处理请求的授权逻辑,你可以完全删除 authorize 方法,或简单地返回 true:
php
/**
* 确定用户是否有权发出此请求。
*/
public function authorize(): bool
{
return true;
}NOTE
你可以在 authorize 方法的签名中类型提示你需要的任何依赖。它们将通过 Laravel 服务容器自动解析。
自定义错误消息
你可以通过重写 messages 方法来自定义表单请求使用的错误消息。此方法应返回属性/规则对及其对应错误消息的数组:
php
/**
* 获取已定义验证规则的错误消息。
*
* @return array<string, string>
*/
public function messages(): array
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}自定义验证属性
Laravel 的许多内置验证规则错误消息包含一个 :attribute 占位符。如果你希望将验证消息的 :attribute 占位符替换为自定义属性名称,你可以通过重写 attributes 方法来指定自定义名称。此方法应返回属性/名称对的数组:
php
/**
* 获取验证器错误的自定义属性。
*
* @return array<string, string>
*/
public function attributes(): array
{
return [
'email' => 'email address',
];
}准备验证输入
如果你需要在应用验证规则之前准备或清理请求中的任何数据,你可以使用 prepareForValidation 方法:
php
use Illuminate\Support\Str;
/**
* 准备验证数据。
*/
protected function prepareForValidation(): void
{
$this->merge([
'slug' => Str::slug($this->slug),
]);
}同样,如果你需要在验证完成后规范化任何请求数据,你可以使用 passedValidation 方法:
php
/**
* 处理通过的验证尝试。
*/
protected function passedValidation(): void
{
$this->replace(['name' => 'Taylor']);
}手动创建验证器
如果你不想使用请求上的 validate 方法,你可以使用 Validator facade 手动创建验证器实例。facade 上的 make 方法会生成一个新的验证器实例:
php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
/**
* 存储新博客文章。
*/
public function store(Request $request): RedirectResponse
{
$validator = Validator::make($request->all(), [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);
if ($validator->fails()) {
return redirect('/post/create')
->withErrors($validator)
->withInput();
}
// 检索验证过的输入...
$validated = $validator->validated();
// 检索验证过的输入的一部分...
$validated = $validator->safe()->only(['name', 'email']);
$validated = $validator->safe()->except(['name', 'email']);
// 存储博客文章...
return redirect('/posts');
}
}传递给 make 方法的第一个参数是待验证的数据。第二个参数是应该应用于数据的验证规则数组。
在确定请求验证是否失败后,你可以使用 withErrors 方法将错误消息闪存到 session。使用此方法时,$errors 变量将在重定向后自动与你的视图共享,允许你轻松地将它们显示给用户。withErrors 方法接受验证器、MessageBag 或 PHP array。
在第一次验证失败时停止
stopOnFirstFailure 方法将通知验证器一旦发生单个验证失败就应停止验证所有属性:
php
if ($validator->stopOnFirstFailure()->fails()) {
// ...
}自动重定向
如果你想手动创建验证器实例,但仍然想利用 HTTP 请求的 validate 方法提供的自动重定向,你可以在现有验证器实例上调用 validate 方法。如果验证失败,用户将自动被重定向,或者在 XHR 请求的情况下,将返回 JSON 响应:
php
Validator::make($request->all(), [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
])->validate();你可以使用 validateWithBag 方法在验证失败时将错误消息存储在命名错误包中:
php
Validator::make($request->all(), [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
])->validateWithBag('post');命名错误包
如果你在单个页面上有多个表单,你可能希望为包含验证错误的 MessageBag 命名,以便你可以检索特定表单的错误消息。为此,将名称作为第二个参数传递给 withErrors:
php
return redirect('/register')->withErrors($validator, 'login');然后你可以从 $errors 变量访问命名的 MessageBag 实例:
blade
{{ $errors->login->first('email') }}自定义错误消息
如果需要,你可以提供自定义错误消息供验证器实例使用,而不是使用 Laravel 提供的默认错误消息。有几种方法可以指定自定义消息。首先,你可以将自定义消息作为第三个参数传递给 Validator::make 方法:
php
$validator = Validator::make($input, $rules, $messages = [
'required' => 'The :attribute field is required.',
]);在此示例中,:attribute 占位符将被替换为正在验证的字段的实际名称。你还可以在验证消息中使用其他占位符。例如:
php
$messages = [
'same' => 'The :attribute and :other must match.',
'size' => 'The :attribute must be exactly :size.',
'between' => 'The :attribute value :input is not between :min - :max.',
'in' => 'The :attribute must be one of the following types: :values',
];为给定属性指定自定义消息
有时你可能只想为特定属性指定自定义错误消息。你可以使用"点"表示法来实现。先指定属性名称,然后是规则:
php
$messages = [
'email.required' => 'We need to know your email address!',
];指定自定义属性值
Laravel 的许多内置错误消息包含一个 :attribute 占位符,它会被替换为正在验证的字段或属性的名称。要自定义用于替换特定字段的这些占位符的值,你可以将自定义属性数组作为第四个参数传递给 Validator::make 方法:
php
$validator = Validator::make($input, $rules, $messages, [
'email' => 'email address',
]);执行额外验证
有时你需要在初始验证完成后执行额外的验证。你可以使用验证器的 after 方法来完成此操作。after 方法接受一个闭包或可调用对象数组,它们将在验证完成后被调用。给定的可调用对象将接收一个 Illuminate\Validation\Validator 实例,允许你在必要时引发额外的错误消息:
php
use Illuminate\Support\Facades\Validator;
$validator = Validator::make(/* ... */);
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field', 'Something is wrong with this field!'
);
}
});
if ($validator->fails()) {
// ...
}如前所述,after 方法也接受一个可调用对象数组,如果你的"后验证"逻辑封装在可调用类中,这将特别方便,这些类将通过其 __invoke 方法接收一个 Illuminate\Validation\Validator 实例:
php
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
$validator->after([
new ValidateUserStatus,
new ValidateShippingTime,
function ($validator) {
// ...
},
]);使用已验证的输入
在使用表单请求或手动创建的验证器实例验证传入的请求数据后,你可能希望检索实际经过验证的请求数据。可以通过几种方式来实现这一点。首先,你可以在表单请求或验证器实例上调用 validated 方法。该方法返回一个经过验证的数据数组:
php
$validated = $request->validated();
$validated = $validator->validated();或者,你可以在表单请求或验证器实例上调用 safe 方法。该方法返回一个 Illuminate\Support\ValidatedInput 实例。该对象提供了 only、except 和 all 方法来检索经过验证的数据的子集或整个经过验证的数据数组:
php
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
$validated = $request->safe()->all();此外,Illuminate\Support\ValidatedInput 实例可以像数组一样迭代和访问:
php
// 可以迭代经过验证的数据...
foreach ($request->safe() as $key => $value) {
// ...
}
// 可以像数组一样访问经过验证的数据...
$validated = $request->safe();
$email = $validated['email'];如果你想向经过验证的数据添加更多字段,你可以调用 merge 方法:
php
$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);如果你想以集合实例的形式检索经过验证的数据,你可以调用 collect 方法:
php
$collection = $request->safe()->collect();处理错误消息
在 Validator 实例上调用 errors 方法后,你将获得一个 Illuminate\Support\MessageBag 实例,该实例提供了许多方便的方法来处理错误消息。所有视图中自动可用的 $errors 变量也是 MessageBag 类的实例。
检索某个字段的第一个错误消息
要检索某个字段的第一个错误消息,可以使用 first 方法:
php
$errors = $validator->errors();
echo $errors->first('email');检索某个字段的所有错误消息
如果你需要检索给定字段的所有消息的数组,可以使用 get 方法:
php
foreach ($errors->get('email') as $message) {
// ...
}如果你正在验证数组表单字段,你可以使用 * 字符检索每个数组元素的所有消息:
php
foreach ($errors->get('attachments.*') as $message) {
// ...
}检索所有字段的所有错误消息
要检索所有字段的所有消息的数组,可以使用 all 方法:
php
foreach ($errors->all() as $message) {
// ...
}确定字段是否存在消息
has 方法可用于确定给定字段是否存在任何错误消息:
php
if ($errors->has('email')) {
// ...
}在语言文件中指定自定义消息
Laravel 的每个内置验证规则都有一个错误消息,位于应用程序的 lang/en/validation.php 文件中。如果你的应用程序没有 lang 目录,你可以使用 lang:publish Artisan 命令指示 Laravel 创建它。
在 lang/en/validation.php 文件中,你将找到每个验证规则的翻译条目。你可以根据应用程序的需要自由更改或修改这些消息。
此外,你可以将此文件复制到另一个语言目录来翻译应用程序语言的消息。要了解更多关于 Laravel 本地化的信息,请查看完整的本地化文档。
WARNING
默认情况下,Laravel 应用程序骨架不包含 lang 目录。如果你想自定义 Laravel 的语言文件,可以通过 lang:publish Artisan 命令发布它们。
特定属性的自定义消息
你可以在应用程序的验证语言文件中自定义用于指定属性和规则组合的错误消息。为此,将你的消息自定义添加到应用程序的 lang/xx/validation.php 语言文件的 custom 数组中:
php
'custom' => [
'email' => [
'required' => 'We need to know your email address!',
'max' => 'Your email address is too long!'
],
],在语言文件中指定属性
Laravel 的许多内置错误消息包含一个 :attribute 占位符,它会被替换为正在验证的字段或属性的名称。如果你希望将验证消息的 :attribute 部分替换为自定义值,你可以在 lang/xx/validation.php 语言文件的 attributes 数组中指定自定义属性名称:
php
'attributes' => [
'email' => 'email address',
],WARNING
默认情况下,Laravel 应用程序骨架不包含 lang 目录。如果你想自定义 Laravel 的语言文件,可以通过 lang:publish Artisan 命令发布它们。
在语言文件中指定值
Laravel 的一些内置验证规则错误消息包含一个 :value 占位符,它会被替换为请求属性的当前值。但是,你可能偶尔需要将验证消息的 :value 部分替换为值的自定义表示。例如,考虑以下规则,它指定当 payment_type 的值为 cc 时需要信用卡号:
php
Validator::make($request->all(), [
'credit_card_number' => ['required_if:payment_type,cc']
]);如果此验证规则失败,它将产生以下错误消息:
text
The credit card number field is required when payment type is cc.你可以通过在 lang/xx/validation.php 语言文件中定义 values 数组,指定更加用户友好的值表示,而不是显示 cc 作为支付类型值:
php
'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],WARNING
默认情况下,Laravel 应用程序骨架不包含 lang 目录。如果你想自定义 Laravel 的语言文件,可以通过 lang:publish Artisan 命令发布它们。
定义此值后,验证规则将产生以下错误消息:
text
The credit card number field is required when payment type is credit card.可用的验证规则
以下是所有可用验证规则及其功能的列表:
布尔值
字符串
有效 URL字母字母、数字、短横线和下划线字母和数字ASCII 字符确认字段当前密码值不同排除指定前缀排除指定后缀电子邮件指定后缀枚举十六进制颜色位于指定列表中IP 地址JSON小写MAC 地址最大值最小值排除指定列表中的值正则表达式排除匹配正则表达式的值值相同大小指定前缀字符串大写URLULIDUUID
数字
数组
日期
文件
数据库
实用规则
满足任一规则集首次失败后停止排除字段满足条件时排除条件不满足时排除其他字段存在时排除其他字段缺失时排除存在时必须有值字段缺失满足条件时缺失条件不满足时缺失任一其他字段存在时缺失所有其他字段存在时缺失可为 null字段存在满足条件时存在条件不满足时存在任一其他字段存在时存在所有其他字段存在时存在禁止字段满足条件时禁止其他字段被接受时禁止其他字段被拒绝时禁止条件不满足时禁止禁止其他字段必填满足条件时必填其他字段被接受时必填其他字段被拒绝时必填条件不满足时必填任一其他字段有值时必填所有其他字段有值时必填任一其他字段为空时必填所有其他字段为空时必填必需的数组键存在时验证
规则构建器
除了字符串形式,你还可以使用 Illuminate\Validation\Rule 类的方法定义许多验证规则。这些方法支持 IDE 自动补全,并且可以与字符串规则组合使用:
php
use Illuminate\Validation\Rule;
'name' => [Rule::required(), Rule::string()->max(255)],
'terms' => [Rule::accepted()],
'enabled' => [Rule::boolean()],
'website' => [Rule::nullable(), Rule::activeUrl()],方法名采用驼峰命名,例如 Rule::hexColor()、Rule::macAddress() 和 Rule::requiredArrayKeys(['name', 'email'])。依赖其他字段的规则接受字段名或比较值作为参数:
php
'terms' => [Rule::acceptedIf('account_type', ['personal', 'business'])],
'nickname' => [Rule::excludeWith('name')],
'email' => [Rule::requiredWithout(['phone', 'mobile'])],
'settings' => [Rule::presentIf('account_type', 'business')],acceptedIf、declinedIf、missingIf、missingUnless、presentIf 和 presentUnless 方法接受单个比较值或比较值数组。requiredWith、requiredWithAll、requiredWithout、requiredWithoutAll、missingWith、missingWithAll、presentWith、presentWithAll 和 prohibits 等方法接受字段名数组或多个字段名参数。
你也可以使用 regex 和 notRegex 方法定义正则表达式:
php
'username' => [Rule::required(), Rule::regex('/^[a-z]+$/i')],
'code' => [Rule::notRegex('/^test-/i')],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 查询,同时保留这些规则的其他验证行为:
php
use Illuminate\Support\Facades\Validator;
Validator::fakeDnsLookups();after:date
验证的字段必须是给定日期之后的值。日期将传递给 strtotime PHP 函数以转换为有效的 DateTime 实例:
php
'start_date' => ['required', 'date', 'after:tomorrow']你也可以指定另一个字段来与日期进行比较,而不是传递由 strtotime 评估的日期字符串:
php
'finish_date' => ['required', 'date', 'after:start_date']为方便起见,基于日期的规则可以使用流畅的 date 规则构建器构建:
php
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->after(today()->addDays(7)),
],afterToday 和 todayOrAfter 方法可用于流畅地表达日期必须在今天之后或今天或之后:
php
'start_date' => [
'required',
Rule::date()->afterToday(),
],after_or_equal:date
验证的字段必须是给定日期之后或等于给定日期的值。有关更多信息,请参阅 after 规则。
为方便起见,基于日期的规则可以使用流畅的 date 规则构建器构建:
php
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->afterOrEqual(today()->addDays(7)),
],anyOf
Rule::anyOf 验证规则允许你指定验证的字段必须满足给定验证规则集中的任何一个。例如,以下规则将验证 username 字段是电子邮件地址或至少 6 个字符长的字母数字字符串(包括破折号):
php
use Illuminate\Validation\Rule;
'username' => [
'required',
Rule::anyOf([
['string', 'email'],
['string', 'alpha_dash', 'min:6'],
]),
],alpha
验证的字段必须完全是包含在 \p{L} 和 \p{M} 中的 Unicode 字母字符。
要将此验证规则限制为 ASCII 范围内的字符(a-z 和 A-Z),你可以向验证规则提供 ascii 选项:
php
'username' => ['alpha:ascii'],alpha_dash
验证的字段必须完全是包含在 \p{L}、\p{M}、\p{N} 中的 Unicode 字母数字字符,以及 ASCII 破折号(-)和 ASCII 下划线(_)。
要将此验证规则限制为 ASCII 范围内的字符(a-z、A-Z 和 0-9),你可以向验证规则提供 ascii 选项:
php
'username' => ['alpha_dash:ascii'],alpha_num
验证的字段必须完全是包含在 \p{L}、\p{M} 和 \p{N} 中的 Unicode 字母数字字符。
要将此验证规则限制为 ASCII 范围内的字符(a-z、A-Z 和 0-9),你可以向验证规则提供 ascii 选项:
php
'username' => ['alpha_num:ascii'],array
验证的字段必须是 PHP array。
当向 array 规则提供额外值时,输入数组中的每个键都必须存在于提供给规则的值列表中。在以下示例中,输入数组中的 admin 键无效,因为它不包含在提供给 array 规则的值列表中:
php
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,且其所有键都包含在给定列表中。必须提供至少一个键:
php
'user' => ['array_keys:name,username'],为方便起见,可以使用 Rule::arrayKeys 方法:
php
'user' => [Rule::arrayKeys('name', 'username')],ascii
验证的字段必须完全是 7 位 ASCII 字符。
bail
在第一次验证失败后停止运行该字段的验证规则。
bail 规则仅在遇到验证失败时停止验证特定字段,而 stopOnFirstFailure 方法将通知验证器一旦发生单个验证失败就应停止验证所有属性:
php
if ($validator->stopOnFirstFailure()->fails()) {
// ...
}before:date
验证的字段必须是给定日期之前的值。日期将传递给 PHP strtotime 函数以转换为有效的 DateTime 实例。此外,与 after 规则一样,可以提供另一个验证字段的名称作为 date 的值。
为方便起见,基于日期的规则也可以使用流畅的 date 规则构建器构建:
php
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->before(today()->subDays(7)),
],beforeToday 和 todayOrBefore 方法可用于流畅地表达日期必须在今天之前或今天或之前:
php
'start_date' => [
'required',
Rule::date()->beforeToday(),
],before_or_equal:date
验证的字段必须是给定日期之前或等于给定日期的值。日期将传递给 PHP strtotime 函数以转换为有效的 DateTime 实例。此外,与 after 规则一样,可以提供另一个验证字段的名称作为 date 的值。
为方便起见,基于日期的规则也可以使用流畅的 date 规则构建器构建:
php
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 时才认为其有效:
php
'foo' => ['boolean:strict']你也可以使用 Rule::boolean 方法,传入 true 以启用严格验证:
php
'foo' => [Rule::boolean(true)],confirmed
验证的字段必须有一个匹配的 {field}_confirmation 字段。例如,如果验证的字段是 password,则输入中必须存在匹配的 password_confirmation 字段。
你也可以传递自定义确认字段名称。例如,confirmed:repeat_username 将期望 repeat_username 字段与验证的字段匹配。
你也可以使用 Rule::confirmed 方法,并通过 customField 方法指定自定义确认字段:
php
'username' => [Rule::confirmed()->customField('repeat_username')],contains:foo,bar,...
验证的字段必须是包含所有给定参数值的数组。由于此规则通常需要你 implode 数组,因此可以使用 Rule::contains 方法来流畅地构建规则:
php
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 方法来流畅地构建规则:
php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'roles' => [
'required',
'array',
Rule::doesntContain(['admin', 'editor']),
],
]);current_password
验证的字段必须与认证用户的密码匹配。你可以使用规则的第一个参数指定认证守卫:
php
'password' => ['current_password:api']你也可以使用 Rule::currentPassword 方法,并通过 guard 方法指定认证 guard:
php
'password' => [Rule::currentPassword()->guard('api')],date
根据 strtotime PHP 函数,验证的字段必须是有效的、非相对的日期。
date_equals:date
验证的字段必须等于给定的日期。日期将传递给 PHP strtotime 函数以转换为有效的 DateTime 实例。
为方便起见,可以使用支持链式调用的 date 规则构建器构建日期规则:
php
use Illuminate\Validation\Rule;
'start_date' => [Rule::date()->equals('2026-01-01')],equals 方法接受日期字符串、DateTimeInterface 实例或用于比较的另一个字段的名称。
date_format:format,...
验证的字段必须匹配给定的 格式 之一。验证字段时,你应该使用 date 或 date_format,而不是两者同时使用。此验证规则支持 PHP DateTime 类支持的所有格式。
为方便起见,基于日期的规则可以使用流畅的 date 规则构建器构建:
php
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->format('Y-m-d'),
],decimal:min,max
验证的字段必须是数字并且必须包含指定数量的小数位:
php
// 必须恰好有两位小数 (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
验证的文件必须是符合规则参数指定的尺寸约束的图像:
php
'avatar' => ['dimensions:min_width=100,min_height=200']可用的约束有:min_width、max_width、min_height、max_height、width、height、ratio、min_ratio、max_ratio。
ratio 约束应该表示为宽度除以高度。可以通过分数(如 3/2)或浮点数(如 1.5)来指定:
php
'avatar' => ['dimensions:ratio=3/2']min_ratio 和 max_ratio 约束可用于定义可接受的宽高比范围:
php
'avatar' => ['dimensions:min_ratio=1/2,max_ratio=3/2']由于此规则需要多个参数,通常使用 Rule::dimensions 方法来流畅地构建规则更方便:
php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'avatar' => [
'required',
Rule::dimensions()
->maxWidth(1000)
->maxHeight(500)
->ratio(3 / 2),
],
]);你也可以使用 minRatio、maxRatio 和 ratioBetween 方法流畅地定义比例约束:
php
Rule::dimensions()->ratioBetween(min: 1 / 2, max: 3 / 2);distinct
验证数组时,验证的字段不能有任何重复值:
php
'foo.*.id' => ['distinct']Distinct 默认使用松散变量比较。要使用严格比较,你可以在验证规则定义中添加 strict 参数:
php
'foo.*.id' => ['distinct:strict']你可以在验证规则的参数中添加 ignore_case 以使规则忽略大小写差异:
php
'foo.*.id' => ['distinct:ignore_case']你也可以使用 Rule::distinct 方法,并按需链式调用 strict 和 ignoreCase 方法:
php
'foo.*.id' => [Rule::distinct()->strict()->ignoreCase()],doesnt_start_with:foo,bar,...
验证的字段不能以给定值之一开头。
doesnt_end_with:foo,bar,...
验证的字段不能以给定值之一结尾。
email
验证的字段必须格式化为电子邮件地址。此验证规则使用 egulias/email-validator 包来验证电子邮件地址。默认情况下,应用 RFCValidation 验证器,但你也可以应用其他验证样式:
php
'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 字符。
为方便起见,电子邮件验证规则可以使用流畅的规则构建器构建:
php
use Illuminate\Validation\Rule;
$request->validate([
'email' => [
'required',
Rule::email()
->rfcCompliant(strict: false)
->validateMxRecord()
->preventSpoofing()
],
]);dns 验证器会执行真实的 DNS 查询,以确认地址的域名具有有效的 MX 记录。它不会判断单个邮箱是否存在。
由于测试不应依赖实时 DNS 查询,你可以使用 Validator::fakeDnsLookups 方法伪造 DNS 查询,同时让其他请求的验证(例如 rfc)继续运行:
php
use Illuminate\Support\Facades\Validator;
Validator::fakeDnsLookups();这允许你的应用程序在测试时继续使用现有验证规则:
php
'email' => ['required', 'email:rfc,dns'],WARNING
dns 和 spoof 验证器需要 PHP intl 扩展。
encoding:encoding_type
验证的字段必须匹配指定的字符编码。此规则使用 PHP 的 mb_check_encoding 函数来验证给定文件或字符串值的编码。为方便起见,encoding 规则可以使用 Laravel 的流畅文件规则构建器构建:
php
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 规则提供一个 backed Enum:
php
use App\Enums\ServerStatus;
use Illuminate\Validation\Rule;
$request->validate([
'status' => [Rule::enum(ServerStatus::class)],
]);Enum 规则的 only 和 except 方法可用于限制哪些枚举情况应被视为有效:
php
Rule::enum(ServerStatus::class)
->only([ServerStatus::Pending, ServerStatus::Active]);
Rule::enum(ServerStatus::class)
->except([ServerStatus::Pending, ServerStatus::Active]);when 方法可用于有条件地修改 Enum 规则:
php
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;
Rule::enum(ServerStatus::class)
->when(
Auth::user()->isAdmin(),
fn ($rule) => $rule->only(...),
fn ($rule) => $rule->only(...),
);exclude
验证的字段将从 validate 和 validated 方法返回的请求数据中排除。
exclude_if:anotherfield,value
如果 anotherfield 字段等于 value,验证的字段将从 validate 和 validated 方法返回的请求数据中排除。
如果需要复杂的条件排除逻辑,你可以使用 Rule::excludeIf 方法。此方法接受一个布尔值或闭包。当给定闭包时,闭包应返回 true 或 false 以指示验证的字段是否应被排除:
php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::excludeIf($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::excludeIf(fn () => $request->user()->is_admin)],
]);exclude_unless:anotherfield,value
除非 anotherfield 字段等于 value,否则验证的字段将从 validate 和 validated 方法返回的请求数据中排除。如果 value 为 null(exclude_unless:name,null),除非比较字段为 null 或比较字段不在请求数据中,否则验证的字段将被排除。
如果需要复杂的条件排除逻辑,可以使用 Rule::excludeUnless 方法。此方法接受一个布尔值或闭包。当传入闭包时,闭包应返回 true 或 false 来指示验证的字段是否不应被排除:
php
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 字段存在,验证的字段将从 validate 和 validated 方法返回的请求数据中排除。
exclude_without:anotherfield
如果 anotherfield 字段不存在,验证的字段将从 validate 和 validated 方法返回的请求数据中排除。
exists:table,column
验证的字段必须存在于给定的数据库表中。
Exists 规则的基本用法
php
'state' => ['exists:states']如果未指定 column 选项,将使用字段名称。因此,在这种情况下,规则将验证 states 数据库表是否包含一条 state 列值与请求的 state 属性值匹配的记录。
指定自定义列名
你可以通过将数据库列名放在数据库表名之后来明确指定验证规则应使用的数据库列名:
php
'state' => ['exists:states,abbreviation']有时你可能需要指定用于 exists 查询的特定数据库连接。你可以通过在表名前面加上连接名来完成此操作:
php
'email' => ['exists:connection.staff,email']你可以指定应用于确定表名的 Eloquent 模型,而不是直接指定表名:
php
'user_id' => ['exists:App\Models\User,id']如果你想自定义验证规则执行的查询,你可以使用 Rule 类来流畅地定义规则。
php
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::exists('staff')->where(function (Builder $query) {
$query->where('account_id', 1);
}),
],
]);你可以通过将列名作为第二个参数传递给 exists 方法来明确指定由 Rule::exists 方法生成的 exists 规则应使用的数据库列名:
php
'state' => [Rule::exists('states', 'abbreviation')],有时你可能希望验证一组值是否存在于数据库中。你可以通过向正在验证的字段同时添加 exists 和 array 规则来实现:
php
'states' => ['array', Rule::exists('states', 'abbreviation')],当这两个规则都分配给一个字段时,Laravel 将自动构建一个单一查询来确定所有给定值是否存在于指定表中。
extensions:foo,bar,...
验证的文件必须具有与列出的扩展名之一对应的用户分配的扩展名:
php
'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、avif、heic 或 heif)。
WARNING
默认情况下,image 规则不允许 SVG 文件,因为可能存在 XSS 漏洞。如果你需要允许 SVG 文件,可以向 image 规则提供 allow_svg 指令(image:allow_svg)。
in:foo,bar,...
验证的字段必须包含在给定的值列表中。由于此规则通常需要你 implode 数组,因此可以使用 Rule::in 方法来流畅地构建规则:
php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'zones' => [
'required',
Rule::in(['first-zone', 'second-zone']),
],
]);当 in 规则与 array 规则组合时,输入数组中的每个值都必须存在于提供给 in 规则的值列表中。在以下示例中,输入数组中的 LAS 机场代码无效,因为它不包含在提供给 in 规则的机场列表中:
php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
$input = [
'airports' => ['NYC', 'LAS'],
];
Validator::make($input, [
'airports' => [
'required',
'array',
],
'airports.*' => Rule::in(['NYC', 'LIT']),
]);in_array:anotherfield.*
验证的字段必须存在于 anotherfield 的值中。
in_array_keys:value.*
验证的字段必须是一个数组,并且至少有一个给定的 values 作为数组中的键:
php
'config' => ['array', 'in_array_keys:timezone']integer
验证的字段必须是整数。
你可以使用 strict 参数仅在字段类型为 integer 时才认为其有效。具有整数值的字符串将被视为无效:
php
'age' => ['integer:strict']WARNING
此验证规则不验证输入是否为"integer"变量类型,仅验证输入是否为 PHP 的 FILTER_VALIDATE_INT 规则接受的类型。如果你需要验证输入是否为数字,请将此规则与 numeric 验证规则结合使用。
ip
验证的字段必须是 IP 地址。
你也可以使用 Rule::ip 方法,并根据需要将 IP 版本限制为 4 或 6:
php
'ip_address' => [Rule::ip()],
'ipv4_address' => [Rule::ip()->version(4)],
'ipv6_address' => [Rule::ip()->version(6)],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 类型之一:
php
'video' => ['mimetypes:video/avi,video/mpeg,video/quicktime'],
'media' => ['mimetypes:image/*,video/*'],为确定上传文件的 MIME 类型,将读取文件内容,框架将尝试猜测 MIME 类型,这可能与客户端提供的 MIME 类型不同。
mimes:foo,bar,...
验证的文件必须具有与列出的扩展名之一对应的 MIME 类型:
php
'photo' => ['mimes:jpg,bmp,png']即使你只需要指定扩展名,此规则实际上是通过读取文件内容并猜测其 MIME 类型来验证文件的 MIME 类型。可以在以下位置找到 MIME 类型及其对应扩展名的完整列表:
https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
MIME 类型和扩展名
此验证规则不验证 MIME 类型与用户分配给文件的扩展名之间的一致性。例如,mimes:png 验证规则会将包含有效 PNG 内容的文件视为有效的 PNG 图像,即使该文件名为 photo.txt。如果你想验证文件的用户分配扩展名,可以使用 extensions 规则。
WARNING
即使文件通过了图像验证,以 .php 扩展名存储时仍可能被当作 PHP 执行。以 GIF 或 JPEG 魔术字节开头的文件可以通过 mimes:gif 或 mimes:jpg 验证,同时包含 PHP 恶意代码。存储上传文件时,请始终使用系统生成的文件名(例如 hashName()),并配置 Web 服务器,禁止在存储目录中执行 PHP。
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 方法可用于流畅地构建规则:
php
use Illuminate\Validation\Rule;
Validator::make($data, [
'toppings' => [
'required',
Rule::notIn(['sprinkles', 'cherries']),
],
]);not_regex:pattern
验证的字段不能匹配给定的正则表达式。
在内部,此规则使用 PHP preg_match 函数。指定的模式应遵守 preg_match 要求的相同格式,因此还必须包含有效的分隔符。例如:'email' => ['not_regex:/^.+$/i']。
nullable
验证的字段可以为 null。
numeric
验证的字段必须是数字。
你可以使用 strict 参数仅在字段值为 integer 或 float 类型时才认为其有效。数字字符串将被视为无效:
php
'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
验证的字段必须缺失或为空。如果字段满足以下条件之一,则为"空":
- 值为
null。 - 值为空字符串。
- 值为空数组或空
Countable对象。 - 值为路径为空的上传文件。
prohibited_if:anotherfield,value,...
如果 anotherfield 字段等于任何 value,验证的字段必须缺失或为空。如果字段满足以下条件之一,则为"空":
- 值为
null。 - 值为空字符串。
- 值为空数组或空
Countable对象。 - 值为路径为空的上传文件。
如果需要复杂的条件禁止逻辑,你可以使用 Rule::prohibitedIf 方法。此方法接受一个布尔值或闭包。当给定闭包时,闭包应返回 true 或 false 以指示验证的字段是否应被禁止:
php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::prohibitedIf($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::prohibitedIf(fn () => $request->user()->is_admin)],
]);prohibited_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对象。 - 值为路径为空的上传文件。
如果需要复杂的条件禁止逻辑,可以使用 Rule::prohibitedUnless 方法。此方法接受一个布尔值或闭包。当传入闭包时,闭包应返回 true 或 false 来指示验证的字段是否不应被禁止:
php
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 中的所有字段必须缺失或为空。如果字段满足以下条件之一,则为"空":
- 值为
null。 - 值为空字符串。
- 值为空数组或空
Countable对象。 - 值为路径为空的上传文件。
regex:pattern
验证的字段必须匹配给定的正则表达式。
在内部,此规则使用 PHP preg_match 函数。指定的模式应遵守 preg_match 要求的相同格式,因此还必须包含有效的分隔符。例如:'email' => ['regex:/^.+@.+$/i']。
required
验证的字段必须存在于输入数据中且不为空。如果字段满足以下条件之一,则为"空":
- 值为
null。 - 值为空字符串。
- 值为空数组或空
Countable对象。 - 值为没有路径的上传文件。
required_if:anotherfield,value,...
如果 anotherfield 字段等于任何 value,验证的字段必须存在且不为空。
如果你想为 required_if 规则构建更复杂的条件,可以使用 Rule::requiredIf 方法。此方法接受一个布尔值或闭包。当传递闭包时,闭包应返回 true 或 false 以指示验证的字段是否为必填:
php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => [Rule::requiredIf($request->user()->is_admin)],
]);
Validator::make($request->all(), [
'role_id' => [Rule::requiredIf(fn () => $request->user()->is_admin)],
]);required_if_accepted:anotherfield,...
如果 anotherfield 字段等于 "yes"、"on"、1、"1"、true 或 "true",验证的字段必须存在且不为空。
required_if_declined:anotherfield,...
如果 anotherfield 字段等于 "no"、"off"、0、"0"、false 或 "false",验证的字段必须存在且不为空。
required_unless:anotherfield,value,...
除非 anotherfield 字段等于任何 value,否则验证的字段必须存在且不为空。这也意味着除非 value 为 null,否则 anotherfield 必须存在于请求数据中。如果 value 为 null(required_unless:name,null),除非比较字段为 null 或比较字段不在请求数据中,否则验证的字段将为必填。
如果你想为 required_unless 规则构建更复杂的条件,可以使用 Rule::requiredUnless 方法。此方法接受一个布尔值或闭包。当传入闭包时,闭包应返回 true 或 false 来指示验证的字段是否不是必填的:
php
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,...
_仅当_所有其他指定字段都为空或不存在时,验证的字段必须存在且不为空。
required_array_keys:foo,bar,...
验证的字段必须是数组,并且必须至少包含指定的键。
same:field
给定的 field 必须与验证的字段匹配。
size:value
验证的字段必须具有与给定 value 匹配的大小。对于字符串数据,value 对应于字符数。对于数字数据,value 对应于给定的整数值(属性还必须具有 numeric 或 integer 规则)。对于数组,size 对应于数组的 count。对于文件,size 对应于以千字节为单位的文件大小。让我们看一些示例:
php
// 验证字符串恰好是 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 规则分配给该字段。
为方便起见,你也可以使用支持链式调用的 Rule::string() 规则构建器构建字符串验证规则:
php
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 方法接受的参数:
php
'timezone' => ['required', 'timezone:all'];
'timezone' => ['required', 'timezone:Africa'];
'timezone' => ['required', 'timezone:per_country,US'];你也可以使用 Rule::timezone 方法,将 listIdentifiers 的参数以数组形式传入:
php
'timezone' => [Rule::timezone(['per_country', 'US'])],unique:table,column
验证的字段不能存在于给定的数据库表中。
指定自定义表/列名:
你可以指定应用于确定表名的 Eloquent 模型,而不是直接指定表名:
php
'email' => ['unique:App\Models\User,email_address']column 选项可用于指定字段对应的数据库列。如果未指定 column 选项,将使用验证的字段名称。
php
'email' => ['unique:users,email_address']指定自定义数据库连接
有时你可能需要为验证器的数据库查询设置自定义连接。为此,你可以在表名前面加上连接名:
php
'email' => ['unique:connection.users,email_address']强制 Unique 规则忽略给定 ID:
有时你可能希望在唯一验证期间忽略给定的 ID。例如,考虑一个包含用户姓名、电子邮件地址和位置的"更新个人资料"界面。你可能希望验证电子邮件地址是否唯一。但是,如果用户只更改了姓名字段而不是电子邮件字段,你不希望抛出验证错误,因为用户已经是该电子邮件地址的所有者。
要指示验证器忽略用户的 ID,我们将使用 Rule 类来流畅地定义规则。
php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);WARNING
你永远不应将任何用户控制的请求输入传递给 ignore 方法。相反,你应该只传递系统生成的唯一 ID,例如来自 Eloquent 模型实例的自增 ID 或 UUID。否则,你的应用程序将容易受到 SQL 注入攻击。
你也可以将整个模型实例传递给 ignore 方法,而不是传递模型键的值。Laravel 将自动从模型中提取键:
php
Rule::unique('users')->ignore($user);如果你的表使用的主键列名不是 id,你可以在调用 ignore 方法时指定列名:
php
Rule::unique('users')->ignore($user->id, 'user_id');默认情况下,unique 规则将检查与正在验证的属性名称匹配的列的唯一性。但是,你可以将不同的列名作为第二个参数传递给 unique 方法:
php
Rule::unique('users', 'email_address')->ignore($user->id);添加额外的 Where 子句:
你可以通过使用 where 方法自定义查询来指定额外的查询条件。例如,让我们添加一个查询条件,将查询范围限定为仅搜索 account_id 列值为 1 的记录:
php
'email' => Rule::unique('users')->where(fn (Builder $query) => $query->where('account_id', 1))在唯一检查中忽略软删除的记录:
默认情况下,unique 规则在确定唯一性时会包含软删除的记录。要从唯一性检查中排除软删除的记录,你可以调用 withoutTrashed 方法:
php
Rule::unique('users')->withoutTrashed();如果你的模型对软删除记录使用的列名不是 deleted_at,你可以在调用 withoutTrashed 方法时提供列名:
php
Rule::unique('users')->withoutTrashed('was_deleted_at');uppercase
验证的字段必须是大写。
url
验证的字段必须是有效的 URL。
如果你想指定应被视为有效的 URL 协议,可以将协议作为验证规则参数传递:
php
'url' => ['url:http,https'],
'game' => ['url:minecraft,steam'],你也可以使用 Rule::url 方法,并通过 protocols 方法指定允许的协议:
php
'url' => [Rule::url()->protocols(['http', 'https'])],ulid
验证的字段必须是有效的通用唯一字典序可排序标识符(ULID)。
uuid
验证的字段必须是有效的 RFC 9562(版本 1、3、4、5、6、7 或 8)通用唯一标识符(UUID)。
你还可以验证给定的 UUID 是否匹配特定版本的 UUID 规范:
php
'uuid' => ['uuid:4']你也可以使用 Rule::uuid 方法,并通过 version 方法指定 UUID 版本:
php
'uuid' => [Rule::uuid()->version(4)],有条件地添加规则
当字段具有特定值时跳过验证
你有时可能希望在另一个字段具有给定值时不验证给定字段。你可以使用 exclude_if 验证规则来完成此操作。在此示例中,如果 has_appointment 字段的值为 false,则不会验证 appointment_date 和 doctor_name 字段:
php
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($data, [
'has_appointment' => ['required', 'boolean'],
'appointment_date' => ['exclude_if:has_appointment,false', 'required', 'date'],
'doctor_name' => ['exclude_if:has_appointment,false', 'required', 'string'],
]);或者,你可以使用 exclude_unless 规则在另一个字段没有给定值时不验证给定字段:
php
$validator = Validator::make($data, [
'has_appointment' => ['required', 'boolean'],
'appointment_date' => ['exclude_unless:has_appointment,true', 'required', 'date'],
'doctor_name' => ['exclude_unless:has_appointment,true', 'required', 'string'],
]);存在时验证
在某些情况下,你可能希望仅在正在验证的数据中存在该字段时才对字段运行验证检查。要快速完成此操作,请将 sometimes 规则添加到你的规则列表中:
php
$validator = Validator::make($data, [
'email' => ['sometimes', 'required', 'email'],
]);在上面的示例中,仅当 email 字段存在于 $data 数组中时才会验证它。
NOTE
如果你尝试验证一个应该始终存在但可能为空的字段,请查看关于可选字段的说明。
复杂条件验证
有时你可能希望根据更复杂的条件逻辑添加验证规则。例如,你可能希望仅在另一个字段的值大于 100 时才要求给定字段。或者,你可能需要两个字段仅在另一个字段存在时才具有给定值。添加这些验证规则并不困难。首先,使用永远不会更改的 静态规则 创建一个 Validator 实例:
php
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'email' => ['required', 'email'],
'games' => ['required', 'integer', 'min:0'],
]);假设我们的 Web 应用程序是为游戏收藏家设计的。如果游戏收藏家在我们的应用程序注册并且拥有超过 100 款游戏,我们希望他们解释为什么拥有这么多游戏。例如,也许他们经营游戏转售店,或者也许他们只是喜欢收集游戏。要有条件地添加此要求,我们可以在 Validator 实例上使用 sometimes 方法。
php
use Illuminate\Support\Fluent;
$validator->sometimes('reason', ['required', 'max:500'], function (Fluent $input) {
return $input->games >= 100;
});传递给 sometimes 方法的第一个参数是我们有条件验证的字段名称。第二个参数是我们要添加的规则列表。如果作为第三个参数传递的闭包返回 true,则将添加规则。此方法使构建复杂的条件验证变得轻而易举。你甚至可以一次为多个字段添加条件验证:
php
$validator->sometimes(['reason', 'cost'], 'required', function (Fluent $input) {
return $input->games >= 100;
});NOTE
传递给闭包的 $input 参数将是 Illuminate\Support\Fluent 的实例,可用于访问正在验证的输入和文件。
复杂条件数组验证
有时你可能希望根据同一嵌套数组中另一个字段来验证一个字段,而你不知道该字段的索引。在这些情况下,你可以允许闭包接收第二个参数,该参数将是正在验证的数组中的当前单个项目:
php
$input = [
'channels' => [
[
'type' => 'email',
'address' => 'abigail@example.com',
],
[
'type' => 'url',
'address' => 'https://example.com',
],
],
];
$validator->sometimes('channels.*.address', 'email', function (Fluent $input, Fluent $item) {
return $item->type === 'email';
});
$validator->sometimes('channels.*.address', 'url', function (Fluent $input, Fluent $item) {
return $item->type !== 'email';
});与传递给闭包的 $input 参数一样,当属性数据是数组时,$item 参数是 Illuminate\Support\Fluent 的实例;否则,它是一个字符串。
验证数组
如数组验证规则文档中所讨论的,array 规则接受允许的数组键列表。如果数组中存在任何额外的键,验证将失败:
php
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] 字段,你可以这样验证它:
php
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'photos.profile' => ['required', 'image'],
]);你还可以验证数组的每个元素。例如,要验证给定数组输入字段中的每个电子邮件是否唯一,你可以这样做:
php
$validator = Validator::make($request->all(), [
'users.*.email' => ['email', 'unique:users'],
'users.*.first_name' => ['required_with:users.*.last_name'],
]);同样,你可以在语言文件中指定自定义验证消息时使用 * 字符,这使得对基于数组的字段使用单个验证消息变得轻而易举:
php
'custom' => [
'users.*.email' => [
'unique' => 'Each user must have a unique email address',
]
],访问嵌套数组数据
有时你可能需要在为属性分配验证规则时访问给定嵌套数组元素的值。你可以使用 Rule::forEach 方法来完成此操作。forEach 方法接受一个闭包,该闭包将在验证的数组属性的每次迭代中被调用,并将接收属性的值和显式的、完全展开的属性名称。闭包应返回要分配给数组元素的规则数组:
php
use App\Rules\HasPermission;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
$validator = Validator::make($request->all(), [
'companies.*.id' => Rule::forEach(function (string|null $value, string $attribute) {
return [
Rule::exists(Company::class, 'id'),
new HasPermission('manage-company', $value),
];
}),
]);错误消息索引和位置
验证数组时,你可能希望在应用程序显示的错误消息中引用验证失败的特定项目的索引或位置。为此,你可以在自定义验证消息中包含 :index(从 0 开始)、:position(从 1 开始)或 :ordinal-position(从 1st 开始)占位符:
php
use Illuminate\Support\Facades\Validator;
$input = [
'photos' => [
[
'name' => 'BeachVacation.jpg',
'description' => 'A photo of my beach vacation!',
],
[
'name' => 'GrandCanyon.jpg',
'description' => '',
],
],
];
Validator::validate($input, [
'photos.*.description' => ['required'],
], [
'photos.*.description.required' => 'Please describe photo #:position.',
]);在上面的示例中,验证将失败,用户将看到以下错误消息 "Please describe photo #2."
如果需要,你可以通过 second-index、second-position、third-index、third-position 等引用更深层嵌套的索引和位置。
php
'photos.*.attributes.*.string' => 'Invalid attribute for photo #:second-position.',验证文件
Laravel 提供了多种验证规则,可用于验证上传的文件,例如 mimes、image、min 和 max。虽然你可以在验证文件时单独指定这些规则,但 Laravel 还提供了流畅的文件验证规则构建器,你可能会觉得很方便:
php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;
Validator::validate($input, [
'attachment' => [
'required',
File::types(['mp3', 'wav'])
->min(1024)
->max(12 * 1024),
],
]);验证文件类型
即使你在调用 types 方法时只需要指定扩展名,此方法实际上是通过读取文件内容并猜测其 MIME 类型来验证文件的 MIME 类型。可以在以下位置找到 MIME 类型及其对应扩展名的完整列表:
https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
验证文件大小
为方便起见,最小和最大文件大小可以指定为带有表示文件大小单位后缀的字符串。支持 kb、mb、gb 和 tb 后缀:
php
File::types(['mp3', 'wav'])
->min('1kb')
->max('10mb');验证图像文件
如果你的应用程序接受用户上传的图像,你可以使用 File 规则的 image 构造方法来确保验证的文件是图像(jpg、jpeg、png、bmp、gif、webp、avif、heic 或 heif)。
此外,dimensions 规则可用于限制图像的尺寸:
php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;
Validator::validate($input, [
'photo' => [
'required',
File::image()
->min(1024)
->max(12 * 1024)
->dimensions(Rule::dimensions()->maxWidth(1000)->maxHeight(500)),
],
]);NOTE
有关验证图像尺寸的更多信息,请参阅 dimension 规则文档。
WARNING
默认情况下,image 规则不允许 SVG 文件,因为可能存在 XSS 漏洞。如果你需要允许 SVG 文件,可以向 image 规则传递 allowSvg: true:File::image(allowSvg: true)。
验证图像尺寸
你还可以验证图像的尺寸。例如,要验证上传的图像至少有 1000 像素宽和 500 像素高,你可以使用 dimensions 规则:
php
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;
File::image()->dimensions(
Rule::dimensions()
->maxWidth(1000)
->maxHeight(500)
);NOTE
有关验证图像尺寸的更多信息,请参阅 dimension 规则文档。
验证密码
为确保密码具有足够的复杂性级别,你可以使用 Laravel 的 Password 规则对象:
php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;
$validator = Validator::make($request->all(), [
'password' => ['required', 'confirmed', Password::min(8)],
]);Password 规则对象允许你轻松自定义应用程序的密码复杂性要求,例如指定密码至少需要一个字母、数字、符号或大小写混合的字符:
php
// 至少需要 8 个字符...
Password::min(8);
// 最多允许 256 个字符...
Password::min(16)->max(256);
// 至少需要一个字母...
Password::min(8)->letters();
// 至少需要一个大写字母和一个小写字母...
Password::min(8)->mixedCase();
// 至少需要一个数字...
Password::min(8)->numbers();
// 至少需要一个符号...
Password::min(8)->symbols();此外,你可以使用 uncompromised 方法确保密码未在公共密码数据泄露中被泄露:
php
Password::min(8)->uncompromised();在内部,Password 规则对象使用 k-匿名模型通过 haveibeenpwned.com 服务确定密码是否已泄露,而不会牺牲用户的隐私或安全。
默认情况下,如果密码在数据泄露中至少出现一次,它将被视为已泄露。你可以使用 uncompromised 方法的第一个参数自定义此阈值:
php
// 确保密码在同一数据泄露中出现最多 3 次...
Password::min(8)->uncompromised(3);当然,你可以链式调用上面示例中的所有方法:
php
Password::min(8)
->max(256)
->letters()
->mixedCase()
->numbers()
->symbols()
->uncompromised();你可以使用 toPasswordRulesString 方法将 Password 规则对象转换为适用于 HTML passwordrules 属性的字符串:
blade
<input
type="password"
name="password"
autocomplete="new-password"
passwordrules="{{ Password::defaults()->toPasswordRulesString() }}"
/>定义默认密码规则
你可能会发现在应用程序的单一位置指定密码的默认验证规则很方便。你可以使用 Password::defaults 方法轻松完成此操作,该方法接受一个闭包。给 defaults 方法的闭包应该返回 Password 规则的默认配置。通常,应在应用程序的某个服务提供者的 boot 方法中调用 defaults 规则:
php
use Illuminate\Validation\Rules\Password;
/**
* 引导任何应用程序服务。
*/
public function boot(): void
{
Password::defaults(function () {
$rule = Password::min(8);
return $this->app->isProduction()
? $rule->mixedCase()->uncompromised()
: $rule;
});
}然后,当你想将默认规则应用于正在验证的特定密码时,你可以不带参数地调用 defaults 方法:
php
'password' => ['required', Password::defaults()],有时你可能想要将额外的验证规则附加到默认密码验证规则。你可以使用 rules 方法来完成此操作:
php
use App\Rules\ZxcvbnRule;
Password::defaults(function () {
$rule = Password::min(8)->rules([new ZxcvbnRule]);
// ...
});自定义验证规则
使用规则对象
Laravel 提供了多种有用的验证规则;但是,你可能希望指定一些自己的规则。注册自定义验证规则的一种方法是使用规则对象。要生成新的规则对象,你可以使用 make:rule Artisan 命令。让我们使用此命令生成一个验证字符串是否为大写的规则。Laravel 会将新规则放在 app/Rules 目录中。如果此目录不存在,Laravel 将在你执行 Artisan 命令创建规则时创建它:
shell
php artisan make:rule Uppercase创建规则后,我们就可以定义它的行为了。规则对象包含一个方法:validate。此方法接收属性名称、其值以及一个在失败时应使用验证错误消息调用的回调:
php
<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class Uppercase implements ValidationRule
{
/**
* 运行验证规则。
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (strtoupper($value) !== $value) {
$fail('The :attribute must be uppercase.');
}
}
}定义规则后,你可以通过将规则对象的实例与其他验证规则一起传递来将其附加到验证器:
php
use App\Rules\Uppercase;
$request->validate([
'name' => ['required', 'string', new Uppercase],
]);翻译验证消息
你也可以提供一个翻译字符串键并指示 Laravel 翻译错误消息,而不是向 $fail 闭包提供字面错误消息:
php
if (strtoupper($value) !== $value) {
$fail('validation.uppercase')->translate();
}如有必要,你可以将占位符替换和首选语言作为第一个和第二个参数提供给 translate 方法:
php
$fail('validation.location')->translate([
'value' => $this->value,
], 'fr');访问额外数据
如果你的自定义验证规则类需要访问正在验证的所有其他数据,你的规则类可以实现 Illuminate\Contracts\Validation\DataAwareRule 接口。此接口要求你的类定义一个 setData 方法。此方法将由 Laravel 自动调用(在验证进行之前),并提供所有正在验证的数据:
php
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;
class Uppercase implements DataAwareRule, ValidationRule
{
/**
* 所有待验证的数据。
*
* @var array<string, mixed>
*/
protected $data = [];
// ...
/**
* 设置待验证的数据。
*
* @param array<string, mixed> $data
*/
public function setData(array $data): static
{
$this->data = $data;
return $this;
}
}或者,如果你的验证规则需要访问执行验证的验证器实例,你可以实现 ValidatorAwareRule 接口:
php
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Contracts\Validation\ValidatorAwareRule;
use Illuminate\Validation\Validator;
class Uppercase implements ValidationRule, ValidatorAwareRule
{
/**
* 验证器实例。
*
* @var \Illuminate\Validation\Validator
*/
protected $validator;
// ...
/**
* 设置当前验证器。
*/
public function setValidator(Validator $validator): static
{
$this->validator = $validator;
return $this;
}
}使用闭包
如果你只需要在整个应用程序中使用一次自定义规则的功能,你可以使用闭包而不是规则对象。闭包接收属性名称、属性值以及一个在验证失败时应调用的 $fail 回调:
php
use Illuminate\Support\Facades\Validator;
use Closure;
$validator = Validator::make($request->all(), [
'title' => [
'required',
'max:255',
function (string $attribute, mixed $value, Closure $fail) {
if ($value === 'foo') {
$fail("The {$attribute} is invalid.");
}
},
],
]);隐式规则
默认情况下,当正在验证的属性不存在或包含空字符串时,不会运行常规验证规则(包括自定义规则)。例如,unique 规则不会针对空字符串运行:
php
use Illuminate\Support\Facades\Validator;
$rules = ['name' => ['unique:users,name']];
$input = ['name' => ''];
Validator::make($input, $rules)->passes(); // true要使自定义规则即使在属性为空时也能运行,该规则必须暗示该属性是必需的。要快速生成新的隐式规则对象,你可以使用带有 --implicit 选项的 make:rule Artisan 命令:
shell
php artisan make:rule Uppercase --implicitWARNING
"隐式"规则仅_暗示_该属性是必需的。它是否实际上使缺失或空属性无效取决于你。