在Yii1.1的數據驗證是由CValidator完成,在CValidator中提供了各類基本的驗證規則php
<?php public static $builtInValidators=array( 'required'=>'CRequiredValidator', 'filter'=>'CFilterValidator', 'match'=>'CRegularExpressionValidator', 'email'=>'CEmailValidator', 'url'=>'CUrlValidator', 'unique'=>'CUniqueValidator', 'compare'=>'CCompareValidator', 'length'=>'CStringValidator', 'in'=>'CRangeValidator', 'numerical'=>'CNumberValidator', 'captcha'=>'CCaptchaValidator', 'type'=>'CTypeValidator', 'file'=>'CFileValidator', 'default'=>'CDefaultValueValidator', 'exist'=>'CExistValidator', 'boolean'=>'CBooleanValidator', 'safe'=>'CSafeValidator', 'unsafe'=>'CUnsafeValidator', 'date'=>'CDateValidator', ); ?>
在Model文件中只須要定義rules方法即可以使用驗證規則前端
public function rules() { return array( array('bianhao, status', 'required','message'=>'{attribute}爲必填項目'), //bianhao,status是必須的;message:提供錯誤信息提示 array('lie, hang, status', 'numerical', 'integerOnly'=>true), //lie,hang,statusbi必須是數字並且必須是整形 array('bianhao', 'length', 'max'=>10), //bianhao的長度最可能是10位 ); }
在驗證數據有效性的時候,框架提供給咱們的驗證規則可能知足不了需求,這時候須要自定義驗證規則,在ThinkPhp中咱們須要新建一個驗證規則文件,這顯得就比較麻煩了,那Yii是如何解決這個問題的呢?Yii提供了一個CInlineValidator類來處理這個問題app
<?php if(method_exists($object,$name)) //$object當前驗證的模型類 { $validator=new CInlineValidator; $validator->attributes=$attributes; $validator->method=$name; if(isset($params['clientValidate'])) { $validator->clientValidate=$params['clientValidate']; unset($params['clientValidate']); } $validator->params=$params; if(isset($params['skipOnError'])) $validator->skipOnError=$params['skipOnError']; } ?>
只要在當前的驗證模型中存在該驗證方法那麼就綁定到CInlineValidator類中而在CInlineValidator中咱們能夠看到框架
<?php protected function validateAttribute($object,$attribute) { $method=$this->method; $object->$method($attribute,$this->params); } ?>
能夠看出,在Yii1.1中自定義驗證只須要在當前Model中建立就能夠了函數
<?php public function rules() { return array( array('lie,hang',"checkNumber","message"=>"{attribute}的值必須小於10"), //自定義checkNumber方法 ); } /** * checkNumber方法 * 驗證值是否小於10 */ public function checkNumber($attribute,$params=array()){ if($this->$attribute>10){ $tihuan['{attribute}']=$this->getAttributeLabel($attribute); $this->addError($attribute,strtr($params["message"],$tihuan)); } } ?>
注意:在驗證函數中不能直接return必須將錯誤信息addErrorui
在驗證數據有效性的時候咱們必須還須要考慮場景的問題,不一樣的場景須要提供不一樣的驗證規則,這點在ThinkPHP5中已經討論過,Tp5的解決方案是比較繁瑣並且不靈活的,那在Yii1.1中是怎麼解決的呢?this
Yii1.1的CVaildate提供了"on"屬性和"except"屬性,而在CActiveRecord中初始化中咱們能夠看到url
public function __construct($scenario='insert') { if($scenario===null) // internally used by populateRecord() and model() return; $this->setScenario($scenario); //咱們先看這個這是表示爲模型設置一個應用場景 $this->setIsNewRecord(true); $this->_attributes=$this->getMetaData()->attributeDefaults; $this->init(); $this->attachBehaviors($this->behaviors()); $this->afterConstruct(); }
在CActiveRecord初始化時咱們就須要爲該模型設置一個應用場景,默認應用場景爲"insert"。再來看CModel中是如何獲取當前須要驗證的Vaildator集合的spa
1 public function getValidators($attribute=null) 2 { 3 if($this->_validators===null) 4 $this->_validators=$this->createValidators(); 5 $validators=array(); 6 $scenario=$this->getScenario(); 7 foreach($this->_validators as $validator) 8 { 9 if($validator->applyTo($scenario)) 10 { 11 if($attribute===null || in_array($attribute,$validator->attributes,true)) 12 $validators[]=$validator; 13 } 14 } 15 return $validators; 16 }
代碼3-4行:獲取當前全部驗證規則code
代碼6行:獲取當前模型驗證規則
代碼7-14行:在這個foreach循環裏篩選符合當前場景的集合,咱們看下$validator->applyTo($scenario) 在CValidator中
1 public function applyTo($scenario) 2 { 3 if(isset($this->except[$scenario])) 4 return false; 5 return empty($this->on) || isset($this->on[$scenario]); 6 }
代碼3-4行:當前場景是否在$this->except中若是在則除掉該驗證規則
代碼5行:當前驗證規則若是沒有on屬性則保留該驗證規則,若是有on屬性而且當前場景在$this->on中則保留該規則若是不在則去除
到這,能發如今CValidator中"on"表示該驗證規則屬於哪一個場景(scenario),若是沒有"on"屬性則該驗證規則屬於任何場景,若是有"on"屬性的話則該驗證規則只能屬於該on屬性下的驗證規則;而"except"則偏偏相反,設置了"except"屬性就表示該驗證規則必定不屬於"except"下的場景
看下簡單的例子
1 public function rules() 2 { 3 return array( 4 array('lie,hang',"checkNumber","message"=>"{attribute}的值必須小於10","on"=>"update,insert"), 5 array('bianhao, status', 'required',"message"=>'{attribute}爲必填項目',"except"=>"insert"), 6 array('lie, hang, status', 'numerical', 'integerOnly'=>true), 7 array('bianhao', 'length', 'max'=>10), 8 ); 9 }
代碼4行:該驗證規則只能屬於update,insert下兩個應用場景
代碼5行:該驗證規則不屬於insert應用場景
代碼6-7行:該驗證規則屬於任何應用場景
想要使用不一樣場景該怎麼辦?很簡單隻須要初始化的時候指定場景就行了 $model=new Model($scenario),若是想改變場景怎麼辦?直接調用$model->setScenario(scenario)就能夠了。
總結:對比下與Tp5的驗證規則,Yii1.1的顯得更加簡潔輕便,對不一樣場景的調用也更加靈活,自定義驗證方法也只須要在Model自己添加自定義函數便可。
ps:Yii1.1還提供了前端JS的數據驗證方法,可是我表示不太喜歡在PHP中寫前端的JS代碼,分開一點不是更好麼