О сайтах и не о сайтах

Теперь и в tg!

tg

Переехал с твиттера на t.me/tulvit_blog, если что.

Добавление пагинатора в Drupal

Прикрутить пагинатор в Drupal'e более чем простая задача. Пара строчек кода, не более, в буквальном смысле. Даже странно (и немного обидно), что я потратил как-то уж слишком много времени, чтобы разобраться в этом.

Для теста создадим модуль test_pager, который просто выводит на страницу какую-то информацию. Нам понадобится два файлика, файл конфигурации test_pager.info и, собственно, test_pager.module.

В .info файл напишем что-нибудь наподобие этого:

name = Test Pager
description = Testing pager
core = 7.x

Ну а в test_pager.module создадим нашу страничку с выводом на ней It works!

'Test pager',
'page callback' => '_test_pager',
'access callback' => TRUE,
);
return $items;
}

function _test_pager() {
return 'It works!';
}

Кстати, имя коллбека начинается с '_' неспроста, это одно из соглашений Друпала по именованию функций. Если функция "строго приватная", т. е. нигде больше не вызывается, то называть ее следует начиная с нижнего подчеркивания.

Все, модуль создан, пора его тестировать. Включаем его и переходим на страницу /test-pager.

Создание модуля в Друпал It works!

It works! - а значит самое время прикручивать пагинатор.

То, как мы будем прикручивать пагинатор, зависит от способа получения данных на вывод - либо мы их формируем через запрос к БД с помощью API Друпала (db_select), либо создаем вручную.

С первым все достаточно просто. Для примера сделаем выборку из таблицы... Хм, модуль тестирую на новом инсталле Друпала, контента никакого нет. Пожалуй, выведу имена переменных, хранящихся в таблице variable, их там штук 20-ть должно быть.

Переписываем содержимое нашего коллбека _test_pager:

function _test_pager() {
$output = '';

$result = db_select('variable', 'v')
->fields('v', array('name'))
->execute();

foreach ($result as $record) {
$output .= '

'. $record->name . '

';
}

return $output;
}

Чистим кэш, обновляем страничку /test-pager, видим следующую картину:

Вывод данных с помощью db_select в Друпале

Как и предполагалось, выводятся имена переменных из таблицы variable (колонка name). Вот сразу скриншот из phpMyAdmin, чтобы понятней было что это и откуда:

Таблица variable в БД Друпала

Ну а теперь заместо того, чтобы выводить все на одной странице, добавляем пагинатор. Для этого нам потребуется в цепочке методов db_select() вызвать метод extend('PagerDefault'). Вызывать его надо до выполнения запроса, т. е. до вызова метода execute(). По умолчанию будет создан пагинатор с 10-тью записями на каждую страницу, но можно назначить и свое значение с помощью метода limit(), например extend('PagerDefault')->limit(3) (т. е. если мы хотим выводить по 10 записей на страницу, то limit(10) можно не вызывать, т. к. это дефолтное значение).

И надо не забыть вывести сам пагинатор, который блок со ссылками « first ‹ previous 1 2 3 4 5 6 7 next › last ». За вывод этого блока отвечает функция theme('pager'), вызов которой и возвращает эти ссылки. Т. е. все что нам надо сделать, это добавить в самом конце к выводу $output .= theme('pager');

Итого, измененный код коллбека должен выглядеть как-то так:

function _test_pager() {
$output = '';

$result = db_select('variable', 'v')
->fields('v', array('name'))
->extend('PagerDefault')
->limit(3)
->execute();

foreach ($result as $record) {
$output .= '

'. $record->name . '

';
}

$output .= theme('pager');

return $output;
}

Чистим кэш, рефрешим страничку и видим... Да, наш уже работающий пагинатор:

вывод пагинатора в Drupal

Красота!

А теперь делаем то же самое, но только предположим, что данные получаем не через db_select(), а собираем вручную (да хотя бы через тот же db_query). Для простоты, будем выводить содержимое вот такого массивчика:

$test_array = array('111',
'222',
'333',
'444',
'555',
'666',
'777',
'888',
'999',
'000',
);

Принцип тот же самый, за тем лишь исключением, что теперь нам надо инициализировать пагинатор вручную. Для этого существует функция pager_default_initialize($total, $limit, $element = 0). Два первых аргумента - обязательные, $total это суммарное количество элементов на вывод, $limit это сколько элементов выводить на одну страницу. Третий аргумент опциональный, и нужен лишь в том случае, если у нас на странице много пагинаторов, чтобы они не путались.

Ну а возвращает эта функция номер страницы, на которой мы находимся, другими словами $_GET['page'] с нулем по умолчанию (т. е. если мы на первой, главной, странице - функция вернет ноль, перейдем по пагинатору на вторую страницу, функция вернет единицу, и так далее).

Вот. Ну а дальше уже дело техники, и главное не забыть вставить сами ссылки пагинатора, theme('pager').

function _test_pager() {
$output = '';

$test_array = array('111',
'222',
'333',
'444',
'555',
'666',
'777',
'888',
'999',
'000',
);

//сколько всего элементов
$total = count($test_array);

//будем выводить по четыре элемента на страницу
$limit = 4;

//инициализируем пагинатор
$page = pager_default_initialize($total, $limit);

//вычисляем смещение
$offset = $page * $limit;

//формируем массив на вывод для текущей страницы
$new_array = array_slice($test_array, $offset, $limit);

foreach ($new_array as $value) {
$output .= '

' . $value . '

';
}

//не забываем добавить пагинатор
$output .= theme('pager');

return $output;
}

Все! Осталось только обновить страницу и радоваться постраничному выводу:

вывод данных из массива с пагинатором в Друпал

И парочка ссылок на документацию:
function theme_pager
function pager_default_initialize

Добавление пагинатора рассмотрено на примере Drupal 7, в Drupal 6 чуток по-другому (как - не разбирался, давно обновил все сайты до семерки, но то что в шестом Друпале нет pager_default_initialize - факт, зато есть pager_query). Для Drupal 8 все останется также, как и для Drupal 7, надо полагать.

Комментарии

Спасибо огромное!