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