Как грамотно реализовать поиск?

Здравствуйте,

Мне надо чтобы искалось по всем полям таблицы.

Тоесть например есть список юзеров

мне надо найти когото по любому из параметров:

Имя, фамилия, телефон, логин и т.д.

вывожу форму и вбиваю любое из полей скажем в имя ввожу имя - выводятся все совпадения.

в адрес ввожу город, если надо найти всех кто живет в том городе например - выводит список всех совпадений.

В настоящий момент сделал пока по одному полю так:


			$model->attributes=$_POST['members_search'];

			if($model->validate())

				{				

					$criteria=new CDbCriteria;

					$criteria->condition='forename=:forename';

					$criteria->params=array(':forename'=>$_POST['members_search']['forename']);

			

					$pages=new CPagination(members_search::model()->count($criteria));

					$pages->pageSize=self::PAGE_SIZE;

					$pages->applyLimit($criteria);

			

					$sort=new CSort('members');

					$sort->applyOrder($criteria);

			

					$models=members_search::model()->findAll($criteria);

			

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

						'models'=>$models,

						'pages'=>$pages,

						'sort'=>$sort,

					));

				}

Полей много в таблице.

Ндо чтобы что-то типа "OR" реализовать через $criteria

Не подскажете советом?

Всем спасибо за ответы, сделал сам

А поделиться примером?

Просто тупо наставил условий и все:)


	public function actionFind()

	{

		$model=new members_search;

		if(isset($_POST['members_search']))

		{

			$model->attributes=$_POST['members_search'];

			if($model->validate())

				{				

					$criteria=new CDbCriteria;

					

					if ($_POST['members_search']['login']!='')

					{

						$criteria->condition='login=:login';

						$criteria->params=array(':login'=>$_POST['members_search']['login']);

					}

					if ($_POST['members_search']['forename']!='')

					{

						$criteria->condition='forename=:forename';

						$criteria->params=array(':forename'=>$_POST['members_search']['forename']);

					}




                                          ................................


					$pages=new CPagination(members_search::model()->count($criteria));

					$pages->pageSize=self::PAGE_SIZE;

					$pages->applyLimit($criteria);

			

					$sort=new CSort('members');

					$sort->applyOrder($criteria);

			

					$models=members_search::model()->findAll($criteria);

			

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

						'models'=>$models,

						'pages'=>$pages,

						'sort'=>$sort,

					));

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

		}

		 else $this->render('find',array('model'=>$model));

	}

Возможно не самое красивое решение, но работает.

т.е. если во все поля будет что-то введено, то будет искаться только по последней цепочке




                                        if ($_POST['members_search']['some-key']!='')

                                        {

                                                // some php code

                                        }



это вроде не очень правильный подход.

ну и в добавок стоило бы почитать вот это

поправил ссылку.

там описываются методы, которые могут вам помочь.

Грамотно реализовать поиск? Наверное лучшее, что можно порекомендовать — не делать поиск через SQL )

Есть великолепный иструмент для таких целей.

Ну а если уж совсем нужно, наверное самым простым будет:

  1. получить список полей

  2. проехаться по ним используя addSearchCondition

Но ИМХО, так делать совсем не стоит, базе будет больно.

Пишу в этой теме так как мне показалась наиболее подходящей. В общем на Yii пишу впервые :blink: , поэтому вопрос звучит таким образом: как создать расширенный поиск по категориям, например: в продаже имеется квартира которая находится в N-ой области N-ом городе, цена на нее лежит в пределах(пределы можно задавать), и тип валюты, все эти данные “хаваются” из базы.

Если есть темы в которых это уже описывалось, киньте урл плз. Помогите, люди добрые)

Заранее спасибо.

Даже на мой взгляд абсолютного новичка решение "не самое красивое".

В примере создания блога yii приводится идеальное решение для такого рода типовой задачи.

Напишу как сам понял, может кому будет интересно.

В модели определяется специальный метод:


   /**

     * Retrieves a list of models based on the current search/filter conditions.

     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

     */

    public function search()

    {

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

        // should not be searched.


        $criteria=new CDbCriteria;


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


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


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


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


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


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


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


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

        $criteria->order='update_time desc';


        return new CActiveDataProvider('Post',array(

                'pagination'=>array('pageSize'=>100,),

                'criteria' => $criteria, // array('order' => 'update_time desc',$criteria,),

        ));

    }

В рендируемое нужным действием контроллера представление вставляется

такой вот widget():


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

    'id'=>'post-grid',

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

    'filter'=>$model,

    'columns'=>array(

        'id',

        'title',

        'content',

        'tags',

        'status',

        array(            // display 'create_time' using an expression

            'name'=>'create_time',

            'value'=>'date("d.m.Y H:i:s",$data->create_time)',

        ),


        array(            // display 'update_time' using an expression

            'name'=>'update_time',

            'value'=>'date("d.m.Y H:i:s",$data->update_time)',

        ),

        array(            // display 'author.username' using an expression

            'name'=>'author_id',

            'value'=>'$data->author->username',

        ),

        array(

            'class'=>'CButtonColumn',

        ),

    ),

)); ?>

[b]Вот и все дела !

Вот эта строчка ‘filter’=>$model, обеспечивает вверху выводимой виджетом таблицы

строку с пустыми атрибутами модели. Вводите нужные значения атрибутов и фильтруйте

вывод нужных записей как душе угодно ! Для цифровых полей даже допускается перед значениями атрибутов писать реально работающие логические операторы такие как <, <= и т.д. Стоит сделать еще маленькое, но м.б. существенное замечание - в спец. методе

public function search() каждый последующий критерий поиска соединяется с предыдущим логической связкой AND, которую, при желании, можно поменять на любую лог. связку, допустимую в SQL-запросе.

Для полноты приведу действие контроллера, где происходит рендирование представления

с этим виджетом:[/b]


    /**

     * Manages all models.

     */

    public function actionAdmin()

    {

        $model=new Post('search');

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

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

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

            'model'=>$model,

        ));

    }


Вообще-то, как посмотрю, доскональное изучение примера yii выводит на хороший базовый

уровень, позволяющий "не городить огород", как вот тут нам нагородили…

Плохо что еще для CListView не придумали такого значения как filter. Пришлось виджет фильтрации самому изобретать.

Может я, как новичек, чего не понял но вот в описание CListView такой пример:

$dataProvider=new CActiveDataProvider(‘Post’);

$this->widget(‘zii.widgets.CListView’, array(

'dataProvider'=&gt;&#036;dataProvider,


'itemView'=&gt;'_post',   // refers to the partial view named '_post'


[b]'sortableAttributes'=&gt;array(


    'title',


    'create_time'=&gt;'Post Time',[/b]


),

));


The above code first creates a data provider for the Post ActiveRecord class. It then uses CListView to display every data item as returned by the data provider. The display is done via the partial view named ‘_post’. This partial view will be rendered once for every data item. In the view, one can access the current data item via variable $data. For more details, see itemView.

In order to support sorting, one has to specify the sortableAttributes property. By doing so, a list of hyperlinks that can sort the data will be displayed.


Тут, собственно, как и для Grid, две сортировки - одна постоянная в самом dataProvider,

а другая динамическая по полям в sortableAttributes. Я пробовал, очень хорошо получается - вверху

для каждого из полей в sortableAttributes вывовдятся этакие "пипочки", при нажатие на которые происходит соответствующая сортировка. При рефреше происходит возврат к сортировке, заложенной для dataProvider.

Это параметры сортировки а не фильтрации, т.е сверху списка появляются кнопки нажимая которые можно отсортировать по цене или дате. Я написал виджет который позволяет выбирать из базы допустим определенный город или диапазон цен и показывать только эти результаты используя AJAX, т.е фильтровать результат а не сортировать его.  Пример можно посмотреть [url=&quot;http://ovlix.com/ru/realestate/buy&quot;]здесь[/url].

Зашел к вам на сайт, попытался зарегистрироваться…ждал…ждал…-ничего на email не пришло…

Обратил пока что внимание, что очень неудобно организован ввод запроса на поиск. Область, город и т.д.

надо вводить самому…как-то это не современно…Где-то я видел как разворачивается карта и из нее

все выбирается вплоть до улицы и номера дома…

Над картой пока что работаю, так что скоро будет, да и автокомплит в этих полях тоже помогает пользователям будет удобно пользоваться и фильтром и картой. :rolleyes:. Почтовый сервер i.ua проверю может блокируется у хостера. Проект пока в ранней альфе так что ошибки не исключены…

Пришло мгновенно на xegorkax@i.ua

Все нормально, зашло в 2.37 по Киеву.