Search code examples
yiicgridviewyii-events

CGridView Sorting with relational table sorts by relaton Id parameter


I have problem in CGrid while on sorting a relational data using relational model in `` page.

Briefly my scenario:

I have a user model: Entities=> id,username And a profile Model: Entities=> id, firstname,lastname, user_id,etc..

I want to list profile model and username from user model in CGrid, so that sorting and searching perms well. In my case sorting username is done by user_id not by username. I want to search it by username,so i do the following,

My Controller Action:

$model = new Profile('search');
$model -> unsetAttributes();// clear any default values
if (isset($_GET['Profile']))
$model -> attributes = $_GET['Profile'];

$this -> render('MyPage', array('model' => $model ));

My Model Relation:

public function relations() {
    // NOTE: you may need to adjust the relation name and the related
    // class name  the relations automatically generated below.

    return array(
     'user' => array(self::BELONGS_TO, 'user', 'user_id'),);
}

Model Rules:

array( 'xxx,yyy,user_name', 'safe', 'on'=>'search' ),

And model search function

if(!empty($this->user_id)){
$criteria->with='user'; 
$criteria->order = ::app()->request->getParam('sort');// 'username ASC'
} 

$criteria -> compare('user.username', $this->user_id, true);

My

$this->widget('zii.widgets.grid.CGrid', array(
'id'=>'profile-grid',
'dataProvider'=>$model->search(),
 'filter'=>$model,
array('name'=>'user_id',
    'header'=>User::model()->getAttributeLabel('username'), 
    'value' =>'$data->getRelated(\'user\')->username',
    'type'=>'raw',
    'htmlOptions'=>array('style'=>'text-align: center'),),
   ---------------

During sorting,sorting works perfectly but sorting is done on the basis of user_id not by username. Anything that i am missing to do so. Please suggest.

Reference:Here (I also tried as by declaring a public variable as suggesting in the link but bot workingg.)

Edit: After Issue Fixed. Thanks for this link too.


Solution

  • Well, the wiki page you found is really a good start...

    Here is an alternative way for doing this :

    In your Profile model :

    // private username attribute, will be used on search
    private $_username;
    
    public function rules()
    {
        return array(
            // .....
            array('username', 'safe', 'on'=>'search'),
            // .....
        );
    }
    
    public function getUsername()
    {
        // return private attribute on search
        if ($this->scenario=='search')
            return $this->_username;
    
        // else return username
        if (isset($this->user_id)) && is_object($this->user))
            return $this->user->username;
    }
    
    public function setUsername($value)
    {
        // set private attribute for search
        $this->_username = $value;
    }
    
    public function search()
    {
        // .....
        $criteria->with = 'user'; 
        $criteria->compare('user.username', $this->username, true);
        // .....
    
        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
            'sort'=>array(
                'attributes'=>array(
                    'username'=>array('asc'=>'user.username', 'desc'=>'user.username DESC'),
                    '*',
                ),
            ),
        ));
    }
    

    And in your view you should simply try :

    $this->widget('zii.widgets.grid.CGridView', array(
        'id'=>'profile-grid',
        'dataProvider'=>$model->search(),
        'filter'=>$model,
        'columns'=>array(
            // .....
            'username',
            // .....
        ),
    );