The ManyManyActiveRecord YII extension class adds up functionality of saving MANY_MANY relation field value using simple arrays.
Requirements ¶
Yii 1.1 or above
Changes ¶
Commit cf8a3d1 @ Aug 19, 2012 ~~~ Added "save model first" exception ~~~
Commit c19cac2 @ Aug 17, 2012 ~~~ Fixed issue with non integer primary keys ~~~
Commit a3da45c @ Aug 17, 2012: ~~~ Fixed issue with non 'id' primary keys Added transaction support on setRelationRecords method ~~~
Usage ¶
To use this extension:
1) copy ManyManyActiveRecord to your components directory
2) check that your config have autoloaded
'import'=>array(
...
'application.components.*',
...
3) extend your model (which has MANY_MANY relation), category for example
class Category extends ManyManyActiveRecord
Then just use it:
If Category has: ~~~ 'posts'=>array(self::MANY_MANY, 'Post', 'tbl_post_category(category_id, post_id)') ~~~ create tbl_post_category (category_id, post_id) table and then
you can set relations by (with erasing old ones) ~~~ $model = Category::model()->findByPk(10); $model->setRelationRecords('posts',array(1, 2, 3)); ~~~ or you can add new relations (without deletions of old ones) ~~~ $model = Category::model()->findByPk(10); $model->addRelationRecords('posts',array(1, 2, 3)); ~~~ or you can remove some relations ~~~ $model = Category::model()->findByPk(10); $model->removeRelationRecords('posts',array(1,2,3)); ~~~ or if you need to save additional data in tbl_post_category (like user_id for example) you add relations with $additionalFields ~~~ $model = Category::model()->findByPk(10); $model->addRelationRecords('posts',array(1, 2, 3), array('user_id' => Yii::app()->user->id)); ~~~ Each of this method saves data to database, you don't need to save the model.
Problems using additional columns
Hello, I have a few problems using the extension let see if you could help me.
Im trying to display different Languages in an activelistbox for the table (tbl_speak_lang), each language should have a corresponding level like native, basic, intermediate and advanced (tbl_speak_lang_level) also i have a person model (tbl_person) where those 3 tables are conected with an intermediate table (tbl_person_has_speak_lang) with the following columns:
Person relation in model:
'rel_speak_lang' => array(self::MANY_MANY, 'SpeakLang', 'tbl_person_has_tbl_speak_lang(tbl_person_id_person, tbl_speak_lang_id_speak_lang)'), 'rel_speak_lang_level' => array(self::MANY_MANY, 'SpeakLangLevel', 'tbl_person_has_tbl_speak_lang(tbl_person_id_person, tbl_speak_lang_level_id_level)'),
In the person update action I have this:
foreach ($speaklang_model as $spl) { echo $spl->speak_lang; echo CHtml::activeListBox($model , 'rel_speak_lang_level[]', CHtml::listData(SpeakLangLevel::model()->findAll(),'id_speak_lang_level','speak_lang_level'), array('object'=>'rel_speak_lang_level','style'=>'width: 205px') ); }
I manually add the [] brakets to be able to receieve an array of all of the languages listdata, if not i only receive one.
In the controller i have the following line:
$model->setRelationRecords('rel_speak_lang_level',$model->rel_speak_lang_level ,array('tbl_speak_lang_id_speak_lang'=>6));
I set the value to 6 for the additional columns just for testing but I receive this error:
CDbCommand falló al ejecutar la sentencia SQL: SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesn't match value count at row 2. The SQL statement executed was: insert into tbl_person_has_tbl_speak_lang (tbl_person_id_person, tbl_speak_lang_level_id_level, tbl_speak_lang_id_speak_lang) VALUES (1, 2, '6'), (1, 1, '6', '6'), (1, 4, '6', '6', '6'), (1, 4, '6', '6', '6', '6')
I didnt understand why it always keep me adding the 6 to the query so i edited the manytomanyactiverecords.php file i found this value that was populating every time.
so in line 80 for the set function I added the following [code] unset($values); [/code]
the code looks like this
if (count($additionalFields) > 0) { foreach($additionalFields as $key=>$value) { $values[] = $value; } $sql[] = '('.$this->primaryKey.', '.$relationData[$i].", '".implode("', '", $values)."')"; } else $sql[] = '('.$this->primaryKey.', '.$relationData[$i].')'; //executes insert each 1000 rows or last time if (($i+1 % 1000) == 0 || $i == $c-1) { $com->setText($insert_sql.implode(', ', $sql)); $com->execute(); $com = Yii::app()->db->createCommand(); $sql = array(); } unset($values);
Now its populating fine. but I receving this error because it always try to use the 6 that i manually set.
CDbCommand falló al ejecutar la sentencia SQL: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '6-1-4' for key 'PRIMARY'. The SQL statement executed was: insert into tbl_person_has_tbl_speak_lang (tbl_person_id_person, tbl_speak_lang_level_id_level, tbl_speak_lang_id_speak_lang) VALUES (1, 2, '6'), (1, 1, '6'), (1, 4, '6'), (1, 4, '6')
So the query looks like fine now but i need to resolve the way to automatically change the 6 number looking in the db like this loop.
foreach (SpeakLang::model()->findAll() as $spl) { $arr_spl[]=$spl->id_speak_lang; }
but i tried with different options but didnt work.
I am using wrong the additionals field value ?
If you have another solution using radio instead of listdata i will appreciate it.
also when the page load is not selectin me the correct level for each language.
hope you understand it and let me know if you have any question. I will appreciate it if you can give me a hand on this.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.