saving many many relationships

Hi everyone,

I just started to investiage the Yii framework since I'm looking for alternatives to CakePHP. The main reason why I want to stop using cake is because of its php4 implementation of ORM and all the restrictions that come with it.

The first problem I encountered when using Yii is that I can't figure out how to efficiently save many many and has many relationships.

If I have a form with multiple checkboxes which will give me the IDs of the relationship items - How do I save them to the database?

The active record section of the guide doesn't say how this is done and I can't seem to figure it out.

thanks for your help

Marc

There is no Active Record way to save MANY_MANY relations, it must be done manually.  The method I use is to create a model for the join table.  For example:

Here are three tables:

Person

Company

CompanyPerson (I always use alphabetical order to save confusion) - this is the join table

Each of the tables has a model.  When a person is being created, in the PersonController I would use the following code to create MANY_MANY relations with companies.



// ignoring XSS filtering


// $_POST['companies'] is an array of Company IDs


foreach ($_POST['companies'] as $companyId) 


{


  $relationship = new CompanyPerson;


  $relationship->personId = $person->personId; // from Person model


  $relationship->companyId = $companyId; // from $_POST form submission


  $relationship->save(FALSE); // No need to validate


}


That's what I do.  It's far from perfect - I'll be interested to hear what others' approaches are. 

Hi Alex

thank you for your reply. I know that you would need a join table.

I was hoping that there would be a way built in to Yii how this could be done without having to write a for loop like the one that you described.

As I have mentioned in my previous post I've been working a lot with CakePHP and with cake it is possible to just pass an array of persons to the company object when it is saved.

I believe that in Rails you can do something similar.

I'm hoping that there is a different way of doing this.

Anyone?

Currently there is no better way to do this in Yii, I hope this will be solved in an upcoming release soon. Still I also decided to use Yii instead of Cake, the code seems better and its build for php5.

I found this code in the blog demo application



	protected function afterSave()


	{


		if(!$this->isNewRecord)


			$this->dbConnection->createCommand('DELETE FROM PostTag WHERE postId='.$this->id)->execute();





		if($this->status==self::STATUS_PUBLISHED)


		{


			foreach($this->getTagArray() as $name)


			{


				if(($tag=Tag::model()->findByAttributes(array('name'=>$name)))===null)


				{


					$tag=new Tag(array('name'=>$name));


					$tag->save();


				}


				$this->dbConnection->createCommand("INSERT INTO PostTag (postId, tagId) VALUES ({$this->id},{$tag->id})")->execute();


			}


		}


	}


It should be possible to write a behaviour that takes a similar approach and takes care of the job.

I don't have time to look into it some more but in a couple weeks I'll probably get around to trying to write something along these lines. Having this in the core would be great of course

@sluderitz:

I agree that Yii seems to be better built than CakePHP. I was getting really annoyed by Cake's ORM and how it relies on arrays instead of objects. I very much prefer writing $this->attribute over having to write $this->data['Modelname']['attribute']

In some areas Yii still falls short of Cake since cake has been around longer.

I hope this is gonna change in the future