laravel
4. 基础知识
验证

介绍

Laravel 为验证应用程序的传入数据提供了几种不同的方法。最常见的是使用所有传入的 HTTP 请求上可用的 validate 方法。不过,我们也会讨论其他验证方法。

Laravel 包含了各种各样的方便验证规则,您可以将其应用于数据,甚至可以验证值在给定数据库表中是否唯一。我们将详细介绍这些验证规则,以便您熟悉 Laravel 的所有验证功能。

验证快速入门

为了了解 Laravel 强大的验证功能,让我们来看一个完整的示例,该示例验证一个表单并将错误消息显示回用户。通过阅读此高级概述,您将能够很好地总体了解如何使用 Laravel 验证传入的请求数据:

定义路由

首先,假设我们在 routes/web.php 文件中定义了以下路由:

use App\Http\Controllers\PostController;

Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);

GET 路由将为用户显示一个创建新博客文章的表单,而 POST 路由将新博客文章存储在数据库中。

创建控制器

接下来,让我们看一个简单的控制器,该控制器处理对这些路由的传入请求。我们现在将 store 方法留空:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PostController extends Controller
{
    /**
     * 显示创建新博客文章的表单。
     */
    public function create(): View
    {
        return view('post.create');
    }

    /**
     * 存储新的博客文章。
     */
    public function store(Request $request): RedirectResponse
    {
        // 验证并存储博客文章...

        $post = /**... */

        return to_route('post.show', ['post' => $post->id]);
    }
}

编写验证逻辑

现在我们准备在 store 方法中填写用于验证新博客文章的逻辑。为此,我们将使用 Illuminate\Http\Request 对象提供的 validate 方法。如果验证规则通过,您的代码将正常继续执行;但是,如果验证失败,将抛出 Illuminate\Validation\ValidationException 异常,并且会自动向用户发送适当的错误响应。

如果在传统的 HTTP 请求期间验证失败,将生成一个重定向响应到上一个 URL。如果传入的请求是 XHR 请求,则会返回一个包含验证错误消息的 JSON 响应

为了更好地理解 validate 方法,让我们回到 store 方法:

/**
 * 存储新的博客文章。
 */
public function store(Request $request): RedirectResponse
{
    $validated = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

    // 博客文章有效...

    return redirect('/posts');
}

如您所见,验证规则被传递到 validate 方法中。不用担心 - 所有可用的验证规则都在 文档中有记录。同样,如果验证失败,将自动生成适当的响应。如果验证通过,我们的控制器将继续正常执行。

或者,验证规则可以指定为规则数组,而不是单个 | 分隔的字符串:

$validatedData = $request->validate([
    'title' => ['required', 'unique:posts', 'max:255'],
    'body' => ['required'],
]);

此外,您可以使用 validateWithBag 方法来验证请求,并将任何错误消息存储在 命名错误包中:

$validatedData = $request->validateWithBag('post', [
    'title' => ['required', 'unique:posts', 'max:255'],
    'body' => ['required'],
]);

在首次验证失败时停止

有时您可能希望在某个属性首次验证失败后停止运行该属性的验证规则。为此,将 bail 规则分配给该属性:

$request->validate([
    'title' => 'bail|required|unique:posts|max:255',
    'body' => 'required',
]);

在此示例中,如果 title 属性的 unique 规则失败,将不会检查 max 规则。规则将按照它们分配的顺序进行验证。

关于嵌套属性的说明

如果传入的 HTTP 请求包含“嵌套”字段数据,您可以使用“点”语法在验证规则中指定这些字段:

$request->validate([
    'title' => 'required|unique:posts|max:255',
    'author.name' => 'required',
    'author.description' => 'required',
]);

另一方面,如果您的字段名称包含一个文字句点,您可以通过用反斜杠转义句点来明确防止其被解释为“点”语法:

$request->validate([
    'title' => 'required|unique:posts|max:255',
    'v1\.0' => 'required',
]);

显示验证错误

那么,如果传入的请求字段未通过给定的验证规则会怎样呢?如前所述,Laravel 将自动将用户重定向回他们的上一个位置。此外,所有验证错误和 请求输入将自动 闪存到会话中。

Illuminate\View\Middleware\ShareErrorsFromSession 中间件会将一个 $errors 变量与您应用程序的所有视图共享,该中间件由 web 中间件组提供。当应用此中间件时,在您的视图中始终可以使用 $errors 变量,这使您可以方便地假设 $errors 变量始终已定义并且可以安全地使用。$errors 变量将是 Illuminate\Support\MessageBag 的一个实例。有关使用此对象的更多信息,请 查看其文档

因此,在我们的示例中,当验证失败时,用户将被重定向到我们控制器的 create 方法,使我们能够在视图中显示错误消息:

<!-- /resources/views/post/create.blade.php -->
 
<h1>创建文章</h1>
 
@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
 
<!-- 创建文章表单 -->

自定义错误消息

Laravel 的内置验证规则每个都有一个错误消息,位于您应用程序的 lang/en/validation.php 文件中。如果您的应用程序没有 lang 目录,您可以使用 lang:publish Artisan 命令指示 Laravel 创建它。

lang/en/validation.php 文件中,您会为每个验证规则找到一个翻译条目。您可以根据应用程序的需要自由更改或修改这些消息。

此外,您可以将此文件复制到另一个语言目录,以翻译应用程序语言的消息。要了解有关 Laravel 本地化的更多信息,请查看完整的 本地化文档

[!警告]
默认情况下,Laravel 应用程序框架不包括 lang 目录。如果您想自定义 Laravel 的语言文件,可以通过 lang:publish Artisan 命令发布它们。

XHR 请求和验证

在这个例子中,我们使用传统的表单将数据发送到应用程序。然而,许多应用程序从由 JavaScript 驱动的前端接收 XHR 请求。在 XHR 请求期间使用 validate 方法时,Laravel 不会生成重定向响应。相反,Laravel 会生成一个包含所有验证错误的 JSON 响应。此 JSON 响应将以 422 HTTP 状态代码发送。

@error 指令

您可以使用 @error Blade 指令快速确定给定属性是否存在验证错误消息。在 @error 指令内,您可以回显 $message 变量以显示错误消息:

<!-- /resources/views/post/create.blade.php -->
 
<label for="title">文章标题</label>
 
<input id="title"
    type="text"
    name="title"
    class="@error('title') is-invalid @enderror">
 
@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

如果您正在使用 命名错误包,则可以将错误包的名称作为第二个参数传递给 @error 指令:

<input... class="@error('title', 'post') is-invalid @enderror">

重新填充表单

当 Laravel 由于验证错误生成重定向响应时,框架将自动 将请求的所有输入闪存到会话中。这样做是为了您可以在下次请求期间方便地访问输入并重新填充用户尝试提交的表单。

要从先前的请求中检索闪存的输入,请在 Illuminate\Http\Request 的实例上调用 old 方法。old 方法将从 会话 中提取先前闪存的输入数据:

$title = $request->old('title');

Laravel 还提供了一个全局 old 助手。如果您在 Blade 模板 中显示旧输入,则使用 old 助手重新填充表单会更方便。如果给定字段不存在旧输入,则将返回 null

<input type="text" name="title" value="{{ old('title') }}">

关于可选字段的说明

默认情况下,Laravel 在您的应用程序的全局中间件堆栈中包含 TrimStringsConvertEmptyStringsToNull 中间件。因此,如果您不希望验证器将 null 值视为无效,您通常需要将“可选”请求字段标记为 nullable。例如:

$request->validate([
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
    'publish_at' => 'nullable|date',
]);

在此示例中,我们指定 publish_at 字段可以是 null 或有效的日期表示形式。如果未将 nullable 修饰符添加到规则定义中,验证器将认为 null 是无效的日期。

验证错误响应格式

当您的应用程序抛出 Illuminate\Validation\ValidationException 异常并且传入的 HTTP 请求期望 JSON 响应时,Laravel 将自动为您格式化错误消息并返回 422 Unprocessable Entity HTTP 响应。

下面,您可以查看验证错误的 JSON 响应格式的示例。请注意,嵌套错误键被展平为“点”表示法格式:

{
    "message": "团队名称必须是字符串。(以及 4 个更多错误)",
    "errors": {
        "team_name": [
            "团队名称必须是字符串。",
            "团队名称必须至少为 1 个字符。"
        ],
        "authorization.role": [
            "所选的 authorization.role 无效。"
        ],
        "users.0.email": [
            "users.0.email 字段是必需的。"
        ],
        "users.2.email": [
            "users.2.email 必须是有效的电子邮件地址。"
        ]
    }
}

表单请求验证

创建表单请求

对于更复杂的验证场景,您可能希望创建一个“表单请求”。表单请求是自定义请求类,它们封装了自己的验证和授权逻辑。要创建表单请求类,您可以使用 make:request Artisan CLI 命令:

php artisan make:request StorePostRequest

生成的表单请求类将放置在 app/Http/Requests 目录中。如果此目录不存在,在您运行 make:request 命令时将创建它。Laravel 生成的每个表单请求都有两个方法:authorizerules

正如您可能已经猜到的,authorize 方法负责确定当前经过身份验证的用户是否可以执行请求所代表的操作,而 rules 方法返回应应用于请求数据的验证规则:

/**
 * 获取适用于请求的验证规则。
 *
 * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
 */
public function rules(): array
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}

[!注意]
您可以在 rules 方法的签名中键入提示您需要的任何依赖项。它们将通过 Laravel 服务容器自动解析。

那么,如何评估验证规则呢?您只需要在控制器方法上键入提示请求。在调用控制器方法之前,会对传入的表单请求进行验证,这意味着您不需要在控制器中添加任何验证逻辑:

/**
 * 存储新的博客文章。
 */
public function store(StorePostRequest $request): RedirectResponse
{
    // 传入的请求是有效的...

    // 检索已验证的输入数据...
    $validated = $request->validated();

    // 检索已验证的输入数据的一部分...
    $validated = $request->safe()->only(['name', 'email']);
    $validated = $request->safe()->except(['name', 'email']);

    // 存储博客文章...

    return redirect('/posts');
}

如果验证失败,将生成一个重定向响应,将用户送回他们的上一个位置。错误也将闪存到会话中,以便它们可以显示。如果请求是 XHR 请求,则会向用户返回一个包含 验证错误的 JSON 表示的 HTTP 响应,状态代码为 422。

[!注意]
需要为您的由 Inertia 驱动的 Laravel 前端添加实时表单请求验证吗?查看 Laravel Precognition

执行额外验证

有时您需要在初始验证完成后执行额外的验证。您可以使用表单请求的 after 方法来实现这一点。

after 方法应该返回一个可调用函数或闭包的数组,这些函数或闭包将在验证完成后被调用。给定的可调用函数将接收一个 Illuminate\Validation\Validator 实例,允许您在必要时提出其他错误消息:

use Illuminate\Validation\Validator;

/**
 * 获取请求的“之后”验证可调用函数。
 */
public function after(): array
{
    return [
        function (Validator $validator) {
            if ($this->somethingElseIsInvalid()) {
                $validator->errors()->add(
                    'field',
                    '此字段有问题!'
                );
            }
        }
    ];
}

如前所述,after 方法返回的数组也可以包含可调用类。这些类的 `

处理错误消息

在对 Validator 实例调用 errors 方法后,您将收到一个 Illuminate\Support\MessageBag 实例,它具有多种处理错误消息的便捷方法。自动提供给所有视图的 $errors 变量也是 MessageBag 类的一个实例。

检索给定字段的第一个错误消息

要检索给定字段的第一个错误消息,请使用 first 方法:

$errors = $validator->errors();

echo $errors->first('email');

检索给定字段的所有错误消息

如果您需要检索给定字段的所有消息的数组,请使用 get 方法:

foreach ($errors->get('email') as $message) {
    //...
}

如果您正在验证数组表单字段,则可以使用 * 字符检索数组每个元素的所有消息:

foreach ($errors->get('attachments.*') as $message) {
    //...
}

检索所有字段的所有错误消息

要检索所有字段的所有消息的数组,请使用 all 方法:

foreach ($errors->all() as $message) {
    //...
}

确定字段是否存在消息

可以使用 has 方法确定给定字段是否存在任何错误消息:

if ($errors->has('email')) {
    //...
}

在语言文件中指定自定义消息

Laravel 的内置验证规则每个都有一个错误消息,位于您应用程序的 lang/en/validation.php 文件中。如果您的应用程序没有 lang 目录,您可以使用 lang:publish Artisan 命令指示 Laravel 创建它。

lang/en/validation.php 文件中,您会为每个验证规则找到一个翻译条目。您可以根据应用程序的需要自由更改或修改这些消息。

此外,您可以将此文件复制到另一个语言目录中,以翻译您应用程序的语言消息。要了解有关 Laravel 本地化的更多信息,请查看完整的本地化文档

[!警告]
默认情况下,Laravel 应用程序框架不包括 lang 目录。如果您想要自定义 Laravel 的语言文件,可以通过 lang:publish Artisan 命令发布它们。

特定属性的自定义消息

您可以在应用程序的验证语言文件的 custom 数组中为指定的属性和规则组合自定义错误消息:

'custom' => [
    'email' => [
        'required' => '我们需要知道您的电子邮件地址!',
        'max' => '您的电子邮件地址太长了!'
    ],
],

在语言文件中指定属性

Laravel 的许多内置错误消息都包含一个 :attribute 占位符,该占位符将被替换为正在验证的字段或属性的名称。如果您希望验证消息的 :attribute 部分被替换为自定义值,则可以在 lang/xx/validation.php 语言文件的 attributes 数组中指定自定义属性名称:

'attributes' => [
    'email' => '电子邮件地址',
],

[!警告]
默认情况下,Laravel 应用程序框架不包括 lang 目录。如果您想要自定义 Laravel 的语言文件,可以通过 lang:publish Artisan 命令发布它们。

在语言文件中指定值

Laravel 的一些内置验证规则错误消息包含一个 :value 占位符,该占位符将被替换为请求属性的当前值。但是,您可能偶尔需要将验证消息的 :value 部分替换为值的自定义表示形式。例如,考虑以下规则,该规则指定如果 payment_type 的值为 cc,则需要信用卡号码:

Validator::make($request->all(), [
    'credit_card_number' => 'required_if:payment_type,cc'
]);

如果此验证规则失败,它将产生以下错误消息:

当付款类型为 cc 时,信用卡号码字段是必需的。

您可以通过在 lang/xx/validation.php 语言文件中定义一个 values 数组,为付款类型指定一个更用户友好的值表示形式,而不是显示 cc 作为付款类型值:

'values' => [
    'payment_type' => [
        'cc' => '信用卡'
    ],
],

[!警告]
默认情况下,Laravel 应用程序框架不包括 lang 目录。如果您想要自定义 Laravel 的语言文件,可以通过 lang:publish Artisan 命令发布它们。

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

当付款类型为信用卡时,信用卡号码字段是必需的。

可用的验证规则

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

Accepted(已接受) Accepted If(如果已接受) Active URL(有效 URL) After (Date)(在(日期)之后) After Or Equal (Date)(在(日期)之后或等于) Alpha(仅字母) Alpha Dash(字母、数字、破折号和下划线) Alpha Numeric(字母数字) Array(数组) Ascii(仅 ASCII 字符) Bail(遇到第一个验证失败时停止) Before (Date)(在(日期)之前) Before Or Equal (Date)(在(日期)之前或等于) Between(在...之间) Boolean(布尔值) Confirmed(已确认) Contains(包含) Current Password(当前密码) Date(日期) Date Equals(日期相等) Date Format(日期格式) Decimal(小数) Declined(已拒绝) Declined If(如果已拒绝) Different(不同) Digits(数字长度) Digits Between(数字长度在...之间) Dimensions (Image Files)(图像文件尺寸) Distinct(唯一) Doesnt Start With(不以...开头) Doesnt End With(不以...结尾) Email(电子邮件) Ends With(以...结尾) Enum(枚举) Exclude(排除) Exclude If(如果...则排除) Exclude Unless(除非...否则排除) Exclude With(如果...存在则排除) Exclude Without(如果...不存在则排除) Exists (Database)(存在于数据库中) Extensions(扩展名) File(文件) Filled(已填充) Greater Than(大于) Greater Than Or Equal(大于或等于) Hex Color(十六进制颜色) Image (File)(图像(文件)) In(在...中) In Array(在数组中) Integer(整数) IP Address(IP 地址) JSON(JSON 格式) Less Than(小于) Less Than Or Equal(小于或等于) List(列表) Lowercase(小写) MAC Address(MAC 地址) Max(最大值) Max Digits(最大数字位数) MIME Types(MIME 类型) MIME Type By File Extension(根据文件扩展名的 MIME 类型) Min(最小值) Min Digits(最小数字位数) Missing(缺失) Missing If(如果...则缺失) Missing Unless(除非...否则缺失) Missing With(如果存在其他指定字段则缺失) Missing With All(如果存在所有其他指定字段则缺失) Multiple Of(倍数) Not In(不在...中) Not Regex(不符合正则表达式) Nullable(可为空) Numeric(数字) Present(存在) Present If(如果...则存在) Present Unless(除非...否则存在) Present With(如果存在其他字段则存在) Present With All(如果存在所有其他字段则存在) Prohibited(被禁止) Prohibited If(如果...则被禁止) Prohibited Unless(除非...否则被禁止) Prohibits(禁止) Regular Expression(正则表达式) Required(必需) Required If(如果...则必需) Required If Accepted(如果已接受则必需) Required If Declined(如果已拒绝则必需) Required Unless(除非...否则必需) Required With(如果存在其他字段则必需) Required With All(如果存在所有其他字段则必需) Required Without(如果不存在其他字段则必需) Required Without All(如果不存在所有其他字段则必需) Required Array Keys(必需的数组键) Same(相同) Size(大小) Sometimes(当存在时验证) Starts With(以...开头) String(字符串) Timezone(时区) Unique (Database)(在数据库中唯一) Uppercase(大写) URL(URL 格式) ULID(ULID 格式) UUID(UUID 格式)

accepted(已接受)

正在验证的字段必须为 "yes""on"1"1"true"true"。这对于验证“服务条款”接受或类似字段很有用。

accepted_if:anotherfield,value,...(如果另一个字段等于指定值则已接受)

如果正在验证的另一个字段等于指定值,则正在验证的字段必须为 "yes""on"1"1"true"true"。这对于验证“服务条款”接受或类似字段很有用。

active_url(有效 URL)

正在验证的字段必须根据 dns_get_record PHP 函数具有有效的 A 或 AAAA 记录。提供的 URL 的主机名使用 parse_url PHP 函数提取,然后传递给 dns_get_record

after:date(在...之后)

正在验证的字段必须是给定日期之后的值。日期将传递到 PHP strtotime 函数中,以便转换为有效的 DateTime 实例:

'start_date' => 'required|date|after:tomorrow'

而不是将由 strtotime 评估的日期字符串传递给它,您可以指定另一个字段来与日期进行比较:

'finish_date' => 'required|date|after:start_date'

after_or_equal:date(在...之后或等于)

正在验证的字段必须是给定日期之后或等于给定日期的值。有关更多信息,请参阅after规则。

alpha(仅字母)

正在验证的字段必须完全是包含在 \p{L} (opens in a new tab)\p{M} (opens in a new tab) 中的 Unicode 字母字符。

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

'username' => 'alpha:ascii',

alpha_dash(字母、数字、破折号和下划线)

正在验证的字段必须完全是包含在 \p{L} (opens in a new tab)\p{M} (opens in a new tab)\p{N} (opens in a new tab) 以及 ASCII 破折号(-)和 ASCII 下划线(_)中的 Unicode 字母数字字符。

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

'username' => 'alpha_dash:ascii',

alpha_num(字母数字)

正在验证的字段必须完全是包含在 \p{L} (opens in a new tab)\p{M} (opens in a new tab)\p{N} (opens in a new tab) 中的 Unicode 字母数字字符。

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

'username' => 'alpha_num:ascii',

array(数组)

正在验证的字段必须是 PHP array

当向 array 规则提供其他值时,输入数组中的每个键都必须存在于提供给规则的值列表中。在以下示例中,输入数组中的 admin 键是无效的,因为它不在提供给 array 规则的值列表中:

use Illuminate\Support\Facades\Validator;

$input = [
    'user' => [
        'name' => 'Taylor Otwell',
        'username' => 'taylorotwell',
        'admin' => true,
    ],
];

Validator::make($input, [
    'user' => 'array:name,username',
]);

一般来说,您应该始终指定允许在您的数组中存在的数组键。

ascii(仅 ASCII 字符)

正在验证的字段必须完全是 7 位 ASCII 字符。

bail(遇到第一个验证失败时停止)

在遇到第一个验证失败后,停止为该字段运行验证规则。

虽然 bail 规则只会在遇到特定字段的验证失败时停止验证该字段,但 stopOnFirstFailure 方法将通知

present(存在)

验证的字段必须存在于输入数据中。

present_if:anotherfield,value,...(当另一字段满足条件时存在)

如果_anotherfield_字段等于任何一个_value_,则验证的字段必须存在。

present_unless:anotherfield,value(除非另一字段满足条件否则存在)

除非_anotherfield_字段等于任何一个_value_,否则验证的字段必须存在。

present_with:foo,bar,...(当其他指定字段存在时存在)

只有当其他任何指定字段存在时,验证的字段才必须存在。

present_with_all:foo,bar,...(当其他所有指定字段存在时存在)

只有当其他所有指定字段都存在时,验证的字段才必须存在。

prohibited(禁止)

验证的字段必须缺失或为空。如果一个字段满足以下任何一个条件,则它被认为是“空”的:

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

prohibited_if:anotherfield,value,...(当另一字段满足条件时禁止)

如果_anotherfield_字段等于任何一个_value_,则验证的字段必须缺失或为空。如果一个字段满足以下任何一个条件,则它被认为是“空”的:

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

如果需要复杂的条件禁止逻辑,可以使用Rule::prohibitedIf方法。该方法接受一个布尔值或一个闭包。当给定一个闭包时,闭包应该返回truefalse,以指示验证的字段是否应该被禁止:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($request->all(), [
    'role_id' => Rule::prohibitedIf($request->user()->is_admin),
]);

Validator::make($request->all(), [
    'role_id' => Rule::prohibitedIf(fn () => $request->user()->is_admin),
]);

prohibited_unless:anotherfield,value,...(除非另一字段满足条件否则禁止)

除非_anotherfield_字段等于任何一个_value_,否则验证的字段必须缺失或为空。如果一个字段满足以下任何一个条件,则它被认为是“空”的:

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

prohibits:anotherfield,...(当自身非空时其他字段为空)

如果验证的字段不是缺失或为空,那么_anotherfield_中的所有字段都必须缺失或为空。如果一个字段满足以下任何一个条件,则它被认为是“空”的:

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

regex:pattern(正则表达式)

验证的字段必须匹配给定的正则表达式。

在内部,此规则使用 PHP 的preg_match函数。指定的模式应遵循preg_match所需的相同格式,因此也应包括有效的分隔符。例如:'email' => 'regex:/^.+@.+$/i'

[!WARNING]
当使用regex / not_regex模式时,可能需要在数组中指定规则,而不是使用|分隔符,特别是如果正则表达式包含|字符。

required(必填)

验证的字段必须存在于输入数据中且不为空。如果一个字段满足以下任何一个条件,则它被认为是“空”的:

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

required_if:anotherfield,value,...(当另一字段满足条件时必填)

如果_anotherfield_字段等于任何一个_value_,则验证的字段必须存在且不为空。

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

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($request->all(), [
    'role_id' => Rule::requiredIf($request->user()->is_admin),
]);

Validator::make($request->all(), [
    'role_id' => Rule::requiredIf(fn () => $request->user()->is_admin),
]);

required_if_accepted:anotherfield,...(当另一字段被接受时必填)

如果_anotherfield_字段等于"yes""on"1"1"true"true",则验证的字段必须存在且不为空。

required_if_declined:anotherfield,...(当另一字段被拒绝时必填)

如果_anotherfield_字段等于"no""off"0"0"false"false",则验证的字段必须存在且不为空。

required_unless:anotherfield,value,...(除非另一字段满足条件否则必填)

除非_anotherfield_字段等于任何一个_value_,否则验证的字段必须存在且不为空。这也意味着,除非_value_为null,否则_anotherfield_必须存在于请求数据中。如果_value_为nullrequired_unless:name,null),则只有当比较字段为null或比较字段在请求数据中不存在时,验证的字段才是必填的。

required_with:foo,bar,...(当其他指定字段存在且非空时必填)

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

required_with_all:foo,bar,...(当其他所有指定字段存在且非空时必填)

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

required_without:foo,bar,...(当其他指定字段为空或不存在时必填)

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

required_without_all:foo,bar,...(当其他所有指定字段为空或不存在时必填)

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

required_array_keys:foo,bar,...(数组必须包含指定键)

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

same:field(与另一字段相同)

给定的_field_必须与验证的字段匹配。

size:value(大小)

验证的字段必须具有与给定_value_相匹配的大小。对于字符串数据,_value_对应于字符数。对于数字数据,_value_对应于给定的整数值(该属性还必须具有numericinteger规则)。对于数组,_size_对应于数组的count。对于文件,_size_对应于文件大小(以千字节为单位)。让我们看一些例子:

// 验证一个字符串正好是 12 个字符长...
'title' => 'size:12';

// 验证提供的整数等于 10...
'seats' => 'integer|size:10';

// 验证一个数组正好有 5 个元素...
'tags' => 'array|size:5';

// 验证上传的文件正好是 512 千字节...
'image' => 'file|size:512';

starts_with:foo,bar,...(以给定值开头)

验证的字段必须以给定的值之一开头。

string(字符串)

验证的字段必须是一个字符串。如果您希望允许该字段也可以为null,则应将nullable规则分配给该字段。

timezone(时区)

验证的字段必须是根据DateTimeZone::listIdentifiers方法的有效时区标识符。

DateTimeZone::listIdentifiers方法接受的参数 (opens in a new tab)也可以提供给此验证规则:

'timezone' => 'required|timezone:all';

'timezone' => 'required|timezone:Africa';

'timezone' => 'required|timezone:per_country,US';

unique:table,column(唯一)

验证的字段在给定的数据库表中必须不存在。

指定自定义表/列名称:

您可以指定应该用于确定表名的 Eloquent 模型,而不是直接指定表名:

'email' => 'unique:App\Models\User,email_address'

可以使用column选项指定字段对应的数据库列。如果未指定column选项,则将使用验证的字段的名称。

'email' => 'unique:users,email_address'

指定自定义数据库连接

有时,您可能需要为验证器进行的数据库查询设置自定义连接。要实现此目的,您可以将连接名称前置到表名:

'email' => 'unique:connection.users,email_address'

强制唯一规则忽略给定 ID:

有时,您可能希望在唯一验证期间忽略给定的 ID。例如,考虑一个“更新配置文件”屏幕,其中包括用户的姓名,电子邮件地址和位置。您可能想要验证电子邮件地址是唯一的。但是,如果用户只更改了姓名字段而不是电子邮件字段,您不希望因为用户已经是所讨论的电子邮件地址的所有者而抛出验证错误。

为了指示验证器忽略用户的 ID,我们将使用Rule类来流畅地定义规则。在这个例子中,我们还将验证规则指定为一个数组,而不是使用|字符来分隔规则:

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::unique('users')->ignore($user->id),
    ],
]);

[!WARNING]
您永远不应该将任何用户控制的请求输入传递到ignore方法中。相反,您应该只传递一个系统生成的唯一 ID,例如来自 Eloquent 模型实例的自动递增 ID 或 UUID。否则,您的应用程序将容易受到 SQL 注入攻击。

您也可以传递整个模型实例,而不是将模型键的值传递给ignore方法。Laravel 将自动从模型中提取键:

Rule::unique('users')->ignore($user)

如果您的表使用的主键列名称不是id,则可以在调用ignore方法时指定列的名称:

Rule::unique('users')->ignore($user->id, 'user_id')

默认情况下,unique规则将检查与正在验证的属性名称匹配的列的唯一性。但是,您可以将不同的列名称作为unique方法的第二个参数传递:

Rule::unique('users', 'email_address')->ignore($user->id)

添加其他 Where 子句:

您可以通过使用where方法自定义查询来指定其他查询条件。例如,让我们添加一个查询条件,将查询范围限制为仅搜索具有account_id列值为1的记录:

'email' => Rule::unique('users')->where(fn (Builder $query) => $query->where('account_id', 1))

uppercase(大写)

验证的字段必须是大写的。

url(网址)

验证的字段必须是一个有效的 URL。

如果您想指定应该被视为有效的 URL 协议,可以将协议作为验证规则参数传递:

'url' => 'url:http,https',
 
'game' => 'url:minecraft,steam',

ulid(通用唯一的字典序可排序标识符)

验证的字段必须是有效的通用唯一的字典序可排序标识符 (opens in a new tab)(ULID)。

uuid(通用唯一标识符)

验证的字段必须是有效的 RFC 4122(版本 1、3、4 或 5)通用唯一标识符(UUID)。

有条件地添加规则

当字段具有某些值时跳过验证

您可能偶尔希望如果另一个字段具有给定值,则不对给定字段进行验证。您可以使用exclude_if验证规则来实现此目的。在这个例子中,如果has_appointment字段的值为false,则appointment_datedoctor_name字段将不会被验证:

use Illuminate\Support\Facades\Validator;

$validator = Validator::make($data, [
    'has_appointment' => 'required|boolean',
    'appointment_date' => 'exclude_if:has_appointment,false|required|date',
    'doctor_name' => 'exclude_if:has_appointment,false|required|string',
]);

或者,您可以使用exclude_unless规则,除非另一个字段具有给定值,否则不对给定字段进行验证:

$validator = Validator::make($data, [
    'has_appointment' => 'required|boolean',
    'appointment_date' => 'exclude_unless:has_appointment,true|required|date',
    'doctor_name' => 'exclude_unless:has_appointment,true|required|string',
]);

仅当存在时进行验证

在某些情况下,您可能希望仅在正在验证的数据中存在该字段时才对其进行验证检查。要快速实现此目的,将sometimes规则添加到您的规则列表中:

$validator = Validator::make($data, [
    'email' => 'sometimes|required|email',
]);

在上面的示例中,只有当$data数组中存在email字段时,才会对其进行验证。

[!NOTE]
如果您试图验证一个应该始终存在但可能为空的字段,请查看关于可选字段的此注释

复杂条件验证

有时您可能希望根据更复杂的条件逻辑添加验证规则。例如,您可能希望仅当另一个字段的值大于 100 时才需要给定的字段。或者,您可能需要当另一个字段存在时,两个字段才具有给定的值。添加这些验证规则并不困难。首先,使用永远不会改变的_静态规则_创建一个Validator实例:

use Illuminate\Support\Facades\Validator;

$validator = Validator::make($request->all(), [
    'email' => 'required|email',
    'games' => 'required|numeric',
]);

假设我们的网络应用程序是为游戏收藏家设计的。如果一个游戏收藏家在我们的应用程序中注册,并且他们拥有超过 100 个游戏,我们希望他们解释为什么他们拥有这么多游戏。例如,也许他们经营一家游戏转售店,或者也许他们只是喜欢收集游戏。为了有条件地添加此要求,我们可以在Validator实例上使用sometimes方法。

use Illuminate\Support\Fluent;

$validator->sometimes('reason', 'required|max:500', function (Fluent $input) {
    return $input->games >= 100;
});

传递给sometimes方法的第一个参数是我们有条件验证的字段的名称。第二个参数是我们要添加的规则列表。如果作为第三个参数传递的闭包返回true,则将添加规则。此方法使构建复杂的条件验证变得轻而易举。您甚至可以一次为多个字段添加条件验证:

$validator->sometimes(['reason', 'cost'], 'required', function (Fluent $input) {
    return $input->games >= 100;
});

[!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)