Yii cgridview filter using data from different model

I know there is an abundance of threads and posts regarding this, but going through them all is actually turning out to be more confusing than helpful.

I have a "user" table, a "customer" table and a "customer_transfer" table that tracks transfers of customers from one user to the other i.e. a user can "transfer" customer ownership from himself to someone else.

The relevant fields are:

User(PK id)

Customer(PK id, user_id)

Customer_Transfer(PK id, from_user, to_user, customer)

My models relations are:

Customer


return array(

    'pages' => array(self::BELONGS_TO, 'Page', 'page_id'),

    'category' => array(self::BELONGS_TO, 'Category', 'category_id'),

    'user' => array(self::BELONGS_TO, 'User', 'user_id'),

);

Customer_Transfer


return array(

    'customer' => array(self::BELONGS_TO, 'Customer', 'customer'),

    'fromUser' => array(self::BELONGS_TO, 'User', 'from_user'),

    'toUser' => array(self::BELONGS_TO, 'User', 'to_user'),

);

After going through these posts:

www.stackoverflow.com/questions/9031514/yii-framework-using-data-from-related-active-record-models-for-searching (almost exactly what I want to do) www.yiiframework.com/forum/index.php/topic/14590-solved-how-filter-cgridview-with-join-table-and-some-condition-and-paging/,

I’ve ended up with a Customer_Transfer search function (which I’ve most likely stuffed up) that’s something like this:


public function search() {

    $criteria=new CDbCriteria;


    $criteria->condition = 'from_userID=:from_userID';

    $criteria->params = array(':from_userID'=>Yii::app()->user->id);


    $criteria->compare('t.lead_id',$this->lead_id);

    $criteria->compare('t.timestamp',$this->timestamp);


    $criteria->together = true;

    $criteria->with = array('lead');

    $criteria->with = array('toUser');

    $criteria->compare('lead.name',$this->name,true);

    $criteria->compare('lead.surname',$this->surname,true);


    // $criteria->compare('user.name',$this->toUser,true);

    // $criteria->compare('user.surname',$this->toUser,true);


    return new CActiveDataProvider($this, array(

        'criteria'=>$criteria,

    ));

}

Finally I’ve got a CGridView that displays for a specific user which customers of his have been transferred and to whom:


$this->widget('zii.widgets.grid.CGridView', array(

    'dataProvider'=>$dataProvider->search(),

    'columns'=>array(

        array(

            'header'=>'Customer Name',

            'name'=>'name',

            'value'=>'$data->customer->name',

        ),

        array(

            'header'=>'Customer Surname',

            'name'=>'surname',

            'value'=>'$data->customer->surname',

        ),

        array(

            'header'=>'Current Customer Holder',

            'value'=>'$data->toUser->name." ".$data->toUser->surname',

        ),

    ),

));

I now want to implement a free text search filter on “Current Customer Holder” (I don’t have a problem on breaking the field up into two separate ones name, surname) and of course on Customer Name and Customer Surname.

Having followed the SO question I keep getting an exception ‘Customer_Transfer.name is not defined’.

I’d also like to avoid defining extra variables as in the second solution and try to do this the “Yii way”.

Any ideas?

Thanks in advance

EDIT

In general it seems that I can’t pass to $criteria->compare() ANY attribute from the user relation without it throwing an exception.

If I add a public variable to the Customer_Transfer model and then do




$criteria->compare('customer.name', $this->customer_name);




$this->widget('zii.widgets.grid.CGridView', array(

    'dataProvider'=>$dataProvider->search(),

    'columns'=>array(

        array(

            'header'=>'Customer Name',

            'name'=>'customer_name',

            'value'=>'$data->customer->name',

        ),

        array(

            'header'=>'Customer Surname',

            'name'=>'customer_surname',

            'value'=>'$data->customer->surname',

        ),

        array(

            'header'=>'Current Customer Holder',

            'value'=>'$data->toUser->name." ".$data->toUser->surname',

        ),

    ),

));

it will display the filter box in the cgridview but it won’t actually filter.

Hi

Check out RelatedSearchBehavior extension - it makes handling the relations easier.

I will definitely use this, thanks a lot!

But on a theoretical basis now, what would be needed to implement such a filter without the extension?

There has been a lot of talk about it so you can find some stuff using a search site while searching on yiiframework.com.

Here is an example:

http://www.yiiframework.com/wiki/281/searching-and-sorting-by-related-model-in-cgridview