laravel 基礎教程 —— 驗證

驗證

簡介

Laravel 對驗證應用的輸入數據提供了多中途徑的實現。默認的,Laravel 的基礎控制器類使用了 ValidatesRequests trait,該性狀允許使用各種強大的驗證約束來驗證 HTTP 的輸入請求。

快速入門

要了解 Laravel 強大的驗證功能,我們需要一個完整的示例來描述表單的驗證,和將表單驗證的錯誤信息顯示給用戶。

定義路由

首先,讓我們假定我們在 app/Http/routes.php 文件中擁有下述的路由:

// Display a form to create a blog post...
Route::get('post/create', 'PostController@create');

// Store a new blog post...
Route::post('post', 'PostController@store');

當然, GET 路由會為用戶創建一個新的博客文章時提供一個表單,而 POST 路由會存儲新的博客文章到數據庫。

創建控制器

接著,我們需要一個控制器來處理這些路由,目前,我們先不在 store 方法里放任何的邏輯:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PostController extends Controller
{
  /**
   * Show the form to create a new blog post.
   *
   * @return Response
   */
   public function create()
   {
     return view('post.create');
   }

   /**
    * Store a new blog post.
    *
    * @param Request $request
    * @return Response
    */
    public function store(Request $request)
    {
      // Validate and store the blog post...
    }
}

編寫驗證邏輯

現在我們準備好了在 store 方法中進行博客文章的驗證邏輯。如果你檢查應用的基礎控制器(App\Http\Controllers\Controller) 類,你會發現該類使用了 ValidatesRequests trait。這個性狀為所有的控制器提供了方便的 validate 方法。

validate 方法接收 HTTP 輸入請求,并設置驗證約束。如果驗證約束通過,那么后續的代碼將會正常的執行。如果驗證失敗,那么將會拋出一個恰當的異常響應返回給用戶。對于傳統的 HTTP 請求,驗證器會自動生成一個重定向響應,而 AJAX 請求,則會返回 JSON 響應。

為了能夠更好的理解 validate 方法,讓我們繼續回到 store 方法:

/**
 * Store a new blog post.
 *
 * @param Request $request
 * @return Response
 */
 public function store(Request $request)
 {
   $this->validate($request, [
     'title' => 'required|unique:posts|max:255',
     'body' => 'required',
   ]);

   // The blog post is valid, store in database...
 }

就如你所看到的,我們簡單的傳遞了一個 HTTP 輸入請求,并且在 validate 方法中設置了預期的驗證約束。而這次,如果驗證失敗,那么相應的響應會被自動的生成并且被返回給請求用戶。如果驗證通過,那么我們的控制器會繼續執行之后的業務。

在初次驗證失敗時停止

有時候你希望在獲取首個驗證約束失敗時停止當前屬性其余約束的驗證。你可以在屬性中加入 bail 約束:

$this->validate($request, [
  'title' => 'bail|required|unique:posts|max:255',
  'body' => 'required',
]);

在這個例子中,如果 title 屬性中的 required 約束驗證失敗,那么 unique 約束就不會再被驗證。約束是按照其被分配的順序來進行驗證的。

嵌套的屬性

如果你的 HTTP 請求包含了嵌套的參數,你可以使用 . 語法來為其指定約束:

$this->validate($request, [
  'title' => 'required|unique:posts|max:255',
  'author.name' => 'required',
  'author.description' => 'required',
]);

顯示驗證錯誤

那么,假如傳入的請求參數并沒有通過給定約束的驗證怎么辦?就如前面所提到的,Laravel 會自動的重定向用戶到之前的位置。另外,所有的驗證錯誤信息都會被自動的閃存到 session 中。

你需要注意到我們并沒有明確的綁定錯誤信息到 GET 路由的響應視圖里。這是因為 laravel 會檢查閃存 seesion 里的錯誤數據,并且會自動的在其可用時注入到視圖中。你可以在視圖中使用 $errors 變量,它是一個 Illuminate\Support\MessageBag 實例。如果需要了解更多這個實例對象,請參考其 文檔

注意:$errors 變量是通過 Illuminate\View\Middleware\ShareErrorsFromSession 中間件來綁定到視圖中的。這個中間件已經被提供到了 web 中間件組中。這個中間件被應用時會自主的在你的視圖中注入 $errors 變量,這允許你方便的假定 $errors 變量總是已經被定義且可以安全的使用。

所以,在我們的例子中,當驗證失敗是,用戶將會被重定向到控制器的 create 方法中,這允許你在視圖中展示錯誤信息:

<!-- /resources/views/post/create.blade.php -->

<h1>Create Post</h1>

@if (count($errors) > 0)
  <div class="alert alert-danger">
    <ul>
      @foreach ($errors->all() as $error)
        <li>{{ $error }}</li>
      @endforeach
    </ul>
  </div>
@endif

<!-- Create Post Form -->

自定義閃存錯誤格式

如果你希望在驗證失敗時可以自定義閃存進 session 中的錯誤消息的格式,你需要在你的基礎控制器中復寫 formatValidationErrors 方法。不要忘記在頂部引入 Illuminate\Contracts\Validation\Validator 類:

<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;

abstract class Controller extends BaseController
{
  use DispatchesJobs, ValidatesRequests;

  /**
   * {@inheritdoc}
   */
   protected function formatValidationErrors(Validator $validator)
   {
     return $validator->errors()->all();
   }
}

AJAX 請求 & 驗證

在上面的示例中,我們使用傳統的表單來發送數據到應用,事實上,如今很多應用都使用 AJAX 請求,當通過 AJAX 請求來使用 validate 方法時,laravel 并不會自動生成重定向的響應,相反的,laravel 會生成一個包含了驗證錯誤消息的 JSON 響應。并且該響應會伴隨 422 HTTP 狀態碼。

驗證數組

驗證數組形式的輸入并不是一件痛苦的事情。比如,去驗證給定的輸入數組中所有的郵件都應該是唯一的,你可以參照如下做法:

$validator = Validator::make($request->all(), [
  'person.*.email' => 'email|unique:users',
  'person.*.first_name' => 'required_with:person.*.last_name',
]);

同樣的,你也可以在使用語言文件來指定特定的驗證消息時使用 * 通配符。這可以輕而易舉的使用單條驗證消息提供給基于數組的輸入:

'custom' => [
  'person.*.email' => [
    'unique' => 'Each person must have a unique e-mail address',
  ]
]

其它驗證途徑

手動的創建 Validators

如果你不喜歡使用 ValidatesRequests trait 的 validator 方法,你也可以通過使用 Validator 假面來創建一個 validator 實例。Validator 假面的 make 方法就可以生成一個新的 validator 實例:

<?php

namespace App\Http\Controllers;

use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PostController extends Controller
{
  /**
   * Store a new blog post.
   *
   * @param Request $request
   * @return Response
   */
   public function store(Request $request)
   {
     $validator = Validator::make($request->all(), [
       'title' => 'required|unique:posts|max:255',
       'body' => 'required',
     ]);

     if ($validator->fails()) {
       return redirect('post/create')
                ->withErrors($validator)
                ->withInput();
     }

     // Store the blog post...
   }
}

make 方法所接受的第一個參數是需要被驗證的數據,第二個參數則是應該施加到數據的驗證約束。

如果請求的驗證失敗,那么你需要使用 withErrors 方法來講錯誤消息存放到 session 中。當使用該方法時,$errors 變量會在重定向之后被自動的共享到你的視圖中,這使你可以輕松的將錯誤信息展示給用戶。withErrors 方法可以接收 validator 實例,或者 MessageBag 實例,又或者原生的 PHP array

被命名的錯誤袋

如果你在一個獨立頁面中包含了多個表單。那么你可能會希望能對 MessageBag 進行命名以展示相應的表單錯誤。你可以直接在 withErrors 方法中傳遞第二個參數對其進行命名:

return redirect('register')
         ->withErrors($validator, 'login');

你之后可以通過 $errors 變量來訪問被命名的 MessageBag 實例:

{{ $errors->login->first('email') }}

驗證之后的 Hook

驗證器也允許你在驗證完成之后執行特定的操作。這允許你輕松的進行進一步的驗證,你也可以在消息集合里添加更多的錯誤消息。在驗證器的實例上使用 after 方法來進行 hook:

$validator = Validator::make(...);

$validator->after(function ($validator) {
  if ($this->somethingElseIsInvalid()) {
    $validator->errors()->ad('field', 'Something is wrong with this field!');
  } 
});

if ($validator->fails()) {
  //
}

表單請求驗證

對于更為復雜的驗證場景,你或許希望構建一個“表單請求”。表單請求是一個自定義的請求類,并且它包含了所有的驗證邏輯。你可以使用 make:request Artisan CLI 命令來創建一個表單請求類:

php artisan make:request StoreBlogPostRequest

被生成的類會被存儲在 app/Http/Requests 目錄。讓我們在 rules 方法中來添加一些驗證約束:

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
 public function rules()
 {
   return [
     'title' => 'required|unique:posts|max:255',
     'body' => 'required',
   ];
 }

那么,這些驗證約束是如何被評定的?你所要做的所有的事情就是在你的控制器方法中添加該請求類的類型提示。傳入進來的表單請求會在控制器方法調用之前被自動的進行約束驗證,這意味著你完全不需要再你的控制器方法中添加任何的驗證邏輯:

/**
 * Store the incoming blog post.
 *
 * @param StoreBlogPostRequest $request
 * @return Response
 */
public function store(StoreBlogPostRequest $request)
{
  // The incoming request is valid...
}

如果驗證失敗,用戶會被自動的重定向到他們之前的位置。那么驗證錯誤消息也會自動的閃存進 session 數據中被用于顯示。如果你使用的是 AJAX 請求,那么會自動的返回一個包含所有驗證錯誤消息的 JSON 格式的響應,它的 HTTP 狀態碼會被設置為 422。

授權表單請求

表單請求類也包含了 authorize 方法。在這個方法中,你可以檢查已認證的用戶是否真的擁有修改所給定資源的權利。比如,如果用戶嘗試修改博客文章中的評論消息,我們需要考慮一下這個評論是屬于他的嗎:

/**
 * 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();
 }

你應該注意到了上述實例中的 route 方法的調用。這個方法用來在路由被訪問時發放所定義的 URL 參數,比如下面路由的 {comment} 參數:

Route::post('comment/{comment}');

如果 authorize 方法返回 false,那么會響應一個 403 的狀態碼,并且控制器的方法不會被執行。

如果你計劃在應用的其它部分來處理授權邏輯,你可以簡單的在 authorize 方法中返回 true:

/**
 * Determine if the user is authorized to make this request.
 *
 * @return bool
 */
 public function authorize()
 {
   return true;
 }

自定義閃存的錯誤格式

如果你希望在驗證失敗時自定義閃存到 session 數據中驗證錯誤消息的格式,那么你需要復寫(App\Http\Requests\Request)基礎請求類中的 formatErros 方法。不要忘記引入 Illuminate\Contracts\Validation\Validator 類:

/**
 * {@inheritdoc}
 */
 protected function formatErrors(Validator $validator)
 {
   return $validator->errors()->all();
 }

自定義錯誤消息

你也可以通過在請求類中復寫 messages 方法來自定義錯誤消息。該方法應該返回一個包含相應錯誤消息的鍵值對數組:

/**
 * Get the error messages for the defined validation rules.
 *
 * @return array
 */
 public function message()
 {
   return [
     'title.required' => 'A title is required',
     'body.required' => 'A message is required',
   ];
 }

與錯誤消息協作

在調用 Validator 實例的 errors 方法之后,你可以檢索到一個 Illuminate\Support\MessageBag 的實例,這實例擁有多種便捷的方法來與錯誤消息進行交互。

檢索給定字段中的首個錯誤消息

你可以使用 first 方法來檢索給定字段的首個錯誤消息:

$message = $validator->errors();

echo $message->first('email');

檢索給定字段的所有錯誤消息

如果你需要檢索給定字段的所有消息所組成的數組,那么你應該使用 get 方法:

foreach ($messages->get('email') as $message) {
  //
}

檢索所有字段的所有錯誤消息

你可以使用 all 方法來檢索所有字段的所有錯誤消息所組成的數組:

foreach ($message->all() as $message) {
  //
}

判斷所給定的字段中是否存在消息

if ($messages->has('email')) {
  //
}

使用給定的格式來檢索獲取錯誤消息

echo $message->first('email', '<p>:message</p>');

使用給定的格式來檢索所有的錯誤消息

foreach ($messages->all('<li>:message</li>') as $message) {
  //
}

自定義錯誤消息

如果你需要,你可以使用自定義的錯誤消息來取代默認的驗證消息。這里有幾種方式來指定自定義的消息。首先,你可以傳遞自定的消息作為 Validator::make 方法的第三個參數:

$messages = [
  'required' => 'The :attribute field is required.',
];

$validator = Validator::make($input, $rules, $messages);

在這個例子中,:attribute 占位符會被驗證數據中真實的名稱所替換。你還可以利用其它的占位符到驗證消息中,比如:

$message = [
  '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',
];

為給定的屬性指定錯誤消息

有時候,你可能希望指定自定義的錯誤消息到特定的字段。你可以使用 . 符號來進行分割,屬性名應該在前,約束應該在后:

$message = [
  'email.required' => 'We need to know your e-mail address!',
];

在語言文件中指定自定義消息

在多數情況下,你可能希望使用一個語言文件中的自定義消息屬性直接傳遞到 Validator。你可以在 resources/lang/xx/validation.php 語言文件中添加 custom 數組來存儲你的消息:

'custom' => [
  'email' => [
    'required' => 'We need to know your e-mail address!',
  ],
],

可用的驗證約束

下面是所有的可用的驗證約束和它們的功能的列表:

accepted

驗證的字段必須為 yeson,1,或者 true。這通常用來驗證服務條款的承諾。

active_url

驗證的字段必須可以通過 checkdnsrr PHP 方法的驗證。

after:date

驗證的字段必須是給定日期之后的值。日期會被傳遞到 strtotime PHP 方法:

`start_date' => 'required|date|after:tomorrow'

你也可以指定使用其它字段的日期來進行評估:

'finish_date' => 'required|date|after:start_date'

alpha

驗證的字段必須全部是由字母字符組成的字符串。

alpha_dash

驗證的字段可以是字母,數字,-,_ 所組成的字符串。

alpha_num

驗證的字段必須全部由字母或數字所組成。

array

驗證的字段必須是一個 PHP array

before:date

驗證的字段的值必須比指定的日期要早。指定的日期會被傳遞到 PHP 的 strtotime 方法。

between:min,max

驗證的字段的大小必須在給定的 minmax 之間。字符串,數字和文件都會使用和 size 約束的相同的評估方式。

boolean

驗證的字段必須能夠轉換為布爾值。所接受的輸入可以是 truefalse10"1""0"

confirmed

驗證的字段必須能夠和 foo_confirmation 字段相匹配。比如,如果驗證的字段是 password,相應的 password_confirmation 字段必須在輸入中被提供且與 password 相匹配。

date

驗證的字段必須是一個有效的日期,它應該能被 strtotime PHP 方法通過。

date_format:format

驗證的字段必須匹配給定的格式。該格式會被 PHP date_parse_from_format 方法評定,你應該只使用 date 或者 date_format 其中之一來進行驗證字段,不要全部都使用。

different:field

驗證的字段必須與給定的字段不同。

digits:value

驗證的字段必須是數字類型并且具有指定的長度。

digits_between:min,max

驗證的字段必須具有指定區間的長度。

dimensions

驗證的字段必須是一個圖片類型的,并且要求符合指定的參數約束:

'avatar' => 'dimensions:min_with=100,min_height=200'

可用的參數有:min_widthmax_widthmin_heightmax_heightwidthheightratio

distinct

當與數組協作時,驗證的字段中必須不能含有重復的值:

'foo.*.id' => 'distinct'

email

驗證的字段必須是一個郵件地址的格式。

exists:table,column

驗證的字段必須能在指定數據庫表中檢索的到。

Exists 基礎約束用法

'state' => 'exists:states'

指定自定義列名稱

'state' => 'exists:states,abbreviation'

你也可以像使用 where 語句一樣指定添加更多的查詢條件:

'email' => 'exists:staff,email,account_id,1'

查詢條件也可以使用 ! 來表明否定值:

'eamil' => 'exists:staff,email,role,!admin'

你也可以傳遞 NULL 或者 NOT_NULL 到查詢語句中:

'eamil' => 'exists:staff,email,deleted_at,NULL'

'eamil' => 'exists:staff,email,deleted_at,NOT_NULL'

極個別的情況下,你可能需要在 exists 查詢下指定特定的數據庫連接。你可以使用 . 語法將數據庫連接名前置來進行指定:

'email' => 'exists:connection.staff,email'

filled

驗證的字段如果出現,那么它一定不能為空值。

image

被驗證的文件必須是一個圖片類型(jpeg,png,bmp,gif,svg)

in:foo,bar,...

驗證的字段必須是給定值列中的一個。

in_array:anotherfield

驗證的字段必須是指定的字段中值列之一。

integer

驗證的字段必須是一個整數。

ip

驗證的字段必須是一個 IP 地址。

json

驗證的字段必須是合法的 JSON 字符串

max:value

驗證的字段必須小于等于指定值。字符串,數字,和文件類型會與 size 約束使用相同的評估方法。

mimetypes:text/plain,...

驗證的字段必須匹配給定的 MIME 類型:

'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'

為了判斷所上傳文件的 MIME 類型,laravel 會讀取文件的內容并且會嘗試猜測文件的 MIME 類型,這可能會與客戶端提供的文件 MIME 類型有所區別。

mimes:foo,bar,...

驗證的文件的 MIME 類型相應的后綴必須是所列的值之一。

基礎用法

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

你只需要指定文件的擴展,這個約束會針對文件的內容進行猜測文件的 MIME 類型,然后進行擴展驗證。

完整的 MIME 類型和其相應的擴展后綴,你可以從 這里 找到。

min:value

驗證的字段必須比指定的值要小。字符串,數字和文件類型會使用 size 約束相同的評估方法。

not_in:foo,bar,...

驗證的字段不應該包含在給定的值列中。

numeric

驗證的字段必須是一個數值類型。

present

驗證的字段必須要求被提供,但是可以為空。

regex:pattern

驗證的字段必須與給定的正則表達式相匹配。

注意:當使用 regex 模式時,你必須將約束放進數組里來取代管道符分隔,特別是在正則表達式中包含管道符時。

required

驗證的字段必須被提供并且不能為空值。判斷空值的依據:

  • 值是 null
  • 值是空字符串
  • 值是一個空數組或者空的 Countable 對象
  • 值是一個沒有傳遞路徑的上傳的文件

required_if:anotherfield,value,...

驗證的字段必須在以下情況下被提供:指定的字段等于任意列出的值。

required_unless:anotherfield,value,...

驗證的字段必須在以下情況下被提供: 所指定的字段和所提供的值都不相等。

required_with:foo,bar,...

驗證的字段只有在其它所指定字段之一被提供時才會被要求提供。

required_with_all:foo,bar,...

驗證的字段只有在其它所指定字段全部被提供時才會被要求提供。

required_without:foo,bar,...

驗證的字段只有在其它所指定字段之一沒有被提供時被要求提供。

required_without_all:foo,bar,...

驗證的字段只有在所指定字段全部沒有被提供時才會被要求提供。

same:field

所驗證的字段必須與指定的字段相匹配。

size:value

驗證的字段必須具有給定值的大小。對于字符串數據,值應該是字符串的字符長度。對于數值數據,值應該是相應的整數值。對于數組,大小匹配數組的 count 大小。對于文件,應該匹配文件的字節大小。

string

驗證的字段必須是一個字符串。

timezone

驗證的字段必須是經過 PHP timezone_identifiers_list 方法驗證的合法的 timezone 標識。

unique:table,column,except,idColumn

驗證的字段必須在給定的數據表中唯一,如果 column 選型沒有被指定,那么會直接使用字段的名字。

指定自定義的列名

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

自定義數據庫連接

極少數情況下,你可能需要指定自定義的數據庫連接來進行驗證。就如上面所看到的,設置 unique:users 會使用默認的數據庫連接來進行約束驗證。如果想指定其他數據庫連接,你可以使用 . 語法并前置指定數據庫連接:

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

強迫 Unique 約束 忽略給定的 ID

有時候,你可能會希望 unique 檢查忽略給定的 ID。比如,考慮一下一個更新個人信息的場景,它應該提供用戶的名稱,郵箱地址,和位置。你可能會想要驗證郵箱的唯一性。但是你只想驗證與用戶的當前郵箱不一致的郵箱的唯一性。也就是說你只想驗證這個郵箱有沒有被其他用戶所使用。你需要傳遞 ID 作為第三個參數來通知 unique 約束來忽略當前用戶的 ID:

'email' => 'unique:users,email_address,'.$user->id

如果表名使用的主鍵列名不是 id ,那么你還需要指定主鍵的列名到第四個參數:

'email' => 'unique:users,email_address,'.$user->id.',user_id'

添加額外的條件查詢

你也可以指定更多的條件查詢:

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

在上面的約束中,只有 account_id1 的行會被約束進行檢查。

url

驗證的字段必須符合 PHP filter_var 方法驗證的有效 URL。

添加約束條件

在一些場景中,你會希望只有字段出現在了輸入數組中時才會對其進行驗證。你可以在約束列中添加 sometimes 約束來快速的完成指定:

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

這上面的例子中,只有 $data 中提供了 email 字段,email 的約束才會對其進行驗證。

復雜的驗證條件

有時候,你可能會希望基于更復雜的條件邏輯去進行約束的驗證。比如,你希望只有另外一個字段擁有比 100 更大的值時才會驗證給定的字段是否被提供。又或者你想要在只有另外一個字段被提供時才會需要其他兩個字段的值。添加這些條件判定并非是痛苦的一件事。首先,你還是需要創建一個 Validator 實例和一些靜態的約束:

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

讓我們假定我們的應用是服務于一些游戲收藏家的。如果一個游戲收藏家注冊了我們的應用,并且它們添加了超過 100 個游戲時。我們需要它們解釋一下為什么他會擁有那么多的游戲。比如,或許他開了一個游戲販賣超市,又或者他僅僅就是喜歡收藏。我們可以使用 Validator 實例上的 sometimes 方法來添加這個必要的條件:

$v->sometimes('reason', 'required|max:500', function ($input) {
  return $input->games >= 100;
});

傳遞到 sometimes 方法的第一個參數是我們需要考慮驗證的字段的名字。第二個參數是我們想要添加的約束。如果第三個參數傳遞的 Closure 返回的結果是 true,那么這個約束就會被添加進去。這就可以輕松的對復雜的驗證場景進行條件的構建。你甚至可以一次性的添加多個字段的條件驗證:

$v->sometimes(['reson', 'cost'], 'required', function ($input) {
  return $input->games >= 100; 
});

注意:傳遞到 Closure 中的 $input 是一個 Illuminate\Support\Flument 實例,并且它可以被用來訪問你的輸入和文件。

自定義驗證約束

Laravel 提供了各種有用的驗證約束。但是,你可能希望添加你自己的特定的約束。你可以使用 Validator 假面的 extend 方法來注冊自己的驗證約束。讓我們在服務提供者里注冊一個自定義的驗證約束:

<?php

namespace App\Providers;

use Validator;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
  /**
   * Bootstrap any application services.
   *
   * @return void
   */
   public function boot()
   {
     Validator::extend('foo', function ($attribute, $value, $parameters, $validator) {
       return $value == 'foo';
     });
   }

   /**
    * Register the service provider.
    *
    * @return void
    */
    public function register()
    {
      //
    }
}

自定義的驗證閉包中接收四個參數:需要被驗證的屬性名稱,屬性的值,一個需要被傳遞到約束的 $paramters 數組,和 Validator 實例。

你也可以傳遞一個類名和方法到 extend 方法中來代替閉包:

Validator::extend('foo', 'FooValidator@validate');

定義錯誤消息

你也需要為你的自定義約束添加一個錯誤消息。你可以使用行內自定義錯誤消息或者將其添加到獨立的驗證語言文件中。這個消息應該被存放在數組的一維中,而不是包含在 custom 數組里:

"foo" => 'Your input was invalid!',

'accepted' => 'The :attribute must be accepted.',

// The rest of the validation error messages...

當構建自定義的驗證約束時,你或許有時候也想為錯誤消息定義一些占位符。你可以使用 Validator 假面的 replacer 方法來進行占位替換。你可以在服務提供者的 boot 方法中來做這些:

/**
 * Bootstrap any application services.
 *
 * @return void
 */
 public function boot()
 {
   Validator::extend(...);

   Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) {
     return str_replace(...);
   });
 }

隱式的擴展

默認的,當屬性被驗證時,如果在輸入數組中沒有被提供,或者驗證約束為 required 卻是一個空值。那么普通的驗證約束,包括自定義的約束擴展,都不會再執行。比如,unique 約束就不會在出現 null 值進行執行:

$rules = ['name' => 'unique'];

$input = ['name' => null];

Validator:make($input, $rules)->passes(); // true

如果需要約束即使是屬性值為空時也繼續執行,那么約束需要暗示屬性是必須的。你可以使用 Validator::extendImplicit() 方法來構建一個 “隱式的” 擴展:

Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
  return $value == 'foo'; 
});

注意: 隱式的擴展僅僅是暗示屬性是必須的,不論它實際上是缺失的值或者是空的屬性,這都取決于你。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內容

  • 1、簡介 Laravel 提供了多種方法來驗證應用輸入數據。默認情況下,Laravel 的控制器基類使用Valid...
    伊Summer閱讀 1,536評論 0 3
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,829評論 18 139
  • HTML表單 在HTML中,表單是 ... 之間元素的集合,它們允許訪問者輸入文本、選擇選項、操作對象等等,然后將...
    蘭山小亭閱讀 3,435評論 2 14
  • 前言 : Laravel 提供了多種方法來驗證應用輸入數據。默認情況下,Laravel 的控制器基類使用Valid...
    科哚洛夫閱讀 5,058評論 0 2
  • 1. Two Sum Given an array of integers, returnindicesof th...
    LdpcII閱讀 488評論 0 0