Thursday, March 31, 2011

How to implement simple and easy search functionality on an index page

Here's how to implement simple and easy search functionality on an index page:

1. Let's say your controller looks like this:
public function actionIndex()
{
  $dataProvider=new CActiveDataProvider('Model');
  $this->render('index',array(
  'dataProvider'=>$dataProvider,
  ));
}
2. Change it to this:
public function actionIndex()
{
    $criteria = new CDbCriteria();

    if(isset($_GET['q']))
    {
      $q = $_GET['q'];
      $criteria->compare('attribute1', $q, true, 'OR');
      $criteria->compare('attribute2', $q, true, 'OR');
    }

    $dataProvider=new CActiveDataProvider("Model", array('criteria'=>$criteria));

    $this->render('index',array(
      'dataProvider'=>$dataProvider,
    ));
}
The above will read in the "q" (for query) parameter, and use the compare function to create the sql to search a few attributes for that value. Note the use of the 'OR' operator.

3. In your index view, add this:
<form method="get">
<input type="search" placeholder="search" name="q" value="<?=isset($_GET['q']) ? CHtml::encode($_GET['q']) : '' ; ?>" />
<input type="submit" value="search" />
</form>
The above creates a form that will submit to itself using the querystring. It displays a search input box, which is a text input box with a "cancel" command. It works in most browsers and defaults to a text field in the rest. When the user hits the search button, the form is submitted and the data is filtered by the search value.

14 comments:

  1. How can I do this in a many-to-many table am passing a variable cat_id via get and I have three tables on post, category and post_category(which has ids post_id and cat_id) but I want to select the post corresponding to a certain category.

    ReplyDelete
  2. Hi,

    what does it means $criteria->compare('attribute1', $q, true, 'OR');
    $criteria->compare('attribute2', $q, true, 'OR');

    what is attribute1, 2?
    how it search in database?

    It shouldn't be something like LIKE

    ReplyDelete
    Replies
    1. attribute1 and attribute2 refers to fields in your table of your database. Suppose you are to compare 'title' and 'detail' of your table with the passed parameter 'q' then you write.
      $criteria= new CDbCriteria();
      $criteria->compare('title', $q, true, 'OR');
      $criteria->compare('detail', $q, true, 'OR');

      this compares your variable $q 's value to 'title' and 'detail' fields in your table.

      Delete
  3. Thanks for the simple, yet powerful, implementation. Would serve the purpose of majority of the websites

    ReplyDelete
  4. I second this: How can I do this in a many-to-many table am passing a variable cat_id via get and I have three tables on post, category and post_category(which has ids post_id and cat_id) but I want to select the post corresponding to a certain category.

    ReplyDelete
  5. if i have more pages on results... when i click another page the results are reseted and it show all the items from that table...
    how can i fix that?

    ReplyDelete
  6. this is a bad solution.. Yii model have a search() function that return criteria for searching. We can use this in most component like ListView or GridView.

    Controller action

    /**
    * Lists all models.
    */
    public function actionIndex() {
    $model = new MyModel('search');
    $model->unsetAttributes(); // clear any default values
    if (isset($_GET['MyModel']))
    $model->attributes = $_GET['MyModel'];

    $this->render('index', array(
    'model' => $model,
    ));
    }


    View page

    <!-- render search form -->
    <?php echo CHtml::link(Yii::t('app','Advanced search'),
    '#',array('class'=>'search-button')); ?>
    <div class="search-form" style="display:none">
    <?php $this->renderPartial('_search',array(
    'model'=>$model,
    )); ?>
    </div><!-- search-form -->

    <!-- render list of MyModel -->
    <?php $this->widget('zii.widgets.CListView', array(
    'id'=>'my-list',
    'dataProvider'=>$model->search(),
    'sortableAttributes'=>array(
    'name',
    'description'
    ),
    'itemView'=>'_view',
    )); ?>

    <!-- easy script for update list with search parameter !-->
    Yii::app()->clientScript->registerScript('my-list-search', "
    $('.search-button').click(function(){
    $('.search-form').toggle();
    return false;
    });
    $('.search-form form').submit(function(){
    $.fn.yiiListView.update('my-list', {
    data: $(this).serialize()
    });
    return false;
    });
    ");

    ReplyDelete
    Replies
    1. can you please explain the code as where is which code supposed to be .. please i am really new and i need to implement this .. just dont know where to put what ... thanks

      Delete
  7. how does the redirect work, after clicking search button?

    ReplyDelete
  8. Thanks! very helpful!

    ReplyDelete
  9. Thanks so much :) youre the best

    ReplyDelete
  10. Thanks a lot...nice work..

    ReplyDelete