Модуль Pagination

Комментарии: 45  Просмотры: 24 701

В данном уроке мы с вами поговорим о модуле формирования постраничных ссылок — так называемом пагинаторе. Вместе с Коханой данный модуль не идет, но проблем с его нахождением на просторах интернета не возникает. До этого я пользовался своим пагинатором, но он несколько кривоват и недоделан (хотя стоит на паре моих сайтов и даже работает). А недавно мне понадобилось установить пагинатор на очередной разрабатываемый на Кохане сайт и я подумал, почему бы не совместить приятное с полезным, — поковырять полуофициальный модуль пагинации и заодно написать по нему урок. Потому что, несмотря на простоту нахождения пагинатора, не факт, что вам попадется новая версия и вот тогда сразу возникнут проблемы с совместимостью и прийдется применять напильник. Поэтому не мучайтесь и скачайте модуль, абсолютно точно работающий на Kohana v3.2 Отсюда.
Как вы помните, все модули мы размещаем в папке modules и этот не станет исключением, поэтому распакуйте его к остальным модулям. Далее рекомендуется скопировать файл конфигурации config.php из modules/pagination/config в /application/config/, чтобы все изменения производить непосредственно в папке нашего проекта, но это в принципе необязательно, так как их можно делать и при создании объекта.
В конфигурационном файле лежит такой вот массив с параметрами:

return array(
    // Application defaults
    'default' => array(
        'current_page'      => array('source' => 'query_string', 'key' => 'page'), // source: "query_string" or "route"
        'total_items'       => 0,
        'items_per_page'    => 10,
        'view'              => 'pagination/basic',
        'auto_hide'         => TRUE,
        'first_page_in_url' => FALSE,
    ),
);

Давайте рассмотрим их:
current_page — этот параметр также содержит массив, в котором source отвечает за формирование адреса («query_string» — будет с гет-параметрами, а «route» — с mod rewrite), а key — это название параметра в роуте;
total_items — общее количество элементов (статей, изображений итд), которые мы будем разбивать на страницы. Стоит 0, но необходимо поменять;
items_per_page — количество элементов на странице (по умолчанию 10);
view — шаблон пагинатора. В комплектации идет два шаблона. Простой и посложнее. Я пользуюсь вторым;
auto_hide — если стоит «true», то при количестве страниц меньше двух пагинатор выводиться не будет;
first_page_in_url — если стоит «true», то добавляет единицу к адресу первой страницы.

Поменяйте данный массив на такой:

return array(
        // Application defaults
        'default' => array(
            'current_page'      => array('source' => 'route', 'key' => 'page'), // source: "query_string" or "route"
            'total_items'       => 0,
            'items_per_page'    => 10,
            'view'              => 'pagination/floating',
            'auto_hide'         => TRUE,
            'first_page_in_url' => FALSE,
        ),
);

Следующее, что мы делаем — это включаем данный модуль в bootstrap.php, т.е. просто дописываем к списку модулей следующую строку:

    'pagination' => MODPATH.'pagination', // Pagination

Там же в bootstrap.php посмотрите, чтобы параметр в роуте, отвечающем за страницу с пагинацией, назывался page. У меня таких вариаций страниц оказалось целых две. Допустим, страница вида www.site.ru/category/3 выводит третью страницу из списка всех категорий товаров, а страница www.site.ru/category/1-computers/3 выводит уже третью страницу категории «Компьютеры». Мне пришлось написать два роута:

Route::set('allcategory', 'category(/<page>)', array('page' => '[0-9]+'))
        ->defaults(array(
            'controller' => 'category',
            'action'     => 'index',
        ));
 
Route::set('category', 'category(/<id>-<catname>(/<page>))', array('id' => '[0-9]+'), array('page' => '[0-9]+'))
        ->defaults(array(
            'controller' => 'category',
            'action'     => 'index',
        ));

Вообщем-то оно даже работает и работает правильно. Но если кто знает способ лучше, милости просим в комментарии.
Итак, все подготовительные работы закончены. Осталось только вывести наш пагинатор. Делается это очень просто. Все, что нужно знать — общее количество элементов. Так как это уже не тема данного урока, то предположим, что у нас 100 статей. Тогда в контроллере просто создаете объект и передаете ему этот параметр следующим образом:

$total_items = 100; //Это вы как будто посчитали количество элементов
$content->pagination = Pagination::factory(array('total_items' => $total_items));

Естественно здесь же можно поменять и другие параметры. Теперь осталось только в шаблоне в нужном месте написать:

<?php echo $pagination; ?>

И вы получите свой пагинатор. Не забудьте только приукрасить его в шаблоне, а то там все на английском. Должно у вас получиться что-то подобное Этому (пагинатор кликабелен). Удачи!

Обсудить на форуме


К записи оставлено 45 коммент.

спасибо большое, но к сожалению не очень помогло. Как связать создание пагинатора в контроллере и запрос offset/limit в модели?

контроллер
bind(‘articles’, $articles);
$article = new Model_Article();
$articles = $article->get_all();
$content->pagination = Pagination::factory(array(‘total_items’ => 100));
$this->template->content = $content;
}

}

Модель
from($this->_tableArticles)->limit(1)->offset(1)
->execute();
}

передавать объект пагинатора в модель? или как получать значения?

Количество записей на страницу мы знаем (limit).
Зная количество записей на страницу и текущий номер страницы $this->request->param(‘page’) можно вычислить offset. Делаем запрос, получаем нужные записи.

А в чем может быть дело, если у меня ссылки из этой навигации ведут на главную? Выводит все как положено с лимитом и сама навигация выведена, но при клике следующая или 2 переходит на главную(((

А как выглядит при этом ссылка в адресной строке ? С цифрами или без ?

Без…я нашел уже выход…такой вот
$pagination = Pagination::factory(array(
‘total_items’ => $count,
))
->route_params(array(
‘controller’ => Request::current()->controller(),
‘action’ => Request::current()->action(),
));

Подскажите как сделать так что бы постраничный вывод шел после параметра…допусти так ((/(/(/)(/)))) у меня есть несколько категорий и не охота под каждую делать свой экшен только из-за pagination…ведь проще выводить по категориям…Очень нужно такое решение…как осуществить?

Написать такой роут, чтобы на один action кидало

так он на него и кидает…и вывод получается всех материалов…а не по категориям((( у меня в экшене перехватывается параметр cat и по нему вывод из базы…можно подробнее как все это работает?

SELECT * FROM table WHERE category = текущая категория LIMIT ….
и подсчет записей с учетом категории

выводит он все правильно…но ссылки не формирует…ссылки на страницы 1,2,3 и т.д. получаются без категорий

и pagination не формерует ссылку в виде controller/action/cat/а потом уже номер страницы

ссылка получается вида controller/action/ номер страницы и категория теряется((

Route::set('category_page', '(<path>/)(page/<page>)',  array('path' => '.+', 'page' => '[0-9]+'))
    ->defaults(array(
    'controller' => 'main',
    'action'     => 'index',
));

Не то…(( Я на форуме сейчас все подробно опишу…может кто еще подскажет.

Ну это я с одного из своих скопировал. А что, роут в статье не подходит ?

Route::set('category', 'category(/<id>-<catname>(/<page>))', array('id' => '[0-9]+'), array('page' => '[0-9]+'))
        ->defaults(array(
            'controller' => 'category',
            'action'     => 'index',
        ));

Он как раз формирует пагинатор по категориям на этом сайте http://www.host4pics.ru

Спасибо! Решение оказалось проще простого…я тут вверху писал что пришлось передавать параметры…вот
$pagination = Pagination::factory(array(
‘total_items’ => $count,
))
->route_params(array(
‘controller’ => Request::current()->controller(),
‘action’ => Request::current()->action(),
и просто добавил сюда еще параметр ‘cat’ => $this->request->param(‘cat’);
));
теперь все ОК!))

Добрый вечер, все сделал по инструкции, но все ссылки в пагинаторе ведут на домашнюю страницу сайта, а именно на http://site.ru/ , имею ввиду на мой домен все ссылки идут, что делать, в чем может быть проблема ?

Уесли вручную вбиваю адрес, то все корректно работает

Добрый день!
Возникла проблема с пагинатоом.

Есть роут
Route::set(‘static’, ‘(/)’, array(‘action’ => ‘index|about|contacts|showpages’))
->defaults(array(
‘controller’ => ‘static’,
));

За отображение пагинатора отвечает метод showpages контроллера static

public function action_showpages()
{
$content = »;
$objects = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

$pag_data = array
(

‘total_items’ => count($objects),
‘items_per_page’ => 3,
‘view’ => ‘pagination/mypager’,
‘first_page_in_url’ => true,
);

$content = Pagination::factory($pag_data)->route_params( array(
‘controller’ => Request::current()->controller(),
‘action’ => Request::current()->action(),
))->render();

$this->template->content = $content;
}

Этот пример работает, но работает с использованием параметра ?page. Пагинатор генерирует ссылки типа kohana/showpages/?page=2

Я хочу использовать роут для приведения ссылок пагинатора к типу kohana/showpages/2

ДЛя этого я добавил в $pag_data

‘current_page’ => array(‘source’ => ‘route’, ‘key’ => ‘page’),
и создал роут
Route::set(‘pagination’, ‘(/)’, array(‘page’ => ‘[0-9]+’))
->defaults(array(
‘controller’ => ‘static’,
‘action’ => ‘showpages’,
));

Но пагинатор для всех ссылок генерирует kohana/showpages

Что я сделал не так?

Для формирования ссылок вида /2 нужно параметр

'current_page' => array('source' => 'query_string', 'key' => 'page'), // source: "query_string" or "route"

поменять на

'current_page' => array('source' => 'route', 'key' => 'page'), // source: "query_string" or "route"

Я так и сделал. Но не работает :( Странно

А подскажите какой роут у вас используется на http://kohanaframework.su/kohana/articles для articles?

а то не могу никак сообразить, как вы сделали так, что бы по
http://kohanaframework.su/kohana/articles/2 — были страницы, а по
http://kohanaframework.su/kohana/articles/articlе2 — была статья.

Спасибо.



Оставить комментарий или два

Пожалуйста, зарегистрируйтесь для комментирования.