Laravel: Как создать полиморфную связь «многие ко многим» hasManyThrough?

Ситуация

У меня есть следующие модели:

  • Post
  • Video
  • Tag

Они хранятся в таблицах базы данных:

  • posts (со столбцами id и name)
  • videos (со столбцами id и name)
  • tags (со столбцами id и name)

А также таблица taggables со столбцами:

  • tag_id (идентификатор Tag)
  • taggable_id (идентификатор Post или Video)
  • taggable_type (либо App\Post, либо App\Video)

Обе модели Post и Video имеют morphToMany отношение к Tag, используя:

public function tags()
{
    return $this->morphToMany('App\Tag', 'taggable');
}

И модель Tag имеет обратные morphedByMany отношения, установленные с:

public function posts()
{
    return $this->morphedByMany('App\Post', 'taggable');
}

public function videos()
{
    return $this->morphedByMany('App\Video', 'taggable');
}

(Пока это работает, и все точно так, как описано в Документы Laravel.)

Теперь, в дополнение к этому, у меня есть модель TagGroup, которая имеет отношение One-to-Many к Tag, поэтому несколько тегов могут принадлежать группе тегов. (Для hasMany('App\Tag') и belongsTo('App\TagGroup') используется столбец tag_group_id в таблице tags.)

Вопрос

Как установить связь между моделью TagGroup и моделями Post и (отдельно) Video? (Например, чтобы получить все сообщения, отмеченные тегами определенной группы.)

Я знаю, что есть hasManyThrough, но, похоже, это не работает с полиморфными отношениями «многие ко многим» в качестве промежуточного звена. Или я что-то не так делаю?

Также есть определение пользовательских промежуточных таблиц с MorphPivot и ->using(), но в документации об этом очень неясно.

Можно ли это сделать без дополнительных плагинов/фреймворков?


person Philip    schedule 10.04.2019    source источник
comment
Поскольку для hasManyThrough отношений "многие ко многим" нет встроенного, то, насколько мне известно, нет и встроенного для таких полиморфных отношений. Вы явно можете создать какие-то методы для загрузки моделей групп тегов, но вы, скорее всего, не выиграете от жадной загрузки...   -  person Namoshek    schedule 11.04.2019


Ответы (1)


Не уверен, что это именно то, что вам нужно, но у меня есть эта настройка

Кампании --(morphedByMany)--> Статьи --(HasMany)--> Теги

Сводная таблица (model_campaign), связывающая кампанию и статьи, имеет следующую структуру:

model_id | модель_тип | идентификатор_кампании

Я получил метод отношений, чтобы работать следующим образом:

class Campaign extends Model
{
    public function tags(): HasManyThrough
    {
        return $this
            ->hasManyThrough(Tag::class, Article::class, 'model_campaign.campaign_id')
            ->join('model_campaign', function ($join) {
                $join
                    ->on('model_campaign.model_id', '=', 'articles.id')
                    ->where('model_campaign.model_type', Article::class);
            });
    }
}

Я еще не тестировал его подробно, но на первый взгляд кажется, что он работает нормально.

person Gregory    schedule 06.02.2020