laravel 基礎(chǔ)教程 —— 驗(yàn)證

驗(yàn)證

簡(jiǎn)介

Laravel 對(duì)驗(yàn)證應(yīng)用的輸入數(shù)據(jù)提供了多中途徑的實(shí)現(xiàn)。默認(rèn)的,Laravel 的基礎(chǔ)控制器類使用了 ValidatesRequests trait,該性狀允許使用各種強(qiáng)大的驗(yàn)證約束來(lái)驗(yàn)證 HTTP 的輸入請(qǐng)求。

快速入門

要了解 Laravel 強(qiáng)大的驗(yàn)證功能,我們需要一個(gè)完整的示例來(lái)描述表單的驗(yàn)證,和將表單驗(yàn)證的錯(cuò)誤信息顯示給用戶。

定義路由

首先,讓我們假定我們?cè)?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');

當(dāng)然, GET 路由會(huì)為用戶創(chuàng)建一個(gè)新的博客文章時(shí)提供一個(gè)表單,而 POST 路由會(huì)存儲(chǔ)新的博客文章到數(shù)據(jù)庫(kù)。

創(chuàng)建控制器

接著,我們需要一個(gè)控制器來(lái)處理這些路由,目前,我們先不在 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...
    }
}

編寫驗(yàn)證邏輯

現(xiàn)在我們準(zhǔn)備好了在 store 方法中進(jìn)行博客文章的驗(yàn)證邏輯。如果你檢查應(yīng)用的基礎(chǔ)控制器(App\Http\Controllers\Controller) 類,你會(huì)發(fā)現(xiàn)該類使用了 ValidatesRequests trait。這個(gè)性狀為所有的控制器提供了方便的 validate 方法。

validate 方法接收 HTTP 輸入請(qǐng)求,并設(shè)置驗(yàn)證約束。如果驗(yàn)證約束通過(guò),那么后續(xù)的代碼將會(huì)正常的執(zhí)行。如果驗(yàn)證失敗,那么將會(huì)拋出一個(gè)恰當(dāng)?shù)漠惓m憫?yīng)返回給用戶。對(duì)于傳統(tǒng)的 HTTP 請(qǐng)求,驗(yàn)證器會(huì)自動(dòng)生成一個(gè)重定向響應(yīng),而 AJAX 請(qǐng)求,則會(huì)返回 JSON 響應(yīng)。

為了能夠更好的理解 validate 方法,讓我們繼續(xù)回到 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...
 }

就如你所看到的,我們簡(jiǎn)單的傳遞了一個(gè) HTTP 輸入請(qǐng)求,并且在 validate 方法中設(shè)置了預(yù)期的驗(yàn)證約束。而這次,如果驗(yàn)證失敗,那么相應(yīng)的響應(yīng)會(huì)被自動(dòng)的生成并且被返回給請(qǐng)求用戶。如果驗(yàn)證通過(guò),那么我們的控制器會(huì)繼續(xù)執(zhí)行之后的業(yè)務(wù)。

在初次驗(yàn)證失敗時(shí)停止

有時(shí)候你希望在獲取首個(gè)驗(yàn)證約束失敗時(shí)停止當(dāng)前屬性其余約束的驗(yàn)證。你可以在屬性中加入 bail 約束:

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

在這個(gè)例子中,如果 title 屬性中的 required 約束驗(yàn)證失敗,那么 unique 約束就不會(huì)再被驗(yàn)證。約束是按照其被分配的順序來(lái)進(jìn)行驗(yàn)證的。

嵌套的屬性

如果你的 HTTP 請(qǐng)求包含了嵌套的參數(shù),你可以使用 . 語(yǔ)法來(lái)為其指定約束:

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

顯示驗(yàn)證錯(cuò)誤

那么,假如傳入的請(qǐng)求參數(shù)并沒(méi)有通過(guò)給定約束的驗(yàn)證怎么辦?就如前面所提到的,Laravel 會(huì)自動(dòng)的重定向用戶到之前的位置。另外,所有的驗(yàn)證錯(cuò)誤信息都會(huì)被自動(dòng)的閃存到 session 中。

你需要注意到我們并沒(méi)有明確的綁定錯(cuò)誤信息到 GET 路由的響應(yīng)視圖里。這是因?yàn)?laravel 會(huì)檢查閃存 seesion 里的錯(cuò)誤數(shù)據(jù),并且會(huì)自動(dòng)的在其可用時(shí)注入到視圖中。你可以在視圖中使用 $errors 變量,它是一個(gè) Illuminate\Support\MessageBag 實(shí)例。如果需要了解更多這個(gè)實(shí)例對(duì)象,請(qǐng)參考其 文檔

注意:$errors 變量是通過(guò) Illuminate\View\Middleware\ShareErrorsFromSession 中間件來(lái)綁定到視圖中的。這個(gè)中間件已經(jīng)被提供到了 web 中間件組中。這個(gè)中間件被應(yīng)用時(shí)會(huì)自主的在你的視圖中注入 $errors 變量,這允許你方便的假定 $errors 變量總是已經(jīng)被定義且可以安全的使用。

所以,在我們的例子中,當(dāng)驗(yàn)證失敗是,用戶將會(huì)被重定向到控制器的 create 方法中,這允許你在視圖中展示錯(cuò)誤信息:

<!-- /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 -->

自定義閃存錯(cuò)誤格式

如果你希望在驗(yàn)證失敗時(shí)可以自定義閃存進(jìn) session 中的錯(cuò)誤消息的格式,你需要在你的基礎(chǔ)控制器中復(fù)寫 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 請(qǐng)求 & 驗(yàn)證

在上面的示例中,我們使用傳統(tǒng)的表單來(lái)發(fā)送數(shù)據(jù)到應(yīng)用,事實(shí)上,如今很多應(yīng)用都使用 AJAX 請(qǐng)求,當(dāng)通過(guò) AJAX 請(qǐng)求來(lái)使用 validate 方法時(shí),laravel 并不會(huì)自動(dòng)生成重定向的響應(yīng),相反的,laravel 會(huì)生成一個(gè)包含了驗(yàn)證錯(cuò)誤消息的 JSON 響應(yīng)。并且該響應(yīng)會(huì)伴隨 422 HTTP 狀態(tài)碼。

驗(yàn)證數(shù)組

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

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

同樣的,你也可以在使用語(yǔ)言文件來(lái)指定特定的驗(yàn)證消息時(shí)使用 * 通配符。這可以輕而易舉的使用單條驗(yàn)證消息提供給基于數(shù)組的輸入:

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

其它驗(yàn)證途徑

手動(dòng)的創(chuàng)建 Validators

如果你不喜歡使用 ValidatesRequests trait 的 validator 方法,你也可以通過(guò)使用 Validator 假面來(lái)創(chuàng)建一個(gè) validator 實(shí)例。Validator 假面的 make 方法就可以生成一個(gè)新的 validator 實(shí)例:

<?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 方法所接受的第一個(gè)參數(shù)是需要被驗(yàn)證的數(shù)據(jù),第二個(gè)參數(shù)則是應(yīng)該施加到數(shù)據(jù)的驗(yàn)證約束。

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

被命名的錯(cuò)誤袋

如果你在一個(gè)獨(dú)立頁(yè)面中包含了多個(gè)表單。那么你可能會(huì)希望能對(duì) MessageBag 進(jìn)行命名以展示相應(yīng)的表單錯(cuò)誤。你可以直接在 withErrors 方法中傳遞第二個(gè)參數(shù)對(duì)其進(jìn)行命名:

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

你之后可以通過(guò) $errors 變量來(lái)訪問(wèn)被命名的 MessageBag 實(shí)例:

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

驗(yàn)證之后的 Hook

驗(yàn)證器也允許你在驗(yàn)證完成之后執(zhí)行特定的操作。這允許你輕松的進(jìn)行進(jìn)一步的驗(yàn)證,你也可以在消息集合里添加更多的錯(cuò)誤消息。在驗(yàn)證器的實(shí)例上使用 after 方法來(lái)進(jìn)行 hook:

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

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

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

表單請(qǐng)求驗(yàn)證

對(duì)于更為復(fù)雜的驗(yàn)證場(chǎng)景,你或許希望構(gòu)建一個(gè)“表單請(qǐng)求”。表單請(qǐng)求是一個(gè)自定義的請(qǐng)求類,并且它包含了所有的驗(yàn)證邏輯。你可以使用 make:request Artisan CLI 命令來(lái)創(chuàng)建一個(gè)表單請(qǐng)求類:

php artisan make:request StoreBlogPostRequest

被生成的類會(huì)被存儲(chǔ)在 app/Http/Requests 目錄。讓我們?cè)?rules 方法中來(lái)添加一些驗(yàn)證約束:

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

那么,這些驗(yàn)證約束是如何被評(píng)定的?你所要做的所有的事情就是在你的控制器方法中添加該請(qǐng)求類的類型提示。傳入進(jìn)來(lái)的表單請(qǐng)求會(huì)在控制器方法調(diào)用之前被自動(dòng)的進(jìn)行約束驗(yàn)證,這意味著你完全不需要再你的控制器方法中添加任何的驗(yàn)證邏輯:

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

如果驗(yàn)證失敗,用戶會(huì)被自動(dòng)的重定向到他們之前的位置。那么驗(yàn)證錯(cuò)誤消息也會(huì)自動(dòng)的閃存進(jìn) session 數(shù)據(jù)中被用于顯示。如果你使用的是 AJAX 請(qǐng)求,那么會(huì)自動(dòng)的返回一個(gè)包含所有驗(yàn)證錯(cuò)誤消息的 JSON 格式的響應(yīng),它的 HTTP 狀態(tài)碼會(huì)被設(shè)置為 422。

授權(quán)表單請(qǐng)求

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

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

你應(yīng)該注意到了上述實(shí)例中的 route 方法的調(diào)用。這個(gè)方法用來(lái)在路由被訪問(wèn)時(shí)發(fā)放所定義的 URL 參數(shù),比如下面路由的 {comment} 參數(shù):

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

如果 authorize 方法返回 false,那么會(huì)響應(yīng)一個(gè) 403 的狀態(tài)碼,并且控制器的方法不會(huì)被執(zhí)行。

如果你計(jì)劃在應(yīng)用的其它部分來(lái)處理授權(quán)邏輯,你可以簡(jiǎn)單的在 authorize 方法中返回 true:

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

自定義閃存的錯(cuò)誤格式

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

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

自定義錯(cuò)誤消息

你也可以通過(guò)在請(qǐng)求類中復(fù)寫 messages 方法來(lái)自定義錯(cuò)誤消息。該方法應(yīng)該返回一個(gè)包含相應(yīng)錯(cuò)誤消息的鍵值對(duì)數(shù)組:

/**
 * 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',
   ];
 }

與錯(cuò)誤消息協(xié)作

在調(diào)用 Validator 實(shí)例的 errors 方法之后,你可以檢索到一個(gè) Illuminate\Support\MessageBag 的實(shí)例,這實(shí)例擁有多種便捷的方法來(lái)與錯(cuò)誤消息進(jìn)行交互。

檢索給定字段中的首個(gè)錯(cuò)誤消息

你可以使用 first 方法來(lái)檢索給定字段的首個(gè)錯(cuò)誤消息:

$message = $validator->errors();

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

檢索給定字段的所有錯(cuò)誤消息

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

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

檢索所有字段的所有錯(cuò)誤消息

你可以使用 all 方法來(lái)檢索所有字段的所有錯(cuò)誤消息所組成的數(shù)組:

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

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

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

使用給定的格式來(lái)檢索獲取錯(cuò)誤消息

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

使用給定的格式來(lái)檢索所有的錯(cuò)誤消息

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

自定義錯(cuò)誤消息

如果你需要,你可以使用自定義的錯(cuò)誤消息來(lái)取代默認(rèn)的驗(yàn)證消息。這里有幾種方式來(lái)指定自定義的消息。首先,你可以傳遞自定的消息作為 Validator::make 方法的第三個(gè)參數(shù):

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

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

在這個(gè)例子中,:attribute 占位符會(huì)被驗(yàn)證數(shù)據(jù)中真實(shí)的名稱所替換。你還可以利用其它的占位符到驗(yàn)證消息中,比如:

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

為給定的屬性指定錯(cuò)誤消息

有時(shí)候,你可能希望指定自定義的錯(cuò)誤消息到特定的字段。你可以使用 . 符號(hào)來(lái)進(jìn)行分割,屬性名應(yīng)該在前,約束應(yīng)該在后:

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

在語(yǔ)言文件中指定自定義消息

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

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

可用的驗(yàn)證約束

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

accepted

驗(yàn)證的字段必須為 yeson,1,或者 true。這通常用來(lái)驗(yàn)證服務(wù)條款的承諾。

active_url

驗(yàn)證的字段必須可以通過(guò) checkdnsrr PHP 方法的驗(yàn)證。

after:date

驗(yàn)證的字段必須是給定日期之后的值。日期會(huì)被傳遞到 strtotime PHP 方法:

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

你也可以指定使用其它字段的日期來(lái)進(jìn)行評(píng)估:

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

alpha

驗(yàn)證的字段必須全部是由字母字符組成的字符串。

alpha_dash

驗(yàn)證的字段可以是字母,數(shù)字,-,_ 所組成的字符串。

alpha_num

驗(yàn)證的字段必須全部由字母或數(shù)字所組成。

array

驗(yàn)證的字段必須是一個(gè) PHP array

before:date

驗(yàn)證的字段的值必須比指定的日期要早。指定的日期會(huì)被傳遞到 PHP 的 strtotime 方法。

between:min,max

驗(yàn)證的字段的大小必須在給定的 minmax 之間。字符串,數(shù)字和文件都會(huì)使用和 size 約束的相同的評(píng)估方式。

boolean

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

confirmed

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

date

驗(yàn)證的字段必須是一個(gè)有效的日期,它應(yīng)該能被 strtotime PHP 方法通過(guò)。

date_format:format

驗(yàn)證的字段必須匹配給定的格式。該格式會(huì)被 PHP date_parse_from_format 方法評(píng)定,你應(yīng)該只使用 date 或者 date_format 其中之一來(lái)進(jìn)行驗(yàn)證字段,不要全部都使用。

different:field

驗(yàn)證的字段必須與給定的字段不同。

digits:value

驗(yàn)證的字段必須是數(shù)字類型并且具有指定的長(zhǎng)度。

digits_between:min,max

驗(yàn)證的字段必須具有指定區(qū)間的長(zhǎng)度。

dimensions

驗(yàn)證的字段必須是一個(gè)圖片類型的,并且要求符合指定的參數(shù)約束:

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

可用的參數(shù)有:min_widthmax_widthmin_heightmax_heightwidthheightratio

distinct

當(dāng)與數(shù)組協(xié)作時(shí),驗(yàn)證的字段中必須不能含有重復(fù)的值:

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

email

驗(yàn)證的字段必須是一個(gè)郵件地址的格式。

exists:table,column

驗(yàn)證的字段必須能在指定數(shù)據(jù)庫(kù)表中檢索的到。

Exists 基礎(chǔ)約束用法

'state' => 'exists:states'

指定自定義列名稱

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

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

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

查詢條件也可以使用 ! 來(lái)表明否定值:

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

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

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

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

極個(gè)別的情況下,你可能需要在 exists 查詢下指定特定的數(shù)據(jù)庫(kù)連接。你可以使用 . 語(yǔ)法將數(shù)據(jù)庫(kù)連接名前置來(lái)進(jìn)行指定:

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

filled

驗(yàn)證的字段如果出現(xiàn),那么它一定不能為空值。

image

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

in:foo,bar,...

驗(yàn)證的字段必須是給定值列中的一個(gè)。

in_array:anotherfield

驗(yàn)證的字段必須是指定的字段中值列之一。

integer

驗(yàn)證的字段必須是一個(gè)整數(shù)。

ip

驗(yàn)證的字段必須是一個(gè) IP 地址。

json

驗(yàn)證的字段必須是合法的 JSON 字符串

max:value

驗(yàn)證的字段必須小于等于指定值。字符串,數(shù)字,和文件類型會(huì)與 size 約束使用相同的評(píng)估方法。

mimetypes:text/plain,...

驗(yàn)證的字段必須匹配給定的 MIME 類型:

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

為了判斷所上傳文件的 MIME 類型,laravel 會(huì)讀取文件的內(nèi)容并且會(huì)嘗試猜測(cè)文件的 MIME 類型,這可能會(huì)與客戶端提供的文件 MIME 類型有所區(qū)別。

mimes:foo,bar,...

驗(yàn)證的文件的 MIME 類型相應(yīng)的后綴必須是所列的值之一。

基礎(chǔ)用法

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

你只需要指定文件的擴(kuò)展,這個(gè)約束會(huì)針對(duì)文件的內(nèi)容進(jìn)行猜測(cè)文件的 MIME 類型,然后進(jìn)行擴(kuò)展驗(yàn)證。

完整的 MIME 類型和其相應(yīng)的擴(kuò)展后綴,你可以從 這里 找到。

min:value

驗(yàn)證的字段必須比指定的值要小。字符串,數(shù)字和文件類型會(huì)使用 size 約束相同的評(píng)估方法。

not_in:foo,bar,...

驗(yàn)證的字段不應(yīng)該包含在給定的值列中。

numeric

驗(yàn)證的字段必須是一個(gè)數(shù)值類型。

present

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

regex:pattern

驗(yàn)證的字段必須與給定的正則表達(dá)式相匹配。

注意:當(dāng)使用 regex 模式時(shí),你必須將約束放進(jìn)數(shù)組里來(lái)取代管道符分隔,特別是在正則表達(dá)式中包含管道符時(shí)。

required

驗(yàn)證的字段必須被提供并且不能為空值。判斷空值的依據(jù):

  • 值是 null
  • 值是空字符串
  • 值是一個(gè)空數(shù)組或者空的 Countable 對(duì)象
  • 值是一個(gè)沒(méi)有傳遞路徑的上傳的文件

required_if:anotherfield,value,...

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

required_unless:anotherfield,value,...

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

required_with:foo,bar,...

驗(yàn)證的字段只有在其它所指定字段之一被提供時(shí)才會(huì)被要求提供。

required_with_all:foo,bar,...

驗(yàn)證的字段只有在其它所指定字段全部被提供時(shí)才會(huì)被要求提供。

required_without:foo,bar,...

驗(yàn)證的字段只有在其它所指定字段之一沒(méi)有被提供時(shí)被要求提供。

required_without_all:foo,bar,...

驗(yàn)證的字段只有在所指定字段全部沒(méi)有被提供時(shí)才會(huì)被要求提供。

same:field

所驗(yàn)證的字段必須與指定的字段相匹配。

size:value

驗(yàn)證的字段必須具有給定值的大小。對(duì)于字符串?dāng)?shù)據(jù),值應(yīng)該是字符串的字符長(zhǎng)度。對(duì)于數(shù)值數(shù)據(jù),值應(yīng)該是相應(yīng)的整數(shù)值。對(duì)于數(shù)組,大小匹配數(shù)組的 count 大小。對(duì)于文件,應(yīng)該匹配文件的字節(jié)大小。

string

驗(yàn)證的字段必須是一個(gè)字符串。

timezone

驗(yàn)證的字段必須是經(jīng)過(guò) PHP timezone_identifiers_list 方法驗(yàn)證的合法的 timezone 標(biāo)識(shí)。

unique:table,column,except,idColumn

驗(yàn)證的字段必須在給定的數(shù)據(jù)表中唯一,如果 column 選型沒(méi)有被指定,那么會(huì)直接使用字段的名字。

指定自定義的列名

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

自定義數(shù)據(jù)庫(kù)連接

極少數(shù)情況下,你可能需要指定自定義的數(shù)據(jù)庫(kù)連接來(lái)進(jìn)行驗(yàn)證。就如上面所看到的,設(shè)置 unique:users 會(huì)使用默認(rèn)的數(shù)據(jù)庫(kù)連接來(lái)進(jìn)行約束驗(yàn)證。如果想指定其他數(shù)據(jù)庫(kù)連接,你可以使用 . 語(yǔ)法并前置指定數(shù)據(jù)庫(kù)連接:

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

強(qiáng)迫 Unique 約束 忽略給定的 ID

有時(shí)候,你可能會(huì)希望 unique 檢查忽略給定的 ID。比如,考慮一下一個(gè)更新個(gè)人信息的場(chǎng)景,它應(yīng)該提供用戶的名稱,郵箱地址,和位置。你可能會(huì)想要驗(yàn)證郵箱的唯一性。但是你只想驗(yàn)證與用戶的當(dāng)前郵箱不一致的郵箱的唯一性。也就是說(shuō)你只想驗(yàn)證這個(gè)郵箱有沒(méi)有被其他用戶所使用。你需要傳遞 ID 作為第三個(gè)參數(shù)來(lái)通知 unique 約束來(lái)忽略當(dāng)前用戶的 ID:

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

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

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

添加額外的條件查詢

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

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

在上面的約束中,只有 account_id1 的行會(huì)被約束進(jìn)行檢查。

url

驗(yàn)證的字段必須符合 PHP filter_var 方法驗(yàn)證的有效 URL。

添加約束條件

在一些場(chǎng)景中,你會(huì)希望只有字段出現(xiàn)在了輸入數(shù)組中時(shí)才會(huì)對(duì)其進(jìn)行驗(yàn)證。你可以在約束列中添加 sometimes 約束來(lái)快速的完成指定:

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

這上面的例子中,只有 $data 中提供了 email 字段,email 的約束才會(huì)對(duì)其進(jìn)行驗(yàn)證。

復(fù)雜的驗(yàn)證條件

有時(shí)候,你可能會(huì)希望基于更復(fù)雜的條件邏輯去進(jìn)行約束的驗(yàn)證。比如,你希望只有另外一個(gè)字段擁有比 100 更大的值時(shí)才會(huì)驗(yàn)證給定的字段是否被提供。又或者你想要在只有另外一個(gè)字段被提供時(shí)才會(huì)需要其他兩個(gè)字段的值。添加這些條件判定并非是痛苦的一件事。首先,你還是需要?jiǎng)?chuàng)建一個(gè) Validator 實(shí)例和一些靜態(tài)的約束:

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

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

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

傳遞到 sometimes 方法的第一個(gè)參數(shù)是我們需要考慮驗(yàn)證的字段的名字。第二個(gè)參數(shù)是我們想要添加的約束。如果第三個(gè)參數(shù)傳遞的 Closure 返回的結(jié)果是 true,那么這個(gè)約束就會(huì)被添加進(jìn)去。這就可以輕松的對(duì)復(fù)雜的驗(yàn)證場(chǎng)景進(jìn)行條件的構(gòu)建。你甚至可以一次性的添加多個(gè)字段的條件驗(yàn)證:

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

注意:傳遞到 Closure 中的 $input 是一個(gè) Illuminate\Support\Flument 實(shí)例,并且它可以被用來(lái)訪問(wèn)你的輸入和文件。

自定義驗(yàn)證約束

Laravel 提供了各種有用的驗(yàn)證約束。但是,你可能希望添加你自己的特定的約束。你可以使用 Validator 假面的 extend 方法來(lái)注冊(cè)自己的驗(yàn)證約束。讓我們?cè)诜?wù)提供者里注冊(cè)一個(gè)自定義的驗(yàn)證約束:

<?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()
    {
      //
    }
}

自定義的驗(yàn)證閉包中接收四個(gè)參數(shù):需要被驗(yàn)證的屬性名稱,屬性的值,一個(gè)需要被傳遞到約束的 $paramters 數(shù)組,和 Validator 實(shí)例。

你也可以傳遞一個(gè)類名和方法到 extend 方法中來(lái)代替閉包:

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

定義錯(cuò)誤消息

你也需要為你的自定義約束添加一個(gè)錯(cuò)誤消息。你可以使用行內(nèi)自定義錯(cuò)誤消息或者將其添加到獨(dú)立的驗(yàn)證語(yǔ)言文件中。這個(gè)消息應(yīng)該被存放在數(shù)組的一維中,而不是包含在 custom 數(shù)組里:

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

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

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

當(dāng)構(gòu)建自定義的驗(yàn)證約束時(shí),你或許有時(shí)候也想為錯(cuò)誤消息定義一些占位符。你可以使用 Validator 假面的 replacer 方法來(lái)進(jìn)行占位替換。你可以在服務(wù)提供者的 boot 方法中來(lái)做這些:

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

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

隱式的擴(kuò)展

默認(rèn)的,當(dāng)屬性被驗(yàn)證時(shí),如果在輸入數(shù)組中沒(méi)有被提供,或者驗(yàn)證約束為 required 卻是一個(gè)空值。那么普通的驗(yàn)證約束,包括自定義的約束擴(kuò)展,都不會(huì)再執(zhí)行。比如,unique 約束就不會(huì)在出現(xiàn) null 值進(jìn)行執(zhí)行:

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

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

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

如果需要約束即使是屬性值為空時(shí)也繼續(xù)執(zhí)行,那么約束需要暗示屬性是必須的。你可以使用 Validator::extendImplicit() 方法來(lái)構(gòu)建一個(gè) “隱式的” 擴(kuò)展:

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1、簡(jiǎn)介 Laravel 提供了多種方法來(lái)驗(yàn)證應(yīng)用輸入數(shù)據(jù)。默認(rèn)情況下,Laravel 的控制器基類使用Valid...
    伊Summer閱讀 1,557評(píng)論 0 3
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,993評(píng)論 19 139
  • HTML表單 在HTML中,表單是 ... 之間元素的集合,它們?cè)试S訪問(wèn)者輸入文本、選擇選項(xiàng)、操作對(duì)象等等,然后將...
    蘭山小亭閱讀 3,443評(píng)論 2 14
  • 前言 : Laravel 提供了多種方法來(lái)驗(yàn)證應(yīng)用輸入數(shù)據(jù)。默認(rèn)情況下,Laravel 的控制器基類使用Valid...
    科哚洛夫閱讀 5,079評(píng)論 0 2
  • 1. Two Sum Given an array of integers, returnindicesof th...
    LdpcII閱讀 488評(píng)論 0 0