yii cgridview filter – customized cols – best practice

Using standard filters in CGridView custom fields

http://www.yiiframework.com/wiki/117/using-standard-filters-in-cgridview-custom-fields/

In this article I’ll try to explain how to use standard quick search fields in CGridView with customized columns.
For example:
We have a record in a database with field switch having 0 or 1 values. After that we want a user to see on or off instead 1 or 0.
So we do the usual thing:

<?php $this->widget('zii.widgets.grid.CGridView', array(
//.....
array(
    'name'=>'switch',
    'header'=>'Switch',
    'type'=>'raw',
    'value'=>'Mii::getSwitch($data->switch)'
),
//.....
));

Mii::getSwitch – is my own helper witch returns on or off according to the current switch value (in the original it returns an image).
After that the user can see on and off values in the column, but he will not be able to filter columns typing on or off in the quicksearch field.
So we do the following thing in model search() function:

public function search()
{
    // Warning: Please modify the following code to remove attributes that
    // should not be searched.
    $criteria=new CDbCriteria;
    //....other fields
    $criteria->compare('switch',$this->getSwitch($this->switch));
    return new CActiveDataProvider(get_class($this), array('criteria'=>$criteria,));
}

//function that returns usual 0 or 1 value dependently user input
public function getSwitch($switch)
{
    if(is_null($switch)) return $switch; //null shows all records
    if(is_numeric($switch)) return $switch; //here we save an ability to search with `0` or `1` value
    if($switch == 'on') {
        return 1; //all fields with `switch` = 1
    } elseif($switch == 'off') {
        return 0; //all fields with `switch` = 0
    } else {
        return null; //all fields
    }
}

In this simple way you can teach standard filter fields to search in customized columns.

Another example:
The column shows news author name according to their id. In this situation we must return reverse value. The column returns it in the following way: id->author and customized filter must return author->id. Lets write simple function:

public function getAuthor($author)
{
     if(empty($author)) return null; //return al if author is empty
     if(is_numeric($author)) return $author; //return fields if id is entered
     $criteria=new CDbCriteria;
     $criteria->select='author_id'; //select id field
     $criteria->compare('author_login',$author,true); //seach author name. partialMatch is on
     $am=authorsModel::model()->find($criteria);
     if(empty($am)) return 0; //if author not found - returns 0
     return $am->attributes['adm_id']; //returns author id
}

That is all!

Note: This was written simple examples. Situation, when there are several authors which logins starts from equal letters must return an array with their IDs.

Example with several authors starting from equal letters:

public function getAuthor($author)
     {
         if(empty($author)) return null;
         if(is_numeric($author)) return $author;
         $criteria=new CDbCriteria;
         $criteria->select='author_id';
         $criteria->distinct = true;
         $criteria->compare('author_login',$author,true);
         $am=authorsModel::model()->findAll($criteria);
         if(empty($am)) return 0;
         if(count($am) == 1) return $am[0]->attributes['author_id'];
         $ids = array();
         foreach($am as $a_id)
         {
             $ids[] = $a_id->attributes['author_id'];
         }
         return $ids;
     }

Leave a Reply