Yii 1.1: History Autocomplete

11 followers

What for? ΒΆ

In application development we often have to choose how to mange recurrent values.

For example, a field color for a cloath. You cannot leave free text, because there whould be too much typos, but you cannot enumerate all possibility because they are a lot and sometime there are new colors.

Often you can solve with a foreign field, with an interface for add a new color. That's great if adding new color is a quite rare operation, if it happens too often and if the users are too stupid for remember how to add a color, it can be odd.

I propose an half way solution: a free text with autocomplete based on history values.

We will use CJuiAutoComplete, what we need is a efficient way for perform searches.

Add this to your components/extensions:

class SearchAction  extends CAction
{
    public $model;
    public $attribute;
    public $criteria=array('limit'=>5);
 
    public function run()
    {
        $criteria=new CDbCriteria($this->criteria);
        $criteria->addCondition("{$this->attribute} IS NOT NULL AND {$this->attribute} LIKE :param");
        $criteria->group=$this->attribute;
        $criteria->order="COUNT({$this->attribute}) desc";
        $criteria->params[':param']='%'.$_GET['term'].'%';
 
        $results=array();
        foreach (CActiveRecord::model($this->model)->findAll($criteria) as $record)
            $results[]=$record->{$this->attribute}; 
 
        echo CJSON::encode($results);
    }
}

Now we can configure a search action in our controller like that:

public function actions()
{
    return array(
        'searchCompany'=>array(
            'class'=>'SearchAction',
            'model'=>'Request',
            'attribute'=>'company',
        )
    );
}

You can pass additional configuration for the search (e.g, some more condition limiting the search in a project/group, sorting or whatever else) using the property $criteria.

Now you can create your search textfield as:

<?php $this->widget('zii.widgets.jui.CJuiAutoComplete', 
    array('model'=>$model,
    'attribute'=>'company', 
    'htmlOptions'=> array('maxlength'=>300, 'class'=>'text'),
    'sourceUrl'=>'searchCompany'));?>

This method is quite efficient and usually customer like it, because is based on the laziness of the users.

Total 2 comments

#7527 report it
zaccaria at 2012/03/28 03:25am
Security issue

It appears that this stuff is quite unsafe, in fact it expose the whole database to be queried out, a malicious user can simply change the search url to:

/site/search?model=User&attribute=username&term=

And get all the username, then the same with passwords end enjoy the combinations.

I have updated the tutorial in order to use an action configurable, for fix the paramter that is supposed to be searched...

#6907 report it
c@cba at 2012/02/12 11:11am
problem with $this

Hi, Thanks for the inspiring article.

The public function activeTextFieldHistory should be public static function activeTextFieldHistory, right?

I used a similar code: I created a static function in my GxHtml class (extends CHtml, like your ZHtml class). In this function I call

$this->widget(...);

which produces the error
Using $this when not in object context

Did your code above work without this error?

Solved: Instead of

`$this->widget(...);`

the following worked:

$w = new CWidget;
$w->widget(...);

Leave a comment

Please to leave your comment.

Write new article