I’m new in Yii and I’m still knowing all framework.
I have a table/model A, this model has relation MANY_MANY with table B. To manage the relation I made a CGridView in the model A form. Now I want to see in this grid that all B rows that has relation with A item or all that doesn’t have realtion with any A item. I did it with an left outer join.
The problem now is how to get checked (in a CCheckBoxColumn) all B item that already has relation with A, and leave unchecked all B item that doesn’t have relation.
The checked expression must be something that return true or false. But I have the A model and then I have an array of B items on A->relationB.
How to make do this efficient ? If I look at A->relationB I will cause a new query. At query to fill the grid I already have this information, but in expression that I put in checked attribute I only have the A model, isn’t it ?
I don’t have a ready solution for your problem but here are my thoughts. I don’t think that CGridView is a good solution for such a problem. It is nice for simple tables, but not for many_many relations. I would use CListView where you are able to render a view for each row. There you could do something like this:
//Render A model stuff
echo $data->someAProperty
//related Bmodels on a checkboxlist
//B models that are related
echo CHtml::checkboxlist('associatedBModels',CHtml::listData($data->relationB,'id','name'),CHtml::listData(BModel::model()->findAll(),'id','name'));
Instead of using BModel::model()->findAll() you could pass additional criteria to only show the B models you want.
As I said. This is just a thought and I didn’t test it, but maybe it is worth a try
Btw: Maybe you’ll have to create an array variable in your A model to hold the associated Bmodel ids to check the checkboxes instead of using CHtml::listData(). Then you could do
class AModel extends CActiveRecord
{
$public bModelIds;
public function rules()
{
return array(array('bModelIds','safe'));
}
public function afterFind()
{
foreach($this->relationB as $bModel)
$this->bModelIds[]=$bModel->id;
}
}
to fill this array every time you load a A model from the db (take care, that could be a performance issue)
Instead of MANY_MANY you could use 2 relations, one HAS_MANY for your link table, and another HAS_MANY which uses the new ‘through’ option to go through the link relation.
At the place where you set up the data provider for your grid view you probably create a CDbCriteria. You can add the link relation in ‘with’ and then use a ‘group’ option on the main table’s Pk. Now the relation for your link table is null if there are no related links.
EDIT: It’s not null, but an empty array if a Model A has no related objects.