在afterSave()中保存模型实例,使其递归运行


Save a model instance in afterSave(), won't it run recursive?

我需要对一些子模型数据求和,并将其存储在父模型实例属性中。但是为了保存属性值,我需要调用$this->save()$this->saveAttributes(array('<attr name>'));它不会永远递归地运行save()过程,如果不是,为什么不呢?Event model:

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

根据Jon的建议,我可能会这样做:

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

我已经更新了我的问题以显示模型的相关代码。我只从子模型累积到父属性的总和。根据lin的要求,我分享模型。这里最主要的是它们的关系:Event(父模型)和EventContent(子模型)与这个关系绑定:

Class EventContent extends CActiveRecord {
  ...
  public function relations()
  {
     return array(
        'event'=>array(self::BELONGS_TO, 'Event', 'eventId'),
     );
  }
}

您对afterSave()的实现是错误的,将导致save()afterSave()的无休止的方法调用,直到PHP达到其脚本执行时间限制。

你有两个选择:

  1. 按照Jon(你的更新1)的建议实现你的代码
  2. 保持afterSave()和使用saveAttributes()里面保存模型。saveAttributes()不会像官方API-docs
  3. 中描述的那样调用beforeSave()afterSave()

在我看来,最好的方法是将您的代码移动到save(),正如Jon已经建议的。