Yii Framework Forum: Saving relation - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Saving relation Rate Topic: -----

#1 User is offline   juhe 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 26
  • Joined: 18-October 09

Posted 18 October 2009 - 02:39 PM

Coming from J2EE platform and having background with hibernate and JPA it seems wierd to me that I cannot update relation this way:

$parent->child = $child;
$parent->save();

It doesnt persist new relation, instead you have to do:
$parent->child_id = $child->id; (persisted relation)
$parent->child = $child; (online relation)
$parent->save();

Why is this necessary or am I missing something?
0

#2 User is offline   Anastazas 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 3
  • Joined: 03-August 09

Posted 19 October 2009 - 01:32 AM

Hello,

Thats what bugged me for a while too. To solve this, I wrote a behavior that executes cascaded save on all desired child objects:

class CascadeSaveBehavior extends CActiveRecordBehavior
{
    public $relations = array();
    
    public function afterSave($event)
    {
        foreach($this->relations as $relation => $attributes)
        {
            if($this->Owner->hasRelated($relation))
            {
                if(is_numeric($relation))
                {
                    $relation = $attributes;
                    
                    $attributes = array();
                }
                
                $objects = $this->Owner->getRelated($relation);
                
                if($objects !== null)
                {
                    foreach($attributes as $attribute => $value)
                    {
                        if($value === $this->Owner)
                        {
                            $attributes[$attribute] = $this->Owner->id;
                        }
                    }
                    
                    if(is_array($objects))
                    {
                        foreach($objects as $object)
                        {
                            foreach($attributes as $attribute => $value)
                            {
                                $object->setAttribute($attribute, $value);
                            }
                        
                            $object->save();
                        }
                    }
                    else
                    {
                        foreach($attributes as $attribute => $value)
                        {
                            $objects->setAttribute($attribute, $value);
                        }
                        
                        $objects->save();
                    }
                }
            }
        }
        
        return true;
    }    
}

Usage example:

    
public function relations()
{
    return array(
        'sampleRelation' => array(self::HAS_MANY, 'ChildClass', 'parentId')
    );
}

public function behaviors()
{
    return array(
        'CascadeSaveBehavior' => array(
            'class' => 'application.components.behaviors.CascadeSaveBehavior',
            'relations' => array(
                // Here we set the attributes of child elements before saving them.
                'sampleRelation' => array('parentId' => $this, 'attribute' => 'value', ...)
            )
        )
     );
 }

I think this behavior could be made more complete by automating the setting of foreign keys. At the moment, for 'has many' relation foreign key should be specified with 'foreignKeyField' => $this. Many other improvements could be made too, I think (like avoid saving objects without changes).
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users