best practice when working with has_many and many_many relationship

Hi everyone,

I’m wondering what would be considered best pratice when working with has_many and many_many relationships in the following situation:

Suppose I have a many_many relationship between Post and Category.

In the update dialog for my post model I’d then have a CHtml::activeCheckBoxList where the user can check the categories a post belongs to.

I have the following questions about this.

[list=1]

[*]The activeCheckBoxList obviously needs to know what categories are available. Shall I fetch those in the controller and pass them on to the view using the data array in the CController::render method and then do something like this:


CHtml::activeCheckBoxList($model, 'category_ids',$groups, 'id', 'name') )

or shall I fetch that data inside the model like this:


CHtml::activeCheckBoxList($model, 'category_ids',CHtml::listData(Category::model()->findAll(), 'id', 'name') )

The same obivously applies to has_many relationships.

[*]What should the name of the activeCheckBoxList be? Currently I’ve created a public category_ids attribute in my Post class which I then process in the afterSave() method to populate the join table. Is this the way it’s supposed to be done or is there a better way? Something tells me there is :)

[/list]

Hi MarcS,

I’m far from being an expert, but here is my opinion.

  1. To my mind, a view should have a minimum of server code. So, views should have minimum of processing and a maximum of variables. I would choose this way

CHtml::activeCheckBoxList($model, 'category_ids',$groups, 'id', 'name') )

  1. Well, this way is a very simple way. You need to save the post before linking it to its categories. So, doing it on [font="Courier New"]afterSave[/font] is correct. What kind of options are you waiting for?

Don’t forget, I’m far from being an expert.

I was hoping that there’d by another way to do this which wouldn’t require me to manually populate the category_ids array so that the selected options get checked.

I made a change to CHtml that allows this, but as I am new to Yii I don’t know if this follows the “best practices”.




	public static function activeCheckBoxList($model,$attribute,$data,$htmlOptions=array())

	{

		self::resolveNameID($model,$attribute,$htmlOptions);

		if(is_array($model->$attribute) && isset($htmlOptions['attributeitem']) && $htmlOptions['attributeitem'])

		{

			$selection=array();

			foreach ($model->$attribute as $a)

				$selection[]=$a->$htmlOptions['attributeitem'];


		} else

			$selection=$model->$attribute;

		if($model->hasErrors($attribute))

			self::addErrorCss($htmlOptions);

		$name=$htmlOptions['name'];

		unset($htmlOptions['name']);


		return self::hiddenField($name,'',array('id'=>self::ID_PREFIX.$htmlOptions['id']))

			. self::checkBoxList($name,$selection,$data,$htmlOptions);

	}







echo $form->checkBoxList($model,'operations',CHtml::listData(WOBJOperation::model()->findAll(array('order'=>'ds_operation_ope')), 'cd_operation_ope', 'ds_operation_ope'), array('attributeitem'=>'cd_operation_ope'));