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.
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.
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.
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.
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
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.