關(guān)于Laravel參數(shù)驗(yàn)證的一些疑與惑
驗(yàn)證器怎么創(chuàng)建的,誰(shuí)創(chuàng)建的
Laravel 文檔調(diào)用驗(yàn)證器,除了通過(guò)控制器,還有就是通過(guò)Facades的方式創(chuàng)建驗(yàn)證器對(duì)象。Validator::make($data,$rule,$message)。
config/app.php 中注冊(cè)了'Validator' => Illuminate\Support\Facades\Validator::class。
<?php
namespace Illuminate\Support\Facades;
/**
* @see \Illuminate\Validation\Factory
*/
class Validator extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'validator';
}
}
從上面可以看出,Validator的實(shí)際實(shí)現(xiàn)類是容器中的validator對(duì)象,那這個(gè)validator對(duì)象是哪個(gè)?
<?php
namespace Illuminate\Foundation;
...
class Application extends Container implements ApplicationContract, HttpKernelInterface
{
...
public function registerCoreContainerAliases()
{
foreach ([
...
'validator'=> [
\Illuminate\Validation\Factory::class,
\Illuminate\Contracts\Validation\Factory::class
],
])
...
}
...
}
可以看出,最終創(chuàng)建驗(yàn)證器是通過(guò)實(shí)現(xiàn)\Illuminate\Contracts\Validation\Factory接口的\Illuminate\Validation\Factory類創(chuàng)建的。再來(lái)看看,這個(gè)工廠類怎么創(chuàng)建實(shí)際的驗(yàn)證器的。
//\Illuminate\Contracts\Validation\Factory 源碼
protected function resolve(array $data, array $rules, array $messages, array $customAttributes)
{
if (is_null($this->resolver)) {
return new Validator(
$this->translator,
$data,
$rules,
$messages,
$customAttributes
);
}
return call_user_func(
$this->resolver,
$this->translator,
$data,
$rules,
$messages,
$customAttributes
);
}
到這里,可以看出Laravel的驗(yàn)證器的創(chuàng)建都是通過(guò)特定的工廠類創(chuàng)建。
如果需要自定義驗(yàn)證器類(比如我需要把5.8的一些新功能遷移到5.5的版本上),有兩種方式:
一,創(chuàng)建一個(gè)自定義的工廠類。然后在AppServiceProvider中重新綁定新的驗(yàn)證器工廠創(chuàng)建類;
二,AppServiceProvider中通過(guò)resolver方法設(shè)置工廠類的resolver屬性,接管驗(yàn)證器的實(shí)例化,例如:
Validator::resolver(function($translator, $data, $rules, $messages, $customAttributes){
return new ExtendValidator($translator, $data, $rules, $messages, $customAttributes);
});
如何自定義驗(yàn)證規(guī)則
Laravel本身提供了很多通用的參數(shù)驗(yàn)證規(guī)則,但是對(duì)于一些特定的場(chǎng)景,還是需要提供驗(yàn)證規(guī)則的擴(kuò)展。
Laravel驗(yàn)證規(guī)則的擴(kuò)展有兩種方式。
1 通過(guò)extend方法擴(kuò)展
//這是一個(gè)簡(jiǎn)單的參數(shù)比較的驗(yàn)證規(guī)則,Laravel5.8中提供,Laravel5.5中未提供
//驗(yàn)證規(guī)則如下: 'max_num'=>'gte:min',
Validator::extend('gte',function($attribute, $value, $parameters, $validator){
if($value>=data_get($validator->getData(),$parameters[0]))
{
return true;
}
return false;
});
//\Illuminate\Contracts\Validation\Factory 源碼
public function extend($rule, $extension, $message = null)
{
$this->extensions[$rule] = $extension;
if ($message) {
$this->fallbackMessages[Str::snake($rule)] = $message;
}
}
//\Illuminate\Validation\Validator 源碼
protected function callExtension($rule, $parameters)
{
$callback = $this->extensions[$rule];
if (is_callable($callback)) {
return call_user_func_array($callback, $parameters);
} elseif (is_string($callback)) {
return $this->callClassBasedExtension($callback, $parameters);
}
}
protected function validateAttribute($attribute, $rule)
{
...
$method = "validate{$rule}";
if ($validatable && ! $this->$method($attribute, $value, $parameters, $this)) {
$this->addFailure($attribute, $rule, $parameters);
}
}
public function __call($method, $parameters)
{
$rule = Str::snake(substr($method, 8));
if (isset($this->extensions[$rule])) {
return $this->callExtension($rule, $parameters);
}
throw new BadMethodCallException(sprintf(
'Method %s::%s does not exist.', static::class, $method
));
}
Factory提供了extend方法用于擴(kuò)展規(guī)則驗(yàn)證方法。所有的擴(kuò)展規(guī)則最終都會(huì)被傳到驗(yàn)證器中。驗(yàn)證器在驗(yàn)證參數(shù)的過(guò)程中,如果找到匹配的驗(yàn)證規(guī)則,則直接進(jìn)行驗(yàn)證。否則調(diào)用魔術(shù)方法__call查找擴(kuò)展驗(yàn)證函數(shù)。擴(kuò)展函數(shù)返回布爾值,返回true則表示驗(yàn)證通過(guò),返回false表示驗(yàn)證失敗。
2 通過(guò)自定義規(guī)則類擴(kuò)展
Laravel 中提供了Illuminate\Contracts\Validation\Rule接口,只有實(shí)現(xiàn)了這個(gè)接口的類都認(rèn)為是符合的自定義驗(yàn)證規(guī)則類。
<?php
namespace Illuminate\Contracts\Validation;
interface Rule
{
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value);
/**
* Get the validation error message.
*
* @return string
*/
public function message();
}
自定義規(guī)則類需要實(shí)現(xiàn)的方法有passes方法,用于驗(yàn)證參數(shù)是否合法。message方法,用于提供驗(yàn)證失敗的錯(cuò)誤提示信息。
使用自定義驗(yàn)證類,相對(duì)于extend方法擴(kuò)展有一個(gè)很大的bug就是無(wú)法在自定義類中獲取到當(dāng)期的驗(yàn)證器對(duì)象。從而導(dǎo)致在當(dāng)前擴(kuò)展的驗(yàn)證規(guī)則中,只能過(guò)獲取到需要驗(yàn)證的數(shù)據(jù),而獲取不到其他的字段數(shù)據(jù),無(wú)法進(jìn)行聯(lián)合字段的驗(yàn)證。像上面比較兩個(gè)字段的大小的驗(yàn)證規(guī)則就無(wú)法實(shí)現(xiàn)。
如果想要通過(guò)自定義驗(yàn)證規(guī)則類實(shí)現(xiàn)上面兩個(gè)字段大小比較的驗(yàn)證規(guī)則,則需要自定義驗(yàn)證類,修改validateUsingCustomRule方法,將當(dāng)期驗(yàn)證器傳入到自定義驗(yàn)證規(guī)則實(shí)例對(duì)象中去。
protected function validateUsingCustomRule($attribute, $value, $rule)
{
if(method_exists($rule, 'setValidator'))
{
$rule->setValidator($this);
}
return parent::validateUsingCustomRule($attribute,$value,$rule);
}
如何實(shí)現(xiàn)用當(dāng)期類方法作為驗(yàn)證規(guī)則驗(yàn)證函數(shù)
像Yii2中,因?yàn)榛旧纤械膶?duì)象都有驗(yàn)證方法,所以很容易用當(dāng)期類方法作為驗(yàn)證規(guī)則驗(yàn)證函數(shù)。
例如,一個(gè)驗(yàn)證規(guī)則如下,表示用當(dāng)期類的validateMinNum對(duì)參數(shù)進(jìn)行驗(yàn)證,那么,這樣的一個(gè)功能,如何在Laravel中實(shí)現(xiàn)呢。
['min_num'=>'validateMinNum']
方法1 通過(guò)自定義類實(shí)現(xiàn) Laravel提供了ClosureValidationRule自定義驗(yàn)證類,用來(lái)添加回調(diào)函數(shù)的驗(yàn)證。
例如
$rule = [ 'min'=>new ClosureValidationRule([$this,'checkv']) ]; $data = ['min'=>10]; $v = Validator::make($data,$rule);
方法2 通過(guò)extend方式實(shí)現(xiàn)
$rule = [
'min'=>'checkv'
];
Validator::extend('checkv',[$this,'checkv']);
但是這種方式對(duì)驗(yàn)證器的影響是全局的。不建議使用。
總結(jié)
通過(guò)以上源碼的學(xué)習(xí),可以看出Laravel驗(yàn)證器的創(chuàng)建都是用過(guò)驗(yàn)證器工廠類創(chuàng)建的。如果需要自定義驗(yàn)證器,可以通過(guò)修改驗(yàn)證器工廠類,或者設(shè)置驗(yàn)證器工廠類的resolver屬性接管驗(yàn)證器的實(shí)例化。
驗(yàn)證規(guī)則的擴(kuò)展有兩種方式,一種是通過(guò)extend方式實(shí)現(xiàn)。extend方式對(duì)驗(yàn)證器的影響是全局的,整個(gè)運(yùn)行進(jìn)程有效??梢垣@取到驗(yàn)證器本身,因此可以做多個(gè)字段關(guān)系的驗(yàn)證;另一種是通過(guò)自定義規(guī)則類實(shí)現(xiàn)。自定義規(guī)則了只對(duì)使用自定義規(guī)則類的驗(yàn)證有效。但是自定義規(guī)則類本身無(wú)法直接獲取到驗(yàn)證器本身,不能夠做多個(gè)字段關(guān)系的驗(yàn)證。如果需要實(shí)現(xiàn),則需要使用自定義驗(yàn)證器,將驗(yàn)證器傳入到驗(yàn)證規(guī)則中去。
Laravel本身提供了ClosureValidationRule的驗(yàn)證規(guī)則用于處理回調(diào)函數(shù)驗(yàn)證規(guī)則。同時(shí)也可以使用extend方式進(jìn)行回調(diào)函數(shù)的驗(yàn)證。
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
- Laravel框架表單驗(yàn)證詳解
- Laravel中使用FormRequest進(jìn)行表單驗(yàn)證方法及問(wèn)題匯總
- 在Laravel框架里實(shí)現(xiàn)發(fā)送郵件實(shí)例(郵箱驗(yàn)證)
- Laravel框架實(shí)現(xiàn)發(fā)送短信驗(yàn)證功能代碼
- Laravel 5框架學(xué)習(xí)之表單驗(yàn)證
- Laravel4中的Validator驗(yàn)證擴(kuò)展用法詳解
- 使用 laravel sms 構(gòu)建短信驗(yàn)證碼發(fā)送校驗(yàn)功能
- Laravel中unique和exists驗(yàn)證規(guī)則的優(yōu)化詳解
- Laravel框架用戶登陸身份驗(yàn)證實(shí)現(xiàn)方法詳解
- Laravel5.2使用Captcha生成驗(yàn)證碼實(shí)現(xiàn)登錄(session巨坑)
相關(guān)文章
PHP SPL標(biāo)準(zhǔn)庫(kù)之文件操作(SplFileInfo和SplFileObject)實(shí)例
這篇文章主要介紹了PHP SPL標(biāo)準(zhǔn)庫(kù)之文件操作(SplFileInfo和SplFileObject)實(shí)例,本文講解SplFileInfo用來(lái)獲取文件詳細(xì)信息、SplFileObject遍歷、查找指定行、寫(xiě)入csv文件等內(nèi)容,需要的朋友可以參考下2015-05-05
php檢測(cè)網(wǎng)頁(yè)是否被百度收錄的函數(shù)代碼
下面給出一段php函數(shù),功能是檢測(cè)一個(gè)網(wǎng)頁(yè)是否被百度收錄,直接給出代碼2013-10-10
詳解Grunt插件之LiveReload實(shí)現(xiàn)頁(yè)面自動(dòng)刷新(兩種方案)
這篇文章主要通過(guò)兩種方案詳解Grunt插件之LiveReload實(shí)現(xiàn)頁(yè)面自動(dòng)刷新,需要的朋友可以參考下2015-07-07
php不使用插件導(dǎo)出excel的簡(jiǎn)單方法
這篇文章主要介紹了php不使用插件導(dǎo)出excel的簡(jiǎn)單方法,首先獲取需要導(dǎo)出的數(shù)據(jù)的數(shù)組,數(shù)組的格式在下面。之后就是定義文件名稱和需要導(dǎo)出的excel的樣式,最后就是循環(huán)數(shù)組,輸出數(shù)據(jù)了2014-03-03
php使用Session和文件統(tǒng)計(jì)在線人數(shù)
這篇文章主要介紹了php使用Session和文件統(tǒng)計(jì)在線人數(shù),本文直接給出實(shí)例代碼,需要的朋友可以參考下2015-07-07
laravel框架分組控制器和分組路由實(shí)現(xiàn)方法示例
這篇文章主要介紹了laravel框架分組控制器和分組路由實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了laravel框架分組控制器和分組路由的基本定義與使用方法,需要的朋友可以參考下2020-01-01
淺談thinkphp的nginx配置,以及重寫(xiě)隱藏index.php入口文件方法
今天小編就為大家分享一篇淺談thinkphp的nginx配置,以及重寫(xiě)隱藏index.php入口文件方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10

