Фильтрация И Пагинация При Выборке

Привет всем!

Подскажите, пожалуйста.

Есть форма фильтрации, где пользователь выберает нужные ему критерии и нажимает поиск.

Данные выбираются из многих таблиц связанных между собой.

С помощью CDbCriteria формируется запрос из множеством условий, к примеру:





$criteria = new CDbCriteria;

            // Загружаем связанные модели

            $criteria->with = array(

                'house_relation',

                'sanitare_relation',

                'street_relation',

                'region_relation',

                'district_relation',

                'underground_relation',

                'type_house_relation',

                'type_area_relation',

                'plan_relation',

            );





$cond = ' ';

$cond .= " AND t.price_of_m2 BETWEEN ".$min_price." AND ".$max_price."";

$cond .= " AND t.flour IN (".$list_rooms.")";

и т.д.

 



и все это затем передается:







$criteria->condition = $cond;

$model = new CActiveDataProvider('Apartament',array(

                'criteria'=>$criteria,

                'pagination' => array(

                    'pageSize'=>3,

                ),


 



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

'dataProvider'=>$model,


'itemView'=>'_view',


'emptyText'=>'Результат не найден. Измените критерий поиска.',


'sortableAttributes'=>array('id','t.price_of_m2'),

));

Проблема состоит в том, что когда появляется пагинация (пейджер) при большом количестве записей (в нашем варианте > 3) и когда нажимаешь на кнопку чтобы перейти на другую страницу вывода, настройки фильтра сбрасуются и отображаются все записи без учета фильтрации (условий).

Тоисть, поиск работает правильно, но если результатов несколько страниц, то при переходе на следующую страницу выводится вторая страница общих данных, т. е. результаты поиска сбрасываются - как это решить?

В чем проблема? Как сделать так что при пролистывании со страницы на страницу фильтры (условия выборки) не сбрасивались.

Что интиресно, что когда сразу открывается страница пейджер отображает правильное количество страниц, а вот при начале пролистывания - все сбрасывается!

Спасибо за любой совет!!!

Попробуйте так:




$count = ModelName::model()->count($criteria);


$pages = new CPagination($count);

$pages->setPageSize(10);

$pages->applyLimit($criteria);


$result = ModelName::model()->findAll($criteria);

$dataProvider = new CArrayDataProvider($result);

 

...

 

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

	'dataProvider' => $dataProvider,

	'pages' => $pages

));



и в представлении:




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

	'dataProvider' => $dataProvider,

	'itemView' => '_view',

	'enablePagination'=>false,

));

$this->widget('CLinkPager', array(

	'header' => '',

	'pages' => $pages,

));



Попробывал как Вы сказали, но опять не работает.

Изначально пагинатор показывает правильное кол-во страниц. Но при переходе на 2-ю страницу все сбрасуется и отображантся все записи.

Вот в скриншотах видно. На первом изображении пагинатор возвращает 2 страницы, но когда переходишь на вторую страницу - сразу все страницы записей!

Разве в Yii нет решений данной проблемы?

Вот скриншот выборки записей и пагинатор который сбрасует все фильтры при переходе на страницы :( .

каждая ссылка в пагинаторе ведет на новую страницу и должна содержать все переменные для фильтра. Если фильтр у вас сбрасывается при использовании пагинатора, значит не все необходимые переменные присутствуют в ссылках на страницы.

Вообще-то CGridView правильно работает с пагинацией, но может быть у вас сложный случай и фильтрация по связанным таблицам…

Т.е. я представляю в чем может быть причина, но не могу посоветовать пути её решения.

Хотя мне кажутся подозрительными имена ваших переменных "$min_price" это что? переменная класса, или параметр из GET?

Столкнулся с похожей проблемой, мне помогло вот это:

РЕШЕНИЕ: Если передаешь переменные через POST, смени его на GET. При пагинации значения фильтров из POSTa почему-то обнуляются (судя по описанию), поэтому и показывает всю выдачу.

Как обнаружил:

В Google Chrome CTRL+SHIFT+I - консоль. На 3-ей вкладке "Network" можно посмотреть передающиеся массивы (GET, POST, Ajax) и их значения. Все ли "OK" и все приходит по назначению.

В CListView выставлял:


'ajaxType' =>'POST'

не помогло. Подскажите причину и решение, если кто знает в чем дело.

И я столкнулся со схожей проблемой. Согласно закону Мерфи “какая бы неприятность с вами не произошла - среди ваших знакомых обязательно найдется человек, с которым произошло то же самое. Только было еще хуже.” :)

Так вот моя ситуация действительно была еще сложнее: у меня поиск по 30 полям модели и шести смежным таблицам. Иногда со вложенными условиями. В любых комбинациях. Данные поисковой формы отсылаются в JSON, и уже на стороне сервера из них создается CDbCriteria. Я пробовал передавать JSON через GET, но ссылка получается отвратительно длинной да и данных слишком много для GET-запроса.

КАК ЭТО УДАЛОСЬ РЕШИТЬ:

При помощи сессии и умной формы поиска.

  1. при нажатии кнопки "найти" форма поиска отправляет все свои условия по AJAX. Сервер запоминает условия поиска в сессию пользователя.

  2. одновременно с этим обновляется CListView/CGridView (по данным из POST или из сессии - уже не важно)

  3. отображением результатов поиска занимается отдельный виджет. Он получает критерии поиска из формы, создает из них CDbCriteria и по этому критерию выводит CListView. Если данные из формы поиска не пришли - значит или отображается новый поиск или мы перешли на вторую страницу результатов. Смотрим, есть ли данные поиска в сессии. Если есть - используем их.

При переходе между страницами условия поиска не меняются, поэтому нам достаточно запомнить их в сессии 1 раз, при поиске на первой странице, а следующих страницах просто брать из сессии.

При таком раскладе переход по страницам работает прекрасно, даже с самыми сложными критериями.

Желательно сделать в форме поиска кнопку "очистить", по AJAX очищающую условия поиска из сессии.

В разных вкладках поиск нормально работать не будет.

Возможно это не самое лучшее решение - но оно гарантированно сработает.

Если у кого-то есть идеи по поводу того как можно сделать проще - буду весьма благодарен.

Я, кстати, так и не смог найти в коде фреймворка то место, где CListView/CGridView обновляет условия выборки (CDbCriteria). Он же должен limit и offset поменять, чтобы получить новые данные?

И еще мне непонятно, как CListView вылавливает из AJAX-ответа только нужный код для обновления таблицы. В AJAX-ответе я вижу полный HTML-код страницы, но обновляется почему-то только CListView.

Кто-нибудь знает как работает эта магия?