Зачем нужен 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
Комментарии
Отличная статья, жду новых статей по yii2!
ОтветитьУ вас ошибка в NewsController в 15 строке
Ответить'query' => 'query' => News::find()->where(['visibility'=>1])->orderBy('date DESC'),
правильно так
'query' => News::find()->where(['visibility'=>1])->orderBy('date DESC'),
Спасибо, исправил.
ОтветитьСпасибо! Очень хорошая, развернутая статья. Побольше таких!
ОтветитьСерйозно?? Запрос в вьшке до бд??????
Ответить$dataProvider = new ActiveDataProvider([
'query' => News::find()->where(['visibility'=>1])->orderBy('date DESC'),
'pagination' => [
'pageSize' => 20,
],
]);
"Серйозно"!!!!
ОтветитьА если подумать, как правильно писать это слово?!))))
На эмоциях писал =)
ОтветитьА лучше в модель добавить константы, например:
Ответитьconst STATUS_ON
const STATUS_OFF
(названия любые по выбору)
а после уже использовать их в выборках и других местах, где нужно выводить значения
'query' => News::find()->where(['visibility'=>News::STATUS_ON])->orderBy('date DESC'),
шпасибо
ОтветитьСпасибо.
ОтветитьОчень помогло.
Побольше бы таких статей
ОтветитьВы ничего не написали про сортировку и фильтрацию
Ответить
Ответить<div class="news-item">
<h2><?= Html::encode($model->header) ?></h2>
<?= HtmlPurifier::process($model->text) ?>
</div>
А echo вставлять не надо???:
<div class="news-item">
<h2><?= echo Html::encode($model->header) ?></h2>
<?= echo HtmlPurifier::process($model->text) ?>
</div>
Здрасте приехали...
идентично записи ОтветитьОткрываем пхп су - http://php.net/manual/ru/ini.core.php
Ищем short_open_tag
Внимательно читаем Замечание.
А.., спасибо, просветили )
Ответитьпомохите
Ответить