Yii1.1的驗證規則


在Yii1.1的數據驗證是由CValidator完成,在CValidator中提供了各種基本的驗證規則

<?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類來處理這個問題

<?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必須將錯誤信息addError

   在驗證數據有效性的時候我們必須還需要考慮場景的問題,不同的場景需要提供不同的驗證規則,這點在ThinkPHP5中已經討論過,Tp5的解決方案是比較繁瑣而且不靈活的,那在Yii1.1中是怎么解決的呢?

   Yii1.1的CVaildate提供了"on"屬性和"except"屬性,而在CActiveRecord中初始化中我們可以看到

    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集合的

 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行:獲取當前所有驗證規則

代碼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代碼,分開一點不是更好么 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM