Зачем нужен ListView?
Виджет ListView предназначен для вывода (отображения) данных. Каждая запись этого списка формируется с использованием указанного файла в котором описан вид одной записи. Виджет ListView не только выводит список записей, но так же организовывает постраничную навигацию, сортировку и фильтрацию списка.
Подготовка
Для начала нам необходимo определиться какой список мы будем выводить. Для простого примера возьмем список новостей. Для этого необходимо создать простую таблицу News, в которой будут храниться наши записи. SQL запрос для создания таблицы:
- CREATE TABLE IF NOT EXISTS `news` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `visibility` tinyint(1) NOT NULL,
- `date` int(11) NOT NULL,
- `header` varchar(255) NOT NULL,
- `text` text NOT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3;
Далее создаем модель с помощью gii, в итоге получим следующий код модели (файл: /project-folder/models/News.php
):
- <?php
- namespace app\models;
- use Yii;
- /**
- * This is the model class for table "news".
- *
- * @property integer $id
- * @property integer $visibility
- * @property integer $date
- * @property string $header
- * @property string $text
- */
- class News extends \yii\db\ActiveRecord
- {
- /**
- * @inheritdoc
- */
- public static function tableName()
- {
- return 'news';
- }
- /**
- * @inheritdoc
- */
- public function rules()
- {
- return [
- [['visibility', 'date', 'header', 'text'], 'required'],
- [['visibility', 'date'], 'integer'],
- [['text'], 'string'],
- [['header'], 'string', 'max' => 255]
- ];
- }
- /**
- * @inheritdoc
- */
- public function attributeLabels()
- {
- return [
- 'id' => 'ID',
- 'visibility' => 'Visibility',
- 'date' => 'Date',
- 'header' => 'Header',
- 'text' => 'Text',
- ];
- }
- }
Далее создаем контроллер для новостей (с помощью gii), получим следующий код контроллера (файл: /project-folder/controllers/NewsController.php
):
- <?php
- namespace frontend\controllers;
- use Yii;
- class NewsController extends \yii\web\Controller
- {
- public function actionIndex()
- {
- $this->view->title = 'News List';
- return $this->render('index');
- }
- }
Вместе с контроллером будет создан и view со следующим кодом (файл: /project-folder/views/news/index.php
):
- <?php
- /* @var $this yii\web\View */
- ?>
- <h1>news/index</h1>
- <p>
- You may change the content of this page by modifying
- the file <code><?= __FILE__; ?></code>.
- </p>
С подготовкой закончили, переходим непосредственно к выводу списка.
Минимальный код для вывода списка записей с помощью виджета ListView
Для вывода списка необходимо добавить в файл /project-folder/views/news/index.php
следующий код:
- <?php
- use app\models\News;
- use yii\widgets\ListView;
- use yii\data\ActiveDataProvider;
- $dataProvider = new ActiveDataProvider([
- 'query' => News::find()->where(['visibility'=>1])->orderBy('date DESC'),
- 'pagination' => [
- 'pageSize' => 20,
- ],
- ]);
- echo ListView::widget([
- 'dataProvider' => $dataProvider,
- 'itemView' => '_list',
- ]);
И создать файл для вывода записей по шаблону (файл: /project-folder/views/news/_list.php
):
- <?php
- use yii\helpers\Html;
- use yii\helpers\HtmlPurifier;
- ?>
- <div class="news-item">
- <h2><?= Html::encode($model->header) ?></h2>
- <?= HtmlPurifier::process($model->text) ?>
- </div>
Разберем код подробнее
Разберемся немного подробнее. В файл /project-folder/views/news/index.php
мы сначала подключаем модель News с помощью пространства имен (строка: 3):
- use app\models\News;
Далее таким же образом подключаем виджет ListView (строка: 4):
- use yii\widgets\ListView;
И подключаем провайдер данных ActiveDataProvider, который работает с ActiveQuery и возвращает массив объектов моделей с их связями. Используется для отображения данных ActiveRecord (строка: 5).
- use yii\data\ActiveDataProvider;
Далее мы инициализируем ActiveDataProvider, который мы подключили выше (что логичнее делать в контроллере, но об этом позже):
- $dataProvider = new ActiveDataProvider([
- 'query' => News::find()->where(['visibility'=>1])->orderBy('date DESC'),
- 'pagination' => [
- 'pageSize' => 20,
- ],
- ]);
И вызываем виджет ListView, который мы подключили выше, для вывода списка записей и переменной $dataProvider
по шаблону который указан в фале /project-folder/views/news/_list.php
.
- echo ListView::widget([
- 'dataProvider' => $dataProvider,
- 'itemView' => '_list',
- ]);
В шаблоне /project-folder/views/news/_list.php
мы подключаем набор статических методов для создания часто используемых HTML тегов (строка: 2):
- use yii\helpers\Html;
И подключаем класс (хелпер) который очищает HTML от любого вредоносного кода (строка: 3):
- use yii\helpers\HtmlPurifier;
Далее выводим сам шаблон с использованием подключенных классов.
Вывода списка записей с помощью виджета ListView
Перенесем получения списка данных из представления (view) в контроллер. Для этого необходимо подправить контроллер /project-folder/controllers/NewsController.php
, подключить к нему модель News и провайдер данных ActiveDataProvider, соответственно эти подключения убрать из представления /project-folder/views/news/index.php
. Таким образом контроллер /project-folder/controllers/NewsController.php
примет вид:
- <?php
- namespace frontend\controllers;
- use Yii;
- use app\models\News;
- use yii\data\ActiveDataProvider;
- class NewsController extends \yii\web\Controller
- {
- public function actionIndex()
- {
- $dataProvider = new ActiveDataProvider([
- 'query' => News::find()->where(['visibility'=>1])->orderBy('date DESC'),
- 'pagination' => [
- 'pageSize' => 10,
- ],
- ]);
- $this->view->title = 'News List';
- return $this->render('index', ['listDataProvider' => $dataProvider]);
- }
- }
А представление (view) project-folder/views/news/index.php
примет вид:
- <?php
- use yii\widgets\ListView;
- echo ListView::widget([
- 'dataProvider' => $listDataProvider,
- 'itemView' => '_list',
- ]);
Шаблон вывода записей /project-folder/views/news/_list.php
остается без изменений.
Настройка вывода списка записей ListView
Вид виджета ListView и его работу можно настроить под свои нужды.
Часто используемые свойства виджета ListView
Название | Тип | Описание |
---|---|---|
dataProvider | Данные списка | |
itemView | string | Имя представления (view) для вывода записи |
options | array | Настройка внешнего контейнера списка (HTML атрибуты для контейнера) |
layout | atring | Макет списка |
summary | string | Информация о списке |
summaryOptions | array | Настройка контейнера для summary (HTML атрибуты для контейнера) |
itemOptions |
array | Настройка контейнера записи списка (HTML атрибуты для контейнера) |
emptyText | string | Текст при отсутствии элементов списка |
emptyTextOptions | array | Настройка контейнера для emptyText (HTML атрибуты для контейнера) |
pager | array | Постраничная навигация |
Options. Настройка внешнего контейнера списка
options - массив для настройки HTML атрибутов внешнего контейнера ListView. Например заключим наш список в блок (div) с классом и идентификатором news-list:
- <?php
- use yii\widgets\ListView;
- echo ListView::widget([
- 'dataProvider' => $listDataProvider,
- 'itemView' => '_list',
- 'options' => [
- 'tag' => 'div',
- 'class' => 'news-list',
- 'id' => 'news-list',
- ],
- ]);
Layout. Макет списка
Макет определяющий как должны быть организованы различные секции списка. Значение по умолчанию: {summary}\n{items}\n{pager}
, где {summary}
- информация о списке (общее количество элементов и количество элементов показано на странице), {items}
- список, {pager}
- постраничный навигатор. Пример:
- <?php
- use yii\widgets\ListView;
- echo ListView::widget([
- 'dataProvider' => $listDataProvider,
- 'itemView' => '_list',
- 'layout' => "{pager}\n{summary}\n{items}\n{pager}",
- ]);
Summary. Информация о списке
Информацию о списке {summary}
также можно настроить под свои нужды.
{begin} | начальный номер строки на странице |
{end} | последний номер строки на странице |
{count} | количество строк в списке на странице |
{totalCount} | общее количество строк в списке |
{page} | номер текущей страницы |
{pageCount} | общее число страниц в списке |
Пример:
- <?php
- use yii\widgets\ListView;
- echo ListView::widget([
- 'dataProvider' => $listDataProvider,
- 'itemView' => '_list',
- 'layout' => "{pager}\n{summary}\n{items}\n{pager}",
- 'summary' => 'Показано {count} из {totalCount}'
- ]);
SummaryOptions. Настройка контейнера для summary
Заключим summary в тег <span></span>
с классом my-summary
:
- <?php
- use yii\widgets\ListView;
- echo ListView::widget([
- 'dataProvider' => $listDataProvider,
- 'itemView' => '_list',
- 'layout' => "{pager}\n{summary}\n{items}\n{pager}",
- 'summary' => 'Показано {count} из {totalCount}'
- 'summaryOptions' => [
- 'tag' => 'span',
- 'class' => 'my-summary'
- ],
- ]);
ItemOptions. Настройка контейнера записи списка
Например обернем каждую запись в блок (div
) с классом news-item
, пример:
- <?php
- use yii\widgets\ListView;
- echo ListView::widget([
- 'dataProvider' => $listDataProvider,
- 'itemView' => '_list',
- 'itemOptions' => [
- 'tag' => 'div',
- 'class' => 'news-item',
- ],
- ]);
EmptyText. Текст при отсутствии элементов списка
Если список пуст, то необходимо пользователю вывести сообщение об этом, например:
- <?php
- use yii\widgets\ListView;
- echo ListView::widget([
- 'dataProvider' => $listDataProvider,
- 'itemView' => '_list',
- 'emptyText' => 'Список пуст',
- ]);
EmptyTextOptions. Настройка контейнера для emptyText
Заключим текст в тег <p></p>
:
- <?php
- use yii\widgets\ListView;
- echo ListView::widget([
- 'dataProvider' => $listDataProvider,
- 'itemView' => '_list',
- 'emptyText' => 'Список пуст',
- 'emptyTextOptions' => [
- 'tag' => 'p'
- ],
- ]);
Pager. Постраничная навигация
Опция pager используется для настройки разбиения списка на страницы. По умолчанию в Yii2 используется Bootstrap стиль постраничного навигатора. Но мы можем его изменить, например:
- <?php
- use yii\widgets\ListView;
- echo ListView::widget([
- 'dataProvider' => $listDataProvider,
- 'itemView' => '_list',
- 'pager' => [
- 'firstPageLabel' => 'Первая',
- 'lastPageLabel' => 'Последняя',
- 'nextPageLabel' => 'Следующая',
- 'prevPageLabel' => 'Предыдущая',
- 'maxButtonCount' => 5,
- ],
- ]);
Все настройки можно посмотреть здесь: http://www.yiiframework.com/doc-2.0/yii-widgets-linkpager.html
Итого
Окончательный вид project-folder/views/news/index.php
:
- <?php
- use yii\widgets\ListView;
- echo ListView::widget([
- 'dataProvider' => $listDataProvider,
- 'itemView' => '_list',
- 'options' => [
- 'tag' => 'div',
- 'class' => 'news-list',
- 'id' => 'news-list',
- ],
- 'layout' => "{pager}\n{summary}\n{items}\n{pager}",
- 'summary' => 'Показано {count} из {totalCount}',
- 'summaryOptions' => [
- 'tag' => 'span',
- 'class' => 'my-summary'
- ],
- 'itemOptions' => [
- 'tag' => 'div',
- 'class' => 'news-item',
- ],
- 'emptyText' => '<p>Список пуст</p>',
- 'emptyTextOptions' => [
- 'tag' => 'p'
- ],
- 'pager' => [
- 'firstPageLabel' => 'Первая',
- 'lastPageLabel' => 'Последняя',
- 'nextPageLabel' => 'Следующая',
- 'prevPageLabel' => 'Предыдущая',
- 'maxButtonCount' => 5,
- ],
- ]);
Дополнительно
С официальной документацией виджета можно ознакомиться здесь: http://www.yiiframework.com/doc-2.0/yii-widgets-listview.html