Skip to content

📖 Класс Paginator

Paginator — это сервис для разбиения результатов запроса (pbQuery) на страницы. Он автоматически считает количество записей, текущую и последнюю страницу, а также формирует список элементов. Класс поддерживает:

  • 🔢 получение данных постранично (items(), total(), currentPage() и т.д.);
  • 🖼 вывод через шаблон (renderItem, view);
  • 🔗 генерацию навигации (links());
  • ⚡ работу через AJAX (если включена системная настройка pageblocks_load_scripts).

📰 Выводим новости

🚦 Маршруты

Для примера с новостями нам нужно зарегистрировать два маршрута:

php
// web.php (routes)
route('/news', 'NewsController@index')->name('news.index');
route('/news/pagination', 'NewsController@pagination')->name('news.pagination');
  • news.index — вывод новостей со встроенной пагинацией;
  • news.pagination — возвращает данные для AJAX-запроса.

🎛 Контроллер

Пример контроллера NewsController с двумя методами:

php
class NewsController
{
    // 1. Метод для вывода новостей
    public function index()
    {
        $paginator = query(\modResource::class)
            ->where(['template' => 5, 'published' => 1])
            ->orderBy('publishedon', 'desc')
            ->paginate(5)
            ->route('news.pagination'); // маршрут для ajax-запросов

        return view('file:templates/news', [
            'paginator' => $paginator,
        ]);
    }

    // 2. Метод для получения данных (AJAX)
    public function pagination()
    {
        $paginator = query(modResource::class)
            ->where(['template' => 5, 'published' => 1])
            ->orderBy('publishedon', 'desc')
            ->paginate(5);

        return array_merge($paginator->toArray(), [
            'links' => $paginator->links(), // html-код постраничной навигации
            'data' => $paginator->renderItem('file:chunks/news/item.tpl'), // готовая верстка элементов
        ]);
    }
}

🖼 Шаблон новостей

Файл: templates/news.tpl

html
<ul>
    {foreach $paginator->items() as $item}
        <li>
            <a href="{$item.uri}">{$item.pagetitle}</a>
            <span class="date">{$item.publishedon|date_format:"%d.%m.%Y"}</span>
        </li>
    {/foreach}
</ul>

<div class="pagination" pb-pagination>
    {$paginator->links()}
</div>

🧩 Шаблон одного элемента

Файл: chunks/news/item.tpl

html
<li>
    <a href="{$uri}">{$pagetitle}</a>
    <span class="date">{$publishedon|date_format:"%d.%m.%Y"}</span>
</li>

🔄 Работа через AJAX

Если в системных настройках включено pageblocks_load_scripts, то блок с пагинацией:

html
<div class="pb-pagination" pb-pagination>
    {$paginator->links()}
</div>

автоматически подхватится JavaScript-классом pbPagination. При клике на ссылку будет отправлен AJAX-запрос к маршруту news.pagination, и список новостей обновится без перезагрузки страницы.

📦 Формат ответа (метод pagination)

Метод pagination() возвращает JSON с такими данными:

json
{
  "success": true,
  "total": 42,          // общее количество новостей
  "count": 5,           // количество элементов на текущей странице
  "per_page": 5,        // сколько элементов на страницу
  "current_page": 2,    // текущая страница
  "last_page": 9,       // всего страниц
  "from": 6,            // порядковый номер первой новости на странице
  "to": 10,             // порядковый номер последней новости на странице
  "data": [ ... ],      // массив новостей (результат выборки)
  "links": "<ul>...</ul>", // html-код постраничной навигации
  "data": "<li>...</li><li>...</li>" // готовая верстка элементов (chunk)
}

👉 Обрати внимание: ключ data здесь перекрывается —

  • первый data идёт от $paginator->toArray() (массив элементов),
  • второй data — это HTML-разметка списка (renderItem).

Таким образом, фронтенд может либо работать с JSON-данными, либо сразу вставлять готовую разметку.

↕️ Сортировка

Теперь мы хотим дать пользователю возможность выбирать, как сортировать новости: по дате или по заголовку, и в каком направлении (ASC/DESC).

Для этого метод pagination примет объект Request:

php
use Boshnik\PageBlocks\Http\Request;

class NewsController
{
    public function pagination(Request $request)
    {
        // определяем параметры сортировки
        $sortby = $request->get('sortby', 'publishedon'); // поле сортировки
        $sortdir = $request->get('sortdir', 'desc');      // направление сортировки

        $paginator = query(modResource::class)
            ->where(['template' => 5, 'published' => 1])
            ->orderBy($sortby, $sortdir)
            ->paginate(5);

        return array_merge($paginator->toArray(), [
            'links' => $paginator->links(),
            'data' => $paginator->renderItem('file:chunks/news/item.tpl'),
        ]);
    }
}

🖼 Верстка с селектом сортировки

В шаблоне новостей (templates/news.tpl) добавим селект с вариантами сортировки:

html
<div pb-sort>
	<label for="sort">Сортировка:</label>
	<select name="sort">
		<option value="publishedon-desc">Дате (убывание)</option>
		<option value="publishedon-asc">Дате (возрастание)</option>
		<option value="pagetitle-desc">Заголовку (убывание)</option>
		<option value="pagetitle-asc">Заголовку (возрастание)</option>
	</select>
</div>

<ul id="news-list">
    {foreach $paginator->items() as $item}
        <li>
            <a href="{$item.uri}">{$item.pagetitle}</a>
            <span class="date">{$item.publishedon|date_format:"%d.%m.%Y"}</span>
        </li>
    {/foreach}
</ul>

<div class="pagination" pb-pagination>
    {$paginator->links()}
</div>

🔄 Как это работает

  1. Пользователь выбирает вариант сортировки в селекте.
  2. JavaScript отправляет AJAX-запрос на маршрут news.pagination, добавляя sortby и sortdir в параметры.
  3. Контроллер использует их при построении запроса.
  4. Ответ возвращается в JSON, обновляется список и пагинация.

© PageBlocks 2019-present