[SOLVED] cgridview filter custom related field

I need some guidance in the right direction.

I have two models, Submissions and Participant.

In Participant I define a custom field FullName which is a combination of FirstName and LastName

The Participant model:





	private $FullName;


	public function rules()

	{

 		...

			array('FullName, Username, ... ', 'safe', 'on'=>'search'),

		...

	}


	public function getFullName()

	{

		return $this->FirstName." ".$this->LastName;

	}


	public function setFullName($value)

	{

		$this->FullName = $value;

	}




In Submissions, I have a ParticipantID field that links Participant, and I want to display all submissions in a grid which has the FullName column, and which should be filterable.

The Submissions model:





	private $FullName;


	public function relations()

	{

		return array(

			'participant' => array(self::BELONGS_TO, 'Participant', 'ParticipantID'),

		);

	}


	public function search()

	{

   	...

		if (isset($_GET['Add']['FullName']))

			$criteria->compare('participant.FirstName',$_GET['Add']['FullName'],true);

    	//$criteria->compare('participant.FirstName', $this->FullName);

  	...

	}


	public function getFullName()

	{

		if ($this->FullName === null && $this->participant !== null) {

    		$this->FullName = $this->participant->FullName;

		}

		return $this->FullName;

	}


	public function setFullName($value)

	{

		$this->FullName = $value;

	}




and in the admin view file I have:




...

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

	'filter'=>$model,

	'columns'=>array(

		array(

			'name'=>'BotanicalName',

			'type'=>'raw',

			'value'=>'$data->master->BotanicalName',

			'filter'=>false,

		),

		array(

			'name'=>'FullName',

			'header'=>'Full Name',

			'type'=>'raw',

			'value'=>'(isset($data->FullName))?$data->FullName:"Not Specified"',

		),

...




If I have the following line in the search function of the admin view file, then the search does not work,




  	...

		$criteria->compare('participant.FirstName', $this->FullName);

  	...



and I have tried various scenarios but can’t seem to get the filtering to work.

Here’s one way to get this to work: In your Participant class, you can remove the $fullname property. Then in your Submissions class, change $FullName to public (I would also name it something else to be more specific and less confusing. $searchFullname maybe?. I’ll stick with what you are using for now) and mark that as a safe attribute in your rules method. You could also remove the getter and setter functions for FullName in your Submissions class, I don’t think those are needed.

Next, in your search() method, you have to join the 2 tables with CDbCriteria::with():




// Eager load the participant table

$criteria->with = 'participant';



Now use a mysql string function to combine the 2 name fields into one, the same way you are building a participant’s full name in your getter class. Do a compare against that using your Submissions class’ $FullName property:




$criteria->compare('CONCAT_WS(" ", participant.FirstName, participant.LastName)', $this->fullname, true);



Finally for the view file, just add your Submission class’ $fullname property as a column and set the appropriate value:




...

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

        'filter'=>$model,

        'columns'=>array(

                ...

                array(

                        'name' => 'FullName',

                        'value'=> function($data) { 

							return $data->participant->getFullName();

						},

                ),

				....

...



You eager loading Participant in your search method should allow you to skip making multiple participant queries for every row.

The following error is thrown by the function above:




[b]Fatal error[/b]:  Call to a member function getFullName() on a non-object in [b]/var/www/plantekey/protected/views/add/admin.php[/b]



thanks for the help!!

got it to work by updating the following line




'value'=> function($data) { 

				return $data->participant->getFullName();

			},



to




'value'=> function($data) { 

				return $data->getFullName();

			},