В данной статье мы рассмотрим достаточно мощный виджет, который входит в стандартный набор Yii2 фрэймворка. GridView - это порой незаменимое решение, позволяющее реализовать 70% функционала вашей системы. В большинстве случаев на создание такого модуля с нуля ушло бы очень много времени, а результат мог бы оказаться неожиданным. Поэтому, я предложу разобраться в его функционировании. Он умеет не просто строить таблицы, а делать это виртуозно!
Прежде чем приступать к реализации, я бы предложил изучить немного теории, а точнее, "внутренности" gridView. Ведь порой там хранится больше ответов, чем в официальной документации. Если в своей работе вы используете PHP STORM, то нажмите "очень быстро" два раза правый шифт и введите в поиск: yii\grid\GridView Выбирайте самый первый результат, и поехали:
Погружение вглубь
Первое, что мы видим - это наследование класса GridView от BaseListView. Давайте сначала перейдем внутрь и посмотрим, что там:
BaseListView - базовый класс для виджетов, отображающих данные от DataProvider (об этом классе немного позже). Он предоставляет такие функции, как сортировка, пагинация, а также, фильтрация данных.
Данный класс наследуется от класса Widget. О его функциях, и о том, как он работает, я рассказывать не буду - это отдельная история. Да, и по большому счету, это не имеет смысла, так как не связано с нашим предметом.
Что здесь нужно понять - так это его основные функции и свойства, которые он реализует:
1 options = [] - Это массив данных, который работает с HTML атрибутами контейнера с данными. Здесь мы можем задать class, id и прочие html атрибуты для всей таблицы
2 dataProvider - Важнейший атрибут, без которого работать не будет вообще ничего. В двух словах: он нужен, чтобы организовать выборку данных для дальнейшей работы с ней. Например, данные из ActiveRecord, это SQL запрос.
3 pagination - Спросите вы: откуда pagination? Дело в том, что свойство называется pager, но оно участвует в функции renderPager(), которая работает через LinkPager, а возвращается в виджет в виде объекта pagination. Как несложно догадаться, оно нужно для построения пагинации
4 sort - здесь история такая же, как и с пагинацией: в общем, оно участвует в построении модуля сортировки
5 summary - благодаря конструкциям {totalCount}, {end} и так далее… как вы можете заметить, там их очень много. Мы можем выводить данные как нам удобно, например: Showing 1-5 of 5 items
6 summaryOptions = [] - это HTML атрибуты для обертки конструкции summary, передав туда массив. Мы можем поменять класс обертки, либо добавить какие-нибудь иные аттрибуты
7 showOnEmpty - принимает true/false показывать ли таблицу, если данные пришли пустые, в случае если false, то будет выведено сообщение из атрибута ниже.
8 emptyText - текст, переведенный на все языки, которые вы можете задать в конфигурации фреймворка. Но задать вы можете свой вариант, например: "Нам не удалось найти, то что вы искали : )"
9 layout - с помощью этого свойства вы можете организовать любой удобный порядок основных секций, их существует всего 4: {summary}\n{sorter}\n{items}\n{pager} Здесь я бы заострил внимание на items - это и есть вся наша контент область, основная таблица. Все остальное по смыслу понятное.
Вот мы и познакомились с основным базовым классом, который и выполняет большую часть функционала, он также используется и для построения списков (ListView). Ну, а теперь, перейдем к десерту.
Класс gridView
Сразу нас встречают 3 константы:
const FILTER_POS_HEADER = 'header';
const FILTER_POS_FOOTER = 'footer';
const FILTER_POS_BODY = 'body';
Это варианты расположения фильтра. Позже мы сможем их использовать. Фильтр может быть над заголовком (header), под заголовком (body), и в футере (footer)
dataColumnClass - это класс, который позволяет нам строить колонки, по умолчанию используется класс yii\grid\DataColumn Теперь перейдем внутрь и разберем его работу
1 grid - это свойство используется для внутренней работы grid view. Не вижу особенного смысла его трогать, если только вы не хотите переписать всю внутренность
2 header - это заголовок колонки
3 footer - это заголовок для footera. Обратите внимание: чтобы он заработал, нужно будет перевести свойство showFooter в true, но об этом немного позже
4 content - это анонимная функция, которая отвечает за наполнение колонки. Выглядит это примерно так:
'content' => function($model, $key, $index, $column) {
return $model->id;
}
Где $model, $key, $index - это все параметры перебора передаваемой модели через $dataProvider, а $column работает с текущим состоянием колонки. Например, в своей логике вы можете использовать $column->footer или $column->attribute, вообще все что угодно)
5 visible - показывать ли данную колонку. Часто встречается ситуация, где в зависимости от логики мы показываем/не показываем колонку пользователю (например, админ видит больше)
6 options = [] - массив HTML атрибутов данной колонки, всякие тэги, классы и прочее.
7 headerOptions = [] массив HTML атрибутов для заголовка данной колонки
8 contentOptions = [] массив HTML атрибутов для каждой строки колонки
9 footerOptions = [] массив HTML атрибутов для футера данной колонки. Не забывайте, чтобы он заработал нужно будет перевести свойство showFooter в true
10 filterOptions = [] массив HTML для ячейки с фильтром
Вот так мы подошли к классу DataColumn, который во многом своем - основа для работы с колонками.
1 attribute - это строковое название атрибута вашей модели. Если этот атрибут существует в модели, то основные данные: значение, заголовок и тд. будут отображаться в колонке. Это необходимые свойство, которое нужно задать, чтобы кастомизировать колонку.
2 label - это название вашей колонки, которое также будет участвовать и в сортировке.
3 encodeLabel - Пропускать или экранировать HTML теги. Например, вы можете обернуть ваш заголовок колонки в тег <i> или еще какой-нибудь. В таком случае, поставьте значение в false.
4 value - может быть строкой, либо анонимной функцией. В случае со строкой - это название любого атрибута из вашей модели. Если же анонимная функция, то она должна содержать следующие параметры : function ($model, $key, $index, $column)
5 format - формат отображения данных. Вот, например, если вы захотите вывести тег <img> то у вас это сделать не получится, так как все HTML теги будут экранированы. Поэтому и существуют следующие форматы: (для примера: `"raw"`, `"text"`, `"html"`,* `['date', 'php:Y-m-d']`). Это еще не все. Изучите самостоятельно функции: \yii\i18n\Formatter::format и GridView::formatter|formatter Там очень много разных вариантов.
6 enableSorting - нужна ли сортировка данной колонки. Тут true или false.
7 sortLinkOptions = [] массив HTML атрибутов у ссылки сортировки. Возможность добавить class, id и прочие атрибуты
8 filter - Тут поподробнее... если значение равно false, то фильтр не будет показываться у этой колонки вообще. Если вы хотите, чтобы фильтр работал - должно быть задано свойство filterModel (о нем еще немного позже). Если вы задали это свойство вообще, в таком случае будет построено автоматически input поле на базе класса: yii\helpers\BaseHtml::activeInput. Если же вы передаете в это свойство массив, то будет построен выпадающий список. Во всех остальных случаях вы туда можете передавать любую структуру данных, которые будут отправляться на filterModel.
9 filterInputOptions = [] Массив HTML атрибутов для инпута у фильтра
Ну, вот мы плавно подошли к основным свойствам класса gridView:
Мы остановились и уже разобрали класс: dataColumnClass. Вы уже, наверное, ощутили весь его размах. Давайте двигаться дальше:
1 caption - это основной заголовок вашей таблицы, который будет обернут в тег <caption>. Тут стоит отметить только то, что HTML символы не экранированы, поэтому вы с легкостью можете использовать HTML теги
2 captionOptions = [] массив HTML атрибутов для тега <caption>
3 tableOptions = [] массив HTML атрибутов для всей таблицы
4 options = [] массив HTML атрибутов для обертки виджета
6 headerRowOptions = [] массив HTML атрибутов для тега <tr> который в заголовке таблицы
7 footerRowOptions = [] массив HTML атрибутов для тега <tr> который в футере таблицы
8 rowOptions - может принимать как массив, так и анонимную функцию. Если это массив, то тут работает хелпер: \yii\helpers\Html::renderTagAttributes и, соответственно, мы можем поменять класс или еще что-то для всех <tr> (кроме заголовка и футера, разумеется). Если мы передаем анонимную функцию, то она должна содержать следующие параметры: function ($model, $key, $index, $grid). Где $model - Это модель из dataProvider, $key - ключи этой модели, $index - индексы от нуля, которые достаются из dataProvider при формировании списка, $grid - объект gridView. Соответственно, запись будет выглядеть примерно вот так:
'rowOptions' => function ($model, $key, $index, $grid) {
return [
'data-key-value' => $key
];
},
а все строки будет выглядеть вот так <tr data-key-value=1> и тд.
9 beforeRow - только анонимная функция, и действуют теже самые правила, что и в примере выше. Работает с предыдущими строками.
10 afterRow - все то же самое, только уже следующая строка
11 showHeader - показывать ли заголовок: true/false по умолчанию true
12 showFooter - вот и добрались до этого свойства. Показывать ли футер. Работает с фильтрами, если вы хотите размещать их в футере. По умолчанию это свойство false, и, чтобы увидеть в футере что-то, нужно перевести это значение в true
13 placeFooterAfterBody - это поле влияет только на изменение html кода . Будут ли у вас идти html теги как <thead><tfoot><tbody> либо <thead><tbody><tfoot>, и не более того
14 showOnEmpty - это свойство такое же, как и мы разбирали в BaseListView
15 formatter - если вам нужно поменять модель форматтера, который отвечает за форматирование данных.
16 columns - Самое интересное свойство в этом классе. Оно же и самое основное, представляющее из себя массив данных. Внутри элемента главным атрибутом является class, куда вы можете передать класс из папки: vendor\yiisoft\yii2\grid\, где находится и наш DataColumn, который мы разбирали ранее. Представляет запись из себя следующее:
[
'class' => DataColumn::className(), // this line is optional
'attribute' => 'name',
'format' => 'text',
'label' => 'Name',
],
По умолчанию 'class' => DataColumn::className() уже задан, эту строчку писать не нужно. Есть также вариант - задавать короткие записи, которые строятся по следующей схеме: attribute:format:label Если же вы используете связанные данные, то можно получать их свойства. Для примера: если вы привязали к таблице Lectures таблицу with(‘Authors’), то вы можете получить свойство name вот так: authors.name
17 emptyCell - что делать если ячейка пустая? Данные пришли типа NULL. В данном случае работает следующий класс: \yii\i18n\Formatter::nullDisplay|nullDisplay. Вы можете задать что-нибудь свое
18 filterModel - класс наследуемый от \yii\base\Model. Если вы хотите, чтобы у вас работал фильтр, то это свойство самое важное! Так как от него зависит, какие атрибуты будут участвовать в фильтрации. Первое правило: если вы хотите, чтобы свойство отображалось в фильтре, то оно должно быть в фильтр-моделе. Также все переданные из фильтра данные, попадут в эту фильтр-модель. Именно здесь вы можете их обработать и задать валидацию.
19 filterUrl - урл, куда данные будут улетать с фильтра. Вы можете задать как строкой, так и массивом в формате [[Url::to()]]
20 filterSelector - дополнительный jQuery селектор, если вы хотите дописать новую логику на frontend
21 filterPosition - мы уже частично затронули данное свойство. Вспомните константы вверху. Они участвуют в расположении фильтра: над заголовком, над body и в футере. Но, вспомните: чтобы в футере работал фильтр, нужно, чтобы свойство showFooter стояло true
22 filterRowOptions = [] - массив HTML атрибутов для свойства <tr> фильтра
23 filterErrorSummaryOptions = [] - массив HTML атрибутов для контейнера ошибок фильтра на странице работает на основе хелпера: Html::errorSummary() Обязательно должен быть задан вывод ошибок в layout (это ниже) {errors}
24 filterErrorOptions = [] массив HTML атрибутов для ошибки, которая срабатывает для конкретного поля
25 layout - мы уже рассмотрели это свойство в классе родителе. Тут лишь добавился параметр вывода ошибок с фильтра, не более того: {errors}
ActiveDataProvider
ActiveDataProvider предоставляет данные, которые преобразуются из класса \yii\db\Query или \yii\db\ActiveQuery. По сути, это пагинация, сортировка и тд на уровне запроса. Все это складывается в результат данного класса к базе данных. Здесь важно только понимать следующее: когда вы пишите запрос, например, User::find()->where(["status" => 3]) ТО, не пишите в конце ->one(), ->all() и так далее!! Туда попадает не выборка, а instance запроса, вот, собственно, и все. На практике будет более понятно. Жду вас в следующем уроке.
Облако тегов
Следующая статья
yii2 все о gridview Часть 2
Вот и настал долгожданный момент практики. Кто не читал предыдущий урок, обязательно с ним ознакомьтесь. А теперь я бы хотел предложить вам реализовать следующий функционал...