GridView и связанные таблицы в Yii 2

Отображение данных из связанных таблиц в GridView одна из самых распространённых задач при работе с Yii/Yii2.

Рассмотрим, её решения для Yii 2.

Допустим у нас имеются две связанные таблицы. Одна (Users) хранит сведения о пользователях, а вторая () перечень их ролей (Администратор, Пользователь и т. д.).

Структура этих таблиц показана на скриншоте ниже.

Как отобразить соответствующие сведения в GridView с поддержкой стандартных сортировки и поиска (как это показано на следующем скриншоте)?

Подготовка
В данной статье предполагается, что у вас уже реализован каркас CRUD интерфейса при помощи Gii или вручную. К сожалению, создание CRUD интерфейса выходит за рамки данной статьи и потому в ней не рассматривается.

Вначале мы должны явно прописать связи между моделями таблиц.

В нашем случае за связь отвечает метод getRole модели Users.

Если вы используете, для автоматизации выполнения рутинных задач Gii и связь между таблицами зафиксирована на уровне базы данных, то вам, скорее всего не о чем будет беспокоиться. Gii создаст связь автоматически.

Далее создаём в модели поиска (в нашем случае класс SearchUsers) поле по которому мы будем осуществлять поиск.

 

Так как в модели Users свойство role_id имеет тип integer, а свойство role доступно только для чтения, нам необходимо дополнительное поле, чтобы мы могли осуществлять поиск и сортировку по названию роли, а не по её id.

Реализация

В начала продолжим дорабатывать модель поиска.

Пропишем наше новое поле в rules, чтобы оно стало доступным для стандартногопоиска.

Далее нам нужно доработать метод search.

Получим сведения о ролях пользователей при помощи метода joinWith объекта ActiveQuery.

Обратите внимание, в методе joinWidth мы указываем свойство role.

Теперь добавим для dataProvider критерии для сортировки по нашему полю.

Для параметров asc и desc мы указываем уже имя таблицы, в которой хранятся роли (получаем его при помощи метода tableName соответствующей модели) и название поля, по которому нужно выполнить сортировку.

Названия таблицы и поля указываются в виде строки в формате «Таблица.Поле». Поэтому, не точка перед именем поля обязательна.

Для полей созданных самостоятельно (как в нашем примере) критерии для сортировки следует обязательно указывать до вызова метода load объекта ActiveQuery.

Зададим критерии для поиска.

Первые два вызова метода andFilterWhere в приведённой цепочке задают критерии для поиска по полям исходной модели user_name и fio. Третий задаёт эти критерии уже для нашего поля.

Критерии поиска задаются в виде простого массива.

Первый элемент – метод поиска (строка). Здесь задан метод like используемый в Yii2 по умолчанию (поиск по частичному совпадению).

Второй элемент – поле в таблице, по которому осуществляется поиск (в нашем случае с указанием названия таблицы, как при сортировке, т. к. поле находится в другой таблице, а не в той, которой сопоставлена данная модель).

Третий элемент — поле модели, которому сопоставляется предыдущий элемент.

Всё вместе

Ниже приведён пример метода search, в котором все вышеописанные действия уже выполнены.

Настройка GridView

Для того, чтобы данные из связанной таблицы отображались корректно и реализованные нами механизмы сортировки и поиска заработали, нам необходимо настроить соответствующий GridView.

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

Пример приведённый ниже уже немного доработан и отличается от «шаблонного» (добавлены русскоязычные названия столбцов), но структура будет примерно такая:

В столбце «Роль» при этом будут находиться целые числа — идентификаторы ролей в соответствующей таблице базы данных.

По этим «цифрам» можно выполнить сортировку и поиск. Но, как уже сказано выше, это не то, что нам нужно.

Заменим role_id на созданное нами поле roleName и установим в качестве отображаемого значения название роли. Последнее доступно посредством ранее упомянутого свойства role.

Наша таблица преобразилась:

Также изменилась работа сортировки и поиска. И в том и в другом механизме теперь используется название роли вместо её идентификатора.

На скриншотах приведены примеры работы. Сортировки:

Поиска:

6 комментариев

  1. Спасибо тебе, добрый человек! Реально очень полезно оказалось. Базовый функционал, пригодится еще много раз.

  2. Спасибо за материал! Подскажите, пожалуйста, у вас связанные таблицы находятся в одной БД, а если связанные таблицы находятся в разных БД как сделать?

    1. Можно попытаться использовать распределённые запросы (если они поддерживаются вашей СУБД) или настроить Yii 2, так, чтобы он работал с двумя БД одновременно (делается это через настройку компонентов для каждой БД и переопределение метода getDb в моделях).

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

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