PDA

View Full Version : یه باگ کوچیک تو activerecord



mojtaba.baghban
چهارشنبه 16 اسفند 1391, 12:34 عصر
فرض کنید کلاس book رو از activerecord مشتق کردین حالا اگه مثلا کد زیر رو وارد کنید


$obj = new book();
echo $obj->birthday;

با یک استثنا روبرو خواید شد که میگه:
Property "Book.birthday" is not defined.
که با توجه به نحوه تعریف تابع جادویی __get در activerecord و component طبیعیه.
حالا اگه کد زیر را وارد کنیم


$obj = new book();
echo $obj->attribute();

دیگه با استثنا
Property "Book.birthday" is not defined.
مواجه نمیشیم و بجاش یک هشدار php داریم که میگه
Missing argument 1 for CActiveRecord::getAttribute(), called in /path/to/yii/base/CComponent.php on line xxx and defined
حالا اگه تابع __get رو در activerecord و component یه مروری بکنیم:
activerecord :


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);
}


component :


public function __get($name)
{
$getter='get'.$name;
if(method_exists($this,$getter))
return $this->$getter();
elseif(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
{
// duplicating getEventHandlers() here for performance
$name=strtolower($name);
if(!isset($this->_e[$name]))
$this->_e[$name]=new CList;
return $this->_e[$name];
}
elseif(isset($this->_m[$name]))
return $this->_m[$name];
elseif(is_array($this->_m))
{
foreach($this->_m as $object)
{
if($object->getEnabled() && (property_exists($object,$name) || $object->canGetProperty($name)))
return $object->$name;
}
}
throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',
array('{class}'=>get_class($this), '{property}'=>$name)));
}


وقتی ما
$obj->attribute رو صدا میزنیم تابع __get از activerecord فراخوانی میشه و چون نمی‌تونه چیزی برگردونه میآد __get والدش یعنی model رو صدا میزنه و چون model تابع جادویی __get رو پیاده‌سازی نکرده لذا __get از کلاس component فراخوانی میشه که اونم با توجه به تعریفش میاد getattribute() رو فراخوانی میکنه که تعداد پارامتراش با اون چیزی که تو activerecord پیاده‌سازی شده فرق می‌کنه و همین باعث میشه php هشدار بده.
خلاصه مطلب اینکه توابع setattribute و getattribute در activerecord با توجه به تعریف توابع جادویی __get و __set در component باعث میشه که php فکر کنه کلاسهایی که از activerecord مشتق میشن داری خاصیتی به نام attribute هستند که در واقع درست نیست.