表單驗證

2018-12-17 10:56 更新

基本用法

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ī)則。

使用數(shù)組來定義規(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 對象。

授權(quán)表單請求

表單請求類同樣也包含了一個 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'); ?>

           

           

可用驗證規(guī)則

以下是現(xiàn)有可用的驗證規(guī)則清單與他們的函數(shù)名稱:

           

accepted

字段值為 yes, on, 或是 1 時,驗證才會通過。這在確認"服務(wù)條款"是否同意時很有用。

           

active_url

字段值通過 PHP 函數(shù) checkdnsrr 來驗證是否為一個有效的網(wǎng)址。

           

after:date

驗證字段是否是在指定日期之后。這個日期將會使用 PHP strtotime 函數(shù)驗證。

           

alpha

字段僅全數(shù)為字母字串時通過驗證。

           

alpha_dash

字段值僅允許字母、數(shù)字、破折號(-)以及底線(_)

           

alpha_num

字段值僅允許字母、數(shù)字

           

array

字段值僅允許為數(shù)組

           

before:date

驗證字段是否是在指定日期之前。這個日期將會使用 PHP strtotime 函數(shù)驗證。

           

between:min,max

字段值需介于指定的 minmax 值之間。字串、數(shù)值或是文件都是用同樣的方式來進行驗證。

           

confirmed

字段值需與對應(yīng)的字段值 foo_confirmation 相同。例如,如果驗證的字段是 password ,那對應(yīng)的字段 password_confirmation 就必須存在且與 password 字段相符。

           

date

字段值通過 PHP strtotime 函數(shù)驗證是否為一個合法的日期。

           

date_format:format

字段值通過 PHP date_parse_from_format 函數(shù)驗證符合 format 制定格式的日期是否為合法日期。

           

different:field

字段值需與指定的字段 field 值不同。

           

digits:value

字段值需為數(shù)字且長度需為 value。

           

digits_between:min,max

字段值需為數(shù)字,且長度需介于 minmax 之間。

           

boolean

字段必須可以轉(zhuǎn)換成布爾值,可接受的值為 true, false, 1, 0, "1", "0"。

           

email

字段值需符合 email 格式。

           

exists:table,column

字段值需與存在于數(shù)據(jù)庫 table 中的 column 字段值其一相同。

Exists 規(guī)則的基本使用方法

'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'

           

           

image

文件必需為圖片(jpeg, png, bmp, gif 或 svg)

           

in:foo,bar,...

字段值需符合事先給予的清單的其中一個值

           

integer

字段值需為一個整數(shù)值

           

ip

字段值需符合 IP 位址格式。

           

max:value

字段值需小于等于 value。字串、數(shù)字和文件則是判斷 size 大小。

           

mimes:foo,bar,...

文件的 MIME 類需在給定清單中的列表中才能通過驗證。

MIME規(guī)則基本用法

'photo' => 'mimes:jpeg,bmp,png'

           

           

min:value

字段值需大于等于 value。字串、數(shù)字和文件則是判斷 size 大小。

           

not_in:foo,bar,...

字段值不得為給定清單中其一。

           

numeric

字段值需為數(shù)字。

           

regex:pattern

字段值需符合給定的正規(guī)表示式。

注意: 當(dāng)使用regex模式時,您必須使用數(shù)組來取代"|"作為分隔,尤其是當(dāng)正規(guī)表示式中含有"|"字串。

           

required

字段值為必填。

           

required_if:field,value

字段值在 field 字段值為 value 時為必填。

           

required_with:foo,bar,...

字段值 僅在 任一指定字段有值情況下為必填。

           

required_with_all:foo,bar,...

字段值 僅在 所有指定字段皆有值情況下為必填。

           

required_without:foo,bar,...

字段值 僅在 任一指定字段沒有值情況下為必填。

           

required_without_all:foo,bar,...

字段值 僅在 所有指定字段皆沒有值情況下為必填。

           

same:field

字段值需與指定字段 field 等值。

           

size:value

字段值的尺寸需符合給定 value 值。對于字串來說,value 為需符合的字串長度。對于數(shù)字來說,value 為需符合的整數(shù)值。對于文件來說,value 為需符合的文件大?。▎挝?kb)。

           

string

必須是字符串類型。

           

timezone

字段值通過 PHP timezone_identifiers_list 函數(shù)來驗證是否為有效的時區(qū)。

           

unique:table,column,except,idColumn

字段值在給定的數(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);

           

唯一(Unique)規(guī)則的基本用法

'email' => 'unique:users'

           

指定一個自定義的字段名稱

'email' => 'unique:users,email_address'

           

強制唯一規(guī)則忽略指定的 ID

'email' => 'unique:users,email_address,10'

           

增加額外的 Where 條件

您也可以指定更多的條件式到 "where" 查詢語句中:

'email' => 'unique:users,email_address,NULL,id,account_id,1'

           

上述規(guī)則為只有 account_id1 的數(shù)據(jù)列會做唯一規(guī)則的驗證。

           

url

字段值需符合 URL 的格式。

注意: 此函數(shù)會使用 PHP filter_var 方法驗證。

           

添加條件驗證規(guī)則

某些情況下,您可能 只想 當(dāng)字段有值時,才進行驗證。這時只要增加 sometimes 條件進條件列表中,就可以快速達成:

$v = Validator::make($data, [
    'email' => 'sometimes|required|email',]);

           

在上述例子中,email 字段只會在當(dāng)其在 $data 數(shù)組中有值的情況下才會被驗證。

復(fù)雜的條件式驗證

有時,您可以希望給指定字段在其他字段長度有超過 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!',
    ],],

           

           

自定義驗證規(guī)則

注冊自定義驗證規(guī)則

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ù)組或是在認證語言文件里新增。

擴展 Validator 類

除了使用閉包回調(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){
    //});


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號