跳轉至內容

驗證

簡介

Laravel 提供了多種不同的方法來驗證應用程式的傳入資料。最常用的是使用所有傳入 HTTP 請求中可用的 validate 方法。不過,我們也會討論其他驗證方法。

Laravel 包含了各種方便的驗證規則,您可以將其應用於資料,甚至還提供了驗證值在指定資料庫表中是否唯一的能力。我們將詳細介紹每一條驗證規則,以便您熟悉 Laravel 的所有驗證功能。

驗證快速入門

為了瞭解 Laravel 強大的驗證功能,讓我們看一個驗證表單並將錯誤訊息顯示回用戶的完整示例。透過閱讀此概覽,您將能夠很好地瞭解如何使用 Laravel 驗證傳入的請求資料。

定義路由

首先,假設我們在 routes/web.php 檔案中定義了以下路由

1use App\Http\Controllers\PostController;
2 
3Route::get('/post/create', [PostController::class, 'create']);
4Route::post('/post', [PostController::class, 'store']);

GET 路由將顯示一個供使用者建立新部落格文章的表單,而 POST 路由將把新的部落格文章儲存在資料庫中。

建立控制器

接下來,讓我們看一個處理這些路由傳入請求的簡單控制器。我們現在先將 store 方法留空

1<?php
2 
3namespace App\Http\Controllers;
4 
5use Illuminate\Http\RedirectResponse;
6use Illuminate\Http\Request;
7use Illuminate\View\View;
8 
9class PostController extends Controller
10{
11 /**
12 * Show the form to create a new blog post.
13 */
14 public function create(): View
15 {
16 return view('post.create');
17 }
18 
19 /**
20 * Store a new blog post.
21 */
22 public function store(Request $request): RedirectResponse
23 {
24 // Validate and store the blog post...
25 
26 $post = /** ... */
27 
28 return to_route('post.show', ['post' => $post->id]);
29 }
30}

編寫驗證邏輯

現在,我們準備好在 store 方法中填充驗證新部落格文章的邏輯了。為此,我們將使用 Illuminate\Http\Request 物件提供的 validate 方法。如果驗證規則透過,您的程式碼將繼續正常執行;但是,如果驗證失敗,將丟擲 Illuminate\Validation\ValidationException 異常,並且適當的錯誤響應會自動傳送回用戶。

如果在傳統的 HTTP 請求期間驗證失敗,將生成一個重定向到前一個 URL 的響應。如果傳入請求是 XHR 請求,則會返回一個 包含驗證錯誤訊息的 JSON 響應

為了更好地理解 validate 方法,讓我們回到 store 方法中

1/**
2 * Store a new blog post.
3 */
4public function store(Request $request): RedirectResponse
5{
6 $validated = $request->validate([
7 'title' => 'required|unique:posts|max:255',
8 'body' => 'required',
9 ]);
10 
11 // The blog post is valid...
12 
13 return redirect('/posts');
14}

如您所見,驗證規則被傳入了 validate 方法。不用擔心 - 所有可用的驗證規則都有 文件記錄。同樣,如果驗證失敗,將自動生成適當的響應。如果驗證透過,我們的控制器將繼續正常執行。

或者,驗證規則可以指定為規則陣列,而不是單個 | 分隔的字串

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

此外,您可以使用 validateWithBag 方法來驗證請求並將任何錯誤訊息儲存在 命名錯誤包

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

在第一次驗證失敗時停止

有時您可能希望在第一次驗證失敗後停止對某個屬性執行驗證規則。為此,請將 bail 規則分配給該屬性

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

在此示例中,如果 title 屬性上的 unique 規則失敗,則不會檢查 max 規則。規則將按照它們分配的順序進行驗證。

關於巢狀屬性的說明

如果傳入的 HTTP 請求包含“巢狀”欄位資料,您可以使用“點”語法在驗證規則中指定這些欄位

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

另一方面,如果您的欄位名稱包含文字句點,您可以透過用反斜槓轉義句點來明確防止其被解釋為“點”語法

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

顯示驗證錯誤

那麼,如果傳入的請求欄位未透過給定的驗證規則會怎樣?如前所述,Laravel 會自動將使用者重定向回其先前的位置。此外,所有的驗證錯誤和 請求輸入 都會自動 快閃記憶體到 session 中

$errors 變數由 web 中介軟體組提供的 Illuminate\View\Middleware\ShareErrorsFromSession 中介軟體與所有應用程式檢視共享。當應用此中介軟體時,$errors 變數將在您的檢視中始終可用,允許您方便地假設 $errors 變數已定義並可安全使用。$errors 變數將是 Illuminate\Support\MessageBag 的一個例項。有關使用此物件的更多資訊,請 檢視其文件

因此,在我們的示例中,當驗證失敗時,使用者將被重定向到我們控制器的 create 方法,從而允許我們在檢視中顯示錯誤訊息

1<!-- /resources/views/post/create.blade.php -->
2 
3<h1>Create Post</h1>
4 
5@if ($errors->any())
6 <div class="alert alert-danger">
7 <ul>
8 @foreach ($errors->all() as $error)
9 <li>{{ $error }}</li>
10 @endforeach
11 </ul>
12 </div>
13@endif
14 
15<!-- Create Post Form -->

自定義錯誤訊息

Laravel 的內建驗證規則每一條都有一個位於應用程式 lang/en/validation.php 檔案中的錯誤訊息。如果您的應用程式沒有 lang 目錄,您可以指示 Laravel 使用 lang:publish Artisan 命令來建立它。

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 變數以顯示錯誤訊息

1<!-- /resources/views/post/create.blade.php -->
2 
3<label for="title">Post Title</label>
4 
5<input
6 id="title"
7 type="text"
8 name="title"
9 class="@error('title') is-invalid @enderror"
10/>
11 
12@error('title')
13 <div class="alert alert-danger">{{ $message }}</div>
14@enderror

如果您正在使用 命名錯誤包,則可以將錯誤包的名稱作為第二個引數傳遞給 @error 指令

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

回填表單

當 Laravel 因驗證錯誤而生成重定向響應時,框架會自動 將所有請求的輸入快閃記憶體到 session 中。這樣做是為了讓您可以在下一次請求中方便地獲取輸入並回填使用者嘗試提交的表單。

要從前一個請求中檢索快閃記憶體的輸入,請在 Illuminate\Http\Request 的例項上呼叫 old 方法。old 方法將從 session 中提取先前快閃記憶體的輸入資料

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

Laravel 還提供了一個全域性的 old 輔助函式。如果您要在 Blade 模板 中顯示舊輸入,使用 old 輔助函式來回填表單會更方便。如果給定欄位沒有舊輸入,將返回 null

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

關於可選欄位的說明

預設情況下,Laravel 在應用程式的全域性中介軟體棧中包含 TrimStringsConvertEmptyStringsToNull 中介軟體。因此,如果您不希望驗證器將 null 值視為無效,通常需要將“可選”請求欄位標記為 nullable。例如

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

在此示例中,我們指定 publish_at 欄位可以是 null,也可以是有效的日期表示形式。如果未將 nullable 修飾符新增到規則定義中,驗證器將認為 null 是無效的日期。

驗證錯誤響應格式

當您的應用程式丟擲 Illuminate\Validation\ValidationException 異常且傳入的 HTTP 請求期望 JSON 響應時,Laravel 將自動為您格式化錯誤訊息並返回 422 Unprocessable Entity HTTP 響應。

下面,您可以檢視驗證錯誤的 JSON 響應格式示例。請注意,巢狀的錯誤鍵被扁平化為“點”符號格式

1{
2 "message": "The team name must be a string. (and 4 more errors)",
3 "errors": {
4 "team_name": [
5 "The team name must be a string.",
6 "The team name must be at least 1 characters."
7 ],
8 "authorization.role": [
9 "The selected authorization.role is invalid."
10 ],
11 "users.0.email": [
12 "The users.0.email field is required."
13 ],
14 "users.2.email": [
15 "The users.2.email must be a valid email address."
16 ]
17 }
18}

表單請求驗證

建立表單請求

對於更復雜的驗證場景,您可能希望建立一個“表單請求”。表單請求是自定義請求類,封裝了它們自己的驗證和授權邏輯。要建立表單請求類,您可以使用 make:request Artisan CLI 命令

1php artisan make:request StorePostRequest

生成的表單請求類將放置在 app/Http/Requests 目錄中。如果該目錄不存在,它將在您執行 make:request 命令時建立。Laravel 生成的每個表單請求都有兩個方法:authorizerules

您可能已經猜到了,authorize 方法負責確定當前經過身份驗證的使用者是否可以執行請求所代表的操作,而 rules 方法返回應用於請求資料的驗證規則

1/**
2 * Get the validation rules that apply to the request.
3 *
4 * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
5 */
6public function rules(): array
7{
8 return [
9 'title' => 'required|unique:posts|max:255',
10 'body' => 'required',
11 ];
12}

您可以在 rules 方法的簽名中對您需要的任何依賴項進行型別提示。它們將透過 Laravel 服務容器 自動解析。

那麼,驗證規則是如何評估的呢?您所需要做的就是在控制器方法上對請求進行型別提示。傳入的表單請求在呼叫控制器方法之前進行驗證,這意味著您無需用任何驗證邏輯使控制器變得雜亂

1/**
2 * Store a new blog post.
3 */
4public function store(StorePostRequest $request): RedirectResponse
5{
6 // The incoming request is valid...
7 
8 // Retrieve the validated input data...
9 $validated = $request->validated();
10 
11 // Retrieve a portion of the validated input data...
12 $validated = $request->safe()->only(['name', 'email']);
13 $validated = $request->safe()->except(['name', 'email']);
14 
15 // Store the blog post...
16 
17 return redirect('/posts');
18}

如果驗證失敗,將生成一個重定向響應,將使用者傳送回其先前的位置。錯誤也會快閃記憶體到 session 中,以便顯示。如果請求是 XHR 請求,將向用戶返回一個包含 422 狀態碼的 HTTP 響應,其中包含 驗證錯誤的 JSON 表示形式

需要為您的 Inertia 驅動的 Laravel 前端新增即時表單請求驗證嗎?請檢視 Laravel Precognition

執行附加驗證

有時您需要在初始驗證完成後執行附加驗證。您可以使用表單請求的 after 方法來完成此操作。

after 方法應返回一個可呼叫物件或閉包陣列,這些物件將在驗證完成後被呼叫。給定的可呼叫物件將接收一個 Illuminate\Validation\Validator 例項,允許您在必要時引發附加的錯誤訊息

1use Illuminate\Validation\Validator;
2 
3/**
4 * Get the "after" validation callables for the request.
5 */
6public function after(): array
7{
8 return [
9 function (Validator $validator) {
10 if ($this->somethingElseIsInvalid()) {
11 $validator->errors()->add(
12 'field',
13 'Something is wrong with this field!'
14 );
15 }
16 }
17 ];
18}

如前所述,after 方法返回的陣列也可以包含可呼叫類。這些類的 __invoke 方法將接收一個 Illuminate\Validation\Validator 例項

1use App\Validation\ValidateShippingTime;
2use App\Validation\ValidateUserStatus;
3use Illuminate\Validation\Validator;
4 
5/**
6 * Get the "after" validation callables for the request.
7 */
8public function after(): array
9{
10 return [
11 new ValidateUserStatus,
12 new ValidateShippingTime,
13 function (Validator $validator) {
14 //
15 }
16 ];
17}

在第一次驗證失敗時停止

透過將 StopOnFirstFailure 屬性新增到您的請求類,您可以通知驗證器在發生單次驗證失敗後停止驗證所有屬性

1<?php
2 
3namespace App\Http\Requests;
4 
5use Illuminate\Foundation\Http\Attributes\StopOnFirstFailure;
6use Illuminate\Foundation\Http\FormRequest;
7 
8#[StopOnFirstFailure]
9class StorePostRequest extends FormRequest
10{
11 // ...
12}

自定義重定向位置

當表單請求驗證失敗時,將生成一個重定向響應,將使用者送回其先前的位置。但是,您可以自由自定義此行為。為此,您可以在表單請求上使用 RedirectTo 屬性

1<?php
2 
3namespace App\Http\Requests;
4 
5use Illuminate\Foundation\Http\Attributes\RedirectTo;
6use Illuminate\Foundation\Http\FormRequest;
7 
8#[RedirectTo('/dashboard')]
9class StorePostRequest extends FormRequest
10{
11 // ...
12}

或者,如果您想將使用者重定向到命名路由,則可以使用 RedirectToRoute 屬性

1<?php
2 
3namespace App\Http\Requests;
4 
5use Illuminate\Foundation\Http\Attributes\RedirectToRoute;
6use Illuminate\Foundation\Http\FormRequest;
7 
8#[RedirectToRoute('dashboard')]
9class StorePostRequest extends FormRequest
10{
11 // ...
12}

自定義錯誤包

當表單請求驗證失敗時,錯誤會快閃記憶體到 default 錯誤包中。如果您需要將錯誤儲存在不同的 命名錯誤包 中,可以使用表單請求上的 ErrorBag 屬性

1<?php
2 
3namespace App\Http\Requests;
4 
5use Illuminate\Foundation\Http\Attributes\ErrorBag;
6use Illuminate\Foundation\Http\FormRequest;
7 
8#[ErrorBag('login')]
9class LoginRequest extends FormRequest
10{
11 // ...
12}

授權表單請求

表單請求類還包含一個 authorize 方法。在此方法中,您可以確定經過身份驗證的使用者是否真的有權更新給定的資源。例如,您可以確定使用者是否確實擁有他們試圖更新的部落格評論。您很可能會在此方法中與您的 授權門和策略 進行互動

1use App\Models\Comment;
2 
3/**
4 * Determine if the user is authorized to make this request.
5 */
6public function authorize(): bool
7{
8 $comment = Comment::find($this->route('comment'));
9 
10 return $comment && $this->user()->can('update', $comment);
11}

由於所有表單請求都擴充套件了基礎 Laravel 請求類,我們可以使用 user 方法來訪問當前經過身份驗證的使用者。另外,請注意上面示例中對 route 方法的呼叫。此方法授予您訪問在路由上定義的 URI 引數的許可權,例如下面示例中的 {comment} 引數

1Route::post('/comment/{comment}');

因此,如果您的應用程式正在利用 路由模型繫結,您可以透過將已解析的模型作為請求的屬性來訪問它,從而使程式碼更加簡潔

1return $this->user()->can('update', $this->comment);

如果 authorize 方法返回 false,將自動返回 403 狀態碼的 HTTP 響應,並且您的控制器方法不會執行。

如果您計劃在應用程式的其他部分處理請求的授權邏輯,您可以完全刪除 authorize 方法,或者直接返回 true

1/**
2 * Determine if the user is authorized to make this request.
3 */
4public function authorize(): bool
5{
6 return true;
7}

您可以在 authorize 方法的簽名中對您需要的任何依賴項進行型別提示。它們將透過 Laravel 服務容器 自動解析。

自定義錯誤訊息

您可以透過覆蓋 messages 方法來自定義表單請求使用的錯誤訊息。此方法應返回一個屬性/規則對及其對應的錯誤訊息的陣列

1/**
2 * Get the error messages for the defined validation rules.
3 *
4 * @return array<string, string>
5 */
6public function messages(): array
7{
8 return [
9 'title.required' => 'A title is required',
10 'body.required' => 'A message is required',
11 ];
12}

自定義驗證屬性

許多 Laravel 內建驗證規則錯誤訊息包含一個 :attribute 佔位符。如果您希望驗證訊息的 :attribute 佔位符被自定義屬性名稱替換,您可以透過覆蓋 attributes 方法來指定自定義名稱。此方法應返回一個屬性/名稱對的陣列

1/**
2 * Get custom attributes for validator errors.
3 *
4 * @return array<string, string>
5 */
6public function attributes(): array
7{
8 return [
9 'email' => 'email address',
10 ];
11}

準備驗證資料

如果您需要在應用驗證規則之前準備或清理請求中的任何資料,可以使用 prepareForValidation 方法

1use Illuminate\Support\Str;
2 
3/**
4 * Prepare the data for validation.
5 */
6protected function prepareForValidation(): void
7{
8 $this->merge([
9 'slug' => Str::slug($this->slug),
10 ]);
11}

同樣,如果您需要在驗證完成後規範化任何請求資料,可以使用 passedValidation 方法

1/**
2 * Handle a passed validation attempt.
3 */
4protected function passedValidation(): void
5{
6 $this->replace(['name' => 'Taylor']);
7}

手動建立驗證器

如果您不想在請求上使用 validate 方法,可以使用 Validator 門面 (facade) 手動建立一個驗證器例項。門面上的 make 方法會生成一個新的驗證器例項

1<?php
2 
3namespace App\Http\Controllers;
4 
5use Illuminate\Http\RedirectResponse;
6use Illuminate\Http\Request;
7use Illuminate\Support\Facades\Validator;
8 
9class PostController extends Controller
10{
11 /**
12 * Store a new blog post.
13 */
14 public function store(Request $request): RedirectResponse
15 {
16 $validator = Validator::make($request->all(), [
17 'title' => 'required|unique:posts|max:255',
18 'body' => 'required',
19 ]);
20 
21 if ($validator->fails()) {
22 return redirect('/post/create')
23 ->withErrors($validator)
24 ->withInput();
25 }
26 
27 // Retrieve the validated input...
28 $validated = $validator->validated();
29 
30 // Retrieve a portion of the validated input...
31 $validated = $validator->safe()->only(['name', 'email']);
32 $validated = $validator->safe()->except(['name', 'email']);
33 
34 // Store the blog post...
35 
36 return redirect('/posts');
37 }
38}

傳遞給 make 方法的第一個引數是正在驗證的資料。第二個引數是應應用於資料的驗證規則陣列。

在確定請求驗證是否失敗後,您可以使用 withErrors 方法將錯誤訊息快閃記憶體到 session 中。使用此方法時,$errors 變數在重定向後將自動與您的檢視共享,使您可以輕鬆地將其顯示回用戶。withErrors 方法接受驗證器、MessageBag 或 PHP 陣列

在第一次驗證失敗時停止

stopOnFirstFailure 方法將通知驗證器在發生單次驗證失敗後停止驗證所有屬性

1if ($validator->stopOnFirstFailure()->fails()) {
2 // ...
3}

自動重定向

如果您想手動建立驗證器例項,但仍想利用 HTTP 請求的 validate 方法提供的自動重定向功能,則可以在現有的驗證器例項上呼叫 validate 方法。如果驗證失敗,使用者將被自動重定向,或者在 XHR 請求的情況下,將返回 JSON 響應

1Validator::make($request->all(), [
2 'title' => 'required|unique:posts|max:255',
3 'body' => 'required',
4])->validate();

如果驗證失敗,您可以使用 validateWithBag 方法將錯誤訊息儲存在 命名錯誤包

1Validator::make($request->all(), [
2 'title' => 'required|unique:posts|max:255',
3 'body' => 'required',
4])->validateWithBag('post');

命名錯誤包

如果您在一個頁面上有多個表單,您可能希望命名包含驗證錯誤的 MessageBag,以便您可以檢索特定表單的錯誤訊息。要實現這一點,請將名稱作為第二個引數傳遞給 withErrors

1return redirect('/register')->withErrors($validator, 'login');

然後,您可以從 $errors 變數訪問已命名的 MessageBag 例項

1{{ $errors->login->first('email') }}

自定義錯誤訊息

如果需要,您可以提供驗證器例項應使用的自定義錯誤訊息,而不是 Laravel 提供的預設錯誤訊息。有幾種指定自定義訊息的方法。首先,您可以將自定義訊息作為第三個引數傳遞給 Validator::make 方法

1$validator = Validator::make($input, $rules, $messages = [
2 'required' => 'The :attribute field is required.',
3]);

在此示例中,:attribute 佔位符將被正在驗證的欄位的實際名稱替換。您還可以在驗證訊息中使用其他佔位符。例如

1$messages = [
2 'same' => 'The :attribute and :other must match.',
3 'size' => 'The :attribute must be exactly :size.',
4 'between' => 'The :attribute value :input is not between :min - :max.',
5 'in' => 'The :attribute must be one of the following types: :values',
6];

為給定屬性指定自定義訊息

有時您可能希望僅為特定屬性指定自定義錯誤訊息。您可以使用“點”語法執行此操作。先指定屬性名稱,後跟規則

1$messages = [
2 'email.required' => 'We need to know your email address!',
3];

指定自定義屬性值

許多 Laravel 內建錯誤訊息包含一個 :attribute 佔位符,該佔位符被正在驗證的欄位或屬性的名稱替換。要自定義用於替換特定欄位的這些佔位符的值,您可以將自定義屬性陣列作為第四個引數傳遞給 Validator::make 方法

1$validator = Validator::make($input, $rules, $messages, [
2 'email' => 'email address',
3]);

執行附加驗證

有時您需要在初始驗證完成後執行附加驗證。您可以使用驗證器的 after 方法來完成此操作。after 方法接受閉包或可呼叫物件陣列,這些物件將在驗證完成後被呼叫。給定的可呼叫物件將接收一個 Illuminate\Validation\Validator 例項,允許您在必要時引發附加的錯誤訊息

1use Illuminate\Support\Facades\Validator;
2 
3$validator = Validator::make(/* ... */);
4 
5$validator->after(function ($validator) {
6 if ($this->somethingElseIsInvalid()) {
7 $validator->errors()->add(
8 'field', 'Something is wrong with this field!'
9 );
10 }
11});
12 
13if ($validator->fails()) {
14 // ...
15}

如前所述,after 方法也接受可呼叫物件陣列,如果您的“驗證後”邏輯封裝在可呼叫類中,這將特別方便,這些類將透過其 __invoke 方法接收一個 Illuminate\Validation\Validator 例項

1use App\Validation\ValidateShippingTime;
2use App\Validation\ValidateUserStatus;
3 
4$validator->after([
5 new ValidateUserStatus,
6 new ValidateShippingTime,
7 function ($validator) {
8 // ...
9 },
10]);

處理已驗證的輸入

在使用表單請求或手動建立的驗證器例項驗證傳入的請求資料後,您可能希望檢索實際透過驗證的傳入請求資料。這可以透過多種方式實現。首先,您可以在表單請求或驗證器例項上呼叫 validated 方法。此方法返回已驗證資料的陣列

1$validated = $request->validated();
2 
3$validated = $validator->validated();

或者,您可以在表單請求或驗證器例項上呼叫 safe 方法。此方法返回 Illuminate\Support\ValidatedInput 的一個例項。此物件公開了 onlyexceptall 方法,以檢索已驗證資料的子集或完整的已驗證資料陣列

1$validated = $request->safe()->only(['name', 'email']);
2 
3$validated = $request->safe()->except(['name', 'email']);
4 
5$validated = $request->safe()->all();

此外,可以像陣列一樣迭代和訪問 Illuminate\Support\ValidatedInput 例項

1// Validated data may be iterated...
2foreach ($request->safe() as $key => $value) {
3 // ...
4}
5 
6// Validated data may be accessed as an array...
7$validated = $request->safe();
8 
9$email = $validated['email'];

如果您想向已驗證的資料新增其他欄位,可以呼叫 merge 方法

1$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);

如果您想將已驗證的資料檢索為 集合 (collection) 例項,可以呼叫 collect 方法

1$collection = $request->safe()->collect();

處理錯誤訊息

Validator 例項上呼叫 errors 方法後,您將收到一個 Illuminate\Support\MessageBag 例項,該例項具有多種用於處理錯誤訊息的便捷方法。自動提供給所有檢視的 $errors 變數也是 MessageBag 類的一個例項。

檢索欄位的第一條錯誤訊息

要檢索給定欄位的第一條錯誤訊息,請使用 first 方法

1$errors = $validator->errors();
2 
3echo $errors->first('email');

檢索欄位的所有錯誤訊息

如果您需要檢索給定欄位的所有訊息陣列,請使用 get 方法

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

如果您正在驗證陣列表單欄位,您可以使用 * 字元檢索每個陣列元素的所有訊息

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

檢索所有欄位的所有錯誤訊息

要檢索所有欄位的所有訊息陣列,請使用 all 方法

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

確定欄位是否存在訊息

has 方法可用於確定給定欄位是否存在任何錯誤訊息

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

在語言檔案中指定自定義訊息

Laravel 的內建驗證規則每一條都有一個位於應用程式 lang/en/validation.php 檔案中的錯誤訊息。如果您的應用程式沒有 lang 目錄,您可以指示 Laravel 使用 lang:publish Artisan 命令來建立它。

lang/en/validation.php 檔案中,您將找到每個驗證規則的翻譯條目。您可以根據應用程式的需要自由更改或修改這些訊息。

此外,您可以將此檔案複製到另一個語言目錄,以翻譯應用程式語言的訊息。要了解有關 Laravel 本地化的更多資訊,請檢視完整的 本地化文件

預設情況下,Laravel 應用程式骨架不包含 lang 目錄。如果您想自定義 Laravel 的語言檔案,可以透過 lang:publish Artisan 命令釋出它們。

特定屬性的自定義訊息

您可以在應用程式的驗證語言檔案中自定義用於指定屬性和規則組合的錯誤訊息。為此,請將您的訊息自定義新增到應用程式 lang/xx/validation.php 語言檔案的 custom 陣列中

1'custom' => [
2 'email' => [
3 'required' => 'We need to know your email address!',
4 'max' => 'Your email address is too long!'
5 ],
6],

在語言檔案中指定屬性

許多 Laravel 內建錯誤訊息包含一個 :attribute 佔位符,該佔位符被正在驗證的欄位或屬性的名稱替換。如果您希望驗證訊息的 :attribute 部分被自定義值替換,您可以在 lang/xx/validation.php 語言檔案的 attributes 陣列中指定自定義屬性名稱

1'attributes' => [
2 'email' => 'email address',
3],

預設情況下,Laravel 應用程式骨架不包含 lang 目錄。如果您想自定義 Laravel 的語言檔案,可以透過 lang:publish Artisan 命令釋出它們。

在語言檔案中指定值

一些 Laravel 內建驗證規則錯誤訊息包含一個 :value 佔位符,該佔位符被請求屬性的當前值替換。但是,有時您可能需要驗證訊息的 :value 部分被值的自定義表示形式替換。例如,考慮以下規則,該規則規定如果 payment_type 的值為 cc,則需要信用卡號

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

如果此驗證規則失敗,它將產生以下錯誤訊息

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

您可以指定更友好的值表示形式,而不是在您的 lang/xx/validation.php 語言檔案中將 cc 顯示為支付型別值,方法是定義一個 values 陣列

1'values' => [
2 'payment_type' => [
3 'cc' => 'credit card'
4 ],
5],

預設情況下,Laravel 應用程式骨架不包含 lang 目錄。如果您想自定義 Laravel 的語言檔案,可以透過 lang:publish Artisan 命令釋出它們。

定義此值後,驗證規則將產生以下錯誤訊息

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

可用驗證規則

以下是所有可用驗證規則及其功能的列表

布林值

字串

數字

陣列

日期

檔案

資料庫

實用工具

accepted

驗證的欄位必須是 "yes""on"1"1"true"true"。這對於驗證“服務條款”接受情況或類似欄位很有用。

accepted_if:anotherfield,value,...

如果驗證的另一個欄位等於指定值,則驗證的欄位必須是 "yes""on"1"1"true"true"。這對於驗證“服務條款”接受情況或類似欄位很有用。

active_url

根據 PHP 的 dns_get_record 函式,驗證的欄位必須具有有效的 A 或 AAAA 記錄。在傳遞給 dns_get_record 之前,提供的 URL 的主機名使用 PHP 的 parse_url 函式提取。

after:date

驗證的欄位必須是給定日期之後的值。日期將被傳遞給 PHP 的 strtotime 函式,以便轉換為有效的 DateTime 例項

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

除了傳遞由 strtotime 評估的日期字串外,您還可以指定另一個欄位來與日期進行比較

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

為方便起見,可以使用流式 date 規則構建器構建基於日期的規則

1use Illuminate\Validation\Rule;
2 
3'start_date' => [
4 'required',
5 Rule::date()->after(today()->addDays(7)),
6],

afterTodaytodayOrAfter 方法可用於流式表達日期,必須分別在今天之後或今天及之後

1'start_date' => [
2 'required',
3 Rule::date()->afterToday(),
4],

after_or_equal:date

驗證的欄位必須是給定日期之後或等於給定日期的值。有關更多資訊,請參閱 after 規則。

為方便起見,可以使用流式 date 規則構建器構建基於日期的規則

1use Illuminate\Validation\Rule;
2 
3'start_date' => [
4 'required',
5 Rule::date()->afterOrEqual(today()->addDays(7)),
6],

anyOf

Rule::anyOf 驗證規則允許您指定驗證的欄位必須滿足給定驗證規則集中的任意一個。例如,以下規則將驗證 username 欄位要麼是電子郵件地址,要麼是至少 6 個字元長的字母數字字串(包括連字元)

1use Illuminate\Validation\Rule;
2 
3'username' => [
4 'required',
5 Rule::anyOf([
6 ['string', 'email'],
7 ['string', 'alpha_dash', 'min:6'],
8 ]),
9],

alpha

驗證的欄位必須完全是包含在 \p{L}\p{M} 中的 Unicode 字母字元。

要將此驗證規則限制為 ASCII 範圍內的字元 (a-zA-Z),您可以為驗證規則提供 ascii 選項

1'username' => 'alpha:ascii',

alpha_dash

驗證的欄位必須完全是包含在 \p{L}\p{M}\p{N} 中的 Unicode 字母數字字元,以及 ASCII 連字元 (-) 和 ASCII 下劃線 (_)。

要將此驗證規則限制為 ASCII 範圍內的字元 (a-zA-Z0-9),您可以為驗證規則提供 ascii 選項

1'username' => 'alpha_dash:ascii',

alpha_num

驗證的欄位必須完全是包含在 \p{L}\p{M}\p{N} 中的 Unicode 字母數字字元。

要將此驗證規則限制為 ASCII 範圍內的字元 (a-zA-Z0-9),您可以為驗證規則提供 ascii 選項

1'username' => 'alpha_num:ascii',

array

驗證的欄位必須是一個 PHP array

當為 array 規則提供其他值時,輸入陣列中的每個鍵都必須存在於提供給規則的值列表中。在以下示例中,輸入陣列中的 admin 鍵是無效的,因為它不包含在提供給 array 規則的值列表中

1use Illuminate\Support\Facades\Validator;
2 
3$input = [
4 'user' => [
5 'name' => 'Taylor Otwell',
6 'username' => 'taylorotwell',
7 'admin' => true,
8 ],
9];
10 
11Validator::make($input, [
12 'user' => 'array:name,username',
13]);

通常,您應該始終指定允許出現在陣列中的陣列鍵。

ascii

驗證的欄位必須完全是 7 位 ASCII 字元。

bail

在第一次驗證失敗後停止對該欄位執行驗證規則。

雖然 bail 規則僅在遇到驗證失敗時停止驗證特定欄位,但 stopOnFirstFailure 方法會通知驗證器在發生單次驗證失敗後停止驗證所有屬性

1if ($validator->stopOnFirstFailure()->fails()) {
2 // ...
3}

before:date

驗證的欄位必須是給定日期之前的值。日期將被傳遞給 PHP 的 strtotime 函式,以便轉換為有效的 DateTime 例項。此外,與 after 規則一樣,可以提供另一個正在驗證的欄位的名稱作為 date 的值。

為方便起見,也可以使用流式 date 規則構建器構建基於日期的規則

1use Illuminate\Validation\Rule;
2 
3'start_date' => [
4 'required',
5 Rule::date()->before(today()->subDays(7)),
6],

beforeTodaytodayOrBefore 方法可用於流式表達日期,必須分別在今天之前或今天及之前

1'start_date' => [
2 'required',
3 Rule::date()->beforeToday(),
4],

before_or_equal:date

驗證的欄位必須是給定日期之前或等於給定日期的值。日期將被傳遞給 PHP 的 strtotime 函式,以便轉換為有效的 DateTime 例項。此外,與 after 規則一樣,可以提供另一個正在驗證的欄位的名稱作為 date 的值。

為方便起見,也可以使用流式 date 規則構建器構建基於日期的規則

1use Illuminate\Validation\Rule;
2 
3'start_date' => [
4 'required',
5 Rule::date()->beforeOrEqual(today()->subDays(7)),
6],

between:min,max

驗證的欄位的大小必須介於給定的 minmax(含)之間。字串、數字、陣列和檔案的評估方式與 size 規則相同。

boolean

驗證的欄位必須能夠轉換為布林值。接受的輸入為 truefalse10"1""0"

您可以使用 strict 引數,僅當欄位的值為 truefalse 時才將其視為有效

1'foo' => 'boolean:strict'

confirmed

驗證的欄位必須具有匹配的 {field}_confirmation 欄位。例如,如果驗證的欄位是 password,則輸入中必須存在匹配的 password_confirmation 欄位。

您還可以傳遞自定義確認欄位名稱。例如,confirmed:repeat_username 將期望 repeat_username 欄位與驗證的欄位匹配。

contains:foo,bar,...

驗證的欄位必須是一個包含所有給定引數值的陣列。由於此規則通常需要您 implode 一個數組,因此可以使用 Rule::contains 方法來流式構建該規則

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rule;
3 
4Validator::make($data, [
5 'roles' => [
6 'required',
7 'array',
8 Rule::contains(['admin', 'editor']),
9 ],
10]);

doesnt_contain:foo,bar,...

驗證的欄位必須是一個不包含任何給定引數值的陣列。由於此規則通常需要您 implode 一個數組,因此可以使用 Rule::doesntContain 方法來流式構建該規則

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rule;
3 
4Validator::make($data, [
5 'roles' => [
6 'required',
7 'array',
8 Rule::doesntContain(['admin', 'editor']),
9 ],
10]);

current_password

驗證的欄位必須與經過身份驗證的使用者密碼匹配。您可以使用規則的第一個引數指定 身份驗證守衛 (authentication guard)

1'password' => 'current_password:api'

date

根據 PHP 的 strtotime 函式,驗證的欄位必須是有效且非相對的日期。

date_equals:date

驗證的欄位必須等於給定的日期。日期將被傳遞給 PHP 的 strtotime 函式,以便轉換為有效的 DateTime 例項。

date_format:format,...

驗證的欄位必須匹配給定的 formats 之一。您在驗證欄位時應該 要麼 使用 date 要麼 使用 date_format,不能同時使用兩者。此驗證規則支援 PHP DateTime 類支援的所有格式。

為方便起見,可以使用流式 date 規則構建器構建基於日期的規則

1use Illuminate\Validation\Rule;
2 
3'start_date' => [
4 'required',
5 Rule::date()->format('Y-m-d'),
6],

decimal:min,max

驗證的欄位必須是數字,並且必須包含指定的小數位數

1// Must have exactly two decimal places (9.99)...
2'price' => 'decimal:2'
3 
4// Must have between 2 and 4 decimal places...
5'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

驗證的整數必須具有介於給定的 minmax 之間的長度。

dimensions

驗證的檔案必須是符合規則引數所指定維度約束的影像

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

可用的約束包括:min_widthmax_widthmin_heightmax_heightwidthheightratio

ratio 約束應表示為寬除以高。這可以指定為分數(如 3/2)或浮點數(如 1.5

1'avatar' => 'dimensions:ratio=3/2'

由於此規則需要多個引數,因此通常更方便使用 Rule::dimensions 方法來流式構建該規則

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rule;
3 
4Validator::make($data, [
5 'avatar' => [
6 'required',
7 Rule::dimensions()
8 ->maxWidth(1000)
9 ->maxHeight(500)
10 ->ratio(3 / 2),
11 ],
12]);

distinct

在驗證陣列時,驗證的欄位不能有任何重複值

1'foo.*.id' => 'distinct'

Distinct 預設使用鬆散變數比較。要使用嚴格比較,您可以在驗證規則定義中新增 strict 引數

1'foo.*.id' => 'distinct:strict'

您可以將 ignore_case 新增到驗證規則的引數中,以使規則忽略大小寫差異

1'foo.*.id' => 'distinct:ignore_case'

doesnt_start_with:foo,bar,...

驗證的欄位不能以給定的值之一開頭。

doesnt_end_with:foo,bar,...

驗證的欄位不能以給定的值之一結尾。

email

驗證的欄位必須格式化為電子郵件地址。此驗證規則利用 egulias/email-validator 包來驗證電子郵件地址。預設情況下,應用 RFCValidation 驗證器,但您也可以應用其他驗證樣式

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

上面的示例將應用 RFCValidationDNSCheckValidation 驗證。以下是您可以應用的驗證樣式的完整列表

  • 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 字元。

為方便起見,可以使用流式規則構建器構建電子郵件驗證規則

1use Illuminate\Validation\Rule;
2 
3$request->validate([
4 'email' => [
5 'required',
6 Rule::email()
7 ->rfcCompliant(strict: false)
8 ->validateMxRecord()
9 ->preventSpoofing()
10 ],
11]);

dnsspoof 驗證器需要 PHP intl 擴充套件。

encoding:encoding_type

驗證的欄位必須匹配指定的字元編碼。此規則使用 PHP 的 mb_check_encoding 函式來驗證給定檔案或字串值的編碼。為方便起見,可以使用 Laravel 的流式檔案規則構建器構建 encoding 規則

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rules\File;
3 
4Validator::validate($input, [
5 'attachment' => [
6 'required',
7 File::types(['csv'])
8 ->encoding('utf-8'),
9 ],
10]);

ends_with:foo,bar,...

驗證的欄位必須以給定的值之一結尾。

enum

Enum 規則是一個基於類的規則,它驗證驗證的欄位是否包含有效的列舉值。Enum 規則接受列舉名稱作為其唯一的建構函式引數。在驗證原始值時,應向 Enum 規則提供一個支援的列舉 (Backed Enum)

1use App\Enums\ServerStatus;
2use Illuminate\Validation\Rule;
3 
4$request->validate([
5 'status' => [Rule::enum(ServerStatus::class)],
6]);

Enum 規則的 onlyexcept 方法可用於限制應視為有效的列舉用例

1Rule::enum(ServerStatus::class)
2 ->only([ServerStatus::Pending, ServerStatus::Active]);
3 
4Rule::enum(ServerStatus::class)
5 ->except([ServerStatus::Pending, ServerStatus::Active]);

when 方法可用於有條件地修改 Enum 規則

1use Illuminate\Support\Facades\Auth;
2use Illuminate\Validation\Rule;
3 
4Rule::enum(ServerStatus::class)
5 ->when(
6 Auth::user()->isAdmin(),
7 fn ($rule) => $rule->only(...),
8 fn ($rule) => $rule->only(...),
9 );

exclude

驗證的欄位將從 validatevalidated 方法返回的請求資料中排除。

exclude_if:anotherfield,value

如果 anotherfield 欄位等於 value,則驗證的欄位將從 validatevalidated 方法返回的請求資料中排除。

如果需要複雜的條件排除邏輯,可以利用 Rule::excludeIf 方法。此方法接受布林值或閉包。當給出閉包時,閉包應返回 truefalse 以指示是否應排除正在驗證的欄位

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rule;
3 
4Validator::make($request->all(), [
5 'role_id' => Rule::excludeIf($request->user()->is_admin),
6]);
7 
8Validator::make($request->all(), [
9 'role_id' => Rule::excludeIf(fn () => $request->user()->is_admin),
10]);

exclude_unless:anotherfield,value

除非 anotherfield 欄位等於 value,否則驗證的欄位將從 validatevalidated 方法返回的請求資料中排除。如果 valuenull (exclude_unless:name,null),則除非比較欄位為 null 或請求資料中缺少比較欄位,否則驗證的欄位將被排除。

exclude_with:anotherfield

如果 anotherfield 欄位存在,則驗證的欄位將從 validatevalidated 方法返回的請求資料中排除。

exclude_without:anotherfield

如果 anotherfield 欄位不存在,則驗證的欄位將從 validatevalidated 方法返回的請求資料中排除。

exists:table,column

驗證的欄位必須存在於給定的資料庫表中。

Exists 規則的基本用法

1'state' => 'exists:states'

如果未指定 column 選項,將使用欄位名稱。因此,在這種情況下,規則將驗證 states 資料庫表是否包含一條記錄,其 state 列的值與請求的 state 屬性值匹配。

指定自定義列名

您可以透過將列名放在資料庫表名之後,明確指定驗證規則應使用的資料庫列名

1'state' => 'exists:states,abbreviation'

有時,您可能需要指定用於 exists 查詢的特定資料庫連線。您可以透過在表名之前加上連線名來完成此操作

1'email' => 'exists:connection.staff,email'

除了直接指定表名外,您還可以指定應用於確定表名的 Eloquent 模型

1'user_id' => 'exists:App\Models\User,id'

如果您想自定義驗證規則執行的查詢,可以使用 Rule 類流式定義規則。在此示例中,我們還將驗證規則指定為陣列,而不是使用 | 字元來分隔它們

1use Illuminate\Database\Query\Builder;
2use Illuminate\Support\Facades\Validator;
3use Illuminate\Validation\Rule;
4 
5Validator::make($data, [
6 'email' => [
7 'required',
8 Rule::exists('staff')->where(function (Builder $query) {
9 $query->where('account_id', 1);
10 }),
11 ],
12]);

您可以透過提供列名作為 exists 方法的第二個引數,明確指定 Rule::exists 方法生成的 exists 規則應使用的資料庫列名

1'state' => Rule::exists('states', 'abbreviation'),

有時,您可能希望驗證值陣列是否存在於資料庫中。您可以透過將 existsarray 規則都新增到正在驗證的欄位來實現這一點

1'states' => ['array', Rule::exists('states', 'abbreviation')],

當這兩個規則都被分配給欄位時,Laravel 將自動構建一個查詢,以確定所有給定值是否存在於指定表中。

extensions:foo,bar,...

驗證的檔案必須具有與列出的副檔名之一相對應的使用者分配的副檔名

1'photo' => ['required', 'extensions:jpg,png'],

您絕對不應僅依賴透過使用者分配的副檔名來驗證檔案。此規則通常應始終與 mimesmimetypes 規則結合使用。

file

驗證的欄位必須是成功上傳的檔案。

filled

如果欄位存在,則驗證的欄位不能為空。

gt:field

驗證的欄位必須大於給定的 fieldvalue。這兩個欄位必須是相同型別。字串、數字、陣列和檔案的評估方式與 size 規則的慣例相同。

gte:field

驗證的欄位必須大於或等於給定的 fieldvalue。這兩個欄位必須是相同型別。字串、數字、陣列和檔案的評估方式與 size 規則的慣例相同。

hex_color

驗證的欄位必須包含 十六進位制 格式的有效顏色值。

image

驗證的檔案必須是影像(jpg、jpeg、png、bmp、gif 或 webp)。

預設情況下,由於存在 XSS 漏洞的可能性,image 規則不允許 SVG 檔案。如果您需要允許 SVG 檔案,可以向 image 規則提供 allow_svg 指令 (image:allow_svg)。

in:foo,bar,...

驗證的欄位必須包含在給定的值列表中。由於此規則通常需要您 implode 一個數組,因此可以使用 Rule::in 方法來流式構建該規則

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rule;
3 
4Validator::make($data, [
5 'zones' => [
6 'required',
7 Rule::in(['first-zone', 'second-zone']),
8 ],
9]);

in 規則與 array 規則結合使用時,輸入陣列中的每個值都必須存在於提供給 in 規則的值列表中。在以下示例中,輸入陣列中的 LAS 機場程式碼是無效的,因為它不包含在提供給 in 規則的機場列表中

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rule;
3 
4$input = [
5 'airports' => ['NYC', 'LAS'],
6];
7 
8Validator::make($input, [
9 'airports' => [
10 'required',
11 'array',
12 ],
13 'airports.*' => Rule::in(['NYC', 'LIT']),
14]);

in_array:anotherfield.*

驗證的欄位必須存在於 anotherfield 的值中。

in_array_keys:value.*

驗證的欄位必須是一個數組,並且在陣列中至少包含給定 values 之一作為鍵

1'config' => 'array|in_array_keys:timezone'

integer

驗證的欄位必須是一個整數。

您可以使用 strict 引數,僅當欄位的型別為 integer 時才將其視為有效。帶有整數值的字串將被視為無效

1'age' => 'integer:strict'

此驗證規則不驗證輸入是否為“整數”變數型別,僅驗證輸入是否為 PHP 的 FILTER_VALIDATE_INT 規則所接受的型別。如果您需要將輸入驗證為數字,請將此規則與 numeric 驗證規則 結合使用。

ip

驗證的欄位必須是 IP 地址。

ipv4

驗證的欄位必須是 IPv4 地址。

ipv6

驗證的欄位必須是 IPv6 地址。

json

驗證的欄位必須是有效的 JSON 字串。

lt:field

驗證的欄位必須小於給定的 field。這兩個欄位必須是相同型別。字串、數字、陣列和檔案的評估方式與 size 規則的慣例相同。

lte:field

驗證的欄位必須小於或等於給定的 field。這兩個欄位必須是相同型別。字串、數字、陣列和檔案的評估方式與 size 規則的慣例相同。

lowercase

驗證的欄位必須是小寫。

list

驗證的欄位必須是一個列表陣列。如果陣列的鍵由從 0 到 count($array) - 1 的連續數字組成,則陣列被視為列表。

mac_address

驗證的欄位必須是 MAC 地址。

max:value

驗證的欄位必須小於或等於最大 value。字串、數字、陣列和檔案的評估方式與 size 規則相同。

max_digits:value

驗證的整數必須具有 value 的最大長度。

mimetypes:text/plain,...

驗證的檔案必須匹配給定的 MIME 型別之一

1'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime',
2 
3'media' => 'mimetypes:image/*,video/*',

為了確定上傳檔案的 MIME 型別,將讀取檔案的內容,並且框架將嘗試猜測 MIME 型別,這可能與客戶端提供的 MIME 型別不同。

mimes:foo,bar,...

驗證的檔案必須具有與列出的副檔名之一相對應的 MIME 型別

1'photo' => 'mimes:jpg,bmp,png'

即使您只需要指定副檔名,此規則實際上是透過讀取檔案的內容並猜測其 MIME 型別來驗證檔案的 MIME 型別。MIME 型別及其對應副檔名的完整列表可以在以下位置找到

https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

MIME 型別和副檔名

此驗證規則不驗證 MIME 型別與使用者分配給檔案的副檔名之間是否一致。例如,mimes:png 驗證規則會將包含有效 PNG 內容的檔案視為有效的 PNG 影像,即使該檔名為 photo.txt 也是如此。如果您想驗證使用者分配的副檔名,可以使用 extensions 規則。

min:value

驗證的欄位必須具有最小 value。字串、數字、陣列和檔案的評估方式與 size 規則相同。

min_digits:value

驗證的整數必須具有 value 的最小長度。

multiple_of:value

驗證的欄位必須是 value 的倍數。

missing

驗證的欄位不能出現在輸入資料中。

missing_if:anotherfield,value,...

如果 anotherfield 欄位等於任何 value,則驗證的欄位不能出現。

missing_unless:anotherfield,value

除非 anotherfield 欄位等於任何 value,否則驗證的欄位不能出現。

missing_with:foo,bar,...

只有在 任何其他指定欄位存在時,驗證的欄位才不能出現。

missing_with_all:foo,bar,...

只有在 所有其他指定欄位存在時,驗證的欄位才不能出現。

not_in:foo,bar,...

驗證的欄位不能包含在給定的值列表中。可以使用 Rule::notIn 方法來流式構建該規則

1use Illuminate\Validation\Rule;
2 
3Validator::make($data, [
4 'toppings' => [
5 'required',
6 Rule::notIn(['sprinkles', 'cherries']),
7 ],
8]);

not_regex:pattern

驗證的欄位不能匹配給定的正則表示式。

在內部,此規則使用 PHP 的 preg_match 函式。指定的模式應遵守 preg_match 所需的相同格式,因此也包括有效的分隔符。例如: 'email' => 'not_regex:/^.+$/i'

當使用 regex / not_regex 模式時,可能需要使用陣列而不是 | 分隔符來指定驗證規則,特別是如果正則表示式包含 | 字元。

nullable

驗證的欄位可以是 null

numeric

驗證的欄位必須是 數字

您可以使用 strict 引數,僅當欄位的值為整數或浮點型別時才將其視為有效。數字字串將被視為無效

1'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 方法。此方法接受布林值或閉包。當給出閉包時,閉包應返回 truefalse 以指示是否應禁止正在驗證的欄位

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rule;
3 
4Validator::make($request->all(), [
5 'role_id' => Rule::prohibitedIf($request->user()->is_admin),
6]);
7 
8Validator::make($request->all(), [
9 'role_id' => Rule::prohibitedIf(fn () => $request->user()->is_admin),
10]);

prohibited_if_accepted:anotherfield,...

如果 anotherfield 欄位等於 "yes""on"1"1"true"true",則驗證的欄位必須缺失或為空。

prohibited_if_declined:anotherfield,...

如果 anotherfield 欄位等於 "no""off"0"0"false"false",則驗證的欄位必須缺失或為空。

prohibited_unless:anotherfield,value,...

除非 anotherfield 欄位等於任何 value,否則驗證的欄位必須缺失或為空。如果欄位滿足以下條件之一,則為“空”

  • 值為 null
  • 值是一個空字串。
  • 值是一個空陣列或空的 Countable 物件。
  • 值是一個路徑為空的上傳檔案。

prohibits:anotherfield,...

如果驗證的欄位不是缺失或為空的,則 anotherfield 中的所有欄位都必須缺失或為空。如果欄位滿足以下條件之一,則為“空”

  • 值為 null
  • 值是一個空字串。
  • 值是一個空陣列或空的 Countable 物件。
  • 值是一個路徑為空的上傳檔案。

regex:pattern

驗證的欄位必須匹配給定的正則表示式。

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

當使用 regex / not_regex 模式時,可能需要使用陣列而不是 | 分隔符來指定規則,特別是如果正則表示式包含 | 字元。

required

驗證的欄位必須存在於輸入資料中且不能為空。如果欄位滿足以下條件之一,則為“空”

  • 值為 null
  • 值是一個空字串。
  • 值是一個空陣列或空的 Countable 物件。
  • 值是一個沒有路徑的上傳檔案。

required_if:anotherfield,value,...

如果 anotherfield 欄位等於任何 value,則驗證的欄位必須存在且不能為空。

如果您想為 required_if 規則構建更復雜的條件,可以使用 Rule::requiredIf 方法。此方法接受布林值或閉包。當傳遞閉包時,閉包應返回 truefalse 以指示是否需要驗證的欄位

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rule;
3 
4Validator::make($request->all(), [
5 'role_id' => Rule::requiredIf($request->user()->is_admin),
6]);
7 
8Validator::make($request->all(), [
9 'role_id' => Rule::requiredIf(fn () => $request->user()->is_admin),
10]);

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,否則驗證的欄位必須存在且不能為空。這也意味著除非 valuenull,否則 anotherfield 必須存在於請求資料中。如果 valuenull (required_unless:name,null),則除非比較欄位為 null 或請求資料中缺少比較欄位,否則驗證的欄位將是必需的。

required_with:foo,bar,...

只有在 任何其他指定欄位存在且不為空時,驗證的欄位才必須存在且不為空。

required_with_all:foo,bar,...

只有在 所有其他指定欄位存在且不為空時,驗證的欄位才必須存在且不為空。

required_without:foo,bar,...

只有當 任何其他指定欄位為空或不存在時,驗證的欄位才必須存在且不為空。

required_without_all:foo,bar,...

只有當 所有其他指定欄位為空或不存在時,驗證的欄位才必須存在且不為空。

required_array_keys:foo,bar,...

驗證的欄位必須是陣列,並且至少包含指定的鍵。

same:field

給定的 field 必須與驗證的欄位匹配。

size:value

驗證的欄位必須具有與給定 value 匹配的大小。對於字串資料,value 對應於字元數。對於數字資料,value 對應於給定的整數值(屬性也必須具有 numericinteger 規則)。對於陣列,size 對應於陣列的 count。對於檔案,size 對應於以千位元組為單位的檔案大小。讓我們看一些示例

1// Validate that a string is exactly 12 characters long...
2'title' => 'size:12';
3 
4// Validate that a provided integer equals 10...
5'seats' => 'integer|size:10';
6 
7// Validate that an array has exactly 5 elements...
8'tags' => 'array|size:5';
9 
10// Validate that an uploaded file is exactly 512 kilobytes...
11'image' => 'file|size:512';

starts_with:foo,bar,...

驗證的欄位必須以給定的值之一開頭。

string

驗證的欄位必須是字串。如果您希望允許該欄位也為 null,則應將 nullable 規則分配給該欄位。

為方便起見,字串驗證規則也可以使用流式 Rule::string() 規則構建器構建

1use Illuminate\Validation\Rule;
2 
3'title' => [
4 'required',
5 Rule::string()
6 ->min(3)
7 ->max(255)
8 ->alphaDash(ascii: true),
9],

字串規則構建器提供了常見字串約束的方法,包括 alphaalphaDashalphaNumericasciibetweendoesntEndWithdoesntStartWithendsWithexactlylowercasemaxminstartsWithuppercase。由於規則構建器是可條件的,您還可以使用 whenunless 方法來有條件地應用約束。

timezone

根據 DateTimeZone::listIdentifiers 方法,驗證的欄位必須是有效的時區識別符號。

傳遞給此驗證規則的引數可以是 DateTimeZone::listIdentifiers 方法接受的引數

1'timezone' => 'required|timezone:all';
2 
3'timezone' => 'required|timezone:Africa';
4 
5'timezone' => 'required|timezone:per_country,US';

unique:table,column

驗證的欄位不能存在於給定的資料庫表中。

指定自定義表/列名

除了直接指定表名外,您還可以指定應用於確定表名的 Eloquent 模型

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

column 選項可用於指定欄位對應的資料庫列。如果未指定 column 選項,將使用驗證的欄位名稱。

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

指定自定義資料庫連線

有時,您可能需要為驗證器進行的資料庫查詢設定自定義連線。要完成此操作,您可以在表名之前加上連線名

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

強制唯一規則忽略給定 ID

有時,您可能希望在唯一驗證期間忽略給定的 ID。例如,考慮一個包含使用者姓名、電子郵件地址和位置的“更新個人資料”螢幕。您可能需要驗證電子郵件地址是否唯一。但是,如果使用者只更改姓名而不更改電子郵件欄位,由於使用者已經是相關電子郵件地址的所有者,您不希望丟擲驗證錯誤。

為了指示驗證器忽略使用者的 ID,我們將使用 Rule 類流式定義規則。在此示例中,我們還將驗證規則指定為陣列,而不是使用 | 字元來分隔規則

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rule;
3 
4Validator::make($data, [
5 'email' => [
6 'required',
7 Rule::unique('users')->ignore($user->id),
8 ],
9]);

您絕不應將任何使用者控制的請求輸入傳遞給 ignore 方法。相反,您應該只傳遞系統生成的唯一 ID,例如 Eloquent 模型例項中的自增 ID 或 UUID。否則,您的應用程式將容易受到 SQL 注入攻擊。

除了將模型鍵的值傳遞給 ignore 方法外,您還可以傳遞整個模型例項。Laravel 將自動從模型中提取鍵

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

如果您的表使用的不是 id 的主鍵列名,則在呼叫 ignore 方法時可以指定列名

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

預設情況下,unique 規則會檢查與被驗證屬性名稱匹配的列的唯一性。但是,您可以傳遞一個不同的列名作為 unique 方法的第二個引數。

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

新增額外的 Where 子句

您可以透過使用 where 方法自定義查詢來指定額外的查詢條件。例如,讓我們新增一個查詢條件,將查詢範圍限制為僅搜尋 account_id 列值為 1 的記錄。

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

在唯一性檢查中忽略軟刪除記錄

預設情況下,unique 規則在確定唯一性時會包含軟刪除記錄。若要從唯一性檢查中排除軟刪除記錄,可以呼叫 withoutTrashed 方法。

1Rule::unique('users')->withoutTrashed();

如果您的模型使用了除 deleted_at 之外的列名來記錄軟刪除,您可以在呼叫 withoutTrashed 方法時提供該列名。

1Rule::unique('users')->withoutTrashed('was_deleted_at');

uppercase

驗證的欄位必須是大寫的。

url

驗證的欄位必須是有效的 URL。

如果您想指定應被視為有效的 URL 協議,您可以將這些協議作為驗證規則引數傳遞。

1'url' => 'url:http,https',
2 
3'game' => 'url:minecraft,steam',

ulid

驗證的欄位必須是有效的 通用唯一詞典排序識別符號 (ULID)。

uuid

驗證的欄位必須是符合 RFC 9562(版本 1、3、4、5、6、7 或 8)的有效通用唯一識別碼 (UUID)。

您也可以按版本驗證給定的 UUID 是否符合 UUID 規範。

1'uuid' => 'uuid:4'

條件新增規則

當欄位具有特定值時跳過驗證

有時您可能希望在另一個欄位具有特定值時不驗證某個欄位。您可以使用 exclude_if 驗證規則來實現這一點。在這個例子中,如果 has_appointment 欄位的值為 false,則 appointment_datedoctor_name 欄位將不會被驗證。

1use Illuminate\Support\Facades\Validator;
2 
3$validator = Validator::make($data, [
4 'has_appointment' => 'required|boolean',
5 'appointment_date' => 'exclude_if:has_appointment,false|required|date',
6 'doctor_name' => 'exclude_if:has_appointment,false|required|string',
7]);

或者,您可以使用 exclude_unless 規則,除非另一個欄位具有特定值,否則不驗證某個欄位。

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

存在時驗證

在某些情況下,您可能希望在被驗證的資料中存在某個欄位時才對其執行驗證檢查。要快速實現這一點,請將 sometimes 規則新增到您的規則列表中。

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

在上面的示例中,email 欄位僅在 $data 陣列中存在時才會被驗證。

如果您嘗試驗證一個應該始終存在但可能為空的欄位,請檢視關於可選欄位的注意事項

複雜的條件驗證

有時您可能希望根據更復雜的邏輯新增驗證規則。例如,您可能希望僅當另一個欄位的值大於 100 時才要求某個欄位必填。或者,您可能需要兩個欄位僅在另一個欄位存在時才具有特定值。新增這些驗證規則並不複雜。首先,使用您的靜態規則(永遠不會改變的規則)建立一個 Validator 例項。

1use Illuminate\Support\Facades\Validator;
2 
3$validator = Validator::make($request->all(), [
4 'email' => 'required|email',
5 'games' => 'required|integer|min:0',
6]);

假設我們的 Web 應用程式是為遊戲收藏家準備的。如果一位遊戲收藏家在我們應用註冊且他們擁有的遊戲超過 100 款,我們希望他們解釋為何擁有這麼多遊戲。例如,也許他們經營著一家遊戲轉售店,或者只是單純喜歡收集遊戲。為了有條件地新增此要求,我們可以在 Validator 例項上使用 sometimes 方法。

1use Illuminate\Support\Fluent;
2 
3$validator->sometimes('reason', 'required|max:500', function (Fluent $input) {
4 return $input->games >= 100;
5});

傳遞給 sometimes 方法的第一個引數是我們正在進行條件驗證的欄位名稱。第二個引數是我們想要新增的規則列表。如果作為第三個引數傳遞的閉包返回 true,則會新增這些規則。該方法使得構建複雜的條件驗證變得輕而易舉。您甚至可以一次為多個欄位新增條件驗證。

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

傳遞給閉包的 $input 引數將是 Illuminate\Support\Fluent 的一個例項,可用於訪問您正在驗證的輸入和檔案。

複雜的條件陣列驗證

有時您可能希望根據同一個巢狀陣列中您不知道索引的另一個欄位來驗證某個欄位。在這種情況下,您可以允許您的閉包接收第二個引數,該引數將是被驗證陣列中的當前單個專案。

1$input = [
2 'channels' => [
3 [
4 'type' => 'email',
5 'address' => '[email protected]',
6 ],
7 [
8 'type' => 'url',
9 'address' => 'https://example.com',
10 ],
11 ],
12];
13 
14$validator->sometimes('channels.*.address', 'email', function (Fluent $input, Fluent $item) {
15 return $item->type === 'email';
16});
17 
18$validator->sometimes('channels.*.address', 'url', function (Fluent $input, Fluent $item) {
19 return $item->type !== 'email';
20});

與傳遞給閉包的 $input 引數一樣,當屬性資料是陣列時,$item 引數是 Illuminate\Support\Fluent 的一個例項;否則,它是一個字串。

驗證陣列

陣列驗證規則文件中所述,array 規則接受允許的陣列鍵列表。如果陣列中存在任何額外的鍵,驗證將失敗。

1use Illuminate\Support\Facades\Validator;
2 
3$input = [
4 'user' => [
5 'name' => 'Taylor Otwell',
6 'username' => 'taylorotwell',
7 'admin' => true,
8 ],
9];
10 
11Validator::make($input, [
12 'user' => 'array:name,username',
13]);

通常,您應該始終指定允許出現在陣列中的陣列鍵。否則,驗證器的 validatevalidated 方法將返回所有經過驗證的資料,包括陣列及其所有鍵,即使這些鍵並未透過其他巢狀陣列驗證規則進行驗證。

驗證巢狀陣列輸入

驗證基於巢狀陣列的表單輸入欄位並不困難。您可以使用“點符號”來驗證陣列中的屬性。例如,如果傳入的 HTTP 請求包含 photos[profile] 欄位,您可以這樣驗證它:

1use Illuminate\Support\Facades\Validator;
2 
3$validator = Validator::make($request->all(), [
4 'photos.profile' => 'required|image',
5]);

您也可以驗證陣列的每個元素。例如,要驗證給定陣列輸入欄位中的每個電子郵件是否唯一,您可以執行以下操作:

1$validator = Validator::make($request->all(), [
2 'users.*.email' => 'email|unique:users',
3 'users.*.first_name' => 'required_with:users.*.last_name',
4]);

同樣,當在語言檔案中指定自定義驗證訊息時,您可以使用 * 字元,從而輕鬆地為基於陣列的欄位使用單個驗證訊息。

1'custom' => [
2 'users.*.email' => [
3 'unique' => 'Each user must have a unique email address',
4 ]
5],

訪問巢狀陣列資料

有時,在為屬性分配驗證規則時,您可能需要訪問給定巢狀陣列元素的值。您可以使用 Rule::forEach 方法來實現這一點。forEach 方法接受一個閉包,該閉包將在被驗證的陣列屬性的每次迭代時被呼叫,並接收屬性的值和完整的展開屬性名稱。閉包應返回一個規則陣列以分配給該陣列元素。

1use App\Rules\HasPermission;
2use Illuminate\Support\Facades\Validator;
3use Illuminate\Validation\Rule;
4 
5$validator = Validator::make($request->all(), [
6 'companies.*.id' => Rule::forEach(function (string|null $value, string $attribute) {
7 return [
8 Rule::exists(Company::class, 'id'),
9 new HasPermission('manage-company', $value),
10 ];
11 }),
12]);

錯誤訊息索引和位置

在驗證陣列時,您可能希望在應用程式顯示的錯誤訊息中引用驗證失敗的特定項的索引或位置。為此,您可以在自定義驗證訊息中包含 :index(從 0 開始)、:position(從 1 開始)或 :ordinal-position(從 1st 開始)佔位符。

1use Illuminate\Support\Facades\Validator;
2 
3$input = [
4 'photos' => [
5 [
6 'name' => 'BeachVacation.jpg',
7 'description' => 'A photo of my beach vacation!',
8 ],
9 [
10 'name' => 'GrandCanyon.jpg',
11 'description' => '',
12 ],
13 ],
14];
15 
16Validator::validate($input, [
17 'photos.*.description' => 'required',
18], [
19 'photos.*.description.required' => 'Please describe photo #:position.',
20]);

根據上面的例子,驗證將失敗,使用者將看到以下錯誤資訊:“Please describe photo #2.”

如有必要,您可以透過 second-indexsecond-positionthird-indexthird-position 等引用更深層的巢狀索引和位置。

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

驗證檔案

Laravel 提供了多種可用於驗證上傳檔案的驗證規則,例如 mimesimageminmax。雖然您可以隨意在驗證檔案時單獨指定這些規則,但 Laravel 還提供了一個流暢的檔案驗證規則構建器,您可能會覺得它很方便。

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rules\File;
3 
4Validator::validate($input, [
5 'attachment' => [
6 'required',
7 File::types(['mp3', 'wav'])
8 ->min(1024)
9 ->max(12 * 1024),
10 ],
11]);

驗證檔案型別

即使在呼叫 types 方法時只需要指定副檔名,該方法實際上是透過讀取檔案內容並猜測其 MIME 型別來驗證檔案的 MIME 型別。有關 MIME 型別及其相應副檔名的完整列表,可以在以下位置找到。

https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

驗證檔案大小

為方便起見,最小和最大檔案大小可以指定為帶有指示檔案大小單位字尾的字串。支援 kbmbgbtb 字尾。

1File::types(['mp3', 'wav'])
2 ->min('1kb')
3 ->max('10mb');

驗證影像檔案

如果您的應用程式接受使用者上傳的影像,您可以使用 File 規則的 image 構造方法來確保被驗證的檔案是影像(jpg、jpeg、png、bmp、gif 或 webp)。

此外,dimensions 規則可用於限制影像的尺寸。

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rule;
3use Illuminate\Validation\Rules\File;
4 
5Validator::validate($input, [
6 'photo' => [
7 'required',
8 File::image()
9 ->min(1024)
10 ->max(12 * 1024)
11 ->dimensions(Rule::dimensions()->maxWidth(1000)->maxHeight(500)),
12 ],
13]);

有關驗證影像尺寸的更多資訊,可以在尺寸規則文件中找到。

預設情況下,由於存在 XSS 漏洞的可能性,image 規則不允許使用 SVG 檔案。如果您需要允許 SVG 檔案,可以將 allowSvg: true 傳遞給 image 規則:File::image(allowSvg: true)

驗證影像尺寸

您也可以驗證影像的尺寸。例如,要驗證上傳的影像寬度至少為 1000 畫素,高度至少為 500 畫素,可以使用 dimensions 規則。

1use Illuminate\Validation\Rule;
2use Illuminate\Validation\Rules\File;
3 
4File::image()->dimensions(
5 Rule::dimensions()
6 ->maxWidth(1000)
7 ->maxHeight(500)
8)

有關驗證影像尺寸的更多資訊,可以在尺寸規則文件中找到。

驗證密碼

為了確保密碼具有足夠的複雜性,您可以使用 Laravel 的 Password 規則物件。

1use Illuminate\Support\Facades\Validator;
2use Illuminate\Validation\Rules\Password;
3 
4$validator = Validator::make($request->all(), [
5 'password' => ['required', 'confirmed', Password::min(8)],
6]);

Password 規則物件允許您輕鬆自定義應用程式的密碼複雜性要求,例如指定密碼必須至少包含一個字母、數字、符號或混合大小寫字元。

1// Require at least 8 characters...
2Password::min(8)
3 
4// Require at least one letter...
5Password::min(8)->letters()
6 
7// Require at least one uppercase and one lowercase letter...
8Password::min(8)->mixedCase()
9 
10// Require at least one number...
11Password::min(8)->numbers()
12 
13// Require at least one symbol...
14Password::min(8)->symbols()

此外,您可以使用 uncompromised 方法確保密碼未在公共密碼資料洩露中被洩露。

1Password::min(8)->uncompromised()

在內部,Password 規則物件使用 k-匿名 (k-Anonymity) 模型,透過 haveibeenpwned.com 服務來確定密碼是否被洩露,而不會犧牲使用者的隱私或安全。

預設情況下,如果一個密碼在資料洩露中出現至少一次,它將被視為已洩露。您可以使用 uncompromised 方法的第一個引數自定義此閾值。

1// Ensure the password appears less than 3 times in the same data leak...
2Password::min(8)->uncompromised(3);

當然,您可以連結上述示例中的所有方法。

1Password::min(8)
2 ->letters()
3 ->mixedCase()
4 ->numbers()
5 ->symbols()
6 ->uncompromised()

定義預設密碼規則

您可能會發現在應用程式的一個位置指定密碼的預設驗證規則很方便。您可以使用接受閉包的 Password::defaults 方法輕鬆實現這一點。傳遞給 defaults 方法的閉包應返回 Password 規則的預設配置。通常,defaults 規則應在應用程式某個服務提供商的 boot 方法中呼叫。

1use Illuminate\Validation\Rules\Password;
2 
3/**
4 * Bootstrap any application services.
5 */
6public function boot(): void
7{
8 Password::defaults(function () {
9 $rule = Password::min(8);
10 
11 return $this->app->isProduction()
12 ? $rule->mixedCase()->uncompromised()
13 : $rule;
14 });
15}

然後,當您想對特定的密碼應用預設規則時,可以呼叫不帶引數的 defaults 方法。

1'password' => ['required', Password::defaults()],

有時,您可能希望將額外的驗證規則附加到您的預設密碼驗證規則中。您可以使用 rules 方法來實現這一點。

1use App\Rules\ZxcvbnRule;
2 
3Password::defaults(function () {
4 $rule = Password::min(8)->rules([new ZxcvbnRule]);
5 
6 // ...
7});

自定義驗證規則

使用規則物件

Laravel 提供了各種有用的驗證規則;但是,您可能希望指定自己的一些規則。註冊自定義驗證規則的一種方法是使用規則物件。要生成一個新的規則物件,您可以使用 make:rule Artisan 命令。讓我們使用這個命令來生成一個驗證字串是否為大寫的規則。Laravel 會將新規則放置在 app/Rules 目錄中。如果該目錄不存在,Laravel 會在您執行 Artisan 命令建立規則時自動建立它。

1php artisan make:rule Uppercase

規則建立完成後,我們就可以定義它的行為。規則物件包含一個單一的方法:validate。此方法接收屬性名稱、其值以及一個回撥函式,該回調函式應在驗證失敗時呼叫以顯示錯誤訊息。

1<?php
2 
3namespace App\Rules;
4 
5use Closure;
6use Illuminate\Contracts\Validation\ValidationRule;
7 
8class Uppercase implements ValidationRule
9{
10 /**
11 * Run the validation rule.
12 */
13 public function validate(string $attribute, mixed $value, Closure $fail): void
14 {
15 if (strtoupper($value) !== $value) {
16 $fail('The :attribute must be uppercase.');
17 }
18 }
19}

規則定義完成後,您可以透過將規則物件的例項與其他驗證規則一起傳遞,將其附加到驗證器。

1use App\Rules\Uppercase;
2 
3$request->validate([
4 'name' => ['required', 'string', new Uppercase],
5]);

翻譯驗證訊息

除了向 $fail 閉包提供字面錯誤訊息外,您還可以提供一個翻譯字串鍵,並指示 Laravel 翻譯該錯誤訊息。

1if (strtoupper($value) !== $value) {
2 $fail('validation.uppercase')->translate();
3}

如有必要,您可以將佔位符替換和首選語言作為 translate 方法的第一個和第二個引數提供。

1$fail('validation.location')->translate([
2 'value' => $this->value,
3], 'fr');

訪問附加資料

如果您的自定義驗證規則類需要訪問正在進行驗證的所有其他資料,您的規則類可以實現 Illuminate\Contracts\Validation\DataAwareRule 介面。該介面要求您的類定義一個 setData 方法。Laravel 會在驗證開始前自動呼叫此方法,並傳入所有正在驗證的資料。

1<?php
2 
3namespace App\Rules;
4 
5use Illuminate\Contracts\Validation\DataAwareRule;
6use Illuminate\Contracts\Validation\ValidationRule;
7 
8class Uppercase implements DataAwareRule, ValidationRule
9{
10 /**
11 * All of the data under validation.
12 *
13 * @var array<string, mixed>
14 */
15 protected $data = [];
16 
17 // ...
18 
19 /**
20 * Set the data under validation.
21 *
22 * @param array<string, mixed> $data
23 */
24 public function setData(array $data): static
25 {
26 $this->data = $data;
27 
28 return $this;
29 }
30}

或者,如果您的驗證規則需要訪問執行驗證的驗證器例項,您可以實現 ValidatorAwareRule 介面。

1<?php
2 
3namespace App\Rules;
4 
5use Illuminate\Contracts\Validation\ValidationRule;
6use Illuminate\Contracts\Validation\ValidatorAwareRule;
7use Illuminate\Validation\Validator;
8 
9class Uppercase implements ValidationRule, ValidatorAwareRule
10{
11 /**
12 * The validator instance.
13 *
14 * @var \Illuminate\Validation\Validator
15 */
16 protected $validator;
17 
18 // ...
19 
20 /**
21 * Set the current validator.
22 */
23 public function setValidator(Validator $validator): static
24 {
25 $this->validator = $validator;
26 
27 return $this;
28 }
29}

使用閉包

如果您只需要在整個應用程式中使用一次自定義規則的功能,可以使用閉包代替規則物件。閉包接收屬性名稱、屬性值以及一個在驗證失敗時呼叫的 $fail 回撥。

1use Illuminate\Support\Facades\Validator;
2use Closure;
3 
4$validator = Validator::make($request->all(), [
5 'title' => [
6 'required',
7 'max:255',
8 function (string $attribute, mixed $value, Closure $fail) {
9 if ($value === 'foo') {
10 $fail("The {$attribute} is invalid.");
11 }
12 },
13 ],
14]);

隱式規則

預設情況下,當被驗證的屬性不存在或包含空字串時,常規驗證規則(包括自定義規則)不會執行。例如,unique 規則不會針對空字串執行。

1use Illuminate\Support\Facades\Validator;
2 
3$rules = ['name' => 'unique:users,name'];
4 
5$input = ['name' => ''];
6 
7Validator::make($input, $rules)->passes(); // true

為了使自定義規則即使在屬性為空時也能執行,該規則必須暗示該屬性是必填的。要快速生成一個新的隱式規則物件,您可以在使用 make:rule Artisan 命令時加上 --implicit 選項。

1php artisan make:rule Uppercase --implicit

“隱式”規則僅暗示屬性是必填的。它是否真正使缺失或空的屬性失效取決於您自己。