Model Search - Merging in a default start criteria

This is a way to preset the search grid with some criteria information. By merging in the criteria it will not break the sorting ability of the search grid columns.

In the model we add in some code to pass a merge criteria to the search method.

snippet from a sample model:




public function search($merge=null)

{

	// Warning: Please modify the following code to remove attributes that

	// should not be searched.


	$criteria=new CDbCriteria;


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

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

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


	if($merge!==null)

		$criteria->mergeWith($merge);


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

		'criteria'=>$criteria,

	));

}



Then in the controller create a criteria but only set it if the ‘call’ is not ajax and then pass it to the view. That way only the first time the page is opened you can sort one of the columns, but then each ajax request for sorting will still work. If the merge is left as a default criteria it will not change anything when it is merged. Also the model checks if the merge is not null before merging it so if we don’t need it, then we simply don’t pass it. You won’t need to ‘fix’ any other code.




$merge=new CDbCriteria;

if(!Yii::app()->request->isAjaxRequest)

	$merge->order = '`number_swiss_accounts` DESC';

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



And then in a view where the search grid will be displayed just pass in criteria to the search method:




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

	'id'=>'order-grid',

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

	'filter'=>$model,

...



This tip really helped.

Thanks,

Marco

Thanks so much for the tip jjones!

I realize that the post is a little old, but just thought I’d throw in another aspect that was necessary for my implementation. I had criteria that I needed to persist no matter the condition or request type. Couldn’t figure out how to get the AJAX request when switching pages or criteria to also throw the added conditions into the request (if anyone else knows how, please share). To overcome this, in the controller I do a check similar to the following to add the criteria to the session, and check for it each time the request is made.




// Check for criteria assignment from both the POST and from an existing session variable

if (isset($_POST['somevar'])) {

	$criteria = (int) $_POST['somevar'];

	Yii::app()->session['somevar'] = $criteria; 

} else {

	// Not explicitly supplied, check if it's been defined beforehand

	if (isset(Yii::app()->session['somevar']))

		$criteria = Yii::app()->session['somevar'];

	else

		$criteria = 1; 

}



(Note: code is rather abstracted, but you get the idea.)

I am trying to use this in an admin view, but whenever I try to sort a column or search within a column the entire database of entries gets displayed instead of just the ones I narrowed down to using the merge technique stated above. Is that what you would expect or do I need to handle the AJAX calls differently?

controller:




public function actionAdmin($u)

	{

		$merge=new CDbCriteria;

		if(!Yii::app()->request->isAjaxRequest)

        {

			$merge->with = array('members','sportUnits');

			$merge->together = true;

			$merge->condition = "unit_id=:unitId AND sportUnits.active=1 AND primary_unit=1";

			$merge->params = array(':unitId'=>$u);

		}

		

		$model=new Team('search');

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

		if(isset($_GET['Team']))

			$model->attributes=$_GET['Team'];

		

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

			'model'=>$model,

			'merge'=>$merge,

			'u'=>$u,

		));

	}



model:





public function search($merge=null)

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;


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

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

				

        if($merge!==null)

        	$criteria->mergeWith($merge);


        return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}



admin view:




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

	'id'=>'team-grid',

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

	'filter'=>$model,

	'columns'=>array(

		'id',

                ...



handy tip

Hi,

I got the same problem, I would say that you do not need this part of code,




if(!Yii::app()->request->isAjaxRequest)



Look at my code below




        $merge = new CDbCriteria;

        $merge->addInCondition('id', $enrolledStudentsId);

        if (!Yii::app()->request->isAjaxRequest) {

            $merge->order = 'name ASC';

        }



The $merge->addInCondition is always applied to the query.

I put if (!Yii::app()->request->isAjaxRequest)… in order to make default sorting to ‘name ASC’ if not ajax call.

Just give it a try…

Thanks Daniel. Well it kind of works the way I want. By removing that as you stated, it is limiting the grid data to only those relevant data units, but when I try to use the active dropdown filter, it throws up some weird pop up window showing a Error 500 condition.