Laravel本身內(nèi)置了許多好用的數(shù)據(jù)校驗(yàn)規(guī)則,拿來即用,但這遠(yuǎn)遠(yuǎn)不夠,我們需要自定義自己的驗(yàn)證規(guī)則是必要的,先看一個(gè)簡單的示例:
簡單驗(yàn)證
直接在
app\Providers\AppServiceProvider.php里擴(kuò)展Validator類
打開 app\Providers\AppServiceProvider.php ,在 boot()方法里添加我們自己的驗(yàn)證規(guī)則,比方說我們需要一個(gè)驗(yàn)證是祖國的手機(jī)號碼(+86):
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Validator;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Validator::extend('cn_phone', function($attribute, $value, $parameters) {
return substr($value, 0, 3) == '+86';
});
}
}
參考文檔我們發(fā)現(xiàn),自定義驗(yàn)證器閉包接收四個(gè)參數(shù),分別是要驗(yàn)證的屬性名稱、屬性值、傳遞給規(guī)則的參數(shù)數(shù)組以及 Validator 實(shí)例。
這里:cn_phone 是我們將在驗(yàn)證請求類中使用的規(guī)則名稱,驗(yàn)證通過返回 TRUE , 失敗返回 FALSE,參數(shù) $attribute 是要驗(yàn)證的字段的名稱,參數(shù) $parameters 用于更復(fù)雜的驗(yàn)證規(guī)則,像 Laravel 中默認(rèn)存在的 min:x 或 same:field 這種。
下面演示:
定義一個(gè) /form_store 路由指向 FormController 的 postForm 方法,再定義個(gè)請求類 CreateUserRequest 依賴注入。
public function postForm(CreateUserRequest $request)
{
return "Success!";
}
app\Http\Requests\CreateUserRequest.php
<?php
namespace App\Http\Requests;
class CreateUserRequest extends Request {
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'phone' => 'required|cn_phone',
];
}
}
我就用自帶的 welcome.blade.php 模板頁面給大家演示一下:
<div class="content">
<div class=title m-b-md>
@if(count($errors) > 0)
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
@endif
<form action="{{ url('form_store') }}" method="post">
{{ csrf_field() }}
<input type="text" name="phone">
<input type="submit" value="確認(rèn)">
</form>
</div>
</div>
preview:

好像出錯(cuò)提示出來了,有木有,但是這不是我們想要的,我們要自定義一個(gè)錯(cuò)誤消息。打開 resources/lang/en/validation.php 找到
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
按照此格式要求,改寫成我們定義的驗(yàn)證字段和對應(yīng)的返回錯(cuò)誤消息提示:
'custom' => [
'phone' => [
'zn_phone' => '請加手機(jī)號的國際區(qū)號+86',
],
],
再次驗(yàn)證:

這還遠(yuǎn)遠(yuǎn)不夠,對于復(fù)雜的數(shù)據(jù)驗(yàn)證呢?
復(fù)雜驗(yàn)證
自定義的
Validator類
假設(shè)有這么個(gè)驗(yàn)證要求,是phone和
首先我們想到的是這個(gè)自定義驗(yàn)證類放哪里好呢?這里我個(gè)人建議在
app下新建一個(gè)目錄,我取名為Librarys,這里放一些公共函數(shù)庫,第三方支付模塊以及我們的自定義驗(yàn)證類等等。上代碼:
app\Providers\MyValidator.php
<?php
namespace App\Librarys;
use Illuminate\Validation\Validator;
class MyValidator extends Validator {
public function validateEmptyWith($attribute, $value, $parameters)
{
return ($value != '' && $this->getValue($parameters[0]) != '') ? false : true;
}
}
App\Providers\AppServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider;
use App\Librarys;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Validator::resolver(function($translator, $data, $rules, $messages)
{
return new MyValidator($translator, $data, $rules, $messages);
});
}
resources\lang\en\validation.php
'custom' => [
'phone' => [
'empty_with' => '只能填一個(gè)字段,不能同時(shí)',
],
],
定義好驗(yàn)證類,這個(gè)類只是擴(kuò)展了 Laravel的內(nèi)置驗(yàn)證基類,想讓我們的驗(yàn)證規(guī)則被 Laravel “承認(rèn)”,必須進(jìn)入 AppServiceProvider 用 boot 方法啟動載入。
分析返回條件,想一想如果達(dá)不到上面的“需求”,那意味著:
- 不輸入手機(jī)號,輸入郵箱
- 不輸入手機(jī)號,不輸入郵箱
- 兩者都不輸入
滿足這三個(gè)條件即為驗(yàn)證通過,那么取反后判斷條件如上,大家不用糾結(jié)這個(gè)判斷,著重看 $this->getValue($parameters[0]) 這個(gè)方法,參數(shù)數(shù)組 $parameters[0] 為對應(yīng)第一個(gè)驗(yàn)證規(guī)則,類似 min:xxx, 這里是 empty_with:email,通過該參數(shù)獲取 email 對應(yīng)的值傳入 getValue() 中再返回 bool 值。問題來了,為什么是 empty_with:email 不是 emptyWith:email 或其他的呢,其實(shí)框架內(nèi)部已經(jīng)為我們處理好了名稱的對應(yīng)的格式,我們自定義的驗(yàn)證類里的驗(yàn)證方法必須以 validate 開頭然后接小駝峰命名,對應(yīng)驗(yàn)證規(guī)則的名稱就是下劃線的方式。這點(diǎn)要牢記。
效果圖就不放了,大家可以嘗試下,這樣,基本上我們單獨(dú)自定義的驗(yàn)證類結(jié)構(gòu)就比較清晰了,利用面向?qū)ο蟮姆绞匠殡x出獨(dú)立的驗(yàn)證類,更符合單一職責(zé)原則,這里其實(shí)還可以優(yōu)化,比如獨(dú)立出一個(gè) ValidationExtensionServiceProvider extends ServiceProvider:
class ValidationExtensionServiceProvider extends ServiceProvider
{
public function register() {}
public function boot()
{
$this->app->validator->resolver( function( $translator, $data, $rules, $messages = array(), $customAttributes = array() ) {
return new ValidatorExtended( $translator, $data, $rules, $messages, $customAttributes );
} );
}
}
然后告訴 laravel 載入該服務(wù),app/config/app.php 里添加進(jìn)去。這樣就更符合 Laravel Way 了。