Yii 1.1: yii-manymanyactiverecord

ManyManyActiveRecord class for simple and quick saving MANY_MANY relation data in models
10 followers

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.

Resources

Total 1 comment

#16311 report it
ITDap at 2014/02/08 08:41pm
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: tbl_person_id_person, tbl_speak_lang_id_speak_lang,tbl_speak_lang_level_id_level

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.

Leave a comment

Please to leave your comment.

Create extension