Сохраните экземпляр модели в afterSave(), не будет ли он работать рекурсивно?
Мне нужно подсчитать некоторые данные дочерней модели и сохранить их в атрибуте экземпляра родительской модели. Но для сохранения значения атрибута мне нужно позвонить $this->save()
или же $this->saveAttributes(array('<attr name>'));
Разве это не будет работать save()
процедура рекурсивно навсегда и, если нет, то почему бы и нет? Внутри модели Event:
protected function afterSave()
{
parent::afterSave();
$contents = EventContent::model()->findAllByAttributes(array('eventId'=>$this->id));
if ($contents)
{
$sum=0;
foreach($contents as $content)
$sum += $content->cost;
$this->totalSum = $sum;
$this->save();
// or $this->saveAttributes(array('totalSum'));
}
}
Обновление 1
Как предположил Джон, я мог бы сделать это следующим образом:
protected function save()
{
$contents = EventContent::model()->findAllByAttributes(array('eventId'=>$this->id));
if ($contents)
{
$sum=0;
foreach($contents as $content)
$sum += $content->cost;
$this->totalSum = $sum; // no need to run $this->save() here
}
parent::save();
}
Обновление 2
Я обновил свой вопрос, чтобы показать соответствующий код модели. Я только накапливаю итоговую сумму из дочерней модели в родительский атрибут. Как спросил Лин, я делюсь моделями. Главное здесь - это их отношение: Event (родительская модель) и EventContent (дочерняя модель) связаны этим отношением:
Class EventContent extends CActiveRecord {
...
public function relations()
{
return array(
'event'=>array(self::BELONGS_TO, 'Event', 'eventId'),
);
}
}
1 ответ
Ваша реализация afterSave()
неправильно и приведет к бесконечным вызовам методов save()
а также afterSave()
пока PHP не достигнет своего времени выполнения скрипта.
У вас есть два варианта:
- Реализуйте свой код в соответствии с предложением Джона (ваше обновление 1)
- Оставаться с
afterSave()
и использоватьsaveAttributes()
внутри, чтобы сохранить модель.saveAttributes()
не буду звонитьbeforeSave()
а такжеafterSave()
как описано в официальных API-документах
На мой взгляд, лучший подход - переместить ваш код в save()
как Джон уже предложил.