Laravel 通過(guò) Validation
類(lèi)讓您可以簡(jiǎn)單、方便的驗(yàn)證數(shù)據(jù)正確性及查看相應(yīng)的驗(yàn)證錯(cuò)誤信息。
$validator = Validator::make(
array('name' => 'Dayle'),
array('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(
array('name' => 'Dayle'),
array('name' => array('required', 'min:5'))
);
$validator = Validator::make(
array(
'name' => 'Dayle',
'password' => 'lamepassword',
'email' => 'email@example.com'
),
array(
'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
)的formatValidationErrors
。不要忘記在文件頂部引入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 = array(...);
$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ì)使用 PHPstrtotime
函數(shù)驗(yàn)證。
字段僅全數(shù)為字母字串時(shí)通過(guò)驗(yàn)證。
字段值僅允許字母、數(shù)字、破折號(hào)(-)以及底線(xiàn)(_)
驗(yàn)證字段是否是在指定日期之前。這個(gè)日期將會(huì)使用 PHPstrtotime
函數(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ò) PHPstrtotime
函數(shù)驗(yàn)證是否為一個(gè)合法的日期。
字段值通過(guò) PHPdate_parse_from_format
函數(shù)驗(yàn)證符合format 制定格式的日期是否為合法日期。
字段值需為數(shù)字且長(zhǎng)度需為value。
字段值需為數(shù)字,且長(zhǎng)度需介于min 與max 之間。
字段必須可以轉(zhuǎn)換成布爾值,可接受的值為true
,false
,1
,0
,"1"
,"0"
。
字段值需與存在于數(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)
字段值需小于等于value。字串、數(shù)字和文件則是判斷size
大小。
文件的 MIME 類(lèi)需在給定清單中的列表中才能通過(guò)驗(yàn)證。
'photo' => 'mimes:jpeg,bmp,png'
字段值需大于等于value。字串、數(shù)字和文件則是判斷size
大小。
字段值需符合給定的正規(guī)表示式。
注意: 當(dāng)使用regex
模式時(shí),您必須使用數(shù)組來(lái)取代"|"作為分隔,尤其是當(dāng)正規(guī)表示式中含有"|"字串。
字段值在field 字段值為value 時(shí)為必填。
字段值的尺寸需符合給定value 值。對(duì)于字串來(lái)說(shuō),value 為需符合的字串長(zhǎng)度。對(duì)于數(shù)字來(lái)說(shuō),value 為需符合的整數(shù)值。對(duì)于文件來(lái)說(shuō),value 為需符合的文件大?。▎挝?kb)。
字段值通過(guò) PHPtimezone_identifiers_list
函數(shù)來(lái)驗(yàn)證是否為有效的時(shí)區(qū)。
字段值在給定的數(shù)據(jù)庫(kù)中需為唯一值。如果column(字段)
選項(xiàng)沒(méi)有指定,將會(huì)使用字段名稱(chēng)。
'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, array(
'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, array(
'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(array('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 = array(
'required' => 'The :attribute field is required.',
);
$validator = Validator::make($input, $rules, $messages);
注意: 在驗(yàn)證中,
:attribute
占位符會(huì)被字段的實(shí)際名稱(chēng)給取代。您也可以在驗(yàn)證信息中使用其他的占位符。
$messages = array(
'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 = array(
'email.required' => 'We need to know your e-mail address!',
);
某些狀況下,您可能希望在語(yǔ)言包文件中設(shè)定您的自定義消息,而非直接將他們傳遞給Validator
。要達(dá)到這個(gè)目的,將您的信息增加至resources/lang/xx/validation.php
文件的custom
數(shù)組中。
'custom' => array(
'email' => array(
'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)中:
<?php
class 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)
{
//
});