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
目錄,您可以使用 lang:publish
Artisan 命令指示 Laravel 創建它。
在 lang/en/validation.php
檔案中,您將找到每個驗證規則的翻譯條目。您可以根據您應用程序的需求自由更改或修改這些訊息。
此外,您可以將此檔案複製到另一個語言目錄以為應用程序的語言翻譯訊息。要了解更多關於 Laravel 本地化的信息,請查看完整的本地化文檔。
Warning
默認情況下,Laravel 應用程序骨架不包括 lang
目錄。如果您想自訂 Laravel 的語言檔案,您可以通過 lang:publish
Artisan 命令來發布它們。
在這個例子中,我們使用傳統表單將數據發送到應用程序。然而,許多應用程序從由 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
方法將從會話中提取先前存儲的輸入數據:
$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 service container 自動解析。
您可以通過覆寫 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
facade 手動創建驗證器實例。該 facade 上的 make
方法會生成一個新的驗證器實例:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
/**
* 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' => '我們需要知道您的電子郵件地址!',
];
許多 Laravel 內建的錯誤訊息包含一個 :attribute
佔位符,該佔位符將被替換為正在驗證的欄位或屬性的名稱。為了自訂用於替換這些佔位符的值,您可以將自訂屬性的陣列作為 Validator::make
方法的第四個參數傳遞:
$validator = Validator::make($input, $rules, $messages, [
'email' => '電子郵件地址',
]);
有時在完成初始驗證後,您需要執行額外的驗證。您可以使用驗證器的 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']);
如果您想將驗證數據作為 collection 實例檢索,可以調用 collect
方法:
$collection = $request->safe()->collect();
在 Validator
實例上調用 errors
方法後,您將收到一個 Illuminate\Support\MessageBag
實例,該實例具有各種方便的方法來處理錯誤消息。自動提供給所有視圖的 $errors
變量也是 MessageBag
類的一個實例。
要檢索給定字段的第一個錯誤消息,請使用 first
方法:
$errors = $validator->errors();
echo $errors->first('email');
如果您需要檢索給定字段的所有消息數組,請使用 get
方法:
foreach ($errors->get('email') as $message) {
// ...
}
如果您正在驗證數組表單字段,可以使用 *
字符檢索每個數組元素的所有消息:
foreach ($errors->get('attachments.*') as $message) {
// ...
}
要取得所有欄位的所有訊息陣列,請使用 all
方法:
foreach ($errors->all() as $message) {
// ...
}
可以使用 has
方法來確定特定欄位是否存在任何錯誤訊息:
if ($errors->has('email')) {
// ...
}
Laravel 內建的驗證規則都有一個錯誤訊息,位於應用程式的 lang/en/validation.php
檔案中。如果您的應用程式沒有 lang
目錄,您可以使用 lang:publish
Artisan 指令指示 Laravel 建立它。
在 lang/en/validation.php
檔案中,您會找到每個驗證規則的翻譯項目。您可以根據應用程式的需求自由更改或修改這些訊息。
此外,您可以將此檔案複製到另一個語言目錄以翻譯應用程式語言的訊息。欲了解更多關於 Laravel 本地化的資訊,請查看完整的本地化文件。
Warning
預設情況下,Laravel 應用程式骨架不包含 lang
目錄。如果您想要自訂 Laravel 的語言檔,您可以透過 lang:publish
Artisan 指令來發佈它們。
您可以在應用程式的驗證語言檔中自訂用於指定屬性和規則組合的錯誤訊息。為此,將您的訊息自訂新增到應用程式的 lang/xx/validation.php
語言檔的 custom
陣列中:
'custom' => [
'email' => [
'required' => 'We need to know your email address!',
'max' => 'Your email address is too long!'
],
],
許多 Laravel 內建的錯誤訊息包含一個 :attribute
佔位符,該佔位符將被替換為正在驗證的欄位或屬性的名稱。如果您希望驗證訊息中的 :attribute
部分被替換為自訂值,您可以在 lang/xx/validation.php
語言檔的 attributes
陣列中指定自訂屬性名稱:
'attributes' => [
'email' => '電子郵件地址',
],
Warning
預設情況下,Laravel 應用程式骨架不包含 lang
目錄。如果您想要自訂 Laravel 的語言檔案,您可以透過 lang:publish
Artisan 指令來發佈它們。
一些 Laravel 內建的驗證規則錯誤訊息包含一個 :value
佔位符,該佔位符將被替換為請求屬性的當前值。然而,您偶爾可能需要將驗證訊息中的 :value
部分替換為值的自訂表示。例如,考慮以下規則,該規則指定如果 payment_type
的值為 cc
,則需要信用卡號碼:
Validator::make($request->all(), [
'credit_card_number' => 'required_if:payment_type,cc'
]);
如果此驗證規則失敗,將產生以下錯誤訊息:
當付款類型為 cc 時,需要信用卡號碼欄位。
您可以在您的 lang/xx/validation.php
語言檔案中定義一個 values
陣列,來指定一個更友好的值表示:
'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],
Warning
預設情況下,Laravel 應用程式骨架不包含 lang
目錄。如果您想要自訂 Laravel 的語言檔案,您可以透過 lang:publish
Artisan 指令來發佈它們。
定義了這個值後,驗證規則將產生以下錯誤訊息:
當付款類型為信用卡時,需要信用卡號碼欄位。
以下是所有可用的驗證規則及其功能列表:
<style> .collection-method-list > p { columns: 10.8em 3; -moz-columns: 10.8em 3; -webkit-columns: 10.8em 3; } .collection-method-list a { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } </style>有效網址 字母 字母及破折號 字母數字 ASCII 已確認 目前密碼 不同 不以...開頭 不以...結尾 電子郵件 以...結尾 列舉 十六進位色碼 在...之中 IP 位址 JSON 小寫 MAC 位址 最大值 最小值 不在...之中 正規表達式 非正規表達式 相同 大小 以...開頭 字串 大寫 網址 ULID UUID
之後 之後或等於 之前 之前或等於 日期 日期相等 日期格式 不同 時區
中斷 排除 如果排除 除非排除 與排除 無排除 填寫 遺失 如果遺失 除非遺失 與遺失 全部遺失 可為空 存在 如果存在 除非存在 與存在 全部存在 禁止 如果禁止 除非禁止 禁止 必填 如果必填 如果接受必填 如果拒絕必填 除非必填 與必填 全部與必填 無必填 全部無必填 必填陣列鍵 有時候
要驗證的欄位必須是 "yes"
, "on"
, 1
, "1"
, true
, 或 "true"
。這對於驗證「服務條款」接受或類似欄位非常有用。
要驗證的欄位必須是 "yes"
, "on"
, 1
, "1"
, true
, 或 "true"
,如果另一個要驗證的欄位等於指定的值。這對於驗證「服務條款」接受或類似欄位非常有用。
驗證的欄位必須根據 dns_get_record
PHP 函數具有有效的 A 或 AAAA 記錄。在傳遞給 dns_get_record
之前,將使用 parse_url
PHP 函數提取提供的 URL 的主機名。
驗證的欄位必須是給定日期之後的值。日期將傳遞給 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)),
],
驗證的欄位必須完全是包含在 \p{L}
和 \p{M}
中的 Unicode 字母字符。
要將此驗證規則限制為 ASCII 範圍內的字符(a-z
和 A-Z
),您可以向驗證規則提供 ascii
選項:
'username' => 'alpha:ascii',
驗證的欄位必須完全是包含在 \p{L}
、\p{M}
、\p{N}
中的 Unicode 字母數字字符,以及 ASCII 破折號(-
)和 ASCII 底線(_
)。
要將此驗證規則限制為ASCII範圍內的字符(a-z
,A-Z
和0-9
),您可以將ascii
選項提供給驗證規則:
'username' => 'alpha_dash:ascii',
要求驗證的字段必須完全是Unicode字母數字字符,包含在\p{L}
,\p{M}
和\p{N}
中。
要將此驗證規則限制為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)),
],
進行驗證的欄位必須具有介於給定 min 和 max(包括)之間的大小。字符串、數字、陣列和檔案的評估方式與 size
規則相同。
進行驗證的欄位必須能夠轉換為布林值。接受的輸入為 true
、false
、1
、0
、"1"
和 "0"
。
進行驗證的欄位必須具有與 {field}_confirmation
匹配的欄位。例如,如果進行驗證的欄位是 password
,則輸入中必須存在一個匹配的 password_confirmation
欄位。
您也可以傳遞自定義的確認欄位名稱。例如,confirmed:repeat_username
將期望欄位 repeat_username
與進行驗證的欄位匹配。
進行驗證的欄位必須是包含所有給定參數值的陣列。
進行驗證的欄位必須與已驗證用戶的密碼匹配。您可以使用規則的第一個參數來指定一個 身份驗證護衛:
'password' => 'current_password:api'
要驗證的字段必須是根據 strtotime
PHP 函數是有效的非相對日期。
要驗證的字段必須等於給定的日期。日期將被傳遞到 PHP strtotime
函數中,以便轉換為有效的 DateTime
實例。
要驗證的字段必須與給定的 formats 之一匹配。在驗證字段時,您應該只使用 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"
。
要驗證的字段必須與 field 的值不同。
要驗證的整數必須具有 value 的確切長度。
整數驗證必須具有給定 min 和 max 之間的長度。
要驗證的文件必須是符合規則參數指定的尺寸限制的圖像:
'avatar' => 'dimensions:min_width=100,min_height=200'
可用的約束條件包括:min_width、max_width、min_height、max_height、width、height、ratio。
一個 ratio 約束應該表示為寬度除以高度。這可以通過分數形式如 3/2
或浮點數形式如 1.5
來指定:
'avatar' => 'dimensions:ratio=3/2'
由於此規則需要多個引數,通常更方便使用 Rule::dimensions
方法來流暢地構建規則:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'avatar' => [
'required',
Rule::dimensions()
->maxWidth(1000)
->maxHeight(500)
->ratio(3 / 2),
],
]);
在驗證陣列時,要驗證的字段不能有任何重複值:
'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
驗證。以下是您可以應用的所有驗證風格的完整列表:
rfc
:RFCValidation
- 根據 RFC 5322 驗證電子郵件地址。strict
:NoRFCWarningsValidation
- 根據 RFC 5322 驗證電子郵件,拒絕尾隨句點或多個連續句點。dns
:DNSCheckValidation
- 確保電子郵件地址的域名具有有效的 MX 記錄。spoof
:SpoofCheckValidation
- 確保電子郵件地址不包含同形異音或具有欺騙性的 Unicode 字元。filter
:FilterEmailValidation
- 根據 PHP 的filter_var
函數確保電子郵件地址有效。filter_unicode
:FilterEmailValidation::unicode()
- 根據 PHP 的filter_var
函數確保電子郵件地址有效,允許一些 Unicode 字元。
為了方便起見,可以使用流暢的規則建構器來建立電子郵件驗證規則:
use Illuminate\Validation\Rule;
$request->validate([
'email' => [
'required',
Rule::email()
->rfcCompliant(strict: false)
->validateMxRecord()
->preventSpoofing()
],
]);
[!WARNING]
dns
和spoof
驗證器需要 PHPintl
擴充功能。
驗證的字段必須以給定的值之一結尾。
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
方法返回的請求數據中排除。
如果 anotherfield 字段等於 value,則將被驗證的字段從 validate
和 validated
方法返回的請求數據中排除。
如果需要複雜的條件性排除邏輯,可以使用 Rule::excludeIf
方法。該方法接受布爾值或閉包。當給定一個閉包時,閉包應返回 true
或 false
以指示是否應排除被驗證的字段:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => Rule::excludeIf($request->user()->is_admin),
]);
Validator::make($request->all(), [
'role_id' => Rule::excludeIf(fn () => $request->user()->is_admin),
]);
將被驗證的字段從 validate
和 validated
方法返回的請求數據中排除,除非 anotherfield 字段等於 value。如果 value 為 null
(exclude_unless:name,null
),則將被驗證的字段排除,除非比較字段為 null
或比較字段缺失於請求數據中。
當 anotherfield 欄位存在時,驗證的欄位將從 validate
和 validated
方法返回的請求資料中排除。
當 anotherfield 欄位不存在時,驗證的欄位將從 validate
和 validated
方法返回的請求資料中排除。
驗證的欄位必須存在於指定的資料庫表中。
'state' => 'exists:states'
如果未指定 column
選項,將使用欄位名稱。因此,在這種情況下,規則將驗證 states
資料庫表中是否包含具有與請求的 state
屬性值匹配的 state
欄位值的記錄。
您可以明確指定應由驗證規則使用的資料庫欄位名稱,方法是將其放在資料庫表名稱之後:
'state' => 'exists:states,abbreviation'
有時,您可能需要指定特定的資料庫連線來執行 exists
查詢。您可以通過在表名之前加上連線名稱來完成這一點:
'email' => 'exists:connection.staff,email'
您可以指定應用於確定表名的 Eloquent 模型,而不是直接指定表名:
'user_id' => 'exists:App\Models\User,id'
如果您想自訂驗證規則執行的查詢,您可以使用 Rule
類來流暢地定義規則。在這個例子中,我們還將指定驗證規則作為一個陣列,而不是使用 |
字元來分隔它們:
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::exists('staff')->where(function (Builder $query) {
$query->where('account_id', 1);
}),
],
]);
您可以通過將欄位名稱作為 exists
方法的第二個參數提供給 exists
方法,明確指定由 Rule::exists
方法生成的 exists
規則應使用的資料庫欄位名稱。
'state' => Rule::exists('states', 'abbreviation'),
驗證的檔案必須具有與列出的擴展名之一對應的使用者指定擴展名:
'photo' => ['required', 'extensions:jpg,png'],
[!WARNING]
永遠不要僅依賴於檔案的使用者指定擴展名來進行驗證。通常應該始終將此規則與mimes
或mimetypes
規則結合使用。
驗證的欄位必須是成功上傳的檔案。
當存在時,驗證的欄位不得為空。
驗證的欄位必須大於給定的 field 或 value。這兩個欄位必須是相同類型的。字串、數值、陣列和檔案將使用與 size
規則相同的慣例進行評估。
驗證的欄位必須大於或等於給定的 field 或 value。這兩個欄位必須是相同類型的。字串、數值、陣列和檔案將使用與 size
規則相同的慣例進行評估。
驗證的欄位必須包含 十六進位 格式中的有效顏色值。
驗證的檔案必須是圖片(jpg、jpeg、png、bmp、gif 或 webp)。
[!WARNING] 默認情況下,圖片規則不允許 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_的值中。
要驗證的欄位必須是整數。
[!WARNING]
此驗證規則不驗證輸入是否為"整數"變數類型,只是確保輸入是PHP的FILTER_VALIDATE_INT
規則接受的類型。如果您需要驗證輸入是否為數字,請將此規則與numeric
驗證規則結合使用。
要驗證的欄位必須是IP地址。
要驗證的欄位必須是IPv4地址。
要驗證的欄位必須是IPv6地址。
要驗證的欄位必須是有效的JSON字串。
要驗證的欄位必須小於給定的_field_。這兩個欄位必須是相同類型。字串、數字、陣列和檔案的評估使用與size
規則相同的慣例。
要驗證的欄位必須小於或等於給定的_field_。這兩個欄位必須是相同類型。字串、數字、陣列和檔案的評估使用與size
規則相同的慣例。
要驗證的欄位必須是小寫。
要驗證的欄位必須是一個清單陣列。如果其鍵由0到count($array) - 1
的連續數字組成,則將陣列視為清單。
要驗證的欄位必須是 MAC 位址。
要驗證的欄位必須小於或等於最大值 value。字串、數值、陣列和檔案的評估方式與 size
規則相同。
要驗證的整數必須具有最大長度 value。
要驗證的檔案必須符合給定 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
規則。
要驗證的欄位必須具有最小值 value。字串、數值、陣列和檔案的評估方式與 size
規則相同。
驗證中的整數必須具有最小長度 value。
驗證中的字段必須是 value 的倍數。
驗證中的字段不得存在於輸入數據中。
如果 anotherfield 字段等於任何 value,則驗證中的字段不得存在。
除非 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
。
驗證中的字段必須是數字。
要驗證的欄位必須存在於輸入資料中。
如果 anotherfield 欄位等於任何 value,則要驗證的欄位必須存在。
除非 anotherfield 欄位等於任何 value,否則要驗證的欄位必須存在。
要驗證的欄位只有在其他指定的欄位中有任何一個存在時才需要存在。
要驗證的欄位只有在所有其他指定的欄位都存在時才需要存在。
要驗證的欄位必須遺漏或為空。如果欄位符合以下條件之一,則該欄位為「空」:
- 值為
null
。 - 值為空字串。
- 值為空陣列或空的
Countable
物件。 - 值為上傳的檔案且路徑為空。
如果 anotherfield 欄位等於任何 value,則要驗證的欄位必須遺漏或為空。如果欄位符合以下條件之一,則該欄位為「空」:
- 值為
null
。 - 值為空字串。
- 值為空陣列或空的
Countable
物件。 - 值為上傳的檔案且路徑為空。
如果需要複雜的條件禁止邏輯,您可以使用 Rule::prohibitedIf
方法。此方法接受布林值或閉包。當給定閉包時,閉包應該返回 true
或 false
以指示是否應禁止驗證欄位:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
Validator::make($request->all(), [
'role_id' => Rule::prohibitedIf($request->user()->is_admin),
]);
Validator::make($request->all(), [
'role_id' => Rule::prohibitedIf(fn () => $request->user()->is_admin),
]);
要驗證的欄位必須遺漏或為空,除非 anotherfield 欄位等於任何 value。如果欄位符合以下條件之一,則該欄位為「空」:
- 值為
null
。 - 值為空字串。
- 值為空陣列或空的
Countable
物件。 - 值為上傳的檔案且路徑為空。
如果驗證的欄位不是遺失或空白,則 anotherfield 中的所有欄位必須是遺失或空白。如果欄位符合以下條件之一,則該欄位為「空白」:
- 值為
null
。 - 值為空字串。
- 值為空陣列或空的
Countable
物件。 - 值為上傳的檔案且路徑為空。
驗證的欄位必須符合給定的正則表達式。
在內部,此規則使用 PHP 的 preg_match
函式。指定的模式應遵守 preg_match
所需的相同格式,因此也應包含有效的定界符。例如:'email' => 'regex:/^.+@.+$/i'
。
[!WARNING]
當使用regex
/not_regex
模式時,可能需要將規則指定為陣列,而不是使用|
定界符,特別是如果正則表達式包含|
字元。
驗證的欄位必須存在於輸入資料中並且不為空。如果欄位符合以下條件之一,則該欄位為「空白」:
- 值為
null
。 - 值為空字串。
- 值為空陣列或空的
Countable
物件。 - 值為上傳的檔案且沒有路徑。
如果驗證的欄位必須存在且不為空,則 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
或比較欄位在請求資料中不存在。
當任何其他指定欄位存在且不為空時,驗證的欄位必須存在且不為空。
當所有其他指定欄位存在且不為空時,驗證的欄位必須存在且不為空。
當任何其他指定欄位為空或不存在時,驗證的欄位必須存在且不為空。
當所有其他指定欄位為空或不存在時,驗證的欄位必須存在且不為空。
驗證的欄位必須是陣列且必須至少包含指定的鍵。
給定的 field 必須與驗證的欄位相符。
進行驗證的欄位必須具有與給定 value 相符的大小。對於字串資料,value 對應到字元數。對於數值資料,value 對應到給定的整數值(屬性也必須具有 numeric
或 integer
規則)。對於陣列,size 對應到陣列的 count
。對於檔案,size 對應到以千位元組為單位的檔案大小。讓我們看一些範例:
// 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'
指定自訂資料庫連線
有時,您可能需要為驗證器進行的資料庫查詢設置自訂連線。為此,您可以在表格名稱之前加上連線名稱:
'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:http,https',
'game' => 'url:minecraft,steam',
驗證的欄位必須是有效的 Universally Unique Lexicographically Sortable Identifier (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|numeric',
]);
假設我們的 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' => '[email protected]',
],
[
'type' => 'url',
'address' => 'https://example.com',
],
],
];
$validator->sometimes('channels.*.address', 'email', function (Fluent $input, Fluent $item) {
return $item->type === 'email';
});
$validator->sometimes('channels.*.address', 'url', function (Fluent $input, Fluent $item) {
return $item->type !== 'email';
});
與傳遞給閉包的 $input
參數一樣,當屬性數據是一個陣列時,$item
參數是 Illuminate\Support\Fluent
的一個實例;否則,它是一個字符串。
如在array
驗證規則文件中所討論的,array
規則接受一個允許的陣列鍵列表。如果陣列中存在任何額外的鍵,驗證將失敗:
use Illuminate\Support\Facades\Validator;
$input = [
'user' => [
'name' => 'Taylor Otwell',
'username' => 'taylorotwell',
'admin' => true,
],
];
Validator::make($input, [
'user' => 'array:name,username',
]);
一般來說,您應該始終指定允許存在於您的陣列中的陣列鍵。否則,驗證器的 validate
和 validated
方法將返回所有驗證過的數據,包括陣列及其所有鍵,即使這些鍵未被其他嵌套陣列驗證規則驗證。
驗證基於嵌套陣列的表單輸入字段不必是一種痛苦。您可以使用“點表示法”來驗證陣列中的屬性。例如,如果傳入的 HTTP 請求包含一個 photos[profile]
字段,您可以這樣驗證它:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'photos.profile' => 'required|image',
]);
您還可以驗證陣列的每個元素。例如,要驗證給定陣列輸入字段中的每個電子郵件是否唯一,您可以執行以下操作:
$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);
同樣地,當指定語言文件中的自定義驗證消息時,您可以使用 *
字符,輕鬆地為基於陣列的字段使用單個驗證消息:
'custom' => [
'person.*.email' => [
'unique' => 'Each person 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
開始)的佔位符:
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' => '照片 #:second-position 的屬性無效。',
Laravel 提供了各種驗證規則,可用於驗證上傳的檔案,例如 mimes
、image
、min
和 max
。雖然您可以在驗證檔案時單獨指定這些規則,但 Laravel 也提供了一個流暢的檔案驗證規則建構器,您可能會發現這很方便:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;
Validator::validate($input, [
'attachment' => [
'required',
File::types(['mp3', 'wav'])
->min(1024)
->max(12 * 1024),
],
]);
即使在調用 types
方法時只需要指定擴展名,但該方法實際上通過讀取檔案的內容並猜測其 MIME 類型來驗證檔案的 MIME 類型。您可以在以下位置找到 MIME 類型及其對應的擴展名的完整列表:
https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
為了方便起見,最小和最大檔案大小可以指定為帶有後綴表示檔案大小單位的字串。支持 kb
、mb
、gb
和 tb
後綴:
File::types(['mp3', 'wav'])
->min('1kb')
->max('10mb');
如果您的應用程式接受使用者上傳的圖片,您可以使用 File
規則的 image
建構方法來確保正在驗證的檔案是圖片(jpg、jpeg、png、bmp、gif 或 webp)。
此外,可以使用 dimensions
規則來限制圖片的尺寸:
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;
Validator::validate($input, [
'photo' => [
'required',
File::image()
->min(1024)
->max(12 * 1024)
->dimensions(Rule::dimensions()->maxWidth(1000)->maxHeight(500)),
],
]);
[!NOTE] 有關驗證圖片尺寸的更多資訊,請參閱尺寸規則文件。
[!WARNING] 默認情況下,
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
方法的第一個引數自訂此閾值:
// 確保密碼在相同資料外洩中出現少於 3 次...
Password::min(8)->uncompromised(3);
當然,您可以將上述範例中的所有方法鏈接在一起:
Password::min(8)
->letters()
->mixedCase()
->numbers()
->symbols()
->uncompromised()
您可能會發現在應用程式的單一位置指定密碼的預設驗證規則很方便。您可以使用 Password::defaults
方法輕鬆實現這一點,該方法接受一個閉包。傳遞給 defaults
方法的閉包應返回密碼規則的預設配置。通常,defaults
規則應在應用程式的服務提供者的 boot
方法內調用:
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.");
}
},
],
]);
預設情況下,當要驗證的屬性不存在或包含空字串時,將不運行正常的驗證規則,包括自定義規則。例如,unique
規則不會針對空字串運行:
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]
"隱式"規則僅 暗示 屬性是必需的。實際上是否使缺少或空屬性無效取決於您。