2

I need to sum count some child model data and store it in the parent model instance attribute. But for saving the attribute value I need to call $this->save() or $this->saveAttributes(array('<attr name>')); Won't it run save() procedure recursively forever and, if not, why not? Inside of 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'));
    }

}

Update 1

As suggested by Jon, I might do it in this way:

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

Update 2

I've updated my question to show the models' relevant code. I only accumulate sum total from child model into parent attribute. As asked by lin i share the models. The main thing here is their relation: Event (parent model) and EventContent (child model) are bound with this relation:

Class EventContent extends CActiveRecord {
  ...
  public function relations()
  {
     return array(
        'event'=>array(self::BELONGS_TO, 'Event', 'eventId'),
     );
  }
}
Igor Savinkin
  • 5,669
  • 8
  • 37
  • 69
  • 1
    You would do this inside `save` directly, not inside `afterSave`. – Jon Jul 29 '14 at 12:40
  • @Jon, do you mean i need to redefine/upgrade model's `save()` function? – Igor Savinkin Jul 29 '14 at 12:53
  • Post your GII generated and all related PHP-Models please. Calling `parent::save();` sounds totally wrong to me -> due to Yii MVC pattern and OOP. – lin Jul 29 '14 at 15:13
  • @lin: Calling `parent::save()` is *totally right* and has absolutely nothing to do with MVC. – Jon Jul 29 '14 at 15:25
  • @IgorSavinkin: Yeah. The full code might be relevant, but the general idea is just fine. It's what you are *supposed* to do. But, don't forget: a) to propagate the return value and b) Yii has calculated columns, which might be relevant. – Jon Jul 29 '14 at 15:26

1 Answers1

2

Your implementation of afterSave() is wrong and will result in endless method calls of save() and afterSave() until PHP reaches its script execution time limit.

You have two options:

  1. Implement your code as suggested by Jon (your Update 1)
  2. Stay with afterSave() and use saveAttributes() inside to save the model. saveAttributes() will not call beforeSave() and afterSave() as described in the official API-docs

In my opinion the best approach is to move your code to save() as Jon already suggested.

SaV
  • 313
  • 1
  • 4
  • thank you. Would you point to some docs related to your main argument and `saveAttributes()` will not call `beforeSave()` and `afterSave()`? – Igor Savinkin Aug 01 '14 at 14:04
  • I included a link to the API-docs where you can find the described behavior of `saveAttributes()` – SaV Aug 12 '14 at 08:55