Yii如何将CActiveRecord的属性数组link赋给class成员?
How does Yii link the attributes array of CActiveRecord to the class members?
我以前从未见过这个,想了解一下。这是我的代码 运行:
$q = new CDbCriteria(array(
'condition'=>'"pKey" = :pKey',
'params' => array(':pKey'=>$id)
));
$oldmodel = Inventory::model()->find($q); //Inventory extends CActiveRecord
$oldmodel->equipmentType = 'Display';
$tmp = $oldmodel->equipmentType;
$tmp2 = $oldmodel->attributes['equipmentType'];
结果是我一改$oldmodel->equipmentType
,$oldmodel->attributes['equipmentType']
就跟着改; $tmp
和 $tmp2
之后将设置为 'Display'。
class 成员如何链接到这样的数组?这不适用于 class 的所有 public 成员(我预料到了这一点)。我只想知道我自己怎么做,因为它看起来很有趣!
equipmentType
不是 public 属性。
当你find
(或findAll
)调用CActiveRecord
, populateRecord()时,它有以下代码($attributes
是来自数据库的列=>值对. 请特别注意 foreach
循环。):
public function populateRecord($attributes,$callAfterFind=true)
{
if($attributes!==false)
{
$record=$this->instantiate($attributes);
$record->setScenario('update');
$record->init();
$md=$record->getMetaData();
foreach($attributes as $name=>$value)
{
if(property_exists($record,$name))
$record->$name=$value;
elseif(isset($md->columns[$name]))
$record->_attributes[$name]=$value;
}
$record->_pk=$record->getPrimaryKey();
$record->attachBehaviors($record->behaviors());
if($callAfterFind)
$record->afterFind();
return $record;
}
else
return null;
}
因此,在您的情况下,$Inventory->_attribute['equipmentType']
填充了数据库中的数据。
如果您随后尝试引用伪 属性 equipmentType
,您实际上最终会调用 CActiveRecord 实例上的魔法 __get() 方法。
如您所见,第一个 if
语句将为真,导致存储的值被 returned。
public function __get($name)
{
if(isset($this->_attributes[$name]))
return $this->_attributes[$name];
elseif(isset($this->getMetaData()->columns[$name]))
return null;
elseif(isset($this->_related[$name]))
return $this->_related[$name];
elseif(isset($this->getMetaData()->relations[$name]))
return $this->getRelated($name);
else
return parent::__get($name);
}
请注意 __set() 将以互补的方式工作,因此当您自己设置属性时(除了从数据库加载时),它会更新 _attributes
属性 还有。
最后,当您尝试将 attributes
属性 作为数组访问时,就像您对 $oldmodel->attributes['equipmentType'];
所做的那样,您实际上是在调用 getAttributes() 方法,该方法再次,将 return 属性存储在 _attributes
属性.
所以,长话短说,大量使用(或滥用)魔术 __get 和 __set 方法允许这种情况发生。注意,我相信(但我自己还没有完全追踪逻辑)为了使用数组语法访问 attributes
,你必须像 CActiveRecord 一样,在你的 class 上实现 ArrayAccess。
只需按照文档页面说明,查看 CActiveRecord 如何实现所需的方法,您应该能够重复结果。
我以前从未见过这个,想了解一下。这是我的代码 运行:
$q = new CDbCriteria(array(
'condition'=>'"pKey" = :pKey',
'params' => array(':pKey'=>$id)
));
$oldmodel = Inventory::model()->find($q); //Inventory extends CActiveRecord
$oldmodel->equipmentType = 'Display';
$tmp = $oldmodel->equipmentType;
$tmp2 = $oldmodel->attributes['equipmentType'];
结果是我一改$oldmodel->equipmentType
,$oldmodel->attributes['equipmentType']
就跟着改; $tmp
和 $tmp2
之后将设置为 'Display'。
class 成员如何链接到这样的数组?这不适用于 class 的所有 public 成员(我预料到了这一点)。我只想知道我自己怎么做,因为它看起来很有趣!
equipmentType
不是 public 属性。
当你find
(或findAll
)调用CActiveRecord
, populateRecord()时,它有以下代码($attributes
是来自数据库的列=>值对. 请特别注意 foreach
循环。):
public function populateRecord($attributes,$callAfterFind=true)
{
if($attributes!==false)
{
$record=$this->instantiate($attributes);
$record->setScenario('update');
$record->init();
$md=$record->getMetaData();
foreach($attributes as $name=>$value)
{
if(property_exists($record,$name))
$record->$name=$value;
elseif(isset($md->columns[$name]))
$record->_attributes[$name]=$value;
}
$record->_pk=$record->getPrimaryKey();
$record->attachBehaviors($record->behaviors());
if($callAfterFind)
$record->afterFind();
return $record;
}
else
return null;
}
因此,在您的情况下,$Inventory->_attribute['equipmentType']
填充了数据库中的数据。
如果您随后尝试引用伪 属性 equipmentType
,您实际上最终会调用 CActiveRecord 实例上的魔法 __get() 方法。
如您所见,第一个 if
语句将为真,导致存储的值被 returned。
public function __get($name)
{
if(isset($this->_attributes[$name]))
return $this->_attributes[$name];
elseif(isset($this->getMetaData()->columns[$name]))
return null;
elseif(isset($this->_related[$name]))
return $this->_related[$name];
elseif(isset($this->getMetaData()->relations[$name]))
return $this->getRelated($name);
else
return parent::__get($name);
}
请注意 __set() 将以互补的方式工作,因此当您自己设置属性时(除了从数据库加载时),它会更新 _attributes
属性 还有。
最后,当您尝试将 attributes
属性 作为数组访问时,就像您对 $oldmodel->attributes['equipmentType'];
所做的那样,您实际上是在调用 getAttributes() 方法,该方法再次,将 return 属性存储在 _attributes
属性.
所以,长话短说,大量使用(或滥用)魔术 __get 和 __set 方法允许这种情况发生。注意,我相信(但我自己还没有完全追踪逻辑)为了使用数组语法访问 attributes
,你必须像 CActiveRecord 一样,在你的 class 上实现 ArrayAccess。
只需按照文档页面说明,查看 CActiveRecord 如何实现所需的方法,您应该能够重复结果。