Полиморфное отношение к множеству одинаковых сущностей в Eloquent Laravel

У вас есть общая таблица (полиморфная) которая может хранить общие записи разных моделек.
Например у вас есть модель комментариев, которые есть у постов и у видео. И вы хотите комментарии к постам делить на обычные комментарии (одна коллекция) и премиум комментарии (другая коллекция).
Чтобы ресурс вам возвращал каждый из типов в отдельности.
По умолчанию связь идет через поля entity_id и entity_type
Через них и проходит вся магия. создавая отношения через

public function comments()
{
    return $this->morphMany(Comment::class, 'entity');
}

вы получаете записи комментариев связаных с данным классом. Связь с классом происходит автоматически по имени текущего класса и на нее нельзя влиять стандартными средствами.
Вы можете подумать что решение задачи заключается в подстановке другого type в колонку с классом, но к сожалению laravel eloqment такое не позволяет. Он позволяет лишь переименовать название поля type и id.

Какие есть варианты решения?

Путей несколько. Во первых а для чего вам понадобилось дробить полиморфное отношение? Быть может вам следует сразу создать отдельную сущность. В нашем примере теоретически можно завести отдельную модель Премиум комментарии и связать ее с таблицей обычных комментариев
Но поле связки entity_type - будет хранить название модели с которой идет связь, а оно будет то же самое, а значит что заводить нужно и таблицу и дублировать все входные и выходные механизмы.

Можно пойти другим путем.

Создать виртуальную модель поста, наследуя обычный пост, связав отношение через отдельный метод. Да, тип связи у вас будет новый. По сути вы создали отдельные посты с ссылкой на основную таблицу постов. Но теперь проблема появляется в том, как получить данные связанные с постом при помощи ресурса. Можно конечно построить отношение между основной и виртуальной моделью, это будет весьма хардкорный, но достижимый путь.
Самое оптимальное видимое решение - разделить полиморфные отношения через дополнительный параметр. Физически - нужно будет в полиморфную модель создать дополнительную колонку, вид комментария. Для всех других связей она будет по умолчанию пуста. У вас также останется маневр, если вы захотите добавить аналогичное разделение на теже самые или новые категории в связки с видео или будущими комментируемыми сущностями. А чтобы держать удобной получение комментариев с разным типом - можете создать себе дополнительные функции

public function logos()
{
    return $this->photos()->where('gallery', 'logo');
}
public function certificates()
{
    return $this->photos()->where('gallery', 'certificate');
}
public function galleryes()
{
    return $this->photos()->where('gallery', 'gallery');
}

При этом прежняя функция comments также будет работать и вернет вам все комментарии, на случай если где-либо оно вам понадобится. Что весьма удобно.
Ну и дополнительно можно пойти самым обычным путем и эмулировать полиморфное отношение вручную,

public function products()
{
    return $this->hasMany(Products::class,'entity_id')->where('entity_type','premium');
}

 

по мотивам

https://laracasts.com/discuss/channels/general-discussion/multiple-polymorphic-relations-on-one-model

  • Автор: kosmom
  • Рейтинг: 0
  • Просмотров: 133
  • Комментариев: 0
  • Создан: 12.04.2021 18:09

Комментарии (0)