Quantcast
Channel: Yii Framework Forum
Viewing all articles
Browse latest Browse all 18717

please test my AR Enhancement: automatically sync MANY_MANY table when calling save()

$
0
0
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);
  }


Viewing all articles
Browse latest Browse all 18717

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>