You are viewing revision #5 of this wiki article.
This is the latest version of this article.
You may want to see the changes made in this revision.
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;
}
Switch example alternative
A simpler approach for the "Swich" example :
array( 'name'=>'switch', 'header'=>'Switch', 'filter'=>array(0=>"Off",1=>"On"), 'value'=>'@$data->switch ? "On" : "Off"', ),
No need to change your 'search' method in that case.
It also works with BELONG_TO relations, for example :
array( 'header'=>'Brand', 'name'=>'brand_id', 'filter'=>CHtml::listData(Brand::model()->findAll(array('order'=>'name')),'id','name'), 'value'=>'$data->brand->name' ),
Regards.
Alban.
@Alban - good comment
It was only simple example for more difficult situations.
In original switch returns an image according to it
s state, In example - only on/off. For me filter in search function must validate (on,off),(1,0),('вкл','выкл') and other different lingual pairs. That
s why it was separate function.Switch example another alternative
array( 'header'=>'Brand', 'name'=>'brand_id', 'filter'=>CHtml::listData(Brand::model()->findAll(array('order'=>'name')),'id','name'), 'value'=>'$data->brand->name' ),
that code will be create a dropdown list filter.
if you need to keep filter with text field u need some modified like this
step 1
array( 'header'=>'Brand', 'name'=>'brand_id', 'value'=>'$data->brand->name' ),
step 2
u need to modified the function search() on models
public function search() { ... $criteria=new CDbCriteria; $criteria->join="LEFT JOIN brandname t1 ON t.brand_id = t1.brand_id "; ... $criteria->compare('t1.name,$this->brand_id,true); return new CActiveDataProvider(get_class($this), array( 'criteria'=>$criteria, )); }
so the the filter will keep shown as textfield and u can search using text
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.