当使用Massive Assignment时,如果form内的数据没有在rules验证规则中明确的指定,对这个字段的赋值将不会生效, 对于那些没有特殊要求的字段至少也好设置safe规则。 ?phppublic function actionCreate(){$model=new Post;if(isset($_POST['Post'])){$model-
当使用Massive Assignment时,如果form内的数据没有在rules验证规则中明确的指定,对这个字段的赋值将不会生效,
对于那些没有特殊要求的字段至少也好设置safe规则。
<?php public function actionCreate() { $model=new Post; if(isset($_POST['Post'])) { $model->attributes=$_POST['Post'];//tag A if($model->save()) $this->redirect(array('view','id'=>$model->id)); } $this->render('create',array( 'model'=>$model, )); }
看tag A部分,它执行了一下的流程:
The key is $model->attributes = $_POST['Comment'];, which is deceptively simple.In reality this is calling
$model->setAttributes( $_POST['Comment'] ); // this is an array!
CModel的setAttributes详细代码如下:
<?php public function setAttributes($values,$safeOnly=true) { if(!is_array($values)) return; $attributes=array_flip($safeOnly ? $this->getSafeAttributeNames() : $this->attributeNames());// tag B foreach($values as $name=>$value)?//tag E { if(isset($attributes[$name])) $this->$name=$value;//tag F else if($safeOnly)//tag G $this->onUnsafeAttribute($name,$value); } }
看tag B 部分,因为$safeOnly默认是true,所以这里首先开始执行$this->getSafeAttributeNames();
CModel的getSafeAttributeNames详细代码如下:
<?php public function getSafeAttributeNames() { $attributes=array(); $unsafe=array(); foreach($this->getValidators() as $validator)?//tag C { if(!$validator->safe) { foreach($validator->attributes as $name) $unsafe[]=$name; } else { foreach($validator->attributes as $name) $attributes[$name]=true; } } foreach($unsafe as $name) unset($attributes[$name]); return array_keys($attributes); }
看tag C部分,此处开始执行$this->getValidators();
CModel的getValidators详细代码如下:
<?php public function getValidators($attribute=null) { if($this->_validators===null) $this->_validators=$this->createValidators();//tag D $validators=array(); $scenario=$this->getScenario(); foreach($this->_validators as $validator) { if($validator->applyTo($scenario)) { if($attribute===null || in_array($attribute,$validator->attributes,true)) $validators[]=$validator; } } return $validators; }
看tag D部分,代码如下:
<?php public function createValidators() { $validators=new CList; foreach($this->rules() as $rule) { if(isset($rule[0],$rule[1])) // attributes, validator name $validators->add(CValidator::createValidator($rule[1],$this,$rule[0],array_slice($rule,2))); else throw new CException(Yii::t('yii','{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.', array('{class}'=>get_class($this)))); } return $validators; }
可以看到在这个方法中开始使用验证规则,如果$this->rules()是个空数组则foreach内的消息体都不会被执行,直接执行下面的return $validators;
最终返回了空的CList的实例。现在回到getValidators()方法,$this->_validators就是一个空的CList实例,$validators初始化为空数组,getValidators直接返回$validators到getSafeAttributeNames的tag C处,同理getSafeAttributeNames也返回了空的数组给setAttributes的tag B处。
最终$attributes为空数组。在执行tag E处循环时一直执行tag G而不是执行tag F部分,而tag F部分才是真正的绑定值。
参考地址:http://www.yiiframework.com/wiki/161/understanding-safe-validation-rules/
原文地址:yii ar中的rules()规则在收集表单中的一些作用, 感谢原作者分享。