@iGyry
Backend developer

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

Такая проблема возникла с фильтрами из связанных таблиц.

Объяснение ситуации/предыстория:
Вот моя структура связанной таблицы.
5b1112acb0430764588758.png
Имеется таблица object(товары). Необходимо было сохранять возможность добавлять разные атрибуты(то есть характеристики) разным объектам.
Имеется отдельная таблица "attribute" в которой сохраняются названия группа путктов
В таблице "group" сохраняются пункты для каждого атрибута(их может быть несколько штук.
Соответственно при сохранение объекта мы сохраняем в отдельную таблицу выбранных параметров (рис. выше)

Вопрос/проблема:
Мне нужно, что бы в фильтр фильтровал группу атрибутов как "OR" (это например аргумент 1.2 и аргумент 1.3)
И что бы когда выбираешь например аргумент 1.2 и аргумент 2.2 фильтр фильтровал их как "AND".
Вывожу я объекты. У меня получается выводить их все только с "OR", но мне так не нужно, и в этом проблема.
Как мне сделать так, чтобы при выборе различных атрибутов фильтровалось по типу "AND", а внутри атрибутов фильтровалось типом "OR"? Как в обычных фильтрах.

Описание своих действий:
Сгенерировал код с помощью GRUD.
Код в Search модели:
$query = Object::find()
    ->andWhere(['status' => 1])
    ->joinWith('objectCheckboxs')          
...            
...            

 $query->andFilterWhere([         
    ...
    ...
    'object_attribute_checkbox.group_id' => $this->getArr($params['GroupCheckboxes'][$this->type_id]),
]);

 private function getArr($list){
    $arr = [];
    if (!is_null($list)){
        foreach ($list as $item){
            foreach ($item as $oneElem){
                $arr[] = $oneElem;
            }
        }
    }
    return $arr;
}

$this->getArr($params['GroupCheckboxes'][$this->type_id] - это я получаю массив айдишников полей "group_id" (по итогу он выглядит следующим образом [9, 12]
Функция getArr() нужна для перебора полученного массива, в й массив типа [9, 12].
Также пробовал настроить фильтр таким способом, но ни чего не вышло:
$query->andFilterWhere([
            'and',
                ['object_attribute_radio.group_id' => 9],
                ['object_attribute_radio.group_id' => 12]
            ,
        ]);
  • Вопрос задан
  • 780 просмотров
Пригласить эксперта
Ответы на вопрос 3
@vnpp
Вероятно вам необходимо выполнить несколько раз - по количеству групп фильтруемых атрибутов (корректируя каждый раз имя присоединяемой таблицы через from).
$query->joinWith(...)
И уже для присоединённых таблиц проверять условия.
Ответ написан
webinar
@webinar Куратор тега Yii
Учим yii: https://youtu.be/-WRMlGHLgRg
Вам надо что бы в searchModel приходил удобный массив, например
SomeModel[groups][9][1]
SomeModel[groups][9][2]
SomeModel[groups][12][3]

тогда простой перевор
foreach($SomeModel[groups] as $one){ 
    $arr = ['or'];
    foreach($one as $attr){
          $arr[] = ['group_id' => $attr];
    }
   $query->andWhere($arr);
}

Это схематично, думаю система понятна

ПС. Мне кажется у Вас не верная структура БД. Не понимаю зачем attribut_id, если для декорации, то вероятно в input можно вывести просто id и не будет проблем, так как id уникален

Как вариант можно поиграться с конкатенацией, например:

SELECT * FROM MyMegaTable WHERE CONCAT(group_id, ".",attribut_id) = "2.1";
Ответ написан
@iGyry Автор вопроса
Backend developer
В общем на данный момент я выбрал путь LEFT JOIN, по другому это невозможно сделать :)
Пример запроса:
SELECT o.* FROM object o
LEFT JOIN object_attribute_radio oar1 ON o.id = oar1.object_id
LEFT JOIN object_attribute_radio oar2 ON o.id = oar2.object_id
WHERE (oar1.group_id = 11 OR oar1.group_id = 10) AND (oar2.group_id = 12)
GROUP BY o.id;
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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