YII2 Как создать представление ListView + исходники.
Yii2 ListView это виджет который используется для создания прдставления на основе вашего списка данных из БД. Данный виджет крайне удобен для вывода ваших материалов с пагинатором. Более того ListView имеет очень гибкие настройки. Сегодня я покажу вам элементарный пример его использования.
Подготовка
Для начала необходимо создать проект на YII2 и подготовить данные которые мы будем выводить через наше представление. Предположим наша БД будет называтся "post" которую вы уже наполнили её рыбными данными, а также создали модель Post. Давайте добавим в наш контроллер Post ответ на запрос "list":
// PostController.php
use app\models\Post;
class PostController extends \yii\web\Controller
public function actionList()
{
$dataProvider = new ActiveDataProvider([
'query' => Post::find()->where(['status' => 1])->orderBy('id DESC'),
'pagination' => [
'pageSize' => 10,
],
]);
$this->view->title = 'Posts List';
return $this->render('list', ['listDataProvider' => $dataProvider]);
}
}
Описанный медот формирует ответ на запрос по ссылке: /index.php?r=post/list и рендерит шаблон из list.php что расположен в папке /views/post/ Давайте посмотрим, как сделать представление ListView в list.php.
Настройка представления ListView
В самом простом примере вы просто выводите ListView передаёте dataProvider в list.php файл предствавления и всё готово!
/* list.php view file*/
<?=
ListView::widget([
'dataProvider' => $listDataProvider,
]);
?>
Но в таком случае ListView просто отобращает список id материалов. По умолчанию он будет отображать список моделей key. Так что нам прийдётся немного настроить данное представление. В следующем изображении описанны наиболее важные опции для кастомизации ListView.
dataProvider
dataProvider используется для указания источника данных. это объект, который исполняется в yii\data\DataProviderInterface. Обычно этот объект является экземпляром ActiveDataProvider класса.
Options
options представляет собой массив, для создания HTML атрибутов обёртки ListView представления. Например:
<?=
ListView::widget([
'dataProvider' => $listDataProvider,
'options' => [
'tag' => 'div',
'class' => 'list-wrapper',
'id' => 'list-wrapper',
],
]);
?>
Layout
layout пределяет структуру разметки ListView. По умолчанию его значение является строкой со следующим содержимым: "{summary}\n{items}\n{pager}". Это означает, во-первых, отрендерить заголовок ListView. Затем последовательность объектов массива и в конце пагинатоа. Вы леко можете это переопределить, например переместив пагинатор наверх, вот так:
<?=
ListView::widget([
'dataProvider' => $listDataProvider,
'options' => [
'tag' => 'div',
'class' => 'list-wrapper',
'id' => 'list-wrapper',
],
'layout' => "{pager}\n{items}\n{summary}",
]);
?>
itemView
itemView может быть либо строкой, либо функцией обратного вызова. Его работа заключается в том, чтобы сказать ListView как визуализировать каждый отдельный элемент списка с данными из модели.
Передача строки
Для передачи строки, строка должна быть именем файла из части шаблона. Например, мы можем создать _list_item.php часть шаблона для определения HTML-разметки каждого элемента списка. Затем мы передаём эту часть в основной шаблон представления itemView таким образом:
<?=
ListView::widget([
'dataProvider' => $listDataProvider,
'options' => [
'tag' => 'div',
'class' => 'list-wrapper',
'id' => 'list-wrapper',
],
'layout' => "{pager}\n{items}\n{summary}",
'itemView' => '_list_item',
]);
?>
В такой конфигурации будет четыре переменные неявно передающиеся и доступные в _list_item части шаблона.
- $model — элемент модели данных
- $key — ключевое значение, связанное с элементом данных
- $index — нулевой индекс элемента данных в массиве элементов, возвращенных в $dataProvider.
- $widget — Сам экземпляр виджета ListView.
Передача Callback'а
Альтернативным вариантом может послужить передача callback'а в itemView и данный callback будет вызыватся каждый раз при рендеринге элемента списка.
<?=
ListView::widget([
'dataProvider' => $listDataProvider,
'options' => [
'tag' => 'div',
'class' => 'list-wrapper',
'id' => 'list-wrapper',
],
'layout' => "{pager}\n{items}\n{summary}",
'itemView' => function ($model, $key, $index, $widget) {
return $this->render('_list_item',['model' => $model]);
// or just do some echo
// return $model->title . ' posted by ' . $model->author;
},
]);
?>
Функция обратного вызова должа быть прописана как показанно ниже и четыре параметра, как в неявных переменных из примера выше.
function ($model, $key, $index, $widget)
Шаблон элемента _list_item.php может иметь следующий вид:
<?php
// _list_item.php
use yii\helpers\Html;
use yii\helpers\Url;
?>
<article class="item" data-key="<?= $model->id; ?>">
<h2 class="title">
<?= Html::a(Html::encode($model->title), Url::toRoute(['post/show', 'id' => $model->id]), ['title' => $model->title]) ?>
</h2>
<div class="item-excerpt">
<?= Html::encode($model->excerpt); ?>
</div>
</article>
Когда и почему
Итак, когда же мы должны передать callback в itemView? Я думаю, что при следующих сценариях будет очень удобно использовать функцию обратного вызова для itemView:
- При изменении или форматировании данных модели до рендеринга
- Вскрыв нормальный поток рендеринга. Например используя $index мы можем вставить рекламу после трёх пунктов элементов.
- Рендеринг различных частей шаблона. Например мы можем отрендерить шаблонный текст, изображение или даже видео в соответствии с категорией модели в поле.
Пагинатор
Пагинатор используется для постраничного вывода эллементов. По умолчанию в YII2 используется компонент пагинации из Bootstrap. Но вы можете добавить свои собственные настройки, чтобы настроить его.
ListView::widget([
'dataProvider' => $listDataProvider,
'options' => [
'tag' => 'div',
'class' => 'list-wrapper',
'id' => 'list-wrapper',
],
'layout' => "{pager}\n{items}\n{summary}",
'itemView' => function ($model, $key, $index, $widget) {
return $this->render('_list_item',['model' => $model]);
// or just do some echo
// return $model->title . ' posted by ' . $model->author;
},
'pager' => [
'firstPageLabel' => 'first',
'lastPageLabel' => 'last',
'nextPageLabel' => 'next',
'prevPageLabel' => 'previous',
'maxButtonCount' => 3,
],
]);
Данный пагинатор абстранируется от классов навяззаных в yii\widgets\LinkPager. Для получения дополнительных возможностей кастомизации пагинатора ListView представления, обратитесь к официальной документации YII2 LinkPager.
Итоги
В итоге у нас есть образцы кода для настройки Yii2 ListView. Ниже пример кода собранный вместе:
<?=
ListView::widget([
'dataProvider' => $listDataProvider,
'options' => [
'tag' => 'div',
'class' => 'list-wrapper',
'id' => 'list-wrapper',
],
'layout' => "{pager}\n{items}\n{summary}",
'itemView' => function ($model, $key, $index, $widget) {
return $this->render('_list_item',['model' => $model]);
// or just do some echo
// return $model->title . ' posted by ' . $model->author;
},
'itemOptions' => [
'tag' => false,
],
'pager' => [
'firstPageLabel' => 'first',
'lastPageLabel' => 'last',
'nextPageLabel' => 'next',
'prevPageLabel' => 'previous',
'maxButtonCount' => 3,
],
]);
?>
Скачать исходники можно на моём гитхабе github.com/markxxv/yii2-listview-sample