Many_Many relation and "correct" form/model handling

Hi @ all,

I have a “simple” problem, cause I’am not sure how its be done the right way.

I have a many_many relation in my model eg. in the blog demo in my model post




public function relations()

    {

      return array(

             'multiple_category'=>array(self::HAS_MANY, 'PostCategory', 'post_id'),

      );

    }



The models I have are Post and Category and i wanted to have a post entry could have multiple categories allocated.

which are stored in a table PostCategory with columns id (autoincrement) post_id (ID of Post) category_id (ID of category)

So nothing special here…

For a simple test i have a post entry with category 2 + 3 (of 1,2,3 categories available) already entered in my tables.

I have added a Listbox on my Post _from.php:




 echo CHtml::activeListBox($post,'multiple_category', CHtml::listData(Category::model()->findAll(),'id','category'),$htmlOptions=array('multiple'=>true));



And when I edit the post only the 1st category is selected regardless what categories are set in the PostCategory for my post entry.

Ok with the OHtml found here

http://www.yiiframework.com/forum/index.php?/topic/3489-php-error-object-of-class-group-could-not-be-converted-to-int-when-i-try-to-use-chtml/page__p__18894__hl__activeListBox%20relation__fromsearch__1&#entry18894

and the code




echo OCHtml::activeListBox($post,'multiple_category',CHtml::listData(Category::model()->findAll(),'id','category'),array('multiple'=>true,'object'=>'category_id'));



The "correct" categories of my post which should be edited are selected (hooray for this).

BUT how to ‘save’ this…

There is another problem, if I wanted to get the form ‘submitted’ values I have to add the listbox name to ‘safeAttributes()’ of my Post model.

But cause there is no attribute in my model I have added it.

so I added


public $multiple_category; 

to my Post model. But hmm the relation of the same name doesn’t work any more…

Don’t know if this should work with the OCHtml Component or if I use it correct.

So I changed the listbox code to this (use a normal listbox again):




echo CHtml::activeListBox($post,'PostCategories',CHtml::listData(Category::model()->findAll(),'id','category'),array('multiple'=>true);



and defining a “public $PostCategories=array();” in my Post model and adding ‘PostCategories’ to safeAttributes.

additionally there is some more code needed in the Post model so set the initial categories on load of a post into $post->PostCategories




protected function afterFind()

{

	$post_categories=$this->multiple_category;

	if (is_array($post_categories)) {

		$categories_selected=array();

		foreach($post_categories as $post_category)

			$categories_selected[]=$post_category->category_id;

		$this->PostCategories=$categories_selected;

	}

}



So here I am anything is submittted and stored in my attributes and loaded correclty from the database and displayed in my form.

The only thing I have to do now is store the submitted values in PostCategories into my database or delete if needed. this can be done in ‘afterSave’ [i won’t go into detail with that]

So here is now my real problem!

following scenario:

  • edit a post entry with categories 2+3 stored into the database

  • deselect anything of the categories

  • And clear a requiered field of the Post fields e.g. Title

  • Submit !

What happens is that validation fails due to the missing Title (or other requiered field).

But my category listbox now displays the “old” values from the database again due to that html doesn’t have

[PostCategories] => array() or '' in $_Post for a empty submitted listbox or checkbox group.

So nothing is “posted” for $_Post[‘PostCategories’] and therefore $post->PostCategories will be nothing else then the “loaded” values from afterfind() instead of array().

The only workaround for this is e.g. public function actionUpdate()




if(isset($_POST['Post']))

{

        // added

	if(!isset($_POST['Post']['PostCategories']))  

		$_POST['Post']['PostCategories']=array(); 

	$post->attributes=$_POST['Post'];

...

}



Is there any other way to prevent this or something I am doing wrong?

hmm 22 views and no reply?

could it be that no one used a many_many relation and set it up with a listbox / checkbox group?

I believe you’ll get far more solutions, if you simplified your question. No one reads such long posts happily only to be able to help.

most of the posting is only explantion of what I have tested.

I just wanted to have a simple selectbox on my form where i can select multiple entries and save the values afterwards in a relation table. But I found some difficulties. And just wanted to know the right way to do it.

hi there!

i had a very similar problem and I could get a solution.

post here the database schema and Models code in orde to make sure if my solution works for your problem

regards.