Problem With Filtering By Related Field

Hi all,

I’m declaring my CActiveRecord in my controller method.


 

        $criteria = new CDbCriteria;

        $criteria->with = array('company', 'venue');

        if(!$this->checkAccess('Admin')){

            $criteria->condition = 'manager_id = :uid AND status > -2';

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

        } else {

            $criteria->condition = 'status > -2';

        }

        $model = new CActiveDataProvider('Events',

            array(

                'criteria' => $criteria,

                'sort' => array(

                    'defaultOrder'=>'t.added DESC',

                    'attributes'=>array(

                        'venue_country_code'=>array(

                            'asc'=>'venue.country_code ASC',

                            'desc'=>'venue.country_code DESC',

                        ),

                        '*',

                    ),

                ),

            )

        );

 

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

            'model' => $model,

        ));

I my model I declared venue_company_code, and sorting already works. Also works filter on all relative attributes of my model. My view:


<?php $this->widget('bootstrap.widgets.TbGridView', array(

        'id'=>'events-grid',

        'dataProvider'=>$model,

        'enableSorting'=>true,

        'filter'=>new Events,

        'columns'=>array(

                'added',

        ...

            array(

                'name'=>'venue_country_code',

                'value'=>'!empty($data->venue->country_code)?$data->venue->country_code:""',

                'visible'=>$this->checkAccess('Admin'),

            ),

        ),

    'itemsCssClass'=>'table table-striped table-hover table-bordered dataTable',

    'summaryText' => '',

    'htmlOptions'=>array('class'=>''),

)); ?>

Now my venue_company_code filter not works. How can I let it work?

P.S. In CRUD-generated files for sorting and filtering model->search() is using. Can anybody explain me what is the reason of this way?

Not sure about Yii-Bootstrap’s TbGridView but with Yii’s CGridView, the search() method is what generates the necessary CActiveDataProvider to properly generate the data passed to the grid. When you do something in the grid like sort or search or change pages, it does an ajax call to the current controller action you are in with some GET variables that match what you did (sort value, page number, attributes searched). The attribute GET variables are then passed to the model you are working with, using the “search” scenario to determine which attributes will actually be massively assigned to the model.




$model=new Account('search');

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

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

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


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

	'model'=>$model,

));



Following the code, it will then rerender the entire page and call the grid again. $model->search() will then be called once again to generate the dataprovider. It will then use whatever attributes that were assigned to the model in the controller to build out the CDbCriteria (by default, gii has the search() method to use a bunch of compare methods for each attribute) to create the dataprovider. If I am not mistakened, CActiveDataProvider will also automatically look at the sort and page GET values if they exist to properly order the data and do pagination. Once that is all done, only the grid is pulled out from the resulting page and replaces the grid you currently see. I believe Yii knows which grid to replace because it passes the grid’s id as a GET variable as well

@georaldc’s explanation is pretty much spot on, and it also applies to TbGridView. The ‘filter’ attribute should be $model->search() and come directly from the model’s class, not from the filtered model you create in the controller. That’s why it doesn’t filter because you’re using ‘new Events’ which provides an empty model with no criteria whatsoever to filter on.

Use Gii’s generated code and add your specific criteria to the model’s search() method, not to the controller.