CGridView - Search filters for relational data

Perhaps I have not done this correctly so would appreciate some guidance. This is model JobApplication:


'job'=>array(self::BELONGS_TO, 'Job', 'job_id'),


public function search()

{

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

	// should not be searched.

	

	$criteria=new CDbCriteria;

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

	$criteria->condition="x.user_id=:user_id";

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

	$criteria->alias="x";

	

	// these are all fields in the 'Job' model

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

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

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

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

	

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

		'criteria'=>$criteria,

	));

}

CGridView attributes config:


array(

	'name'=>'title',

	'value'=>'$data->job->title',

),

array(

	'name'=>'location_id',

	'value'=>'$data->job->Location',

),

array(

	'name'=>'active',

	'value'=>'$data->job->IsActive',

),

array(

	'name'=>'expires_at',

	'value'=>'$data->job->ExpiresAtDate',

),

The attributes display correctly but the search function is throwing up an error. This is because those fields don’t belong to JobApplication model - but even if I do something like $this->job->title it still gives an error - Trying to get property of non-object.

The simplest way would probably be to define $title, $Location, $IsActive, and $ExpiresAtDate as public properties of your Job class:


public $title, $Location, $IsActive, $ExpiresAtDate;

Then, when performing a search, you use


$criteria->compare('job.title', $this->title, true);

$criteria->compare('job.Location', $this->Location, true);

$criteria->compare('job.IsActive', $this->IsActive, true);

$criteria->compare('job.ExpiresAtDate', $this->ExpiresAtDate, true);



Be sure to define the attributes as safe for search in your rules, or they won’t work. To make the attributes sortable, you’ll also need to define custom sorting rules for them like so:




$search = $model->search();


$sort = $search->sort;


$sort->attributes = array(

	'title'=> array(

		'asc'=>'job.title',

		'desc'=>'job.title DESC',

		'label'=>'Job'

	),

	'Location'=> array(

		'asc'=>'job.Location',

		'desc'=>'job.Location DESC',

		'label'=>'Location'

	),

	'IsActive'=> array(

		'asc'=>'job.IsActive',

		'desc'=>'job.IsActive DESC',

		'label'=>'IsActive'

	),

	'ExpiresAtDate'=> array(

		'asc'=>'job.ExpiresAtDate',

		'desc'=>'job.ExpiresAtDate DESC',

		'label'=>'ExpiresAtDate'

	),

	'*'

);




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

	'id'=>'product-grid',

	'dataProvider'=>$search,

	'filter'=>$model,

	'columns'=>$columns,

	)

);



That should do the trick.

Cheers Lilt. That has helped get rid of those errors now, however the search isn’t working.

The search value stays in the filter field but doesn’t perform the search.

Can you tell me what should be put in the controller action? Is it:

$model=new Job(‘search’);

or

$model=new JobApplication(‘search’);

The relation is one Job has many many JobApplication

(or JobApplication belongs to Job)

And in which model do I need to set the search attributes as safe, and does it need to be in format job.title or just title?

I think I’ve managed to figure this out:

Controller:


$model=new JobApplication('search');


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

		

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

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

		

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

	'model'=>$model,

));

In the model I just create public properties for each of the attributes in Job model and then declare these attributes as safe on search. Also I did not have to prefix these attributes with ‘job’ - for some reason it works without the prefix, even in the compare methods.

One thing I don’t understand - I know this isn’t the case, but what if in my JobApplication model there was also an attribute called ‘title’ - wouldn’t this conflict with my public $title Job attribute? What would you have to do in that case?

I explain how in this post: http://learnyii.blogspot.com/2011/01/using-relations-in-views.html

Cheers mate. Do you know anything about this:

[size=“4”]Oh GOD, THANKS THANKS THANKS. This trick has removed all my headaches!!! Thanks LILT!![/size] :P