表單驗證
使用閉包
快速驗證
要了解 Laravel 強大的驗證功能,讓我們看一個驗證表單並將錯誤訊息顯示回給使用者的完整範例。
定義路由
#首先,讓我們假設在routes/web.php
文件中定義了下面這些路由:
Route::get('post/create', 'PostController@create'); Route::post('post', 'PostController@store');
顯然,GET
路由會顯示一個供用戶創建一個新的博客帖子的表單,而POST 路由會將新的博客文章存儲在數據庫中。
# 建立路由器
##下面讓我們一起來看看處理這些路由的控制器,store
方法暫時留空。
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class PostController extends Controller{ /** * 显示创建博客文章的表单。 * * @return Response */ public function create() { return view('post.create'); } /** * 保存一篇新的博客文章。 * * @param Request $request * @return Response */ public function store(Request $request) { // 验证并存储博客文章... } }
編寫驗證器邏輯
現在我們開始在store
# 方法中寫邏輯來驗證新的部落格文章。為此,我們將使用 Illuminate\Http\Request
物件提供的 validate
方法 。如果驗證通過,程式碼就可以正常的運行。如果驗證失敗,則會拋出異常,並自動將對應的錯誤回應傳回給使用者。在典型的 HTTP 請求的情況下,會產生一個重新導向回應,而對於 AJAX 請求則會傳送 JSON 回應。
讓我們接著回到store
方法來深入理解validate
方法:
/** * 保存一篇新的博客文章。 * * @param Request $request * @return Response */ public function store(Request $request){ $validatedData = $request->validate([ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]); // 博客文章验证通过 }
如你所見,我們將所需的驗證規則傳遞至validate
方法中。另外再提醒一次,如果驗證失敗,會自動產生一個對應的回應。如果驗證通過,那麼我們的控制器將會繼續正常運作。
首次驗證失敗後停止執行
如果你希望在某個屬性第一次驗證失敗後停止執行驗證規則,你需要附加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', ]);#
顯示驗證錯誤訊息
如果傳入的請求參數未通過給定的驗證規則呢?如同前面所提到的,Laravel 會自動把使用者重新導向到之前的位置。另外,所有的驗證錯誤訊息會被自動 儲存到 session
中。
重申一次,我們不必在 GET
路由中將錯誤訊息明確綁定到視圖。因為 Lavarel 會檢查在 Session 資料中的錯誤訊息,並自動將其綁定到視圖(如果這個視圖檔案存在)。而其中的變數 $errors
是 Illuminate\Support\MessageBag
的一個實例。要獲取關於這個對象的更多信息,請 查閱這個文檔 。
{tip}
$errors
變數被Web
# 中間件群組提供的Illuminate\View\Middleware\ShareErrorsFromSession
中介軟體綁定定到視圖中。 當這個中間件被應用後,在你的視圖中就可以獲取到$error
變數 , 可以使一直假定$errors
變數存在並且可以安全地使用。
在上面的範例中,當驗證失敗的時候,使用者將會被重定向到控制器的create
方法,使我們能在視圖中顯示錯誤訊息:
<!-- /resources/views/post/create.blade.php --> <h1>创建文章</h1> @if ($errors->any()) <div class="alert alert-danger"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <!-- 创建文章表单 -->
關於可選欄位的注意事項
預設情況下,在Laravel 應用的全域中間件堆疊App\Http\Kernel
類別中包含了TrimStrings
和ConvertEmptyStringsToNull
中介軟體。因此,如果你不希望驗證程式將null
值視為無效的話,那就需要將「可選」的請求欄位標記為nullable
,舉個例子:
$request->validate([ 'title' => 'required|unique:posts|max:255', 'body' => 'required', 'publish_at' => 'nullable|date', ]);
在這個例子裡,我們指定publish_at
欄位可以是null
或是一個有效的日期格式。如果 nullable
的修飾詞沒有被加入到規則定義中,驗證器會認為 null
是一個無效的日期格式。
AJAX 請求& 驗證
在這個例子中,我們使用傳統的表單將資料傳送到應用程式。但在實際情況中,許多程式會使用 AJAX 來發送請求。當我們對 AJAX 的請求中使用 validate
方法時,Laravel 並不會產生一個重定向回應,而是會產生一個包含所有驗證錯誤訊息的 JSON 回應。這個 JSON 回應會包含一個 HTTP 狀態碼 422 被傳送出去。
#驗證表單請求
#建立表單請求驗證
面對更複雜的驗證情境中,你可以建立一個「表單請求」來處理更複雜的邏輯。表單請求是包含驗證邏輯的自訂請求類別。可使用 Artisan 指令 make:request
來建立表單請求類別:
php artisan make:request StoreBlogPost
新產生的類別保存在 app/Http/Requests
目錄下。如果這個目錄不存在,執行 make:request
指令時它會被建立出來。讓我們加入一些驗證規則到 rules
方法中:
/** * 获取适用于请求的验证规则。 * * @return array */ public function rules(){ return [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]; }
#{tip} 你可以向
rules
方法傳入所需的任何依賴項。他們會自動被 Laravel 提供的 服務容器 自動解析。
驗證規則是如何運作的呢?你所需要做的就是在控制器方法中類型提示傳入的請求。在呼叫控制器方法之前驗證傳入的表單請求,這表示你不需要在控制器中寫任何驗證邏輯:
/** * 存储传入的博客文章。 * * @param StoreBlogPost $request * @return Response */ public function store(StoreBlogPost $request){ // 传入的请求通过验证... // 获取通过验证的数据... $validated = $request->validated(); }
如果驗證失敗,就會產生一個讓使用者回到先前的位置的重定向響應。這些錯誤也會被閃存到 session
中,以便這些錯誤都可以在頁面中顯示出來。如果傳入的請求是 AJAX,則會向使用者傳回具有 422 個狀態碼和驗證錯誤訊息的 JSON 資料的 HTTP 回應。
新增表單請求後鉤子
如果你想在表單要求「之後」新增鉤子,可以使用 withValidator
方法。這個方法接收一個完整的驗證建構器,允許你在驗證結果返回之前呼叫任何方法:
/** * 配置验证器实例。 * * @param \Illuminate\Validation\Validator $validator * @return void */ public function withValidator($validator){ $validator->after(function ($validator) { if ($this->somethingElseIsInvalid()) { $validator->errors()->add('field', 'Something is wrong with this field!'); } }); }
表單請求授權驗證
表單請求類別內也包含了authorize
方法。在這個方法中,你可以檢查經過身份驗證的使用者確定是否具有更新給定資源的權限。比方說,你可以判斷使用者是否擁有更新文章評論的權限:
/** * 判断用户是否有权限做出此请求。 * * @return bool */ public function authorize(){ $comment = Comment::find($this->route('comment')); return $comment && $this->user()->can('update', $comment); }
由於所有的表單請求都是繼承了Laravel 中的請求基類,所以我們可以使用user
方法去取得目前認證登入的使用者。同時請注意上述範例中對 route
方法的呼叫。這個方法允許你在被呼叫的路由上取得其定義的URI 參數,譬如下面例子中的{comment}
參數:
Route::post('comment/{comment}');
如果authorize
方法返回false
,則會自動傳回包含403 狀態碼的HTTP 回應,也不會執行控制器的方法。
如果你打算在應用程式的其它部分處理授權邏輯,只需從authorize
方法返回true
:
/** * 判断用户是否有权限进行此请求。 * * @return bool */ public function authorize(){ return true; }
##{ tip} 你可以向authorize
方法傳入所需的任何依賴項。他們會自動被 Laravel 提供的 服務容器 自動解析。
自訂錯誤訊息
你可以透過重寫表單請求的 messages
方法來自訂錯誤訊息。此方法應傳回屬性/ 規則對陣列及其對應錯誤訊息:
/** * 获取已定义验证规则的错误消息。 * * @return array */ public function messages(){ return [ 'title.required' => 'A title is required', 'body.required' => 'A message is required', ]; }
#自訂驗證屬性
如果你希望將驗證訊息的:attribute
部分替換為自訂屬性名稱,則可以重寫attributes
方法來指定自訂名稱。此方法應傳回屬性/ 名稱對的陣列:
/** * 获取验证错误的自定义属性。 * * @return array */ public function attributes(){ return [ 'email' => 'email address', ]; }
#手動建立驗證器
如果你不想在在請求上使用validate
方法,你可以透過Validator
facade 手動建立一個驗證器範例。
用Validator
facade 上的make
方法建立一個驗證器範例:
<?php namespace App\Http\Controllers;use Validator; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class PostController extends Controller{ /** * 保存一篇新的博客文章。 * * @param Request $request * @return Response */ public function store(Request $request) { $validator = Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]); if ($validator->fails()) { return redirect('post/create') ->withErrors($validator) ->withInput(); } // Store the blog post... } }
傳給make
方法的第一個參數是需要驗證的數據。第二個參數則是該資料的驗證規則。
如果驗證失敗,則可以使用 withErrors
方法把錯誤訊息閃存到 Session 。使用這個方法進行重定向後, $errors
變數會自動和視圖共享,你可以把這些訊息顯示給使用者。 withErrors
方法接收驗證器、MessageBag
或 PHP Array
。
自動重定向
#如果你想手動建立驗證器實例,又想使用validates
方法提供的自動重定向,那麼你可以在現有的驗證器範例上呼叫validate
方法。如果驗證失敗,使用者將會自動重定向。在 AJAX 請求中,則會傳回 JSON 格式的回應。
Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ])->validate();
命名錯誤包
如果你一個頁面中有多個表單,你可以透過命名錯誤包來檢索特定表單的錯誤訊息。只要給withErrors
方法傳遞一個名字作為第二個參數
return redirect('register') ->withErrors($validator, 'login');
然後你就可以從$errors
變數中取得指定表單的錯誤訊息:
{{ $errors->login->first('email') }}
驗證後鉤子
驗證器也允許你添加在驗證成功之後允許的回調函數,以便你進行下一步的驗證,甚至在訊息集合中添加更多的錯誤訊息。使用它只需在驗證實例上使用 after
方法:
$validator = Validator::make(...);$validator->after(function ($validator) { if ($this->somethingElseIsInvalid()) { $validator->errors()->add('field', 'Something is wrong with this field!'); } }); if ($validator->fails()) { // }#
處理錯誤訊息
在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')) { // }自訂錯誤訊息如果有需要的話,你也可以使用自訂錯誤訊息取代預設值進行驗證。有幾種方法可以指定自訂訊息。首先,你可以將自訂訊息作為第三個參數傳遞給
Validator::make 方法:
$messages = [ 'required' => 'The :attribute field is required.', ]; $validator = Validator::make($input, $rules, $messages);在這個範例中,
:attribute 佔位符會被驗證欄位的實際名稱取代。除此之外,你還可以在驗證訊息中使用其它佔位符。例如:
$messages = [ 'same'=> 'The :attribute and :other must match.', 'size'=> 'The :attribute must be exactly :size.', 'between' => 'The :attribute value :input is not between :min - :max.', 'in'=> 'The :attribute must be one of the following types: :values', ];為給定屬性指定自訂訊息有時候你可能只想為特定的欄位自訂錯誤訊息。只需在屬性名稱後面使用「點」語法來指定驗證的規則即可:
$messages = [ 'email.required' => 'We need to know your e-mail address!', ];在語言檔案中指定自定義訊息在大多數情況下,您可能會在語言檔案中指定自訂訊息,而不是直接將它們傳遞給
Validator。為此,需要把你的訊息放在
resources/lang/xx/validation.php 語言檔案內的
custom 陣列中。
'custom' => [ 'email' => [ 'required' => 'We need to know your e-mail address!', ], ],在語言檔案中指定自訂屬性如果你希望將驗證訊息的
:attribute 佔位符替換為自訂屬性名稱,你可以在
resources/lang/xx/validation.php 語言檔案的
attributes 陣列中指定自訂名稱:
'attributes' => [ 'email' => 'email address', ],
在語言檔案中指定自訂值
有時可能需要將驗證訊息的 :value
佔位符替換為值的自訂文字。例如,如果payment_type
的值為cc
,使用下列驗證規則,則該規則指定需要信用卡號:
$request->validate([ 'credit_card_number' => 'required_if:payment_type,cc' ]);
如果此驗證規則失敗,則會產生下列錯誤訊息:
当payment type为cc时,credit card number 不能为空。
您可以透過定義values
數組,在validation
語言檔案中指定自訂值表示,而不是顯示cc
作為支付類型值:
'values' => [ 'payment_type' => [ 'cc' => '信用卡' ], ],
現在,如果驗證規則失敗,它將產生以下訊息:
当payment type 为信用卡时,credit card number不能为空。
可用的驗證規則
以下是所有可用的驗證規則及其功能的清單:
#已接受
#有效的URL
之後(日期)
##之後或等於(日期)
Alpha
# Alpha Dash ##字母數字
#陣列
之前(日期)
早於或等於(日期)
##介於
##布林型
#已確認
##日期##日期等於
##日期格式
不同
#數字
##之間的數字##尺寸(圖片檔案)
##獨特
#電子郵件
#存在(資料庫)
##檔案##已填入
大於
#大於或等於
圖像(檔案)
在
在陣列中
##整數
IP位址
JSON
##小於##小於或等於
#最大
# MIME 類型
按檔案副檔名列出的MIME 類型
Min
Not In
#Not Regex
##可空
##數字
目前
正規表示式
#必填##必填如果
##必填除非
##必填
#必填所有
必填無
#必填無全部
相同##尺寸
#開頭
##字串
##時區
唯一(資料庫)
# URL
# UUID
##
accepted
驗證欄位必須是 yes, on, 1,或 true。這在確認“服務條款”是否同意時相當有用。
active_url
#根據PHP 函數dns_get_record
,驗證欄位必須具有有效的A 或AAAA 記錄。
after:date
#驗證欄位必須是給定日期之後的值。日期值將傳遞到PHP 函數strtotime
:
'start_date' => 'required|date|after:tomorrow'
您可以指定另一個要與日期進行比較的字段,而不是傳遞要由strtotime
處理的日期字串:
'finish_date' => 'required|date|after:start_date'
after_or_equal:date
驗證欄位必須是給定日期之後或與此日期相同的值。更多信息,請參閱 after 規則。
alpha
#驗證欄位必須完全由字母構成。
alpha_dash
驗證欄位可能包含字母、數字,以及破折號 (-) 和底線 ( _ )。
alpha_num
#驗證欄位必須是完全是字母、數字。
array
#驗證的欄位必須是一個 PHP 陣列。
bail
#在第一次驗證失敗後停止執行驗證規則。
before:date
驗證欄位必須是在給定日期之前。這個日期值將會被傳遞給 PHP 的 strtotime
函數來計算。
before_or_equal:date
驗證欄位必須是在給定日期之前或與之相同的日期。這個日期值將會被傳遞給 PHP 的 strtotime
函數來計算。
between:min,max
驗證欄位的大小必須在給定的 min 和 max 之間。字串、數字、陣列和檔案的計算方式都使用 size
方法。
boolean
驗證的欄位必須可以轉換為 Boolean 類型。可接受的輸入為true
, false
, 1
, 0
, "1"
, 和"0"
。
confirmed
#驗證欄位必須有符合欄位 foo_confirmation
。例如,驗證欄位為 password
,輸入中必須存在與之相符的 password_confirmation
欄位。
date
#根據 PHP 函數 strtotime
,驗證欄位必須是有效的日期。
date_equals:date
驗證欄位必須等於給定日期。日期將傳遞到 PHP 函數 strtotime
。
date_format:format
驗證欄位必須符合給定的日期格式。當驗證某個欄位的時候,你應該 只使用 date
或 date_format
,而不是同時使用。
different:field
驗證欄位必須具有與field 不同的值。
digits:value
驗證欄位必須為numeric ,且必須具有_value_的確切長度。
digits_between:min,max
驗證的字段的長度必須在給定的 min 和 max 之間。
dimensions
驗證中的檔案必須是圖片,並且符合指定的規則約束:
'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\Validation\Rule; Validator::make($data, [ 'avatar' => [ 'required', Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2), ], ]);
distinct
#當驗證數組時,驗證欄位不得包含任何重複值。
'foo.*.id' => 'distinct'
驗證欄位必須為正確格式的電子郵件地址。
exists:table,column
驗證欄位必須存在於給定的資料庫表中。
Exists 規則基本用法
'state' => 'exists:states'
如果未指定 column
選項,則將使用欄位名稱。
指定自訂的表格欄位
'state' => 'exists:states,abbreviation'
有時,你可能需要指定要用於「exists」查詢的特定資料庫連線。你可以使用「點」語法將連接名稱新增至表名稱前來完成此操作:
'email' => 'exists:connection.staff,email'
如果您想要自訂驗證規則執行的查詢,您可以使用Rule
類別來流暢地定義規則。在下面的範例中,我們也以陣列的形式指定驗證規則,而不是使用|
字元來分隔它們:
use Illuminate\Validation\Rule; Validator::make($data, [ 'email' => [ 'required', Rule::exists('staff')->where(function ($query) { $query->where('account_id', 1); }), ], ]);##file驗證的欄位必須是成功上傳的檔案。 filled#在驗證欄位存在時不得為空。 gt:
field
驗證欄位必須大於給定的field 。兩個欄位必須是相同的類型。字串、數字、陣列和檔案都使用 size 進行相同的評估。
field
驗證欄位必須大於或等於給定的field。兩個欄位必須是相同的類型。字串、數字、陣列和檔案都使用 size 進行相同的評估。
foo,bar,...
#驗證欄位必須包含在給定的值清單中。由於此規則通常要求您implode 數組,因此可以使用
Rule :: in 方法流暢地建構規則:
use Illuminate\Validation\Rule; Validator::make($data, [ 'zones' => [ 'required', Rule::in(['first-zone', 'second-zone']), ], ]);in_array:
anotherfield
驗證的欄位必須存在於另一個欄位anotherfield 的值中。
integer#驗證的欄位必須是整數。 ip已驗證的欄位必須是 IP 位址。 ipv4驗證的欄位必須是 IPv4 位址。 ipv6驗證的欄位必須是 IPv6 位址。json
驗證的欄位必須是有效的 JSON 字串。
lt:field
驗證中的欄位必須小於給定的欄位。這兩個字段必須是相同的類型。字串、數值、陣列和檔案大小的計算方式與 size
方法進行評估。
lte:field
驗證中的欄位必須小於或等於給定的字段。這兩個字段必須是相同的類型。字串、數值、陣列和檔案大小的計算方式與 size
方法進行評估。
max:value
驗證中的欄位必須小於或等於 value。字串、數字、陣列或是檔案大小的計算方式都用 size
方法進行評估。
mimetypes:text/plain,...
##驗證的檔案必須與給定MIME 類型之一符合:'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'要確定上傳檔案的MIME 類型,會讀取檔案的內容來判斷MIME 類型,這可能與客戶端提供的MIME 類型不同。 mimes:
foo,bar,...
#驗證的檔案必須具有與列出的其中一個副檔名相對應的MIME 類型。 MIME 規則基本用法'photo' => 'mimes:jpeg,bmp,png'
即使你可能只需要驗證指定副檔名,但此規則實際上會驗證檔案的MIME 類型,其透過讀取文件的內容以猜測它的MIME 類型。 可以在以下連結中找到完整的MIME 類型清單及其對應的副檔名:https://svn.apache.org/repos/asf/httpd/htt...
value
驗證中的欄位必須具有最小值。字串、數字、陣列或是檔案大小的計算方式都用 not_in:foo,bar,...
驗證的欄位不能包含在給定的值清單中。Rule::notIn 方法可以用來建構規則:
use Illuminate\Validation\Rule; Validator::make($data, [ 'toppings' => [ 'required', Rule::notIn(['sprinkles', 'cherries']), ], ]);
not_regex:pattern
驗證中的欄位必須與給定的正規表示式不符。
在內部,此規則使用 PHP preg_match
函數。輸入的值應遵循 preg_match
函數所需的相同格式,因此也包含有效的分隔符號。例如:'email' => 'not_regex:/^. $/i'
。
注意: 當使用regex
/not_regex
模式時,可能需要在陣列中指定規則,而不是使用管道分隔符,尤其是在正規表示式包含管道字元的情況下。
nullable
#驗證的欄位可以為 null
。這在驗證基本資料類型時特別有用,例如可以包含空值的字串和整數。
numeric
#驗證的欄位必須是數字。
#present
#驗證的欄位必須存在於輸入資料中,但可以為空。
regex:pattern
已驗證的欄位必須與給定的正規表示式匹配。
在內部,此規則使用 PHP preg_match
函數。輸入的值應遵循 preg_match
函數所需的相同格式,因此也包含有效的分隔符號。例如:'email' => 'regex:/^. @. $/i'
。
注意: 當使用regex
規則時,你必須使用數組,而不是使用|
分隔符,特別是如果正規表示式包含|
字元。
required
#驗證的欄位必須存在於輸入資料中,而不是空。如果滿足下列條件之一,則欄位被視為「空」:
- 值為
null
。 - 值為空字串。
- 值為空數組或空
Countable
物件。 - 值為無路徑的上傳檔案。
#required_if:anotherfield,value,.. .
如果anotherfield 欄位等於任一value,驗證的欄位必須出現且不為空。
如果你想為 required_if
規則建構一個更複雜的條件,你可以使用 Rule::requiredIf
方法。此方法接受布林值或閉包。當傳遞一個閉包時,應傳回true
或false
以確認是否需要驗證欄位:
use Illuminate\Validation\Rule; Validator::make($request->all(), [ 'role_id' => Rule::requiredIf($request->user()->is_admin),]); Validator::make($request->all(), [ 'role_id' => Rule::requiredIf(function () use ($request) { return $request->user()->is_admin; }), ]);
required_unless:anotherfield,value,...
如果anotherfield 欄位不等於任一value ,驗證的欄位必須出現且不為空。
required_with:foo,bar,...
只有在其他任一指定欄位出現時,驗證的欄位才必須出現且不為空。
required_with_all:foo,bar,...
只有在其他指定欄位全部出現時,驗證的欄位才必須出現且不為空。
required_without:foo,bar,...
只在其他指定任一欄位不出現時,驗證的欄位才必須出現且不為空。
required_without_all:foo,bar,...
#只有在其他指定欄位全部不出現時,驗證的欄位才必須出現且不為空。
same:field
驗證的欄位必須與給定欄位相符。
size:value
已驗證的欄位必須具有與給定值相符的大小。對於字串,value 對應字元數。對於數字,value 對應給定的整數值。對於數組,size 對應數組的 count
值。對於文件,size 對應文件大小(單位 kb)。
starts_with:foo,bar,...
驗證的欄位必須以給定值之一開頭。
string
#驗證的欄位必須是字串。如果允許這個欄位為 null
,需要給這個欄位指派 nullable
規則。
timezone
#已驗證的欄位必須是基於PHP 函數 timezone_identifiers_list
的有效時區標識。
unique:table,column,except,idColumn
驗證的欄位在給定的資料庫表中必須是唯一的。如果沒有指定 column
,將會使用欄位本身的名稱。
指定自訂欄位
'email' => 'unique:users,email_address'
自訂資料庫連線
有時,你可能需要為驗證程式建立的資料庫查詢設定自訂連線。在上面的範例中,將 unique:users
設定為驗證規則,等於使用預設資料庫連線來查詢資料庫。如果要對其進行修改,請使用「點」方法指定連線和表名:
'email' => 'unique:connection.users,email_address'
強迫Unique 規則忽略指定ID :
有時,你可能想要在進行欄位唯一性驗證時忽略指定ID 。例如, 在「更新個人資料」頁面會包含使用者名稱、信箱和地點。這時你會想要驗證更新的 E-mail 值是否唯一。如果使用者僅更改了使用者名字段而沒有改 E-mail 字段,就不需要拋出驗證錯誤,因為此使用者已經是這個 E-mail 的擁有者了。
使用 Rule
類別定義規則來指示驗證器忽略使用者的 ID。這個範例中透過陣列來指定驗證規則,而不是使用| 字元來分隔:
use Illuminate\Validation\Rule; Validator::make($data, [ 'email' => [ 'required', Rule::unique('users')->ignore($user->id), ], ]);
#{tip} 您永遠不應將任何使用者控制的請求輸入傳遞給
ignore
方法。相反,您應該只從 Eloquent 模型實例傳遞系統產生的唯一 ID,例如自增 ID 或 UUID。否則,您的應用程式將容易受到 SQL 注入攻擊。
你可以傳遞整個模型實例,而不是將模型鍵的值傳遞給 ignore
方法。 Laravel 將自動從模型中提取主鍵:
Rule::unique('users')->ignore($user)
如果你的資料表使用的主鍵名稱不是id
,那就在呼叫ignore
方法時指定欄位的名稱:
Rule::unique('users')->ignore($user->id, 'user_id')
預設情況下,unique
規則將檢查與要驗證的屬性的名稱相符的資料列是否唯一。但是你可以將不同的列名稱作為第二個參數傳遞給unique
方法:
Rule::unique('users', 'email_address')->ignore($user->id),
增加額外的Where 語句:
##你也可以透過where 方法指定額外的查詢條件。例如, 我們新增
account_id 為
1 的限制條件:
'email' => Rule::unique('users')->where(function ($query) { return $query->where('account_id', 1); })
#驗證的欄位必須是有效的URL。
#驗證欄位必須是有效的RFC 4122(版本1,3,4 或5)通用唯一識別碼(UUID)。
存在時則驗證
在某些情況下,只有在該欄位存在於陣列中時, 才可以對欄位執行驗證檢查。可透過增加sometimes
到規則清單來實現:
$v = Validator::make($data, [ 'email' => 'sometimes|required|email',]);
在上面的範例中,email
欄位只有在 $data
陣列中存在才會被驗證。
{tip} 如果你嘗試驗證應該始終存在但可能為空的字段,請查閱可選字段的注意事項
複雜的條件驗證
有時候你可能需要增加基於更複雜的條件邏輯的驗證規則。例如,你可以希望某個指定欄位在另一個欄位的值超過 100 時才為必填。或當某個指定欄位存在時,另外兩個欄位才能具有給定的值。增加這樣的驗證條件並不難。首先,使用 靜態規則 建立一個 Validator
實例:
$v = Validator::make($data, [ 'email' => 'required|email', 'games' => 'required|numeric', ]);
假設我們有一個專為遊戲收藏家設計的網頁應用程式。如果遊戲收藏家收藏超過一百款遊戲,我們會希望他們來說明為什麼他們會有這麼多遊戲。比如說他們有可能經營了一家遊戲分銷商店,或者只是為了享受收集的樂趣。為了在特定條件下加入此驗證需求,可以在 Validator
實例中使用 sometimes
方法。
$v->sometimes('reason', 'required|max:500', function ($input) { return $input->games >= 100; });
傳入 sometimes
方法的第一個參數是要用來驗證的欄位名稱。第二個參數是我們想要使用的驗證規則。 閉包
作為第三個參數傳入,如果其傳回 true
, 則額外的規則就會被加入。這個方法可以輕鬆地建立複雜的條件驗證。你甚至可以一次對多個欄位增加條件驗證:
$v->sometimes(['reason', 'cost'], 'required', function ($input) { return $input->games >= 100; });
{tip} 傳入
閉包
的$input
參數是Illuminate \Support\Fluent
的一個實例,可用來存取你的輸入或檔案物件。
驗證陣列
驗證表單的輸入為陣列的欄位也不難。你可以使用 “點”方法來驗證數組中的屬性。例如,如果傳入的 HTTP 請求中包含 photos[profile]
字段, 可以如下驗證:
$validator = Validator::make($request->all(), [ 'photos.profile' => 'required|image', ]);
你也可以驗證數組中的每個元素。例如,要驗證指定數組輸入字段中的每一個email 是唯一的,可以這麼做:
$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 e-mail address', ] ],
#自訂驗證規則
####################### ##########使用規則物件
Laravel 提供了許多有用的驗證規則;同時也支援自訂規則。註冊自訂驗證規則的方法之一,就是使用規則物件。可以使用 Artisan 指令 make:rule
來產生新的規則物件。接下來,讓我們用這個命令產生一個驗證字串是大寫的規則。 Laravel 會將新的規則存放在 app/Rules
目錄中:
php artisan make:rule Uppercase
一旦建立了規則,我們就可以定義它的行為。規則物件包含兩個方法: passes
和 message
。 passes
方法接收屬性值和名稱,並根據屬性值是否符合規則而傳回 true
或 false
。 message
方法應傳回驗證失敗時應使用的驗證錯誤訊息:
<?php namespace App\Rules; use Illuminate\Contracts\Validation\Rule; class Uppercase implements Rule{ /** * 判断验证规则是否通过。 * * @param string $attribute * @param mixed $value * @return bool */ public function passes($attribute, $value) { return strtoupper($value) === $value; } /** * 获取验证错误消息。 * * @return string */ public function message() { return 'The :attribute must be uppercase.'; } }
當然, 如果你希望從翻譯檔案中傳回錯誤訊息,你可以從message
方法中呼叫輔助函數trans
:
/** * 获取验证错误消息。 * * @return string */ public function message(){ return trans('validation.uppercase'); }
一旦規則物件被定義好後,你可以透過將規則物件的實例和其他驗證規則一起傳遞給驗證器:
use App\Rules\Uppercase;$request->validate([ 'name' => ['required', 'string', new Uppercase], ]);
使用閉包
如果你在應用程式中只需要一次自訂規則的功能,則可以使用閉包而不是規則物件。閉包接收屬性的名稱,屬性的值如果驗證失敗則應該使用回呼中的$fail
:
$validator = Validator::make($request->all(), [ 'title' => [ 'required', 'max:255', function ($attribute, $value, $fail) { if ($value === 'foo') { $fail($attribute.' is invalid.'); } }, ], ]);##使用擴充功能註冊自訂的驗證規則的另一種方法是使用
Validator facade 中的
extend 方法。讓我們在服務容器中使用這個方法來註冊自訂驗證規則:
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Validator; class AppServiceProvider extends ServiceProvider{ /** * 引导任何应用程序。 * * @return void */ public function boot() { Validator::extend('foo', function ($attribute, $value, $parameters, $validator) { return $value == 'foo'; }); } /** * 注册服务提供器。 * * @return void */ public function register() { // } }自訂的驗證閉包接收四個參數:要被驗證的屬性名稱
$attribute、屬性的值
$value、傳入驗證規則的參數陣列
$parameters 、以及
Validator 實列。
extend 方法中:
Validator::extend('foo', 'FooValidator@validate');定義錯誤訊息你還需要為自訂規則定義錯誤訊息。你可以使用內聯自訂訊息數組或在驗證語言檔案中新增條目來實現這項功能。訊息應該被放到數組的第一位,而不是在只用於存放屬性指定錯誤訊息的
custom 數組內:
"foo" => "Your input was invalid!", "accepted" => "The :attribute must be accepted.", // 其余的验证错误消息...當建立一個自訂驗證規則時,你可能有時候需要為錯誤訊息定義自訂佔位符。可以透過建立自訂驗證器然後呼叫
Validator 門面上的
replacer 方法。你可以在 服務容器 的
boot 方法中執行以下操作:
/** * 启动应用程序。 * * @return void */ public function boot(){ Validator::extend(...); Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) { return str_replace(...); }); }
隱含擴充
預設情況下, 當要驗證的屬性不存在或包含由 required
規則定義的空值時,那麼正常的驗證規則,包括自訂擴充功能將不會執行。例如,unique
規則將不會檢驗null
值:
$rules = ['name' => 'unique']; $input = ['name' => null]; Validator::make($input, $rules)->passes(); // true
如果要求即使為空時也要驗證屬性,則必須要暗示屬性是必須的。要建立這樣一個「隱式」擴展, 可以使用Validator::extendImplicit()
方法:
Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) { return $value == 'foo'; });
{note} “隱式”擴充只暗示該屬性是必需的。至於它到底是缺失的還是空值這取決於你。