Фильтрация полей gridview для связанных таблиц

Есть GridView в которой надо отобразить данные из связанной модели.

Это можно сделать двумя способами: через объявление публичного виртуального поля в модели и манипулирование наименованиями и значениями этих полей в dataProvider и gridView. Так же есть способ не указывать виртуальное поле, а просто в методе search прописать $query->joinWith с необходимой моделью, а в фильтр добавить условие поиска по id, например:

public function search($params) {
    $query = User::find();
    $query->joinWith('user');

    ...
    $query->andFilterWhere(['ilike', Settings::tableName() . '.name', $this->settings_id])
    ...
}

и в гриде можно будет манипулировать через атрибут user.settings_id без проблем.

Первый вариант выглядит очень костыльно (хоть и описан в гайдах фреймворка). А второй вариант не пройдет если будет несколько связанных моделей, например три или четыре

Есть несколько вопросов:

  1. Нет ли способа, чтобы не писать виртуальное поле, лишь для того, чтобы организовать по нему поиск и чтобы не оперировать чисто идентификатором вида user_id? Потому что оба способа выглядят просто абсолютными костылями. Зачем нужно было делать возможность обращаться к связанным моделям и полям в gridview, если фильтр пропадает и приходится городить такой странный огород?
  2. Как можно сделать поиск и сортировку для связанных полей через одну или даже две, три таблицы не прибегая к виртуальным полям? Например firmsubdepartmentusersettingsname. Т.е. в gridView это будет как:

    [
        'attribute' => 'Наименование настройки',
        'value' => 'subdepartment.user.setttings.name',
    ]
    

Ответы (1 шт):

Автор решения: UKRman

В смысле костыльно?! Создаете SerchModel которая наследуется от класса Modal, добавляете нужные поля для фильтра к примеру $settingName, пишете rulse для данного поля, джойните таблицу. В GridView в элемент ('attribute' => 'settingName') вписываете значения атрибута фильтра, в 'value' как у вас или через 'content' => function ($model) { return $model->user->setttings->name } связи можно оформлять также как и в вывод:

$query = User::find();
$query->joinWith('user.setttings'); // екземпляр User -> Setttings
$query->andFilterWhere(['LIKE', Settings::tableName() . '.name', $this->settingName])

Так работает фильтр в фреймовому, у фреймворка хватает других костелен, так что на такую мелочь как фильтр можно закрыть глаза.

→ Ссылка