Search code examples
yiicgridviewdatabase-relations

yii cgridview relation multiple level


I have 4 tables of order payments user and profiles. Payments has a belongs_to relation with order. Order has a belongs_to relation with user, and user has_many profiles.

While displaying payments in cgridview I need to display the firstname and lastname of user stored in profile.

I tried using:

$data->order->user->profiles->firstname;

Also tried to add parameter firstname to the model class of Payment and tried to create the setter method as:

public function getFirstname(){
    if ($this->_firstname=== null && $this->order !== null) {
                $this->_firstname = $this->order->user->profiles->firstname;
            }
            return $this->_firstname ;
    }
    public function setFirstname($value){
        $this->_firstname = $value ;
    }

But I have not been able to get the desired result.

Edit: the search method has the following code:

public function search() {
        $criteria = new CDbCriteria;
        $criteria->with = array('order.user.profiles') ;
. . . .
        $criteria->compare('firstname', $this->_firstname, true);

. . . .     
        return new CActiveDataProvider($this, array(
            'criteria' => $criteria,
        ));
    }

Solution

  • I would suggest using the "through" relation as it makes life easier. All you have to do is, goto your "payments" model and add the following relations,

    public function relations()
    {
        return array(
            'order' => array(self::BELONGS_TO, 'Orders', 'order_id'),
            'user'=>array(
                self::BELONGS_TO,'User',array('user_id'=>'id'),'through'=>'order'
            ),
            'profiles'=>array(
                self::HAS_MANY,'Profile',array('id'=>'user_id'),'through'=>'user'
            ),
        );
    }
    

    and in the grid you can access the first_name by using,

    $data->profiles[0]->firstname