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.

yii2-listview-config.png

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

 
Ищу разработчиков: NodeJS, PHP, удалённая работа. Зарплата в € Необходим опыт работы в FinTech. Практика работы со Stripe будет большим плюсом.
Расскажите кратко о себе и навыках в Telegram @markvi