[SOLVED]CGridView relational data search box not showing

yii-1.1.7.r3135 on apache 2.2 under linux, with php5.3.5 and mysql 5.5.51

customizing a CGridView display to use relational criteria can’t get the search box to show for the relational criteria.

I have searched the wiki and the forums and read many many posts on this subject and tried all suggested remedies but can’t get the search box to show above the relational column although the data for that column shows just fine.

The admin view:


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

        'id'=>'position-member-links-grid',

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

        'filter'=>$model,

        'columns'=>array(

                'id',

                array(

                        'filter'=>Positions::model(),

                        'name'=>'Position',

                        'value'=>'$data->position->position_title',

                        'type'=>'text',

                        'header'=>'Pozz',

                ), 

                'seat_id',

                'member_id',

                'from_when',

                'to_when',

                array(

                        'class'=>'CButtonColumn',

                ), 

        ), 

)); ?>



controller:




class PositionMemberLinksController extends Controller

{

...

        public function actionIndex()

        {

                $dataProvider=new CActiveDataProvider('PositionMemberLinks', array(

                        'criteria'=>array(

                                'with'=>array('member','position'),

                        )

                ));

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

                        'dataProvider'=>$dataProvider,

                ));

        }

        public function actionAdmin()

        {

                $model=new PositionMemberLinks('search');

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

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

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


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

                        'model'=>$model,

                ));

        }




the model:




         public function rules()

        {

                // NOTE: you should only define rules for those attributes that

                // will receive user inputs.

                return array(                        

                        array('position_id, member_id', 'required'),

                        array('position_id, seat_id, member_id', 'numerical', 'integerOnly'=>true),

                        array('from_when to_when','date','format'=>'yyyy-M-d H:m:s'),//'allowEmpty' defau

lts to true

                        // The following rule is used by search().

                        // Please remove those attributes that should not be searched.

                        array('id, position_title, seat_id, member_id, from_when, to_when', 'safe', 'on'=

>'search'),

                );

        }

       public function relations()

        {   

                // NOTE: you may need to adjust the relation name and the related

                // class name for the relations automatically generated below.

                return array(                        

                        'member'=>array(self::HAS_ONE,'Members','',

                        'on'=>'t.member_id=member.id',

                        ),  

                        'position'=>array(self::HAS_ONE,'Positions','',

                        'on'=>'t.position_id=position.id'),

                        );  

        }   


        public function search()

        {

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

                // should not be searched.


                $criteria=new CDbCriteria;


                $criteria->with=array('member','position');


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

                $criteria->compare('position_title',$this->position->position_title);

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

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

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

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


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

                        'criteria'=>$criteria,

                ));

        }




The relational data shows correctly in the position column but no search box shows above it, and the other search boxes show. No errors displayed.

Bound to be something simple but it has me beat. Thanks for your help.

I’m doing like this by introducing some additional properties for searching in the model.




// model

class PositionMemberLinks extends CActiveRecord

{

    public $srch_title;  // for searching position title


    public function rules()

    {

        return array(

        ....

            array('aaa, bbb, ccc, ... srch_title', 'safe', 'on'=>'search'),

        );

    }


    public function search()

    {

        $criteria=new CDbCriteria;

        $criteria->with=array('member','position');

        $criteria->together=true;

        ....

        $criteria->compare('position.position_title', $this->srch_title, true);

        ....

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

            'criteria'=>$criteria,

        ));

    }

}


// view

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

        'id'=>'position-member-links-grid',

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

        'filter'=>$model,

        'columns'=>array(

                ....

                array(

                        'name'=>'srch_title',

                        'value'=>'$data->position->position_title',

                        'type'=>'text',

                        'header'=>'Pozz',

                ), 

                ....

        ), 

)); ?>



I’m not very sure, but I hope it could be of some help.

Thanks for your reply. You are on the right track.

I had tried that approach with no success and tried over now also with no success.

So I looked in the source and rediscovered what gjb found here

the line

else if($this->filter!==false && $this->grid->filter!==null && $this->name!==null && strpos($this->name,’ .’)===false)

which stops a relation (has a . in the name) from being directly rendered, so you need the extra property as you said.

After much futzing about found that as well as using the extra property that there had to be: either no filter; or the filter had to be an array e.g., ‘filter’=>array(‘janitor’,‘cook’).

‘filter’=>‘RelatedModelname’::model(),

doesn’t cut it, and that is what was failing all my attempts.

No filter puts a text box for the search and the array puts a drop-down.

However although I now have the search box showing it does not search correctly. When as a text box always returns all items no matter what is entered and as a drop down returns all no matter what is selected.

I made a simplest test case for working out the kinks:

data:




CREATE TABLE `pos` (

 `id` int(11) NOT NULL AUTO_INCREMENT,

 `position_title` varchar(255) NOT NULL,

 PRIMARY KEY (`id`),

 KEY `position_title` (`position_title`)

) ENGINE=MyISAM


CREATE TABLE `mem` (

 `id` int(11) NOT NULL AUTO_INCREMENT,

 `first` varchar(128) NOT NULL,

 `middle` varchar(128) DEFAULT NULL,

 `last` varchar(128) NOT NULL,

 PRIMARY KEY (`id`)

) ENGINE=MyISAM

CREATE TABLE `posMemLinks` (

 `id` int(11) NOT NULL AUTO_INCREMENT,

 `position_id` int(11) NOT NULL,

 `member_id` int(11) NOT NULL,

 PRIMARY KEY (`id`),

 KEY `lookup` (`position_id`,`member_id`)

) ENGINE=MyISAM



with minimal data:

with 2 pos: ‘janitor’ and ‘cook’

and 2 mem: ‘jo toe’ and ‘aya blogs’

and posMemLinks: id 1:position_id=>1 member_id=>2 id2:position_id=>2 member_id=>1

model:




        public function rules()

        {

                return array(

                        ...

                         array('id, position_id, position_srch, member_id', 'safe', 'on'=>'search'),

                );

        }


        public function relations()

        {

                return array(

                        'mem'=>array(self::HAS_ONE,'Mem','',

                        'on'=>'t.member_id=mem.id',

                        ),

                        'pos'=>array(self::HAS_ONE,'Pos','',

                        'on'=>'t.position_id=pos.id',

                        ),

                );

        }


        public function search()

        {

                $criteria=new CDbCriteria;

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

                $criteria->together=true;


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

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

                $criteria->compare('position_srch',$this->pos->position_title,true);

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


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

                        'criteria'=>$criteria,

                ));

        }




and the admin view:


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

        'id'=>'pos-mem-links-grid',

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

        'filter'=>$model,

        'columns'=>array(

                'id',

                'position_id',

                /*array (

                'name'=>'position_id',

                'filter'=>array('1','2'),

                ),*/

                array(

                        //'filter'=>Pos::Model(),// fails: no filter shown

                        //'filter'=>CHtml::listData(Pos::model()->findAll(), 'id', 'position_title'), //shows drop-down

\                        //'filter'=>array('janitor'=>'janitor','cook'=>'cook'),// shows drop-down

                        //'filter'=>array('janitor','cook'),// shows drop down

                        //'name'=>'pos.position_title',// fails: no filter shown

                        'name'=>'position_srch', // shows filter is property of same name exists

                        //'value'=>'$data->pos->position_title', // shows data correctly

                        'value'=>'Pos::model()->FindByPk($data->position_id)->position_title', // shows data correctly

                ),

                'member_id',

                array(

                        'class'=>'CButtonColumn',

                ),

        ),

)); ?>



But as yet although the filter shows above the related coumn I can’t get good search results. So almost there…

Solved!

Had a hint from here

Needed to connect the new property to the database column:




public function search()

{

...

$criteria->compare('position_srch',$this->pos->position_title,true);

$criteria->addSearchCondition('pos.position_title',$this->position_srch);

...

}



Thanks all.

try this in your model->search() to get it works




public function search()

        {

                $criteria=new CDbCriteria;

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

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

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

                $criteria->with('pos');

                $criteria->addSearchCondition('pos.position_title',$this->position_srch);


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

                        'criteria'=>$criteria,

                ));

        }



[quote=“ressaince, post:5, topic:38456”]

try this in your model->search() to get it works

Thanks ressaince ;D you nailed it and better than my solution, the compare was not needed.

Summary for other folks:

for related filter:

  1. in model need a property for the related column

  2. add related column property name to search rules

  3. column array has either no filter for text or a filter that returns an array

  4. in model search add $criteria->addSearchCondition(‘relatedtable.column’,$this->related_property);

Thanks all.