CGridView sorting

Hello all, first post here and new to yii.

I have a question about sorting in CGridView, but first, is there some kind of tutorial that walks

you through each class, giving concrete examples on their usage. I did the blog tutorial, and I

read the guide, but I still feel lost. I’m an experienced OOP PHP developer who completely understand

MVC programming and other applicable design patterns. Anyway, onto my real question.

Here’s my index action:




$criteria = new CDbCriteria(array(

	'condition' => 'is_retired = 0',

	'order' => 'last_name ASC'

));





$dataProvider = new CActiveDataProvider('User', array(

	'criteria' => $criteria,

	'pagination' => array(

		'pageSize' => 10

	),

	'sort' => array(

		'attributes' => array(

			'first_name',

			'last_name',

			'email',

			'home_phone',

			'cell_phone',

			'last_login'   

		)                    

	)

));


$this->render('index',array(

	'dataProvider' => $dataProvider,

	'model' => new User('search')

));



Gii had originally generated this:




$model=new User('search');

$model->unsetAttributes();  // clear any default values

if(isset($_GET['User'])) $model->attributes=$_GET['User'];


$this->render('index',array(

	'model'=>$model,

));



When I modified it, the sorting & filtering stopped working in the view. Here’s the code I’m using:




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

	'id'=>'user-grid',

	'dataProvider'=>$dataProvider,

	'filter'=>$model,

	'columns'=>array(

		'first_name',

		'last_name',

		'email',

		'home_phone',

		'cell_phone',

		'is_allowed_access',

		array(

			'name' => 'last_login',

			'value' => '$data->last_login ? date("m/d/Y h:ia", strtotime($data->last_login)) : ""'

		),

		'is_retired',

		array(

			'class'=>'CButtonColumn',

		),

	),

));



Thanks for any help!

Hello Jonathon, welcome to the forum.

The sequence is important.

  1. Create a model instance which will hold the filtering and searching parameters.

  2. Empty the model instance to clear the parameters.

  3. Get the user input parameters into it if there are any.

  4. Create a data provider instance with the model instance which holds the filtering/searching parameters.

  5. Create a grid view widget with the data provider instance and display the results.

Note that the model instance is not for the searched data, but for the searching parameters in this context.

I know it’s a little bit hard when you start using Yii. I had the same difficulty myself.

But I’m sure you’ll be loving it. :)

Thank you very much for your response. I fear I’m still quite lost though! What do you mean by ‘Get the user input parameters into it if there are any’?

I’m guessing this is what you mean to do, but it’s still not working…

controller:




$model = new User('search');

$model->unsetAttributes(); // clear any default values

if (isset($_GET['User'])) $model->attributes = $_GET['User'];


$criteria = new CDbCriteria(array(

'condition' => 'is_retired = 0 OR is_retired IS NULL',

'order' => 'last_name ASC'

));


$dataProvider = new CActiveDataProvider($model, array(

'criteria' => $criteria,

'pagination' => array(

    'pageSize' => 15

)

));


$this->render('index',array(

'dataProvider' => $dataProvider,

'model' => $model

));



view




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

    'id'=>'user-grid',

    'dataProvider'=>$dataProvider,

    'ajaxUpdate' => false,

    'columns'=>array(

            'first_name',

            'last_name',

            'email',

            'home_phone',

            'cell_phone',

            array(

               'name' => 'state',

                'value' => '($data->state) ? $data->state : ""'

            ),

            array (

                'name' => 'is_allowed_access',

                'value' => '$data->is_allowed_access ? "Yes" : "No"'

            ),

            array(

                'name' => 'last_login',

                'value' => '$data->last_login ? date("m/d/Y h:ia", strtotime($data->last_login)) : ""'

            ),

            array(

                    'class'=>'CButtonColumn',

                    'template' => '{view} {update}'

            ),

    ),

));




It just refers to the following line.




if (isset($_GET['User'])) $model->attributes = $_GET['User'];



Initially $_GET[‘User’] is not defined when the page is requested at the first time. But in the subsequent calls to the page, it may contain some filtering values that the user has input.

In your code, the criteria does not reflect the user input. Use gii-generated User::search() function instead to create a data provider, then you will get a data provider with a criteria that reflects the user input filtering values.

If you always have to apply the same filter regarding "is_retired", then you can do it by changing a line in User::search() which is creating a condition for "is_retired".

Okay, I understand – change the model to pull the records, don’t do it in the controller?

So, I added a method in the model to pull just ‘non-retired’ users and set the dataprovider to $model->searchNonRetired(). This works perfectly, thanks! However, now I am unable to customize the page size or set a default sort order!

I was able to set a default sort order with this:




if (!isset($_GET['User_sort'])) $_GET['User_sort'] = 'last_name';



But, I suspect this is not the way to do it :) You’ve been really helpful, thanks again.

They can also be specified in search() or searchNonRetired().




		return new CActiveDataProvider(get_class($this), array(

			'criteria' => $criteria,

			'sort' => array(

			 	'defaultOrder' => 'last_name',

			),

			'pagination' => array(

				'pageSize' => 30,

			),

		));



Check those properties of ‘sort’ and ‘pagination’ in the reference of CActiveDataProvider + CSort + CPagination.

Now, you may have reached the "3 posts" limit. http://www.yiiframework.com/forum/index.php?/topic/19451-guidelines-for-posting-this-forum/

Bye for now. Have a nice day. :)

[EDIT] Ah, it’s not your first day. So there’s no “3 posts” limit anymore.

Ahhhh, I wasn’t paying attention and didn’t notice that it was returning an object of CActiveDataProvider, perfect! All is wonderful. I guess this kind of forced me to make it more model-heavy anyway… My final methods:


public function searchNonRetired() {

		$criteria=new CDbCriteria;


		$criteria->compare('id',$this->id);

		$criteria->compare('first_name',$this->first_name,true);

		$criteria->compare('last_name',$this->last_name,true);

		$criteria->compare('email',$this->email,true);

		$criteria->compare('password',$this->password,true);

		$criteria->compare('last_login',$this->last_login,true);

		$criteria->compare('home_phone',$this->home_phone,true);

		$criteria->compare('cell_phone',$this->cell_phone,true);

		$criteria->compare('address',$this->address,true);

		$criteria->compare('city',$this->city,true);

		$criteria->compare('state',$this->state);

		$criteria->compare('zip',$this->zip,true);

		$criteria->compare('date_of_birth',$this->date_of_birth,true);

		$criteria->compare('is_allowed_access',$this->is_allowed_access);

		$criteria->compare('is_retired',$this->is_retired);

		$criteria->condition = 'is_retired = 0 OR is_retired IS NULL';		


		return new CActiveDataProvider(get_class($this), array(

			'criteria'=>$criteria,

			'sort' => array(

				'defaultOrder' => 'last_name ASC'

			),

			'pagination' => array(

				'pageSize' => 15

			)

		));

	}

	

	

	public function searchRetired() {

		$criteria=new CDbCriteria;


		$criteria->compare('id',$this->id);

		$criteria->compare('first_name',$this->first_name,true);

		$criteria->compare('last_name',$this->last_name,true);

		$criteria->compare('email',$this->email,true);

		$criteria->compare('password',$this->password,true);

		$criteria->compare('last_login',$this->last_login,true);

		$criteria->compare('home_phone',$this->home_phone,true);

		$criteria->compare('cell_phone',$this->cell_phone,true);

		$criteria->compare('address',$this->address,true);

		$criteria->compare('city',$this->city,true);

		$criteria->compare('state',$this->state);

		$criteria->compare('zip',$this->zip,true);

		$criteria->compare('date_of_birth',$this->date_of_birth,true);

		$criteria->compare('is_allowed_access',$this->is_allowed_access);

		$criteria->compare('is_retired',$this->is_retired);

		$criteria->condition = 'is_retired = 1';


		return new CActiveDataProvider(get_class($this), array(

			'criteria'=>$criteria,

			'sort' => array(

				'defaultOrder' => 'last_name ASC'

			),

			'pagination' => array(

				'pageSize' => 15

			)

		));

	}