Вывод данных в Yii2 с помощью GridView и ListView

Привет тебе, %username%! Предлагаю разобраться с отображением данных в Yii2. В этой статье мы рассмотрим DataProviders, которые у нас есть в наличии, как ими пользоваться, а так же такие супер удобные штуки как GridView и ListView. Добро пожаловать!

Итак, давайте представим, что у нас есть несколько табличек в базе и есть ActiveRecord модели, которые им соответствуют. Подразумевается, что вы знаете что это такое и понимаете как это работает, хотя бы в общих чертах. Допустим, у нас есть 4 таблички для нашего блога. Их структура и взаимосвязь изображена ниже.

1415009651db_structure

Структура банальная, но замечательно подходит нам для обучения.

Что мы имеем в моделях:

  • Модель Authors имеет связь типа “один ко многим” с моделью Articles с помощью метода getArticles() . Магия Yii2 (методы __Set()  и __Get() ) предоставляют нам доступ к атрибуту модели  articles[]
  • Модель Articles имеет один связующий метод типа getAuthor() , который возвращает модель Author для данной статьи, и связующий метод getTags() , который обеспечивает нам атрибут tags[] .
  • Ну, и модель Tags тоже имеет связующий метод getArticles() , который обеспечивает нам свойство articles[] , позволяет получать массив статей с данным тегом.

P.S. Я тут не упоминал модель ArticlesTags , но она есть, и используется для реализации связи “многие-ко-многим”.

Итак, с этим все понятно. Собственно давайте посмотрим какие у нас есть инструменты для того, чтоб все это дело как-то выводить пользователю на экран.

DataProviders

В Yii2 есть три различных провайдера данных:

  1. ActiveDataProvider — работает с ActiveQuery и, как правило, возвращает массив объектов ActiveRecord моделей со всеми ихними связями. Как вы понимаете он используется для отображения данных ActiveRecord моделей. Надеюсь понятно выразился.
  2. ArrayDataProvider строится на основе массива. Это довольно удобный способ реализации всяческих сортировок, когда вы отображаете данные из многих разных табличек, используя какие-то изощренные группировки или еще что-то.
  3. SqlDataProvider как вы можете догадаться строится на основе простых sql запросов.

Все эти провайдеры не имеют каких-то особых отличий при отображении. Разница в том, что они по-разному создаются. В первом случае, на основе ActiveQuery какой-либо ActiveRecord модели. Во втором, на основе какого-то обычного массива, а в третьем sql-запроса. Но все они в итоге хранят данные и реализуют функционал сортировки и пагинации (разбивки на страницы) для них.

ActiveDataProvider

Итак, я уже сказал, что этот провайдер строится на основе объекта ActiveQuery . Что это такое? Объясняю. Любой вызов YourModel::find()  вернет вам объект ActiveQuery . Например YourModel::find()->where(['active' => 1]) тоже вернет вам ActiveQuery   и т.д. Просто не заканчивайте цепочку методом, который возвращает результат one(), all(), count()   и т.п. Надеюсь с этим ясно. Вот простой пример:

С последним примером нужно быть осторожным, так как вы ограничите способность вашего провайдера к сортировкам.

SqlDataProvider

Этот провайдер будет собирать данные с помощью SQL запроса. Вот пример:

Этот провайдер удобен, когда нужно вытащить из базы данные используя всякие JOIN, GROUP BY, UNION и т.д. Чем более заковыристый у вас запрос, тем более нужно использоваться данный провайдер, а не ActiveRecord и все остальное.

ArrayDataProvider

Очень удобный провайдер. Он берет данные на основе простого массива. Вот пример из официальной документации:

Этот провайдер хранит данные всех авторов. Очень просто, реально. Но давайте сделаем его чуть более приближенным к суровой реальности. Допустим, я хочу вывести список авторов вместе с количеством их статей и датой последней публикации. Я сделаю это создав свой провайдер, который будет наследоваться от ArrayDataProvider . Я буду использовать метод init() , который доступен практически во всех компонентах Yii2. Этот метод вызывается в самом начале, после инициализации объекта. Это своего рода конструктор.

Вы видите, что переменная allModels  содержит все нужные нам данные.

 

Отображение данных

Ну наконец-то! А то все какие-то провайдеры…

У нас есть DataProvider . Неважно как мы его сделали, с помощью ActiveRecord, Sql или обычного массива. Нам нужно отобразить данные, которые в нем содержаться и для этого у нас есть два инструмента:

  • GridView выведет данные в виде HTML таблицы, если вы ничего не настраивали, то по-умолчанию эта таблица будет иметь кликабельные заголовки колонок, клик по которым будет сортировать данные по этой колонке, пагинацию (разбивку на страницы) а так же выведет данные о том, сколько всего записей в таблице.
  • ListView позваляет вам указать какую-то произвольную вьюху (view), для рендера каждой модели (строчки).

Лучше все это продемонстрировать на нескольких примерах. Допустим у нас есть такой провайдер:

Создадим GridView, с помощью которого выведем несколько колонок.

Код выше выведет нам такую таблицу:

1435348197YiiGridViewBlogArticlesExample

Смотрите как круто. У нас тут есть и пагинация, и возможность сортировки, если кликнуть на заголовок колонки. И данные отформатированы согласно конфигу приложения (формат даты автоматически преобразовался из того, что хранится в БД в тот, как у нас указано в конфиге config/web.php ). Данный компонент реально упрощает жизнь.

Если мы джйним несколько табличек, то можем обращаться к полям каждой из них используя формат table_name.field_name .

Вы можете настраивать вывод под ваши нужды.

Очень удобный атрибут layout , вы наверно из примера догадались зачем он нужен. Он позволяет настроить порядок, в котором будут идти блоки. Вы можете добавить блоки  {summary}, {errors}, {items}, {sorter}, {pager} несколько раз. Например pager может быть вверху таблицы и внизу. Это еще далеко не все возможности настройки GridView . Вы буквально можете делать там все, что угодно вашей фантазии, настраивать вывод каждой конкретной строчки, добавлять в них всякие виджеты, кнопки ajax и прочее. Но это уже предмет другой статьи.

Настройка сортировки и пагинации

В GridView сортировка и пагинация будет у вас по-умолчанию. Этот функционал уже настроен в  yii\data\BaseDataProvider . Вы можете его настроить под себя, естественно. По-умолчанию, на странице отображается 20 элементов. Вы можете изменить это, установив параметр pageSize в нужное вам значение.

Так же вы можете настроить параметры сортировки под себя. Например, сортировка по какому-то столбцу может быть осуществлена сразу по нескольким полям в БД. Вот пример:

Как вы наверно догадались, параметр defaultOrder определяет, то, как данные будут отсортированы изначально. В нашем примере, они будут отсортированы по убыванию поля published, затем по убыванию поля lastEdited.

Параметр attributes содержит данные обо всех полях (колонках, столбцах), которые могут сортироваться и правила, как они это будут делать.

Есть еще один момент, который нужно знать про то, как работает пагинация в разных провайдерах. Как вы понимаете, чтобы отобразить пагинацию, нужно знать сколько отображать на каждой странице элементов, и сколько этих элементов всего. Провайдеры ActiveDataProvider и SqlDataProvider это знают. Но если вы используете ArrayDataProvider , он же никак не знает сколько у вас там всего данных. Вы просто передаете ему массив и он его выводит. Вам придется делать дополнительные толодвижения, чтоб настроить там адекватную пагинацию.

 

В заключении

ListView и GridView очень удобные и практичные компоненты, которые экономят огромное количество времени и сил разработчика и помогают быстро отобразить данные в нормальном виде, сразу с сортировкой и пагинацией. Они просто незаменимы при разработке всяких админок. Напоследок дам ссылку на прокачанный GridView от очень крутого создателя целой кучи крутых компонентов для yii2 – Kartik Visweswaran.

Как честный человек, честно признаюсь, что данная статья является вольным переводом статьи другого парня с английского языка. Если интересно, оригинал можете увидеть здесь.

 

Комментарии
  1. Денис:

    Здравствуйте, подскажите как можно с виджетом листВью сделать пагинацию чтобы отображались только две ссылки – на предыдущию и следующую страницу?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *