Laravel 通過 Validation
類讓您可以簡單、方便的驗證數(shù)據(jù)正確性及查看相應(yīng)的驗證錯誤信息。
$validator = Validator::make( ['name' => 'Dayle'], ['name' => 'required|min:5']);
上文中傳遞給 make
這個方法的第一個參數(shù)用來設(shè)定所需要被驗證的數(shù)據(jù)名稱,第二個參數(shù)設(shè)定該數(shù)據(jù)可被接受的規(guī)則。
多個驗證規(guī)則可以使用"|"符號分隔,或是單一數(shù)組作為單獨的元素分隔。
$validator = Validator::make( ['name' => 'Dayle'], ['name' => ['required', 'min:5']]);
$validator = Validator::make( [ 'name' => 'Dayle', 'password' => 'lamepassword', 'email' => 'email@example.com' ], [ 'name' => 'required', 'password' => 'required|min:8', 'email' => 'required|email|unique:users' ]);
當(dāng)一個 Validator
實例被建立后,fails
(或 passes
) 這兩個方法就可以在驗證時使用,如下:
if ($validator->fails()){ // The given data did not pass validation}
假如驗證失敗,您可以從驗證器中接收錯誤信息。
$messages = $validator->messages();
您可能不需要錯誤信息,只想取得無法通過驗證的規(guī)則,您可以使用 failed
方法:
$failed = $validator->failed();
Validator
類提供了一些規(guī)則用來驗證文件,例如 size
, mimes
等等。當(dāng)需要驗證文件時,您僅需將它們和您其他的數(shù)據(jù)一同送給驗證器即可。
驗證器也允許你在完成驗證后增加回調(diào)函數(shù)。這也允許你可以進(jìn)行更進(jìn)一步的驗證,甚至在消息集合中增加更多的錯誤信息。我們在驗證器實例中使用 after
方法來作為開始:
$validator = Validator::make(...);$validator->after(function($validator){ if ($this->somethingElseIsInvalid()) { $validator->errors()->add('field', 'Something is wrong with this field!'); }});if ($validator->fails()){ //}
您可以根據(jù)需要為驗證器增加任意的 after
回調(diào)函數(shù)。
當(dāng)然,如果每一次需要驗證的時候都手動的建立并且驗證 Validator
實例會非常的麻煩。不用擔(dān)心,你有其他的選擇!Laravel自帶的 App\Http\Controllers\Controller
基類使用了一個 ValidatesRequests
的 trait。這個 trait 提供了一個單一的、便捷的方法來驗證 HTTP 請求。代碼如下:
/** * Store the incoming blog post. * * @param Request $request * @return Response */public function store(Request $request){ $this->validate($request, [ 'title' => 'required|unique|max:255', 'body' => 'required', ]); //}
如果驗證通過了,你的代碼會正常繼續(xù)執(zhí)行。如果驗證失敗,那么會拋出一個 Illuminate\Contracts\Validation\ValidationException
異常。這個異常會被自動捕獲,然后重定向至用戶上一個頁面。而錯誤信息甚至已經(jīng)存儲至 session 中!
如果收到的是一個 AJAX 請求,那么不會生成一個重定向。相反的,一個帶有 422 狀態(tài)碼的 HTTP 響應(yīng)會被返回給瀏覽器,包含了一個含有錯誤信息的 JSON 對象。
比如,如下是手動創(chuàng)建驗證的等效寫法:
/** * Store the incoming blog post. * * @param Request $request * @return Response */public function store(Request $request){ $v = Validator::make($request->all(), [ 'title' => 'required|unique|max:255', 'body' => 'required', ]); if ($v->fails()) { return redirect()->back()->withErrors($v->errors()); } //}
如果你想要自定義驗證失敗后已經(jīng)閃存至 session 的錯誤消息格式,可以通過覆蓋基類控制器的 formatValidationErrors
。不要忘記在文件頂部引入 Illuminate\Validation\Validator
類。
/** * {@inheritdoc} */protected function formatValidationErrors(Validator $validator){ return $validator->errors()->all();}
如果是更復(fù)雜的驗證場景,你可能需要創(chuàng)建一個"表單請求"。表單請求是一個自定義的請求類包含了一些驗證的邏輯。你可以通過 Artisan 的命令行 make:request
來創(chuàng)建一個表單請求類。
php artisan make:request StoreBlogPostRequest
生成的類會放置在 app/Http/Requests
目錄中。 我們在 rules
方法中增加一些驗證規(guī)則:
/** * Get the validation rules that apply to the request. * * @return array */public function rules(){ return [ 'title' => 'required|unique|max:255', 'body' => 'required', ];}
那么,我們的驗證規(guī)則是怎么執(zhí)行的呢?你所要做的只是在控制器方法中加上請求的類型提示:
/** * Store the incoming blog post. * * @param StoreBlogPostRequest $request * @return Response */public function store(StoreBlogPostRequest $request){ // The incoming request is valid...}
當(dāng)控制器的方法被調(diào)用前,表單請求已經(jīng)驗證了,意味著你不需要在控制器里寫任何的驗證邏輯。它已經(jīng)驗證完了!
如果驗證失敗,用戶會收到一個重定向請求至上一個頁面。而錯誤信息也已經(jīng)存儲至 session 中方便視圖展示。如果收到的是一個 AJAX 請求,一個帶有 422 狀態(tài)碼的 HTTP 響應(yīng)會被返回給瀏覽器,包含了一個含有錯誤信息的 JSON 對象。
表單請求類同樣也包含了一個 authorize
方法。通過這個方法,你可以檢查認(rèn)證后的用戶是否有權(quán)限去更新一個已有的資源。比如,如果一個用戶嘗試去更新一篇博客的評論,他是否真的發(fā)布過這個評論?舉個例子:
/** * Determine if the user is authorized to make this request. * * @return bool */public function authorize(){ $commentId = $this->route('comment'); return Comment::where('id', $commentId) ->where('user_id', Auth::id())->exists();}
注意上面例子中調(diào)用的 route
方法。這個方法允許你獲取調(diào)用路由中定義的 URI 參數(shù),比如下面例子中的 {comment}
參數(shù):
Route::post('comment/{comment}');
如果 authorize
方法返回 false
, 一個帶有 403 狀態(tài)碼的 HTTP 響應(yīng)會被返回給瀏覽器,你控制器的方法也不會被執(zhí)行。
如果你打算在應(yīng)用的其他地方做一些權(quán)限的邏輯,在 authorize
方法中返回 true
即可:
/** * Determine if the user is authorized to make this request. * * @return bool */public function authorize(){ return true;}
如果你想要自定義驗證失敗后已經(jīng)閃存至 session 的錯誤消息格式,可以通過覆蓋基類請求類(App\Http\Requests\Request
)的 formatErrors
。不要忘記在文件頂部引入 Illuminate\Validation\Validator
類:
/** * {@inheritdoc} */protected function formatErrors(Validator $validator){ return $validator->errors()->all();}
當(dāng)您調(diào)用一個 Validator
實例的 messages
方法后,您會得到一個命名為 MessageBag
的實例,該實例里有許多方便的方法能讓您取得相關(guān)的錯誤信息。
echo $messages->first('email');
foreach ($messages->get('email') as $message){ //}
foreach ($messages->all() as $message){ //}
if ($messages->has('email')){ //}
echo $messages->first('email', '<p>:message</p>');
注意: 默認(rèn)錯誤信息以 Bootstrap 兼容語法輸出。
foreach ($messages->all('<li>:message</li>') as $message){ //}
當(dāng)您開始進(jìn)行驗證數(shù)據(jù)時,您會需要一個簡易的方法去取得錯誤信息并返回到您的視圖中,在 Laravel 中您可以很方便的處理這些操作,您可以通過下面的路由例子來了解:
Route::get('register', function(){ return View::make('user.register');});Route::post('register', function(){ $rules = [...]; $validator = Validator::make(Input::all(), $rules); if ($validator->fails()) { return redirect('register')->withErrors($validator); }});
需要記住的是,當(dāng)驗證失敗后,我們會使用 withErrors
方法來將 Validator
實例進(jìn)行重定向。這個方法會將錯誤信息存入 session 中,這樣才能在下個請求中被使用。
然而,我們并不需要特別去將錯誤信息綁定在我們 GET 路由的視圖中。因為 Laravel 會確認(rèn)在 Session 數(shù)據(jù)中檢查是否有錯誤信息,并且自動將它們綁定至視圖中。所以請注意,$errors
變量存在于所有的視圖中,所有的請求里,讓您可以直接假設(shè) $errors
變量已被定義且可以安全地使用。$errors
變量是 MessageBag
類的一個實例。
所以,在重定向之后,您可以自然的在視圖中使用 $errors
變量:
<?php echo $errors->first('email'); ?>
假如您在一個頁面中有許多的表單,您可能希望為錯誤命名一個 MessageBag
。 這樣能方便您針對特定的表單查看其錯誤信息, 我們只要簡單的在 withErrors
的第二個參數(shù)設(shè)定名稱即可:
return redirect('register')->withErrors($validator, 'login');
接著您可以從一個 $errors
變量中取得已命名的 MessageBag
實例:
<?php echo $errors->login->first('email'); ?>
以下是現(xiàn)有可用的驗證規(guī)則清單與他們的函數(shù)名稱:
字段值為 yes, on, 或是 1 時,驗證才會通過。這在確認(rèn)"服務(wù)條款"是否同意時很有用。
字段值通過 PHP 函數(shù) checkdnsrr
來驗證是否為一個有效的網(wǎng)址。
驗證字段是否是在指定日期之后。這個日期將會使用 PHP strtotime
函數(shù)驗證。
字段僅全數(shù)為字母字串時通過驗證。
字段值僅允許字母、數(shù)字、破折號(-)以及底線(_)
字段值僅允許字母、數(shù)字
字段值僅允許為數(shù)組
驗證字段是否是在指定日期之前。這個日期將會使用 PHP strtotime
函數(shù)驗證。
字段值需介于指定的 min 和 max 值之間。字串、數(shù)值或是文件都是用同樣的方式來進(jìn)行驗證。
字段值需與對應(yīng)的字段值 foo_confirmation
相同。例如,如果驗證的字段是 password
,那對應(yīng)的字段 password_confirmation
就必須存在且與 password
字段相符。
字段值通過 PHP strtotime
函數(shù)驗證是否為一個合法的日期。
字段值通過 PHP date_parse_from_format
函數(shù)驗證符合 format 制定格式的日期是否為合法日期。
字段值需與指定的字段 field 值不同。
字段值需為數(shù)字且長度需為 value。
字段值需為數(shù)字,且長度需介于 min 與 max 之間。
字段必須可以轉(zhuǎn)換成布爾值,可接受的值為 true
, false
, 1
, 0
, "1"
, "0"
。
字段值需符合 email 格式。
字段值需與存在于數(shù)據(jù)庫 table 中的 column 字段值其一相同。
'state' => 'exists:states'
'state' => 'exists:states,abbreviation'
您可以指定更多條件且那些條件將會被新增至 "where" 查詢里:
'email' => 'exists:staff,email,account_id,1'/* 這個驗證規(guī)則為 email 需存在于 staff 這個數(shù)據(jù)庫表中 email 字段中且 account_id=1 */
通過NULL
搭配"where"的縮寫寫法去檢查數(shù)據(jù)庫的是否為NULL
'email' => 'exists:staff,email,deleted_at,NULL'
文件必需為圖片(jpeg, png, bmp, gif 或 svg)
字段值需符合事先給予的清單的其中一個值
字段值需為一個整數(shù)值
字段值需符合 IP 位址格式。
字段值需小于等于 value。字串、數(shù)字和文件則是判斷 size
大小。
文件的 MIME 類需在給定清單中的列表中才能通過驗證。
'photo' => 'mimes:jpeg,bmp,png'
字段值需大于等于 value。字串、數(shù)字和文件則是判斷 size
大小。
字段值不得為給定清單中其一。
字段值需為數(shù)字。
字段值需符合給定的正規(guī)表示式。
注意: 當(dāng)使用regex
模式時,您必須使用數(shù)組來取代"|"作為分隔,尤其是當(dāng)正規(guī)表示式中含有"|"字串。
字段值為必填。
字段值在 field 字段值為 value 時為必填。
字段值 僅在 任一指定字段有值情況下為必填。
字段值 僅在 所有指定字段皆有值情況下為必填。
字段值 僅在 任一指定字段沒有值情況下為必填。
字段值 僅在 所有指定字段皆沒有值情況下為必填。
字段值需與指定字段 field 等值。
字段值的尺寸需符合給定 value 值。對于字串來說,value 為需符合的字串長度。對于數(shù)字來說,value 為需符合的整數(shù)值。對于文件來說,value 為需符合的文件大小(單位 kb)。
必須是字符串類型。
字段值通過 PHP timezone_identifiers_list
函數(shù)來驗證是否為有效的時區(qū)。
字段值在給定的數(shù)據(jù)庫中需為唯一值。如果 column(字段)
選項沒有指定,將會使用字段名稱。
Occasionally, you may need to set a custom connection for database queries made by the Validator. As seen above, setting unique:users
as a validation rule will use the default database connection to query the database. To override
this, do the following:
$verifier = App::make('validation.presence');$verifier->setConnection('connectionName');$validator = Validator::make($input, [ 'name' => 'required', 'password' => 'required|min:8', 'email' => 'required|email|unique:users',]);$validator->setPresenceVerifier($verifier);
'email' => 'unique:users'
'email' => 'unique:users,email_address'
'email' => 'unique:users,email_address,10'
您也可以指定更多的條件式到 "where" 查詢語句中:
'email' => 'unique:users,email_address,NULL,id,account_id,1'
上述規(guī)則為只有 account_id
為 1
的數(shù)據(jù)列會做唯一規(guī)則的驗證。
字段值需符合 URL 的格式。
注意: 此函數(shù)會使用 PHP
filter_var
方法驗證。
某些情況下,您可能 只想 當(dāng)字段有值時,才進(jìn)行驗證。這時只要增加 sometimes
條件進(jìn)條件列表中,就可以快速達(dá)成:
$v = Validator::make($data, [ 'email' => 'sometimes|required|email',]);
在上述例子中,email
字段只會在當(dāng)其在 $data
數(shù)組中有值的情況下才會被驗證。
有時,您可以希望給指定字段在其他字段長度有超過 100 時才驗證是否為必填?;蛘吣M袃蓚€字段,當(dāng)其中一字段有值時,另一字段將會有一個默認(rèn)值。增加這樣的驗證條件并不復(fù)雜。首先,利用您尚未更動的 靜態(tài)規(guī)則 創(chuàng)建一個 Validator
實例:
$v = Validator::make($data, [ 'email' => 'required|email', 'games' => 'required|numeric',]);
假設(shè)我們的網(wǎng)頁應(yīng)用程序是專為游戲收藏家所設(shè)計。如果游戲收藏家收藏超過一百款游戲,我們希望他們說明為什么他們擁有這么多游戲。如,可能他們經(jīng)營一家二手游戲商店,或是他們可能只是享受收集的樂趣。有條件的加入此需求,我們可以在 Validator
實例中使用 sometimes
方法。
$v->sometimes('reason', 'required|max:500', function($input){ return $input->games >= 100;});
傳遞至 sometimes
方法的第一個參數(shù)是我們要條件式認(rèn)證的字段名稱。第二個參數(shù)是我們想加入驗證規(guī)則。 閉包(Closure) 作為第三個參數(shù)傳入,如果返回值為 true 那該規(guī)則就會被加入。這個方法可以輕而易舉的建立復(fù)雜的條件式驗證。您也可以一次對多個字段增加條件式驗證:
$v->sometimes(['reason', 'cost'], 'required', function($input){ return $input->games >= 100;});
注意:
注意: 傳遞至您的
Closure
的$input
參數(shù)為Illuminate\Support\Fluent
的實例且用來作為獲取您的輸入及文件的對象。
如果有需要,您可以設(shè)置自定義的錯誤信息取代默認(rèn)錯誤信息。這里有幾種方式可以設(shè)定自定義消息。
$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 must be 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!',];
某些狀況下,您可能希望在語言包文件中設(shè)定您的自定義消息,而非直接將他們傳遞給 Validator
。要達(dá)到這個目的,將您的信息增加至 resources/lang/xx/validation.php
文件的 custom
數(shù)組中。
'custom' => [ 'email' => [ 'required' => 'We need to know your e-mail address!', ],],
Laravel 提供了各種有用的驗證規(guī)則,但是,您可能希望可以設(shè)定自定義驗證規(guī)則。注冊生成自定義的驗證規(guī)則的方法之一就是使用 Validator::extend
方法:
Validator::extend('foo', function($attribute, $value, $parameters){ return $value == 'foo';});
自定義驗證器閉包接收三個參數(shù):要被驗證的 $attribute(屬性)
的名稱,屬性的值 $value
,傳遞至驗證規(guī)則的 $parameters
數(shù)組。
您同樣可以傳遞一個類和方法到 extend
方法中,取代原本的閉包:
Validator::extend('foo', 'FooValidator@validate');
注意,您同時需要為您的自定義規(guī)則制訂一個錯誤信息。您可以使用行內(nèi)自定義信息數(shù)組或是在認(rèn)證語言文件里新增。
除了使用閉包回調(diào)來擴展 Validator 外,您一樣可以直接擴展 Validator 類。您可以寫一個擴展自 Illuminate\Validation\Validator
的驗證器類。您也可以增加驗證方法到以 validate
為開頭的類中:
<?phpclass CustomValidator extends Illuminate\Validation\Validator { public function validateFoo($attribute, $value, $parameters) { return $value == 'foo'; }}
接下來,您需要注冊您自定義驗證器擴展:
Validator::resolver(function($translator, $data, $rules, $messages){ return new CustomValidator($translator, $data, $rules, $messages);});
當(dāng)創(chuàng)建自定義驗證規(guī)則時,您可能有時需要為錯誤信息定義自定義的占位符。您可以如上所述創(chuàng)建一個自定義的驗證器,然后增加 replaceXXX
函數(shù)進(jìn)驗證器中。
protected function replaceFoo($message, $attribute, $rule, $parameters){ return str_replace(':foo', $parameters[0], $message);}
如果您想要增加一個自定義信息 "replacer" 但不擴展 Validator 類,您可以使用 Validator::replacer
方法:
Validator::replacer('rule', function($message, $attribute, $rule, $parameters){ //});
更多建議: