Постраничный вывод и сортировка
Когда статей сотни, их показывают частями — по десять на странице, со ссылками «1, 2, 3». Это называют постраничным выводом. В Yii число страниц и смещение считает класс Pagination, а ссылки рисует виджет LinkPager.
Pagination в контроллере
// controllers/PostController.php
use yii\data\Pagination;
public function actionIndex(): string
{
$query = Post::find()->where(['status' => 1]);
$pages = new Pagination([
'totalCount' => $query->count(),
'pageSize' => 10,
]);
$posts = $query
->orderBy(['created_at' => SORT_DESC])
->offset($pages->offset)
->limit($pages->limit)
->all();
return $this->render('index', ['posts' => $posts, 'pages' => $pages]);
}Pagination получает общее число строк и размер страницы, читает номер страницы из параметра адреса page и вычисляет offset и limit для запроса.
Ссылки на страницы
В шаблоне views/post/index.php после списка статей выведите виджет:
<?php
// views/post/index.php
use yii\bootstrap5\LinkPager;
?>
<?= LinkPager::widget(['pagination' => $pages]) ?>Под списком появятся ссылки на страницы. Вторая страница открывается по адресу /posts?page=2. Если страница всего одна, виджет ничего не выводит.
Сортировка
Класс Sort разрешает посетителю выбирать порядок строк:
use yii\data\Sort;
$sort = new Sort([
'attributes' => ['title', 'created_at'],
'defaultOrder' => ['created_at' => SORT_DESC],
]);
$posts = Post::find()->orderBy($sort->orders)->all();В attributes перечислены столбцы, по которым можно сортировать. Передайте $sort в шаблон и выведите ссылку: <?= $sort->link('title') ?>. Щелчок по ней откроет /posts?sort=title, повторный — /posts?sort=-title с обратным порядком.
Поставщик данных
ActiveDataProvider объединяет запрос, постраничный вывод и сортировку в одном объекте:
use yii\data\ActiveDataProvider;
public function actionIndex(): string
{
$dataProvider = new ActiveDataProvider([
'query' => Post::find()->where(['status' => 1]),
'pagination' => ['pageSize' => 10],
'sort' => ['defaultOrder' => ['created_at' => SORT_DESC]],
]);
return $this->render('index', ['dataProvider' => $dataProvider]);
}Считать строки и задавать offset вручную больше не нужно.
| Вызов | Что возвращает |
|---|---|
$dataProvider->getModels() | Статьи текущей страницы |
$dataProvider->getTotalCount() | Общее число статей |
$dataProvider->pagination | Объект Pagination для LinkPager |
$dataProvider->sort | Объект Sort |
Поставщик данных — основа готовых таблиц и списков, которые разобраны в уроке о виджетах данных.
Частая ошибка
В запросе для поставщика данных не вызывают all(), limit() и offset(). Ему нужен невыполненный запрос: он сам посчитает строки и добавит ограничения. Если передать Post::find()->all(), возникнет ошибка, потому что это уже массив, а не запрос.