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ù)。這也允許你可以進行更進一步的驗證,甚至在消息集合中增加更多的錯誤信息。我們在驗證器實例中使用 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
方法。通過這個方法,你可以檢查認證后的用戶是否有權(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>');
注意: 默認錯誤信息以 Bootstrap 兼容語法輸出。
foreach ($messages->all('<li>:message</li>') as $message){ //}
當(dāng)您開始進行驗證數(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
實例進行重定向。這個方法會將錯誤信息存入 session 中,這樣才能在下個請求中被使用。
然而,我們并不需要特別去將錯誤信息綁定在我們 GET 路由的視圖中。因為 Laravel 會確認在 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 時,驗證才會通過。這在確認"服務(wù)條款"是否同意時很有用。
字段值通過 PHP 函數(shù) checkdnsrr
來驗證是否為一個有效的網(wǎng)址。
驗證字段是否是在指定日期之后。這個日期將會使用 PHP strtotime
函數(shù)驗證。
字段僅全數(shù)為字母字串時通過驗證。
字段值僅允許字母、數(shù)字、破折號(-)以及底線(_)
字段值僅允許字母、數(shù)字
字段值僅允許為數(shù)組
驗證字段是否是在指定日期之前。這個日期將會使用 PHP strtotime
函數(shù)驗證。
字段值需介于指定的 min 和 max 值之間。字串、數(shù)值或是文件都是用同樣的方式來進行驗證。
字段值需與對應(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)字段有值時,才進行驗證。這時只要增加 sometimes
條件進條件列表中,就可以快速達成:
$v = Validator::make($data, [ 'email' => 'sometimes|required|email',]);
在上述例子中,email
字段只會在當(dāng)其在 $data
數(shù)組中有值的情況下才會被驗證。
有時,您可以希望給指定字段在其他字段長度有超過 100 時才驗證是否為必填。或者您希望有兩個字段,當(dāng)其中一字段有值時,另一字段將會有一個默認值。增加這樣的驗證條件并不復(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ù)是我們要條件式認證的字段名稱。第二個參數(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è)置自定義的錯誤信息取代默認錯誤信息。這里有幾種方式可以設(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
。要達到這個目的,將您的信息增加至 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ù)組或是在認證語言文件里新增。
除了使用閉包回調(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ù)進驗證器中。
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){ //});
更多建議: