Задать вопрос
t-alexashka
@t-alexashka
Сразу пишу legacy код

Как настроить фильтр и сортировку по связанным таблицам?

Привет друзья!

У меня есть модель User и UserSearch(для gridview). в User есть связь с таблицей балансов Balance:
/**
     * Внешняя связь с таблицей балансов
     */
    public function getBalance()
    {
        return $this->hasMany(Balance::className(), ['user_id' => 'id'])->sum('summ');
    }

т.е. в гридвью я вывожу текущую сумму баланса юзера. Вывод работает, но как мне сделать чтобы работал и фильтр для поиска и сортировка по балансу? В UserSearch сделал так:
// Если в фильтре был передан баланс
            if($this->balance) {
                $query->joinWith(['balance' => function ($q) {
                    $q->where('sum(balance.summ) = ' . $this->balance);
                }]);
            }

и получаю бяку:
common\models\User has no relation named "balance".

в User и UserSearch public $balance объявлены, в function rules добавлены.
  • Вопрос задан
  • 516 просмотров
Подписаться 2 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 3
qonand
@qonand
Software Engineer
Как сделать фильтрацию и сортировку по связанным данным довольно подробно описано в документации
что касается конкретно Вашей ошибки - то тут ничего удивительного у Вас есть свойство $balance и реляция с таким же именем, которая так же доступна как свойство. В результате у Вас получается два свойства с одним именем - одно объявленное Вами, второе - "магическое" на основе реляции.
Выход: или переименуйте реляцию или свое свойство
Ответ написан
slo_nik
@slo_nik Куратор тега Yii
Доброе утро.
Покажите, именно, как Вы фильтруете в поисковой модели.
Если настроить нужно по разным моделям фильтрацию, то Вам надо ещё создать псевдонимы таблиц.
Покажу на своём примере.
Мне требовалось в маршрутах сделать поиск по городам.
В модели "маршруты" создал публичное свойство "$city_id;". Так же есть связующая таблица, где маршруты связаны с городами. В самом запросе добавил связь и joinWith().
$query = Routes::find()
            ->from(['r' => Routes::tableName()])
            ->with(['city', 'routesCities', 'price'])
            ->joinWith([
                'city' => function(ActiveQuery $query){
                    $query->from(['rc1' => Cities::tableName()]);
                }
            ])
            ->joinWith([
                'routesCities' => function(ActiveQuery $query){
                    $query->from(['rc2' => RoutesCities::tableName()]);
                }
            ])

В этом запросе я делаю псевдоним для таблицы маршрутов, для таблицы city и связующей таблицы.
Соответственно получаю три псевдонима "r" - маршруты, "rc1" - города, "rc2" - связующая таблица, хранится привязка города к маршруту.
И тогда в фильтрации пишу следующее:
$query->andFilterWhere([
            'r.id' => $this->id,
            /*****/
            'rc1.id' => $this->city_id, // фильтрую по id города.
        ]);

И в GridView делаю саму колонку фильтра, вывожу через запятую города, через которые проходит маршрут.
[
                'attribute' => 'city_id',
                'label' => "Города",
                'filter' => Cities::find()->select(['title', 'id'])->indexBy('id')->orderBy(['title' => SORT_ASC])->column(),
                'value' => function(Routes $routes){
                     return implode(',', ArrayHelper::map($routes->city, 'id', 'title'));
                }
            ],
Ответ написан
Комментировать
webinar
@webinar Куратор тега Yii
Учим yii: https://youtu.be/-WRMlGHLgRg
в User и UserSearch public $balance объявлены

вот тут и проблема, так как Вы объявили в UserSearch public $balance то и получили в $this->balance строку или число, а не связь как ожидается. Так что просто переименуйте или связь или переменную публичную. Что бы они по разному назывались.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы