Laravel 提供了几种不同的方法来验证应用程序的传入数据。最常见的方法是使用所有传入 HTTP 请求上可用的 validate 方法。但是,我们也将讨论其他验证方法。
Laravel 包含各种便捷的验证规则,可以应用于数据,甚至提供在给定数据库表中验证值是否唯一的能力。我们将详细介绍这些验证规则中的每一个,以便您熟悉 Laravel 的所有验证功能。
为了了解 Laravel 强大的验证功能,让我们看一个完整的表单验证并将错误消息显示给用户的示例。通过阅读这份高级概述,您将能够很好地全面了解如何使用 Laravel 验证传入的请求数据:
首先,让我们假设在我们的 routes/web.php 文件中定义了以下路由:
use App\Http\Controllers\PostController;
Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);该 GET 路由将显示一个供用户创建新博客文章的表单, 而 POST 路由会将新的博客文章存储到数据库中.
接下来,让我们来看看一个简单的控制器,它负责处理发送到这些路由的传入请求。我们暂时将 store 方法留空:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class PostController extends Controller
{
/**
* Show the form to create a new blog post.
*/
public function create(): View
{
return view('post.create');
}
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
// Validate and store the blog post...
$post = /** ... */
return to_route('post.show', ['post' => $post->id]);
}
}现在我们准备好填充我们的 store 方法,其中包含验证新博客文章的逻辑。为此,我们将使用 Illuminate\Http\Request 对象提供的 validate 方法。如果验证规则通过,您的代码将继续正常执行;但是,如果验证失败,则会抛出 Illuminate\Validation\ValidationException 异常,并且适当的错误响应将自动发送回用户。
如果在传统的 HTTP 请求期间验证失败,将生成一个重定向响应到上一个 URL。如果传入的请求是 XHR 请求,将返回一个 包含验证错误消息的 JSON 响应。
为了更好地理解 validate 方法,让我们回到 store 方法中:
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// The blog post is valid...
return redirect('/posts');
}正如你所看到的,验证规则被传递给 validate 方法。别担心 - 所有可用的验证规则都已 文档化。同样,如果验证失败,将自动生成相应的响应。如果验证通过,我们的控制器将继续正常执行。
或者,验证规则可以指定为规则数组,而不是单个 | 分隔字符串:
$validatedData = $request->validate([
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);此外,您可以使用validateWithBag方法来验证请求并将所有错误消息存储于命名错误包:
$validatedData = $request->validateWithBag('post', [
'title' => ['required', 'unique:posts', 'max:255'],
'body' => ['required'],
]);有时,你可能希望在某个属性的首次验证失败后停止运行其验证规则。 为此,请将 bail 规则分配给该属性:
$request->validate([
'title' => 'bail|required|unique:posts|max:255',
'body' => 'required',
]);在此示例中,如果 title 属性上的 unique 规则失败,max 规则将不会被检查。规则将按照它们被分配的顺序进行验证。
如果传入的 HTTP 请求包含"嵌套"字段数据,你可以在你的验证规则中使用"点"语法来指定这些字段:
$request->validate([
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);另一方面, 如果你的字段名包含字面上的句点, 你可以明确阻止它被解释为“点”语法, 通过用反斜杠转义该句点:
$request->validate([
'title' => 'required|unique:posts|max:255',
'v1\.0' => 'required',
]);那么,如果传入的请求字段未通过给定的验证规则怎么办?
如前所述,Laravel 将自动把用户重定向回其之前的位置。
此外,所有验证错误和 请求输入 将自动 闪存到会话。
一个 $errors 变量通过 Illuminate\View\Middleware\ShareErrorsFromSession 中间件与您应用程序的所有视图共享, 该中间件由 web 中间件组提供. 当应用此中间件时, 一个 $errors 变量将始终在您的视图中可用, 这使您可以方便地假设 $errors 变量始终已定义并可以安全使用. 该 $errors 变量将是 Illuminate\Support\MessageBag 的一个实例. 有关使用此对象的更多信息, 请查阅其文档.
因此,在我们的示例中,用户将被重定向到我们控制器的 create 方法当验证失败时,从而使我们能够在视图中显示错误消息:
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Create Post Form -->Laravel 内置的验证规则各自都有一个错误消息,位于你的应用程序的 lang/en/validation.php 文件中。 如果你的应用程序没有 lang 目录,你可以指示 Laravel 使用 lang:publish Artisan 命令来创建它。
`
此外,您还可以将此文件复制到另一个语言目录,以翻译您的应用程序所用语言的消息。要了解有关 Laravel 本地化的更多信息,请查看完整的本地化文档。
[!WARNING]
默认情况下,Laravel 应用骨架不包含lang目录。如果您想自定义 Laravel 的语言文件,可以通过lang:publishArtisan 命令发布它们。
在此示例中,我们使用了传统表单向应用程序发送数据。但是,许多应用程序从JavaScript驱动的前端接收XHR请求。在XHR请求期间使用 validate 方法时,Laravel将不会生成重定向响应。相反,Laravel会生成一个包含所有验证错误的JSON响应。此JSON响应将以422 HTTP状态码发送。
您可以使用 @error Blade 指令,以快速判断给定属性是否存在验证错误消息。 在 @error 指令内,您可以输出 $message 变量以显示错误消息:
<!-- /resources/views/post/create.blade.php -->
<label for="title">Post Title</label>
<input
id="title"
type="text"
name="title"
class="@error('title') is-invalid @enderror"
/>
@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror如果你正在使用 命名错误包, 你可以将错误包的名称作为第二个参数传递给 @error 指令:
<input ... class="@error('title', 'post') is-invalid @enderror">当 Laravel 因验证错误而生成重定向响应时,框架将自动将请求的所有输入闪存到会话。这样做是为了方便你在下一次请求中访问输入,并重新填充用户尝试提交的表单。
要从之前的请求中获取闪存输入,请在 Illuminate\Http\Request 的实例上调用 old 方法。 old 方法将从 session 中拉取之前闪存的输入数据:
$title = $request->old('title');Laravel 也提供了一个全局的 old 助手。如果你正在在一个 Blade 模板 中显示旧输入,使用 old 助手来重新填充表单会更方便。如果给定字段没有旧输入,将返回 null:
<input type="text" name="title" value="{{ old('title') }}">默认情况下,Laravel 会在应用的全局中间件栈中包含 TrimStrings 和 ConvertEmptyStringsToNull 中间件。因此,如果你不希望验证器将 null 值视为无效,通常需要将你的“可选”请求字段标记为 nullable。例如:
$request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]);在此示例中,我们指定 publish_at 字段可以是 null 或有效的日期表示。 如果在规则定义中不添加 nullable 修饰符,验证器会将 null 视为无效日期。
当你的应用抛出一个 Illuminate\Validation\ValidationException 异常,并且传入的 HTTP 请求期望得到 JSON 响应时,Laravel 会自动为你格式化错误消息,并返回一个 422 Unprocessable Entity HTTP 响应。
下面,您可以查看验证错误的 JSON 响应格式示例。请注意,嵌套的错误键被扁平化为“点”表示法格式:
{
"message": "The team name must be a string. (and 4 more errors)",
"errors": {
"team_name": [
"The team name must be a string.",
"The team name must be at least 1 characters."
],
"authorization.role": [
"The selected authorization.role is invalid."
],
"users.0.email": [
"The users.0.email field is required."
],
"users.2.email": [
"The users.2.email must be a valid email address."
]
}
}对于更复杂的验证场景,你可能希望创建一个“表单请求”。表单请求是自定义请求类,它们封装了自己的验证和授权逻辑。要创建一个表单请求类,你可以使用 make:request Artisan CLI 命令:
php artisan make:request StorePostRequest生成的表单请求类将被放置在 app/Http/Requests 目录。如果此目录不存在,它将在你运行 make:request 命令时被创建。每个由 Laravel 生成的表单请求都有两个方法:authorize 和 rules。
顾名思义,authorize 方法负责判断当前已认证的用户是否可以执行请求所代表的操作,而 rules 方法返回应应用于请求的数据的验证规则:
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}[!NOTE]
你可以在rules方法的签名中类型提示你需要的任何依赖。 它们将通过 Laravel 服务容器 自动解析。
那么,验证规则是如何评估的?您只需在控制器方法上进行请求类型提示即可。传入的表单请求会在控制器方法被调用之前进行验证,这意味着您无需在控制器中添加任何验证逻辑:
/**
* Store a new blog post.
*/
public function store(StorePostRequest $request): RedirectResponse
{
// The incoming request is valid...
// Retrieve the validated input data...
$validated = $request->validated();
// Retrieve a portion of the validated input data...
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
// Store the blog post...
return redirect('/posts');
}如果验证失败,系统将生成一个重定向响应,将用户发送回其先前位置。错误也会被闪存到会话中,以便显示。如果请求是 XHR 请求,则会向用户返回一个状态码为 422 的 HTTP 响应,其中包含一个 验证错误的 JSON 表示。
[!NOTE]
需要为您的 Inertia 驱动的 Laravel 前端添加实时表单请求验证吗?查看 Laravel Precognition。
有时你需要在初始验证完成后执行额外的验证。你可以通过使用表单请求的 after 方法来实现这一点。
该 after 方法应返回一个由可调用对象或闭包组成的数组,它们将在验证完成后被调用。给定的可调用对象将接收一个 Illuminate\Validation\Validator 实例,允许你在必要时引发额外的错误消息:
use Illuminate\Validation\Validator;
/**
* Get the "after" validation callables for the request.
*/
public function after(): array
{
return [
function (Validator $validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add(
'field',
'Something is wrong with this field!'
);
}
}
];
}如前所述,由 after 方法返回的数组也可能包含可调用类。这些类的 __invoke 方法将接收一个 Illuminate\Validation\Validator 实例:
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
use Illuminate\Validation\Validator;
/**
* Get the "after" validation callables for the request.
*/
public function after(): array
{
return [
new ValidateUserStatus,
new ValidateShippingTime,
function (Validator $validator) {
//
}
];
}通过向你的请求类添加一个 stopOnFirstFailure 属性,你可以通知验证器,一旦发生一次验证失败,它就应该停止验证所有属性:
/**
* Indicates if the validator should stop on the first rule failure.
*
* @var bool
*/
protected $stopOnFirstFailure = true;当表单请求验证失败时,将生成一个重定向响应,将用户发送回他们之前的位置。但是,你可以自由定制此行为。为此,在你的表单请求上定义一个 $redirect 属性:
/**
* The URI that users should be redirected to if validation fails.
*
* @var string
*/
protected $redirect = '/dashboard';或者,如果你想将用户重定向到一个命名路由,你可以定义一个$redirectRoute属性来代替:
/**
* The route that users should be redirected to if validation fails.
*
* @var string
*/
protected $redirectRoute = 'dashboard';表单请求类也包含一个authorize方法。在此方法中,你可以判断认证用户实际是否拥有更新给定资源的权限。例如,你可以判断一个用户实际是否拥有他们正尝试更新的博客评论。很可能,你会在该方法中与你的授权门和策略进行交互:
use App\Models\Comment;
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
$comment = Comment::find($this->route('comment'));
return $comment && $this->user()->can('update', $comment);
}由于所有表单请求都继承了 Laravel 的基础请求类,我们可以使用 user 方法来访问当前认证用户。另外,请注意上述示例中对 route 方法的调用。此方法允许您访问在被调用的路由上定义的 URI 参数,例如下面示例中的 \{comment} 参数:
Route::post('/comment/{comment}');因此,如果您的应用程序正在利用路由模型绑定,您的代码可以通过将解析后的模型作为请求的一个属性来访问,从而变得更加简洁:
return $this->user()->can('update', $this->comment);如果 authorize 方法返回 false,则会自动返回一个状态码为 403 的 HTTP 响应并且你的控制器方法将不会执行。
如果您计划在应用程序的另一部分处理请求的授权逻辑,您可以完全删除 authorize 方法,或者直接返回 true:`
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}[!NOTE]
你可以在authorize方法的签名中类型提示任何你需要的依赖。它们将通过 Laravel 服务容器 自动解析。
您可以通过覆盖 messages 方法来定制表单请求所使用的错误消息。此方法应返回一个包含属性 / 规则对及其相应错误消息的数组:
/**
* Get the error messages for the defined validation rules.
*
* @return array<string, string>
*/
public function messages(): array
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}许多 Laravel 内置的验证规则错误消息包含一个 :attribute 占位符。如果你希望你的验证消息中的 :attribute 占位符被替换为一个自定义属性名,你可以通过覆盖 attributes 方法来指定自定义名称。这个方法应该返回一个属性/名称对数组:
/**
* Get custom attributes for validator errors.
*
* @return array<string, string>
*/
public function attributes(): array
{
return [
'email' => 'email address',
];
}如果您需要在应用您的验证规则之前,准备或清理来自请求的任何数据,您可以使用 prepareForValidation 方法:
use Illuminate\Support\Str;
/**
* Prepare the data for validation.
*/
protected function prepareForValidation(): void
{
$this->merge([
'slug' => Str::slug($this->slug),
]);
}同样,如果你需要在验证完成后标准化任何请求数据,你就可以使用 passedValidation 方法:
/**
* Handle a passed validation attempt.
*/
protected function passedValidation(): void
{
$this->replace(['name' => 'Taylor']);
}如果你不想使用请求中的 validate 方法,你可以手动使用 Validator 外观 创建一个验证器实例。该外观上的 make 方法会生成一个新的验证器实例:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
/**
* Store a new blog post.
*/
public function store(Request $request): RedirectResponse
{
$validator = Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
if ($validator->fails()) {
return redirect('/post/create')
->withErrors($validator)
->withInput();
}
// Retrieve the validated input...
$validated = $validator->validated();
// Retrieve a portion of the validated input...
$validated = $validator->safe()->only(['name', 'email']);
$validated = $validator->safe()->except(['name', 'email']);
// Store the blog post...
return redirect('/posts');
}
}传递给 make 方法的第一个参数是待验证的数据。第二个参数是一个验证规则的数组,这些规则将应用于数据。
在确定请求验证是否失败后,您可以使用 withErrors 方法将错误消息闪存到会话中。使用此方法时,$errors 变量将在重定向后自动与您的视图共享,使您能够轻松地将它们显示给用户。withErrors 方法接受一个验证器、一个 MessageBag 或一个 PHP 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', 'Something is wrong with this field!'
);
}
});
if ($validator->fails()) {
// ...
}如前所述,after 方法也接受一个可调用对象数组,如果你的“验证后”逻辑封装在可调用类中,这将特别方便,这些类将通过它们的 __invoke 方法接收一个 Illuminate\Validation\Validator 实例:
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
$validator->after([
new ValidateUserStatus,
new ValidateShippingTime,
function ($validator) {
// ...
},
]);在使用表单请求或手动创建的验证器实例验证传入请求数据后,你可能希望检索实际经过验证的传入请求数据。这可以通过多种方式实现。首先,你可以在表单请求或验证器实例上调用 validated 方法。此方法返回一个包含已验证数据的数组:
$validated = $request->validated();
$validated = $validator->validated();或者,你可以在表单请求或验证器实例上调用 safe 方法。此方法返回一个 Illuminate\Support\ValidatedInput 实例。此对象提供了 only、except 和 all 方法,以检索验证数据的子集或整个验证数据数组:
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
$validated = $request->safe()->all();此外,Illuminate\Support\ValidatedInput 实例可以像数组一样进行迭代和访问:
// Validated data may be iterated...
foreach ($request->safe() as $key => $value) {
// ...
}
// Validated data may be accessed as an array...
$validated = $request->safe();
$email = $validated['email'];如果您想向已验证数据添加额外字段,您可以调用 merge 方法:
$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);如果您希望将验证后的数据作为 集合实例,您可以调用 collect 方法:
$collection = $request->safe()->collect();调用 Validator 实例上的 errors 方法后,你将收到一个 Illuminate\Support\MessageBag 实例,它具有多种方便的方法来处理错误消息。自动提供给所有视图的 $errors 变量也是 MessageBag 类的一个实例。
要获取给定字段的第一个错误消息,请使用 first 方法:
$errors = $validator->errors();
echo $errors->first('email');如果你需要获取针对给定字段的所有消息数组,请使用 get 方法:
foreach ($errors->get('email') as $message) {
// ...
}如果你正在验证一个数组表单字段,你可以使用 * 字符为每个数组元素获取所有消息:
foreach ($errors->get('attachments.*') as $message) {
// ...
}要获取所有字段的所有消息数组,请使用 all 方法:
foreach ($errors->all() as $message) {
// ...
}该 has 方法可用于确定给定字段是否存在任何错误消息:
if ($errors->has('email')) {
// ...
}Laravel 内置的验证规则每个都带有一个错误消息,该消息位于你的应用程序的 lang/en/validation.php 文件中。如果你的应用程序没有 lang 目录,你可以指示 Laravel 使用 lang:publish Artisan 命令来创建它。
在 lang/en/validation.php 文件中,您会找到一个针对每个验证规则的翻译条目。您可以根据应用程序的需求更改或修改这些消息。
此外,您可以将此文件复制到另一个语言目录,以翻译您应用程序语言的消息。要了解有关 Laravel 本地化的更多信息,请查阅完整的本地化文档。
[!WARNING]
默认情况下,Laravel 应用程序骨架不包含lang目录。如果您想自定义 Laravel 的语言文件,您可以通过lang:publishArtisan 命令发布它们。
您可以在应用程序的验证语言文件中自定义用于指定属性和规则组合的错误消息。 为此,请将您的消息自定义项添加到应用程序的 lang/xx/validation.php 语言文件中的 custom 数组:
'custom' => [
'email' => [
'required' => 'We need to know your email address!',
'max' => 'Your email address is too long!'
],
],许多 Laravel 内置的错误消息包含一个 :attribute 占位符,该占位符会被替换为正在验证的字段或属性的名称。如果你想让验证消息中的 :attribute 部分被自定义值替换,你可以在你的 lang/xx/validation.php 语言文件中的 attributes 数组中指定自定义属性名称:
'attributes' => [
'email' => 'email address',
],[!警告]
默认情况下,Laravel 应用程序骨架不包含lang目录。如果您想自定义 Laravel 的语言文件,您可以通过lang:publishArtisan 命令发布它们。
Laravel 的一些内置验证规则错误消息包含一个 :value 占位符,该占位符会被请求属性的当前值替换。然而,您可能偶尔需要验证消息的 :value 部分被值的自定义表示替换。例如,考虑以下规则,该规则指定如果 payment_type 的值为 cc,则信用卡号是必需的:
Validator::make($request->all(), [
'credit_card_number' => 'required_if:payment_type,cc'
]);如果此验证规则失败,将会产生以下错误消息:
The credit card number field is required when payment type is cc.您可以不显示cc作为支付类型值,而是在您的lang/xx/validation.php语言文件中通过定义一个values数组来指定一个更友好的值表示:
'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],[!WARNING]
默认情况下,Laravel 应用程序骨架不包含lang目录。如果你想自定义 Laravel 的语言文件,你可以通过lang:publishArtisan 命令发布它们。
定义此值后,验证规则将生成以下错误消息:
The credit card number field is required when payment type is credit card.以下是所有可用验证规则及其功能的列表:
Accepted
Accepted If
Boolean
Declined
Declined If
待验证字段必须是 "yes","on",1,"1",true,或 "true"。这对于验证 "服务条款" 接受情况或类似字段很有用。
待验证字段必须是"yes", "on", 1, "1", true, 或 "true" 如果另一个待验证字段等于指定值。这对于验证"服务条款"接受或类似字段很有用。
待验证字段必须根据 dns_get_record PHP 函数拥有一个有效的 A 或 AAAA 记录。所提供 URL 的主机名会先使用 parse_url PHP 函数提取,然后再传递给 dns_get_record。
待验证字段的值必须晚于给定日期。这些日期将被传入 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 规则。
为方便起见,可以使用流畅的 date 规则构建器来构建基于日期的规则:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->afterOrEqual(today()->addDays(7)),
],Rule::anyOf 验证规则允许您指定被验证的字段必须满足给定的任何验证规则集。例如,以下规则将验证 username 字段是电子邮件地址,或者是至少有 6 个字符长的字母数字字符串(包括破折号):
use Illuminate\Validation\Rule;
'username' => [
'required',
Rule::anyOf([
['string', 'email'],
['string', 'alpha_dash', 'min:6'],
]),
],被验证字段必须完全是 Unicode 字母字符,包含在 \p 和 \p 中。
要将此验证规则限制为 ASCII 范围内的字符(a-z 和 A-Z),您可以将 ascii 选项提供给验证规则:
'username' => 'alpha:ascii',被验证的字段必须完全由Unicode字母数字字符组成,这些字符包含在\p, \p, \p中,以及ASCII连字符(-)和ASCII下划线(_)。
为了将此验证规则限制为 ASCII 范围内的字符 (a-z, A-Z, and 0-9),您可以为此验证规则提供 ascii 选项:
'username' => 'alpha_dash:ascii',待验证字段必须完全是 Unicode 字母数字字符 包含在 \p, \p, 和 \p 中。
将此验证规则限制为 ASCII 范围内的字符 (a-z, A-Z, 和 0-9), 您可以将 ascii 选项提供给此验证规则:
'username' => 'alpha_num:ascii',待验证字段必须为 PHP array。
当为 array 规则提供额外值时,输入数组中的每个键都必须存在于提供给该规则的值列表中。在以下示例中,输入数组中的 admin 键是无效的,因为它不包含在提供给 array 规则的值列表中:
use Illuminate\Support\Facades\Validator;
$input = [
'user' => [
'name' => 'Taylor Otwell',
'username' => 'taylorotwell',
'admin' => true,
],
];
Validator::make($input, [
'user' => 'array:name,username',
]);一般来说,你应该始终指定在你的数组中允许存在的数组键。
待验证的字段必须完全是7位ASCII字符。
在首次验证失败后,停止运行该字段的验证规则。
尽管 bail 规则只会在遇到验证失败时停止验证特定字段,stopOnFirstFailure 方法会通知验证器,一旦发生单个验证失败,它就应该停止验证所有属性:
if ($validator->stopOnFirstFailure()->fails()) {
// ...
}待验证字段必须是一个早于给定日期的值。这些日期将会被传入 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(),
],待验证字段必须是一个早于或等于给定日期的值。这些日期将被传入 PHP 的 strtotime 函数,以便转换为一个有效的 DateTime 实例。此外,与 after 规则类似,另一个待验证字段的名称可以作为 date 的值提供。
为方便起见,也可以使用流畅的 date 规则构建器来构建基于日期的规则:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->beforeOrEqual(today()->subDays(7)),
],待验证字段的大小必须介于给定的 最小值 和 最大值 之间(含)。字符串、数字、数组和文件的评估方式与 size 规则相同。
待验证字段必须能够转换为布尔值。接受的输入包括 true, false, 1, 0, "1", 和 "0"。
您可以使用 strict 参数,仅当字段的值为 true 或 false 时才将其视为有效:
'foo' => 'boolean:strict'被验证的字段必须有一个匹配的字段 {field}_confirmation. 例如, 如果被验证的字段是 password, 则输入中必须存在一个匹配的 password_confirmation 字段.
您还可以传递一个自定义的确认字段名称。例如,confirmed:repeat_username 将期望字段 repeat_username 与被验证字段匹配。
待验证字段必须是一个包含所有给定参数值的数组。由于此规则通常要求你 implode 一个数组,Rule::contains 方法可用于流畅地构建此规则:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'roles' => [
'required',
'array',
Rule::contains(['admin', 'editor']),
],
]);待验证字段必须是一个不包含任何给定参数值的数组。由于此规则通常需要您 implode 一个数组,因此可以使用 Rule::doesntContain 方法来流畅地构建规则:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'roles' => [
'required',
'array',
Rule::doesntContain(['admin', 'editor']),
],
]);待验证字段必须与已认证用户的密码匹配。你可以通过规则的第一个参数来指定一个 认证守卫:
'password' => 'current_password:api'待验证字段必须是根据 strtotime PHP 函数确定的有效非相对日期。
验证的字段必须等于给定日期。这些日期将被传入 PHP strtotime 函数,以便转换为一个有效的 DateTime 实例。
待验证字段必须匹配给定的其中一种格式。在验证字段时,你应该要么使用date或date_format,而不是两者都用。此验证规则支持 PHP 的 DateTime 类支持的所有格式。
为方便起见,可以使用流畅的 date 规则构建器来构建基于日期的规则:
use Illuminate\Validation\Rule;
'start_date' => [
'required',
Rule::date()->format('Y-m-d'),
],待验证字段必须是数字,并且必须包含指定的小数位数:
// Must have exactly two decimal places (9.99)...
'price' => 'decimal:2'
// Must have between 2 and 4 decimal places...
'price' => 'decimal:2,4'待验证字段必须是 "no", "off", 0, "0", false, 或 "false".
待验证字段必须是 "no", "off", 0, "0", false, 或 "false" 如果另一个待验证字段等于指定值。
待验证的字段必须与 字段 的值不同。
待验证的整数必须具有精确的长度为 值。
待验证的整数长度必须在给定的 min 和 max 之间。
待验证的文件必须是图片,符合由规则参数指定的尺寸限制:
'avatar' => 'dimensions:min_width=100,min_height=200'可用的约束条件有: 最小宽度, 最大宽度, 最小高度, 最大高度, 宽度, 高度, 比例.
一个 长宽比 约束应表示为宽度除以高度。这可以通过一个分数(例如 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),
],
]);当验证数组时,被验证的字段不得包含任何重复值:
'foo.*.id' => 'distinct'Distinct 默认使用松散变量比较。要使用严格比较,您可以将 strict 参数添加到您的验证规则定义中:
'foo.*.id' => 'distinct:strict'你可以添加 ignore_case 到验证规则的参数中,以使该规则忽略大小写差异:
'foo.*.id' => 'distinct:ignore_case'验证字段不能以给定值之一开头。
待验证字段不得以给定值之一结尾。
待验证字段必须格式为电子邮件地址。此验证规则利用 egulias/email-validator 包来验证电子邮件地址。默认情况下,RFCValidation 验证器被应用,但您也可以应用其他验证样式:
'email' => 'email:rfc,dns'以上示例将应用 RFCValidation 和 DNSCheckValidation 验证。以下是您可以应用的完整验证样式列表:
为方便起见,可以使用流式规则构建器构建电子邮件验证规则:
use Illuminate\Validation\Rule;
$request->validate([
'email' => [
'required',
Rule::email()
->rfcCompliant(strict: false)
->validateMxRecord()
->preventSpoofing()
],
]);[!WARNING]
这些dns和spoof验证器 需要 该 PHPintl扩展.
待验证字段必须匹配指定的字符编码。此规则使用 PHP 的 mb_check_encoding 函数来验证给定文件或字符串值的编码。为了方便起见,encoding 规则可以使用 Laravel 的流畅文件规则构建器来构建:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;
Validator::validate($input, [
'attachment' => [
'required',
File::types(['csv'])
->encoding('utf-8'),
],
]);待验证字段必须以给定值之一结尾。
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(...),
);待验证的字段将从 validate 和 validated 方法返回的请求数据中排除。
待验证字段将从由 validate 和 validated 方法返回的请求数据中排除如果 anotherfield 字段等于 value。
如果需要复杂的条件排除逻辑,您可以使用 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),
]);待验证字段将从 validate 和 validated 方法返回的请求数据中排除,除非 anotherfield 字段等于 value。如果 value 为 null (exclude_unless:name,null),则待验证字段将被排除,除非比较字段为 null 或比较字段在请求数据中缺失。
待验证字段将从由 validate 和 validated 方法返回的请求数据中排除,如果 anotherfield 字段存在。
待验证字段将从由 validate 和 validated 方法返回的请求数据中排除如果 anotherfield 字段不存在。
正在验证的字段必须存在于给定数据库表中。
'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);
}),
],
]);你可以显式指定应由 Rule::exists 方法生成的 exists 规则使用的数据库列名,方法是:将列名作为第二个参数提供给 exists 方法:
'state' => Rule::exists('states', 'abbreviation'),有时,您可能希望验证一个值数组是否存在于数据库中。您可以通过向待验证字段同时添加 exists 和 array 规则来做到这一点:
'states' => ['array', Rule::exists('states', 'abbreviation')],当这两条规则都被分配给一个字段时,Laravel 将自动构建一个单独的查询,来判断所有给定值是否存在于指定的表中。
待验证文件必须具有一个用户指定的扩展名,该扩展名需与列出的扩展名之一相对应:
'photo' => ['required', 'extensions:jpg,png'],[!警告]
您绝不应该仅仅依靠用户指定的文件扩展名来验证文件。这条规则通常应始终与 mimes 或 mimetypes 规则结合使用。
正在验证的字段必须是一个成功上传的文件。
待验证字段在存在时不能为空。
待验证字段必须大于给定的 字段 或 值。 这两个字段必须是相同类型。 字符串、数字、数组和文件使用与 size 规则相同的约定进行评估。
验证字段必须大于或等于给定的 字段 或 值。这两个字段必须是相同的类型。字符串、数字、数组和文件使用与 size 规则相同的约定进行评估。
待验证字段必须包含一个有效的颜色值,以十六进制格式。
待验证文件必须是一个图片 (jpg、jpeg、png、bmp、gif 或 webp)。
[!WARNING]
默认情况下,image规则不允许使用 SVG 文件,因为存在 XSS 漏洞的可能性。如果您需要允许使用 SVG 文件,您可以向image规则提供allow_svg指令 (image:allow_svg)。
待验证字段必须包含在给定值列表中。由于此规则通常要求您 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']),
]);待验证字段必须存在于 anotherfield 的值中。
待验证字段必须是一个数组,其中至少包含所给定 值 中的一个作为键:
'config' => 'array|in_array_keys:timezone'待验证字段必须是一个整数。
您可以使用 strict 参数,仅当字段类型为 integer 时才将其视为有效。包含整数值的字符串将被视为无效:
'age' => 'integer:strict'[!WARNING]
此验证规则不验证输入是否为 "integer" 变量类型,仅验证输入是否为 PHP 的FILTER_VALIDATE_INT规则所接受的类型。 如果您需要将输入验证为数字 请将此规则与 此numeric验证规则 结合使用。
验证字段必须是一个 IP 地址。
待验证字段必须是一个 IPv4 地址。
待验证字段必须是一个 IPv6 地址。
待验证字段必须是一个有效的 JSON 字符串。
待验证字段必须小于给定字段。这两个字段必须是相同类型。字符串、数字、数组和文件使用与size规则相同的约定进行评估。
待验证字段必须小于或等于给定的 字段。这两个字段必须是相同类型。字符串、数字、数组和文件的评估方式与 size 规则相同。
待验证字段必须是小写。
待验证字段必须是一个数组,且是一个列表。如果其键由从0到count($array) - 1的连续数字组成,则该数组被视为一个列表。
待验证字段必须是 MAC 地址。
待验证字段必须小于或等于一个最大值。字符串、数字、数组和文件会以与 size 规则相同的方式进行评估。
待验证的整数必须具有最大长度为 值。
待验证的文件必须匹配给定的 MIME 类型之一:
'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'为了确定上传文件的 MIME 类型,将读取文件内容,并且框架将尝试猜测 MIME 类型,这可能与客户端提供的 MIME 类型不同。
被验证的文件必须具有与列出的扩展名之一对应的 MIME 类型:
'photo' => 'mimes:jpg,bmp,png'即使您只需要指定扩展名,此规则实际上会通过读取文件内容并猜测其 MIME 类型来验证文件的 MIME 类型。MIME 类型及其对应扩展名的完整列表可在以下位置找到:
https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
此验证规则不验证 MIME 类型与用户为文件分配的扩展名之间的一致性。例如,mimes:png 验证规则会将包含有效 PNG 内容的文件视为有效的 PNG 图像,即使该文件名为 photo.txt。如果您想验证用户为文件分配的扩展名,可以使用 extensions 规则。
待验证字段必须具有一个最小值。字符串、数字、数组和文件会以与大小规则相同的方式进行评估。
待验证的整数必须具有最小长度为 值。
待验证字段必须是 值 的倍数。
待验证的字段不得存在于输入数据中。
待验证的字段如果另一个字段等于任何值,则不得存在。
验证字段不得存在除非 anotherfield 字段等于任意 value。
待验证字段不得存在 仅当 任何其他指定字段存在时。
待验证字段不得存在 仅当 所有其他指定字段都存在时。
验证字段不能包含在给定的值列表中。可以使用 Rule::notIn 方法流畅地构建规则:
use Illuminate\Validation\Rule;
Validator::make($data, [
'toppings' => [
'required',
Rule::notIn(['sprinkles', 'cherries']),
],
]);被验证的字段不得匹配给定的正则表达式。
在内部,此规则使用 PHP preg_match 函数。 指定的模式应遵循 preg_match 所要求的相同格式,因此也应包含有效的分隔符。 例如:'email' => 'not_regex:/^.+$/i'。
[!WARNING]
使用regex/not_regex模式时,可能需要使用数组来指定您的验证规则,而不是使用|分隔符,特别是如果正则表达式包含|字符。
待验证字段可能为null。
待验证字段必须是数值型。
您可以使用 strict 参数,以便仅当字段的值为整数或浮点类型时才将其视为有效。 数字字符串将被视为无效:
'amount' => 'numeric:strict'待验证字段必须存在于输入数据中。
待验证字段必须存在,如果 anotherfield 字段等于任何 value。
待验证字段必须存在,除非 另一个字段 字段等于任何 值。
待验证字段必须存在 仅当 其他任何指定的字段存在。
待验证字段必须存在 仅当 所有其他指定字段都存在。
待验证字段必须缺失或为空。 字段"为空"如果它满足以下条件之一:
待验证字段必须缺失或为空,如果 anotherfield 字段等于任何 value。 如果字段满足以下条件之一,则字段为“空”:
如果需要复杂的条件禁止逻辑,您可以使用 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),
]);待验证字段必须缺失或为空,如果 anotherfield 字段等于 "yes", "on", 1, "1", true, 或 "true".
待验证字段必须缺失或为空 如果 anotherfield 字段等于 "no", "off", 0, "0", false, 或 "false".
验证中的字段必须缺失或为空除非 anotherfield 字段等于任何 value。一个字段“为空”如果它满足以下条件之一:
如果验证中的字段不缺失或为空,则 anotherfield 中的所有字段都必须缺失或为空。如果字段满足以下任一条件,则称其为“空”:
待验证字段必须匹配给定的正则表达式。
在内部, 此规则使用 PHP preg_match 函数. 指定的模式应遵循 preg_match 所要求的相同格式, 因此也应包含有效的定界符. 例如: 'email' => 'regex:/^.+@.+$/i'.
[!WARNING]
在使用regex/not_regex模式时,可能需要以数组形式指定规则,而不是使用|分隔符,特别是当正则表达式本身包含|字符时。
待验证字段必须存在于输入数据中且不能为空。一个字段被认为是“空的”,如果它满足以下任一条件:
待验证字段必须存在且不为空 如果 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),
]);验证字段必须存在且不为空,如果 anotherfield 字段等于 "yes","on",1,"1",true, 或 "true"。
被验证的字段必须存在且不为空,如果 anotherfield 字段等于 "no", "off", 0, "0", false, 或 "false".
待验证字段必须存在且不为空除非 anotherfield 字段等于任何 value。这也意味着 anotherfield 必须存在于请求数据中除非 value 是 null。如果 value 是 null (required_unless:name,null),待验证字段将是必需的除非比较字段是 null 或者比较字段在请求数据中缺失。
被验证的字段必须存在且不为空 仅当 任何其他指定的字段存在且不为空时。
待验证字段必须存在且非空 仅当 所有其他指定字段存在且非空。
被验证的字段必须存在且非空 仅当 任何其他指定的字段为空或不存在。
待验证字段必须存在且不为空,仅当所有其他指定字段为空或不存在时。
待验证字段必须是数组并且必须包含至少指定的键。
给定字段必须匹配待验证的字段。
待验证字段的大小必须等于给定的 值。对于字符串数据,值 对应于字符数量。对于数值数据,值 对应于给定的整数值 (该属性还必须具有 numeric 或 integer 规则)。对于数组,大小 对应于数组的 count。对于文件,大小 对应于文件大小,单位为千字节。我们来看一些示例:
// Validate that a string is exactly 12 characters long...
'title' => 'size:12';
// Validate that a provided integer equals 10...
'seats' => 'integer|size:10';
// Validate that an array has exactly 5 elements...
'tags' => 'array|size:5';
// Validate that an uploaded file is exactly 512 kilobytes...
'image' => 'file|size:512';待验证字段必须以其中一个给定值开头。
待验证字段必须是字符串。如果您希望允许该字段也可以是 null,您应该为该字段分配 nullable 规则。
正在验证的字段必须是一个有效时区标识符根据 DateTimeZone::listIdentifiers 方法。
这些参数由 DateTimeZone::listIdentifiers 方法接受也可以提供给此验证规则:
'timezone' => 'required|timezone:all';
'timezone' => 'required|timezone:Africa';
'timezone' => 'required|timezone:per_country,US';待验证字段不得存在于给定的数据库表中。
指定自定义表 / 列名:
与其直接指定表名,您可以指定 Eloquent 模型,该模型将用于确定表名:
'email' => 'unique:App\Models\User,email_address'column 选项可用于指定字段对应的数据库列。如果未指定 column 选项,验证中字段的名称将被使用。
'email' => 'unique:users,email_address'指定自定义数据库连接
偶尔,您可能需要为 Validator 发起的数据库查询设置自定义连接。为此,您可以将连接名称前置到表名:
'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,例如自增ID或Eloquent模型实例的UUID。否则,您的应用程序将容易受到SQL注入攻击。
您也可以传递整个模型实例,而不是将模型键的值传递给 ignore 方法。Laravel 将自动从模型中提取键:
Rule::unique('users')->ignore($user)如果你的表使用的主键列名不是id,你可以在调用ignore方法时指定列名:
Rule::unique('users')->ignore($user->id, 'user_id')默认情况下,unique 规则将检查与被验证属性名称匹配的列的唯一性。然而,你可以将不同的列名作为第二个参数传递给 unique 方法:
Rule::unique('users', 'email_address')->ignore($user->id)添加额外的 Where 子句:
您可以通过使用 where 方法自定义查询来指定额外的查询条件。例如,我们来添加一个查询条件,将查询范围限定为仅搜索 account_id 列值为 1 的记录:
'email' => Rule::unique('users')->where(fn (Builder $query) => $query->where('account_id', 1))忽略唯一性检查中的软删除记录:
默认情况下,唯一性规则在判断唯一性时会包含软删除的记录。若要排除软删除的记录不参与唯一性检查,你可以调用 withoutTrashed 方法:
Rule::unique('users')->withoutTrashed();如果您的模型使用除 deleted_at 以外的列名用于软删除记录,您可以在调用 withoutTrashed 方法时提供该列名:
Rule::unique('users')->withoutTrashed('was_deleted_at');待验证字段必须为大写。
待验证字段必须是有效的 URL。
如果您想指定应被视为有效的 URL 协议,您可以将协议作为验证规则参数传递:
'url' => 'url:http,https',
'game' => 'url:minecraft,steam',待验证字段必须是一个有效的全局唯一字典序可排序标识符 (ULID)。
待验证字段必须是一个有效的 RFC 9562 (版本 1、3、4、5、6、7 或 8) 通用唯一标识符 (UUID)。
您还可以验证给定的 UUID 是否符合按版本区分的 UUID 规范:
'uuid' => 'uuid:4'你可能偶尔希望在另一个字段具有给定值时,不验证某个给定字段。你可以使用 exclude_if 验证规则来完成此操作。在此示例中,如果 has_appointment 字段的值为 false,则 appointment_date 和 doctor_name 字段将不会被验证:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($data, [
'has_appointment' => 'required|boolean',
'appointment_date' => 'exclude_if:has_appointment,false|required|date',
'doctor_name' => 'exclude_if:has_appointment,false|required|string',
]);或者,您可以使用 exclude_unless 规则来不验证给定字段除非另一个字段具有给定值:
$validator = Validator::make($data, [
'has_appointment' => 'required|boolean',
'appointment_date' => 'exclude_unless:has_appointment,true|required|date',
'doctor_name' => 'exclude_unless:has_appointment,true|required|string',
]);在某些情况下,你可能希望对某个字段运行验证检查仅当该字段存在于待验证数据中时。
要快速实现此目的,请将 sometimes 规则添加到你的规则列表中:
$validator = Validator::make($data, [
'email' => 'sometimes|required|email',
]);在上面的例子中, email 字段将仅被验证如果它存在于 $data 数组中。
[!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 规则接受一个允许的数组键列表。如果数组中存在任何额外的键,验证将失败:
use Illuminate\Support\Facades\Validator;
$input = [
'user' => [
'name' => 'Taylor Otwell',
'username' => 'taylorotwell',
'admin' => true,
],
];
Validator::make($input, [
'user' => 'array:name,username',
]);通常,你应该始终指定在你的数组中允许存在的数组键。否则,验证器的 validate 和 validated 方法将返回所有已验证的数据,包括该数组及其所有键,即使这些键未被其他嵌套数组验证规则验证。
验证嵌套的基于数组的表单输入字段不必是一件麻烦事。您可以使用“点表示法”来验证数组中的属性。例如,如果传入的HTTP请求包含一个 photos[profile] 字段,您可以这样验证它:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'photos.profile' => 'required|image',
]);您还可以验证数组的每个元素。例如,要验证给定数组输入字段中的每个电子邮件地址都是唯一的,您可以执行以下操作:
$validator = Validator::make($request->all(), [
'users.*.email' => 'email|unique:users',
'users.*.first_name' => 'required_with:users.*.last_name',
]);同样地,你可以使用 * 字符在指定 自定义验证消息在你的语言文件中 时,使得针对基于数组的字段使用单个验证消息变得轻而易举:
'custom' => [
'users.*.email' => [
'unique' => 'Each user must have a unique email address',
]
],有时,你可能需要在为属性分配验证规则时,访问给定嵌套数组元素的值。你可以使用 Rule::forEach 方法来完成此操作。forEach 方法接受一个闭包,该闭包将在验证数组属性的每次迭代时被调用,并将接收属性的值以及明确的、完全展开的属性名称。该闭包应返回一个规则数组,以分配给数组元素:
use App\Rules\HasPermission;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
$validator = Validator::make($request->all(), [
'companies.*.id' => Rule::forEach(function (string|null $value, string $attribute) {
return [
Rule::exists(Company::class, 'id'),
new HasPermission('manage-company', $value),
];
}),
]);在验证数组时,您可能希望在应用程序显示的错误消息中引用验证失败的特定项的索引或位置。为此,您可以在自定义验证消息中包含 :index(从 0 开始)、:position(从 1 开始)或 :ordinal-position(从 1st 开始)占位符:
use Illuminate\Support\Facades\Validator;
$input = [
'photos' => [
[
'name' => 'BeachVacation.jpg',
'description' => 'A photo of my beach vacation!',
],
[
'name' => 'GrandCanyon.jpg',
'description' => '',
],
],
];
Validator::validate($input, [
'photos.*.description' => 'required',
], [
'photos.*.description.required' => 'Please describe photo #:position.',
]);鉴于上述示例,验证将失败,用户将收到以下错误:"请描述照片 #2。""
如果需要,您可以引用更深层嵌套的索引和位置 通过 second-index、 second-position、 third-index、 third-position、 等。
'photos.*.attributes.*.string' => 'Invalid attribute for photo #:second-position.',Laravel 提供了多种可用于验证上传文件的验证规则,例如 mimes、image、min 和 max。虽然你可以自由地单独指定这些规则来验证文件,但 Laravel 也提供了一个流畅的文件验证规则构建器,你可能会觉得它很方便:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;
Validator::validate($input, [
'attachment' => [
'required',
File::types(['mp3', 'wav'])
->min(1024)
->max(12 * 1024),
],
]);尽管在调用 types 方法时您只需要指定扩展名,但此方法实际上通过读取文件内容并猜测其 MIME 类型来验证文件的 MIME 类型。MIME 类型及其对应扩展名的完整列表可在以下位置找到:
[https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types](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]
默认情况下,image规则不允许 SVG 文件,因为存在 XSS 漏洞的可能性。如果您需要允许 SVG 文件,可以将allowSvg: true传递给image规则:File::image(allowSvg: true)。
您还可以验证图片的尺寸。例如,要验证上传的图片宽度至少为 1000 像素,高度至少为 500 像素,您可以使用 dimensions 规则:
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;
File::image()->dimensions(
Rule::dimensions()
->maxWidth(1000)
->maxHeight(500)
)[!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 规则对象允许您轻松自定义针对您的应用程序的密码复杂性要求, 例如指定密码要求至少包含一个字母, 数字, 符号, 或混合大小写字符:
// Require at least 8 characters...
Password::min(8)
// Require at least one letter...
Password::min(8)->letters()
// Require at least one uppercase and one lowercase letter...
Password::min(8)->mixedCase()
// Require at least one number...
Password::min(8)->numbers()
// Require at least one symbol...
Password::min(8)->symbols()此外,您可以确保密码未在公共密码数据泄露中被泄露,使用uncompromised方法:
Password::min(8)->uncompromised()在内部,Password 规则对象使用 k-匿名性 模型来确定密码是否已通过 haveibeenpwned.com 服务泄露,同时不牺牲用户的隐私或安全。
默认情况下,如果一个密码在数据泄露中出现至少一次,它将被视为已泄露。你可以使用uncompromised方法的第一个参数来自定义此阈值:
// Ensure the password appears less than 3 times in the same data leak...
Password::min(8)->uncompromised(3);当然,你可以链式调用上述示例中的所有方法:
Password::min(8)
->letters()
->mixedCase()
->numbers()
->symbols()
->uncompromised()您可能会觉得在应用程序的单一位置指定密码的默认验证规则很方便。您可以使用 Password::defaults 方法轻松实现此目的,该方法接受一个闭包。传递给 defaults 方法的闭包应该返回 Password 规则的默认配置。通常,应该在您应用程序的某个服务提供者的 boot 方法中调用 defaults 规则:
use Illuminate\Validation\Rules\Password;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Password::defaults(function () {
$rule = Password::min(8);
return $this->app->isProduction()
? $rule->mixedCase()->uncompromised()
: $rule;
});
}然后,当您希望将默认规则应用于正在验证的特定密码时,您可以调用不带任何参数的 defaults 方法:
'password' => ['required', Password::defaults()],有时,你可能希望为默认密码验证规则附加额外的验证规则。你可以使用 rules 方法来完成此操作:
use App\Rules\ZxcvbnRule;
Password::defaults(function () {
$rule = Password::min(8)->rules([new ZxcvbnRule]);
// ...
});Laravel 提供了各种有用的验证规则;但是,你可能希望指定一些自己的规则。注册自定义验证规则的一种方法是使用规则对象。要生成新的规则对象,你可以使用 make:rule Artisan 命令。让我们使用此命令生成一个验证字符串是否为大写的规则。Laravel 会将新规则放置在 app/Rules 目录中。如果此目录不存在,Laravel 会在你执行 Artisan 命令创建规则时创建它:
php artisan make:rule Uppercase一旦规则创建成功, 我们就可以定义其行为了. 一个规则对象包含一个方法: validate. 这个方法接收属性名, 其值, 以及一个回调函数, 当验证失败时, 该回调函数应被调用并附带验证错误消息:
<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class Uppercase implements ValidationRule
{
/**
* Run the validation rule.
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (strtoupper($value) !== $value) {
$fail('The :attribute must be uppercase.');
}
}
}一旦规则被定义,你可以通过将规则对象的一个实例与其他验证规则一起传递,从而将其附加到验证器:
use App\Rules\Uppercase;
$request->validate([
'name' => ['required', 'string', new Uppercase],
]);与其向 $fail 闭包提供字面错误消息,您也可以提供一个 翻译字符串键 并指示 Laravel 翻译该错误消息:
if (strtoupper($value) !== $value) {
$fail('validation.uppercase')->translate();
}如有必要,您可以将占位符替换和首选语言作为第一个和第二个参数提供给 translate 方法:
$fail('validation.location')->translate([
'value' => $this->value,
], 'fr');如果你的自定义验证规则类需要访问所有其他正在进行验证的数据,你的规则类可以实现 Illuminate\Contracts\Validation\DataAwareRule 接口。此接口要求你的类定义一个 setData 方法。Laravel 将自动调用此方法(在验证进行之前),并传入所有正在验证的数据:
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;
class Uppercase implements DataAwareRule, ValidationRule
{
/**
* All of the data under validation.
*
* @var array<string, mixed>
*/
protected $data = [];
// ...
/**
* Set the data under validation.
*
* @param array<string, mixed> $data
*/
public function setData(array $data): static
{
$this->data = $data;
return $this;
}
}或者,如果您的验证规则需要访问执行验证的验证器实例,您可以通过实现 ValidatorAwareRule 接口:
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Contracts\Validation\ValidatorAwareRule;
use Illuminate\Validation\Validator;
class Uppercase implements ValidationRule, ValidatorAwareRule
{
/**
* The validator instance.
*
* @var \Illuminate\Validation\Validator
*/
protected $validator;
// ...
/**
* Set the current validator.
*/
public function setValidator(Validator $validator): static
{
$this->validator = $validator;
return $this;
}
}如果您在整个应用程序中只需要自定义规则的一次性功能,您可以使用闭包而不是规则对象。该闭包接收属性名称、属性值以及一个 $fail 回调,如果验证失败,则应调用该回调:
use Illuminate\Support\Facades\Validator;
use Closure;
$validator = Validator::make($request->all(), [
'title' => [
'required',
'max:255',
function (string $attribute, mixed $value, Closure $fail) {
if ($value === 'foo') {
$fail("The {$attribute} is invalid.");
}
},
],
]);默认情况下,当正在验证的属性不存在或包含空字符串时,正常的验证规则,包括自定义规则,将不会运行。例如,唯一 规则将不会针对空字符串运行:
use Illuminate\Support\Facades\Validator;
$rules = ['name' => 'unique:users,name'];
$input = ['name' => ''];
Validator::make($input, $rules)->passes(); // true对于自定义规则,即使属性为空也能运行,该规则必须暗示此属性是必需的。要快速生成新的隐式规则对象,你可以使用 make:rule Artisan 命令并附带 --implicit 选项:
php artisan make:rule Uppercase --implicit[!WARNING]
"隐式"规则仅仅暗示属性是必需的。它是否真的会使缺失或空的属性无效,则由你决定。