Hi everyone,
let´s think about pimping up our relation ActiveRecord up even further.
Assuming the following MANY-to-MANY relation:
Post has:
'categories'=>array(self::MANY_MANY, 'Category',
'tbl_post_category(post_id, category_id)'),
Category has:
'posts'=>array(self::MANY_MANY, 'Post',
'tbl_post_category(category_d, post_id)'),
Now we can do this:
$post = new Post();
$post->categories = Category::model()->findAll();
$post->save();
This will save our new Post in the table Post, and in addition to this it updates our N:M-Table with every Category available in the System.
We can also do this:
$category = new Category();
$category->posts = array(5, 6, 7, 10);
$caregory->save();
This saves our new Category and adds the Post with the primary key of 5, 6, 7 and 10 in the Databases. 5 Queries will be performed here, one for the Category-Model and four for the N:M-Table tbl_post_category.
We can also pass a single object:
$category = new Category();
$category->posts = Post::model()->findByPk(12);
$category->save();
or a single integer:
$post = new Post();
$post->categories = 7;
$post->save();
This is my basic implementation of this behavior. It would like to hear what you low-level Yii Cracks think about it
Place this anywhere in your Model file:
public function afterSave() {
parent::afterSave();
Yii::trace('writing MANY_MANY data for '.get_class($this),'system.db.ar.CActiveRecord');
foreach($this->relations() as $key => $relation)
{
if($relation['0'] == self::MANY_MANY) // relationType
{
if(isset($this->$key))
{
if(is_object($this->$key) || is_numeric($this->$key))
{
$query = $this->makeManyManyCommand(
$relation[2],
$this->{$this->tableSchema->primaryKey},
(is_object($this->$key))
? $this->$key->{$this->$key->tableSchema->primaryKey}
: $this->{$key});
$this->insertManyManyEntry($query);
}
else if (is_array($this->$key) && $this->$key != array())
{
foreach($this->$key as $foreignobject)
{
$query = $this->makeManyManyCommand(
$relation[2],
$this->{$this->tableSchema->primaryKey},
(is_object($foreignobject))
? $foreignobject->{$foreignobject->tableSchema->primaryKey}
: $foreignobject);
$this->insertManyManyEntry($query);
}
}
}
}
}
}
public function insertManyManyEntry($query) {
if(!Yii::app()->db->createCommand($query)->execute())
throw new CException(Yii::t('yii','an Error occured while trying to update MANY_MANY relation table'));
}
public function makeManyManyCommand($model, $rel, $foreignrel) {
return sprintf("insert into %s values ('%s', '%s')", $model, $rel, $foreignrel);
}