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(); ?>