CCheckBoxColumn check if relation exist

Hi,

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.

to save the whole thing you could try using http://www.yiiframework.com/extension/esaverelatedbehavior/

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.