Saving Many to Many relationships

Hi all,

Im having some trouble figuring out how to save many to many relations

I ahve:


Class A extends CActiveRecord{

   public function relations()

	{

             'bs' => array(self::MANY_MANY, 'A', 'a_b(A_ID, B_ID)'),

		);

	}

}


Class B extends CActiveRecord{

   public function relations()

	{

             'as' => array(self::MANY_MANY, 'B', 'a_b(A_ID, B_ID)'),

		);

	}

}



Ive tryied :




$bs = Array();

$a = new A();

$a->bs = $bs;



But it fails, how can i save many to many relations?

Thanks,

Ok, Ive tryed modifyig a behaviour I found on the forum:

after using CActiverecord::addRelatedRecord();




$transaction = Yii::app()->db->beginTransaction();

try{

    $b = new B;

    $b->save();

    $a = new A;

    $a->addRelatedRecord('bs', $b, true);

    $a->save();

    $transaction->commit();

}catch(Exception $e)

{

    $transaction->rollBack();

} 







<?php


class ActiveRecordRelationSavableBehavior extends CActiveRecordBehavior

{

	public function afterSave($event)

	{

		$relations = $this->owner->relations();

		

		foreach($relations as $name=>$config)

		{

			if(!isset($config[0],$config[1],$config[2]))

				continue;

			if($config[0]!==CActiveRecord::MANY_MANY)

				continue;

			list($table,$fk1,$fk2) = $this->parseTableDefinition($config[2]);

			

			if(!$this->owner->isNewRecord) {

				$command=conn()->createCommand("DELETE FROM $table WHERE $fk1 = {$this->owner->primaryKey}");

				$command->execute();

				Yii::trace(get_class($this->owner).'.afterSave() relation: '.$name.' trying to execute: '."DELETE FROM $table WHERE $fk1 = {$this->owner->primaryKey}",'application.models.Leaf');

			}

			$relateds = $this->owner->getRelated($name);

			foreach($relateds as $rel) {

				$command=conn()->createCommand("INSERT INTO $table($fk1,$fk2) VALUES({$this->owner->primaryKey},{$rel->primaryKey}) ");

				$command->execute();

				Yii::trace(get_class($this->owner).'.afterSave() relation: '.$name.' trying to execute: '."INSERT INTO $table($fk1,$fk2) VALUES({$this->owner->primaryKey},{$rel->primaryKey}) ",'application.models.Leaf');

			}

		}

	}


	private function parseTableDefinition($table_definition) {

		preg_match('/([^(]+)\(([^,*]+), ([^)]+)\)/',$table_definition,$matches);

		if(count($matches) !== 4) {

			throw new CHttpException('404', "unable to parse $table_definition");

		}

		return array_slice($matches,1);

	}


}

?>

http://www.yiiframework.com/forum/index.php?/topic/3479-an-idea-for-handling-many-many-relationships/

But I having problems with transacctions,

In the controller I start a transacion, and inside of It i call Model::save() which triggers the afterSave of the behavior, the thing is that it fails on constraint validation on the foreing keys, because as I can think of, the transaccion hasent commited yet.

Which is weird cause the insertion shouldnt be "commited" either, until the whole transaccion (started in the controller) has been commited.

Any thoughs?

Solved :blush:

It was my own issue xD

The behavior works very well but you need to change the fk2 order from


$command=conn()->createCommand("INSERT INTO $table($fk1,$fk2) VALUES({$this->owner->primaryKey},{$rel->primaryKey}) ");


 $command=conn()->createCommand("DELETE FROM $table WHERE $fk1 = {$this->owner->primaryKey}");




to.


$command=conn()->createCommand("INSERT INTO $table($fk2,$fk1) VALUES({$this->owner->primaryKey},{$rel->primaryKey}) ");


 $command=conn()->createCommand("DELETE FROM $table WHERE $fk2 = {$this->owner->primaryKey}");



xD

I hate making this stupid mistakes that takes me time.

=(

Is there a full example code showing how it all works and fits in? Especially, how data gets to the model from the form and then gets saved to the database in the related tables?

Thanks in advance.