Home PageКаталог Изменения НовыеКомментарии Пользователи Регистрация
CakePHP: Manual/Pagination ...

Разбиение на страницы (pagination)

Оглавление документа

Одним из основных препятствий при создании гибких и дружественных к пользователю веб-приложений является создание интуитивно-понятного интерфейса. Большинство приложений очень быстро разрастаются и разработчики обнаруживают, что они не в состоянии справиться с отображением сотен или даже тысяч записей. Рефакторинг долог, а производительность и удовлетворение пользователя могут пострадать.


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


PaginatorHelper является отличным решением, потому что его легко использовать. Кроме собственно разбиения на страницы, он включает в себя несколько возможностей сортировки. Также поддерживается ajax-сортировка и разбиение на страницы.

Настройка контроллера

В контроллере мы установим параметры разбиения в переменной $paginate. Здесь следует упомянуть, что ключ сортировки (order) должен быть задан в виде массива.


<?php
class RecipesController extends AppController {
 
    var 
$paginate = array(
        
'limit' => 5
        
'order' => array(
            
'Post.title' => 'asc'
        
)
    );
}
?>


Другие ключи, которые могут быть включены в массив $paginate, соответствуют параметрам метода Model->findAll() (conditions, fields, order, limit, page и recursive). Можно определить несколько наборов параметров в контроллере, достаточно просто разместить их после модели, которую необходимо настроить.


<?php
class RecipesController extends AppController {
    var 
$paginate = array(
        
'Recipe' => array (...),
        
'Author' => array (...)
    );
}
?>


После того, как переменная $paginate определена, можно вызвать метод paginate() в действиях контроллера. Он вернет результаты вызова findAll(), разбитые на страницы, а также передаст дополнительную статистику в отображение. Этот метод также добавляет PaginatorHelper в список хелперов контроллера, если это еще не было сделано.


function list_recipes() {
    // аналогично findAll(), но результат разбит на страницы
    $data = $this->paginate('Recipe');
    $this->set(compact('data'));
}

Разбиение на страницы в отображениях

Ваше дело решать, как показывать данные пользователю, но чаще всего они отображаются в HTML таблицах. Пример ниже предполагает размещение в таблице, но PaginatorHelper, доступный в отображениях не всегда должен быть так ограничен.


Как упоминалось, PaginatorHelper предоставляет возможности сортировки, которые могут быть интегрированы в заголовки таблицы:


app/views/recipes/list_recipes.ctp

<table>
    <tr> 
        <th><?php echo $paginator->sort('ID''id');?></th> 
        <th><?php echo $paginator->sort('Title''title');?></th> 
    </tr> 
    <?php foreach($data as $recipe): ?> 
    <tr> 
        <td><?php echo $recipe['Recipe']['id']; ?></td> 
        <td><?php echo $recipe['Recipe']['title']; ?></td> 
    </tr> 
    <?php endforeach; ?> 
</table>


Ссылки, которые создает метод PaginatorHelper->sort(), позволяют пользователю сортировать данные по определенному полю, щелкнув на заголовке столбца таблицы.


И последний ингредиент разбиения на страницы в отображениях –- навигация по страницам, также генерируемая PaginatorHelper.


<!-- Отображает ссылки на предыдущую и следующую страницы-->
<?php
    
echo $paginator->prev('<< Previous 'nullnull, array('class' => 'disabled'));
    echo 
$paginator->next(' Next >>'nullnull, array('class' => 'disabled'));
?>
 
<!—выводит X из Y, где X – текущая страница, а Y – их общее количество. -->
<?php echo $paginator->counter() ?>


Вывод метода counter() может быть настроен с помощью специальных маркеров:


<?php
echo $paginator->counter(
    array(
        
'format' => 'Страница %page% из %pages%, просматривается %current% записей
            из %count% всего, начиная с %start%и заканчивая на %end%'
    
)
);
?>

Разбиение на страницы с использованием ajax

В разбиение страниц легко добавить ajax-функциональность. Единственное, что потребуется –- это подключить js-библиотеку Prototype, установить индикатор (иконка загрузки внутри DIV’а) и указать DIV, который будет обновляться вместо перезагрузки страницы.

Изменения в верстке

В заголовке подключаем Prototype, устанавливаем индикатор (spinner.gif), и определяем DIV с содержимым («content»).


Верстка может выглядеть вот так (код приведен частично):

<html>
    <head>
        <title><?php echo $title_for_layout?></title>
        <?php echo $javascript->link(array('prototype')); ?>
        <style type="text/css">
            div.disabled {
                display: inline;
                float: none;
                clear: none;
                color: #C0C0C0;
            }
        </style>
    </head>
    <body>
        <div id="main">
            <div id="spinner" style="display: none; float: right;">
                <?php echo $html->image('spinner.gif'); ?>
            </div>
            <div id="content">
                <?php echo $content_for_layout?>
            </div>
        </div>
    </body>
</html>

Изменения в отображении

Единственная дополнительная настройка для разбиения на страницы с использованием ajax производится с помощью метода PaginationHelper::options(), который определяет необходимые параметры ajax. В данном случае, мы определяем, что все ссылки должны обновлять элемент, ID которого равен “content”, данными и во время загрузки будет отображаться “spinner”.


Обратите внимание: если ключ 'update' не задан, PaginationHelper будет выводить обычные (не-ajax) ссылки.


<?php
//Sets the update and indicator elements by DOM ID
$paginator->options(array('update' => 'content''indicator' => 'spinner')); 
echo 
$paginator->prev('<< Previous'nullnull, array('class' => 'disabled'));
echo 
$paginator->next('Next >>'nullnull, array('class' => 'disabled'));
?>
<!-- prints X of Y, where X is current page and Y is number of pages -->
<?php echo $paginator->counter(); ?>


 
Комментарии

Надо заметить, что paginating подерживается начиная с 1.2.x. В stable еще нет.

89.250.7.241 (2008-01-12 09:39:39)

Ну надо заметить, что это мануал именно к 1.2 =)

EvilBloodyDemon? (2008-01-12 10:19:27)

Приношу извинения за клевету %), проглядел, ибо новичок в Cake PHP? и на этом ресурсе. Отличный ресурс, творческих успехов в этом году всем, кто его развивает!

nat.tushino.com (2008-01-13 00:51:41)

Эм, а как изменить кол-во записей на странице?.. Кроме того, что выставить по умолчанию ?

77.120.224.9 (2009-02-09 03:09:58)

'limit' => 5 в var $paginate, первый же пример. вместо 5 – нужное число.

EvilBloodyDemon? (2009-02-09 08:09:06)

Это да, но я не об этом. Как сделать что чтото вроде такого:
Record per page 5|10|20|30
Нажал на к примеру на 30, 30 записей и выводит...

77.120.224.9 (2009-02-09 13:37:43)

а я об этом. сделай ссылки и в пиши в куку/сессию/бд/передавай именованным параметром это значение. а при паджинации указывай это число в лимите.

EvilBloodyDemon? (2009-02-09 13:53:20)

...а примерный кусочек кода можно ?

77.120.224.9 (2009-02-09 18:55:39)
есть такой вопрос:
пусть есть три класса – Game, Server, Location.
Причем Game belongsToServer, Server belongsToLocation.
И хочется, чтобы при вызове pagination можно было сделать что-то вроде:
foreach ($game['Server'] as $server)
{
echo $server['Location']['name'];
}
broadband-95-84-158-161.nationalcablenetworks.ru (2009-05-06 16:21:57)
разобрался надо просто в контроллере написать -
var $paginate = array ('recursive' => '2');
broadband-95-84-158-161.nationalcablenetworks.ru (2009-05-06 21:16:30)
Доброго времени суток.

Использую постраничку с Ajax, но есть маленький ньюанс – почемуто в указанный мною div для update загружается все содержимое переменной $content_for_layout; из layouta и получается так, что у меня вместо просто обновленных данных – две страницы.

Кто-то сталкивался с такой проблемой или это свойство, что обнавляется вся рабочая область layouta?
51-28-135-95.pool.ukrtel.net (2009-08-26 13:47:54)
В Router у меня написано вот :
Router::connect('/news/', array('controller' => 'reports', 'action' => 'index'), array())

При включении Paginator`а ссылки на следующую и предыдущую принимают вид http://site.com/reports/index/page:2

Если настраивать через options, то при добавлении например:
$paginator->options(array('url' => array(«news», “all”)));
ссылки становятся http://site.com/reports/index/news/all/page:2

Как настроить ссылки вида http://site.com/news/page:2 ?
194.158.213.231 (2009-09-26 09:17:45)
$paginator->options(array('url' => '../../news/'));
ссылки получаются http://site.com/news/page:2
194.158.212.56 (2009-09-26 11:38:23)
ну когда уже все переведут?
89.189.141.93.dynamic.ufanet.ru (2009-10-20 22:25:10)
с ajax не работает :( почему-то в 1.3 формирует простые ссылки..
195.12.102.15 (2010-09-14 15:55:26)
да заебали вы суки со своими ечами блять!
шаблонизаторов на вас нет!
блять принесли мне проект переделывать на вашем пироге ебаном
в папке app нетбинс нашел 3 358 “<?php echo”
хватит блять гавнакодеров воспитывать нахуй!!!
всадите же наконец в ваше ебаное ядро какой нибудь шаблонизатор
<?php echo ""; ?>...
пошел блевать
gw.hiqo-solutions.com (2010-12-16 22:50:30)
^ нервный какой-то попался...
188-115-129-82.broadband.tenet.odessa.ua (2010-12-28 19:11:11)
ребята руки оторвать нужно за это!
function list_recipes() {
// аналогично findAll(), но результат разбит на страницы
$data = $this->paginate('Recipe');
$this->set(compact('data'));
}
это не правильно!!!

нужно вот так!!!

function list_recipes() {
// similar to findAll(), but fetches paged results
$data = $this->paginate('Recipe');
$this->set('data', $data);
}
109.201.183.249 (2011-01-14 20:40:07)
перечитни хелпеца, дружок, это одно и то же
109.168.140.77 (2011-01-15 00:28:29)
а не подскажете как сделать не prev и next, а чтобы выводились страницы в виде:
1 2 3 ... 11 12 13 – как-то так)
pool-77-222-101-20.is74.ru (2011-07-08 15:15:28)
Как показать странички я знаю. как сделать именно ...
тоесть как сделать так, чтобы часть страниц скрывалась?
pool-77-222-101-20.is74.ru (2011-07-08 15:31:29)
Черт, более сложная проблема(((( как сделать вывод сообщений только с нужным id?
Без пагинации было сделано так:
$this->set('data', $this->model->query(«SELECT * FROM base WHERE `razdel` = '" . $id . “'"));
как сделать такое же с пагинацией?
pool-77-222-101-20.is74.ru (2011-07-08 16:13:42)
Все. Решение нашел. Что-то все сайты о cakephp умерли( Наверное создам свой...
pool-77-222-101-20.is74.ru (2011-07-08 21:47:27)
если я правильно понял суть траблы, то опуская выборку, сфокусируемся на самой проблеме как передавать id из view, так чтобы требуемые переменные были закинуты в ссылки сформированные во view (prev(), sort(), next(), numbers, ...), то есть чтобы получалось что-то вроде: http://site.com/index/mypage/page:2/id:16/sort:LOGIN/direction:asc, нашёл такой костыль так чтобы в контроллере указать можно было: $this->request->params['named']['id'] = $id;

Но вскоре после внимательного прочтения хелпа был найден правильный способ, нужно во view делать так:
до формирования всех ссылок
<?php
$this->Paginator->options(array(
'url' => array(
'id'=>'16'
)
));?>

тогда все будет логически правильно.
31.28.246.117 (2011-12-01 19:13:43)
Добавить комментарий:

Файлов нет. [Показать файлы/форму]