背景
我们在 Yii
中经常会这样处理传来的数据。
$newModel = new NewModel();
$newModel->attributes = $data->attributes;
$newModel->save();
整个过程如下:
新建一个 model
=> 给 model
参数赋值 => save
方法存入数据库
setAttribues 方法
先看到参数赋值这句话:
$newModel->attributes = $data->attributes;
这里会调用 CModel
类的 setAttributes
方法。
public function setAttributes($values,$safeOnly=true)
{
if(!is_array($values))
return;
$attributes=array_flip($safeOnly ? $this->getSafeAttributeNames() : $this->attributeNames());
foreach($values as $name=>$value)
{
if(isset($attributes[$name]))
$this->$name=$value;
elseif($safeOnly)
$this->onUnsafeAttribute($name,$value);
}
}
这里 $safeOnly
参数表示是否对产来的数据进行 rule
规则里的 safe
判断。经过此方法,首先 $attributes
会获得数据,其次我们可以用 $newModel->property
的形式来访问不同的属性。
至于这里为什么会调用 setAttribute()
方法,那是因为在 CModel
的父类CComponent
中重写了魔术方法 __set()
方法。部分代码如下:
public function __set($name,$value)
{
$setter='set'.$name;
if(method_exists($this,$setter))
return $this->$setter($value);
...
save 方法
$newModel
获得数据后,接下来我们看到 save
方法是如何定义的:
public function save($runValidation=true,$attributes=null)
{
if(!$runValidation || $this->validate($attributes))
return $this->getIsNewRecord() ? $this->insert($attributes) : $this->update($attributes);
else
return false;
}
save
方法有两个参数,第一个参数是 bool
类型,表示是否对传来的参数进行验证,第二个参数表示存储的参数数组,默认为空,表示传来的参数全部都将被存储。
如果 $runValidation
为 false
,那么就直接执行插入或更新,否则先执行
$this->validate($atttributes)
验证通过后返回 true
,再执行插入或更新,否则返回 false
。假设数据为新,那么接下来就是做 insert
操作。由于 insert
方法较长,这里截取关键语句分析:
$command=$builder->createInsertCommand($table,$this->getAttributes($attributes));
这里,我们看到通过 getAttributes
来获得参数列表,我们在 CModel
里看下getAttributes
方法的定义:
public function getAttributes($names=null)
{
$values=array();
foreach($this->attributeNames() as $name)
$values[$name]=$this->$name;
if(is_array($names))
{
$values2=array();
foreach($names as $name)
$values2[$name]=isset($values[$name]) ? $values[$name] : null;
return $values2;
}
else
return $values;
}
如果 $attributes
如果为空,则通过 $this->attributeNames()
获得全部合法参数,否则则获得 $attributes
列表中指定的参数。
总结
Yii
通过重写魔术方法来赋值 Model
,同时结合 rule
规则判断传入数据是否合法,继而存储数据。