Another Gridview Filter By Related Table Question

I have active record Notes and related Genres as $note->genre

Now i want to filter in gridview by $note->genre->name

I can assign filter value directly to $note->genre, making from object a string, but that’s not good i guess.

Tutorial http://www.yiiframework.com/wiki/281/searching-and-sorting-by-related-model-in-cgridview/ doesn’t work, probably due to it’s out date.

my problem is next

Which means __setter cannot set. i understand that i can declare in model something like


public $filter_genre;

but i don’t want to do it, 'cause at some point i simply return whole class via jso_encode

here’s related parts of the code




//models/Notes.php


	public function rules()

	{

		return [

                          .....		

			['genre filter_genre', 'safe', 'on' => 'filter']

		];

	}




//controllers/NotesController.php


	public function actionGetNotes()

	{

		$filter_note = new Notes('filter');

		$dp_criteria = new CDbCriteria(['with' => ['tempo','genre']]);

		$dp_notes = new CActiveDataProvider('Notes');

		$dp_notes->setCriteria($dp_criteria);


		if (empty($_GET['Notes'])) {

			.......

		} else { //filter

			$filter_note->attributes = $_GET['Notes'];

			$dp_criteria->compare('note_id', $filter_note->note_id, true);

			$dp_criteria->compare('title', $filter_note->title, true);

			$dp_criteria->compare('genre.name', $filter_note->filter_genre, true); // not defined

			$dp_criteria->compare('genre.name', $filter_note->genre, true); //WTF, but works if use genre name in list

		}




		$this->render('list', [

			'dp_notes' => $dp_notes,

			'filter_note' => $filter_note

		]);


// views/notes/list.php


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

    'id' => 'notes-grid',

    'dataProvider' => $dp_notes,

    'filter' => $filter_note,

    'columns' => [

         .....

        ['name' => 'filter_genre', 'value' => '$data->genre->name'],

    ],

]);




thanks in advance

Yii doesn’t create related objects when it creates a CActiveRecord object instance.




    $filter_note = new Notes('filter');



At this point, "filter_genre" is not created yet.

You’d be better think that those objects are intended for storing related data when you are reading data from db.

That is, they are not meant for the container of user inputs like form data or filtering parameters.

Probably you could instantiate the related object manually in order to use it as the container of the filtering parameter, but an active form for the main object will not create the proper input field for the related object automatically, and the massive assignments of the main object will not work for it.

So, as it is suggested in the wiki you mentioned (it’s not outdated, btw), defining a variable for the filter parameter is the right choice.

If you don’t want to include such properties in the main model, you could create a dedicated model for searching extended from the main model.

got it, thanks

so, i made a solution for myself by extending getter and setter




<?php

//models/Notes.php


class Notes extends CActiveRecord

{

.....

	public function __get($name)

	{

		if (in_array($name, ['filter_genre']) && !property_exists($this, $name)) {

			$this->__set($name, null);

			return $this->$name;

		}		

		return parent::__get($name);

	}

		

	public function __set($name, $value)

	{

		if (in_array($name, ['filter_genre'])) {

			$this->$name = $value;

			return;

		}

		parent::__set($name, $value);

	}

}



which now will contain filter_genre only if i set it

I recommend to look at my RelatedSearchBehavior extension.

In the demo you can see the filtering in action.