Некоторое время назад озадачился поиском решения, которое позволило бы заменить стандартный «паджинатор» (CLinkPager) Yii на такой, который бы вместо номеров страниц писал что-то более внятное. Скажем, первые символы значений полей на последующих страницах. Не нашел и решил написать свой.

Крайне неудобно переключаться между нумерованными страницами, скажем, в списке пользователей. Особенно, когда список большой. Каждое переключение при поиске пользователя на 5-10 страниц, как «гадание на кофейной гуще». То перескочишь нужного пользователя, то наоборот слишком осторожничаешь и не дойдешь. Конечно, поиск помогает, но только тогда, когда точно знаешь фамилию или иные атрибуты. Даже знание имени не помогает, т.к. разных Саш, Маш, Даш, Вань может быть в таблице десятки!
Поиск готового решения, как я написал выше, ничего не дал. Может плохо искал, исправьте, если не прав.
Пришлось изучать строение CLinkPager и писать свой класс «паджинатора».
Требования к нему были простые:
Отображение значений, а не номеров страниц — означает, что нужно отобразить первое значение поля каждой страницы. Иными словами, значение поля записи текущей страницы, потом значение поля записи следующей страницы (со смещением равным размеру страницы) и т.д.
Отображение значений целиком или фрагмент — означает, что вывод, например, целой фамилии в «паджинатор» неудобно. Куда удобнее вывести, скажем, первую букву, а лучше две, в общем, столько, сколько будет нужно.
Отображение значений только определенных полей — означает, что выводить �� «паджинатор» кусочки значений полей типа число или дата удобства не добавит, хотя, кому как. Поэтому, надо указывать список полей, значения которых будут отображаться в «паджинаторе», а для остальных показывать обычные номера страниц.
Выяснил, что за отрисовку кнопок отвечает функция createPageButtons() класса CLinkPager. Перекрыть выборочно код создания тех или иных кнопок нельзя, поэтому решил унаследовать класс и дополнить код.
Интересно то, что базовый класс CLinkPager получается универсальным как бы «сам по себе» для любого провайдера данных. Мне же пришлось обрабатывать два класса провайдера данных: CActiveDataProvider, CArrayDataProvider. Каждый отдельно.
При работе с CActiveDataProvider получение значений с каждой страницы получаю с помощью offset:
При работе с CArrayDataProvider получение значений с каждой страницы получаю по индексу:
В классе объявил две переменные:
fields — массив имен полей для которых должны отображаться значения, а не номера страниц;
length — длина обрезки значения, если null, то целиком.
Использовать класс, например, в CGridView можно так:
В общем, немного обкатав код решил им поделиться. Кому интересно, может получить исходный код моего класса AlxdTitlePager безвозмездно.

Крайне неудобно переключаться между нумерованными страницами, скажем, в списке пользователей. Особенно, когда список большой. Каждое переключение при поиске пользователя на 5-10 страниц, как «гадание на кофейной гуще». То перескочишь нужного пользователя, то наоборот слишком осторожничаешь и не дойдешь. Конечно, поиск помогает, но только тогда, когда точно знаешь фамилию или иные атрибуты. Даже знание имени не помогает, т.к. разных Саш, Маш, Даш, Вань может быть в таблице десятки!
Поиск готового решения, как я написал выше, ничего не дал. Может плохо искал, исправьте, если не прав.
Задача
Пришлось изучать строение CLinkPager и писать свой класс «паджинатора».
Требования к нему были простые:
- отображение значений, а не номеров страниц
- отображение значений целиком или фрагмент
- отображение значений только определенных полей.
Отображение значений, а не номеров страниц — означает, что нужно отобразить первое значение поля каждой страницы. Иными словами, значение поля записи текущей страницы, потом значение поля записи следующей страницы (со смещением равным размеру страницы) и т.д.
Отображение значений целиком или фрагмент — означает, что вывод, например, целой фамилии в «паджинатор» неудобно. Куда удобнее вывести, скажем, первую букву, а лучше две, в общем, столько, сколько будет нужно.
Отображение значений только определенных полей — означает, что выводить �� «паджинатор» кусочки значений полей типа число или дата удобства не добавит, хотя, кому как. Поэтому, надо указывать список полей, значения которых будут отображаться в «паджинаторе», а для остальных показывать обычные номера страниц.
Решение
Выяснил, что за отрисовку кнопок отвечает функция createPageButtons() класса CLinkPager. Перекрыть выборочно код создания тех или иных кнопок нельзя, поэтому решил унаследовать класс и дополнить код.
Интересно то, что базовый класс CLinkPager получается универсальным как бы «сам по себе» для любого провайдера данных. Мне же пришлось обрабатывать два класса провайдера данных: CActiveDataProvider, CArrayDataProvider. Каждый отдельно.
При работе с CActiveDataProvider получение значений с каждой страницы получаю с помощью offset:
if ($this->owner->dataProvider instanceof CActiveDataProvider) { $pagesize = $this->owner->dataProvider->pagination->pagesize; $criteria = $this->owner->dataProvider->criteria; $this->owner->dataProvider->sort->applyOrder($criteria); $criteria->limit = 1; for($i=$beginPage;$i<=$endPage;++$i) { $criteria->offset = $i*$pagesize; $m = $this->owner->dataProvider->model->find($criteria); $buttons[]=$this->createPageButton(is_null($this->length) ? $m->{$field} : mb_substr($m->{$field}, 0, $this->length, 'utf-8'), $i,$this->internalPageCssClass,false,$i==$currentPage); } }
При работе с CArrayDataProvider получение значений с каждой страницы получаю по индексу:
if ($this->owner->dataProvider instanceof CArrayDataProvider) { $pagesize = $this->owner->dataProvider->pagination->pagesize; $data = $this->owner->dataProvider->rawData; for($i=$beginPage;$i<=$endPage;++$i) { $m = $data[$i*$pagesize]; $buttons[]=$this->createPageButton(is_null($this->length) ? $m[$field] : mb_substr($m[$field], 0, $this->length, 'utf-8'), $i,$this->internalPageCssClass,false,$i==$currentPage); } }
В классе объявил две переменные:
fields — массив имен полей для которых должны отображаться значения, а не номера страниц;
length — длина обрезки значения, если null, то целиком.
Использовать класс, например, в CGridView можно так:
'pager'=>array( 'class' => 'AlxdTitlePager', 'fields'=>array('lastname','firstname','middlename','email'), 'length'=>'2', 'maxButtonCount'=>10, 'firstPageLabel'=>'<<', 'header'=>'', 'hiddenPageCssClass'=>'disabled', 'lastPageLabel'=>'>>', 'nextPageLabel'=>'>', 'selectedPageCssClass'=>'active', 'prevPageLabel'=>'<', 'htmlOptions'=>array('class'=>'pagination') )
В общем, немного обкатав код решил им поделиться. Кому интересно, может получить исходный код моего класса AlxdTitlePager безвозмездно.
