Yii2 связь многие ко многим поиск по тегам

375
08 августа 2017, 15:08

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

Вопрос №1: как мне сделать так, что бы по команде (доустим нажата кнопка) все значения атрибутов tag-id у блоков, которые имеют класс Active, считывались и попадали в (допустим) массив?

Далее допустим я получил массив $tags, который содержит в себе id тегов, выбранных для поиска, допустим их будет три

Array(
[0] => 24
[1] => 12
[2] => 5)

Но что дальше? Как объяснить системе, что нужно искать картинки, которые имеют теги с выбранными id? Искать нужно картинки, а теги это ведь совсем другая таблица в БД. Единственное, что я нашёл, это использование связи как вызова к БД.

public function getArts()
{
    return $this->hasMany(Art::className(), ['id' => 'art_id'])->viaTable('art_tag', ['tag_id' => 'id']);
}
public function getTagArts()
{
    return $this->getArts()->asArray()->all();
}

Но это работает только если в поиске указан только один тег, поэтому в случае указания трёх тегов, я просто делал поиск для каждого по отдельности и потом соединял всё это в массив.

foreach($tags as $tag)
        {
            $search = Tag::findOne($tag);
            $result[] = $search->getTagArts();
        }

и таким образом поиск по трём тегам в отдельности превращается в это (для запроса использовался $_GET. И вроде всё нормально, для получения конечного результата нужно просто найти совпадения (в данном примере - картинка с id = 66).

Вопрос №2: а как совпадения-то искать? Массив-то трёхуровневый получается! Не нашёл я в документации PHP подходящих функций. А что будет, когда на сайте разместятся 12 000 картинок и у каждой по 3-5 тегов? Это же запрос по 3-4 тегам потребует миллионов сравнений! Может мне пересмотреть подход к поиску? Может я что-то упустил?

Answer 1

Определите в модели с картинками отношение, по аналогии с

public function getArts()
{
    return $this->hasMany(Art::className(), ['id' => 'art_id'])->viaTable('art_tag', ['tag_id' => 'id']);
}

У вас есть массив id тегов, осталось составить условие

Arts::find()
    ->joinWith('tags')
    ->where(['tags.id'=>$tagsIds])
    ->all();

Документация

P.S. Код писал без проверки, если не работает, придется поправить =)

READ ALSO
MySQL репликация на три мастера

MySQL репликация на три мастера

Есть три сервера в разных местахХотелось бы пользоваться каждым локально

333
сравнение полей двух подзапросов

сравнение полей двух подзапросов

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

287
Удаление дублей в json array java

Удаление дублей в json array java

Имеется JSON файл с информацией о более чем 26 тысаэропортов с такими данными:

458
vk api авторизация

vk api авторизация

При попытке отправки запроса на code в ответе нет заголовка "location"Находил рекомендацию отключить следование редиректу

423