Laravel - полиморфные отношения "многие ко многим"

Я бьюсь головой о определение полиморфных отношений в Laravel 5.7

Вот ситуация с данными: У меня есть модель для пользователей, модель для продуктов и модель для мерчендайзинга. Я в основном хочу создать WishList для своего пользователя, который может содержать как товары, так и продукты, и я хочу иметь там полиморфные отношения, потому что мне придется добавлять новые типы вещей для продажи позже.

В моей (упрощенной) текущей схеме данных у меня есть

users
-email
-id

products
-id
-name

merchandises
-id
-name

И печально известный

wish_list_items
-user_id
-wish_list_item_type
-wish_list_id

В отношении взаимоотношений (на Пользователе):

public function wishListProducts()
{
    return $this->morphedByMany(Product::class, 'wish_list_items');
}

public function wishListMerchandises()
{
    return $this->morphedByMany(Merchandise::class, 'wish_list_items');
}

Теперь это отлично работает. Но этого недостаточно для того, чего я хочу достичь - мне не хватает шага, чтобы получить ВСЕ элементы из списка желаний, независимо от их типа. В данный момент:

public function wishListAll()
{
    return $this->load(['wishListProducts','wishListMerchandises']);
}

Которые, очевидно, дают мне список всего, но в отдельных коллекциях - а я хочу единую.

Первый вопрос: есть ли способ получить все, что связано с этим пользователем, независимо от типа? Это может быть довольно просто, но я нигде не могу его найти.

Если это невозможно (что я действительно подозреваю, но это будет означать, что эти полиморфные отношения - не более чем способ избежать создания еще одной сводной таблицы, что я бы не прочь сделать), то что люди думают, было бы лучшим способом? продолжать? Первоначальной идеей было создать интерфейс, который будет реализовывать вся моя продаваемая модель, чтобы все унифицировать - мне все равно придется перебирать все мои отдельные коллекции, если нет простого способа объединить их, поскольку они реализуют то же самое. интерфейс? Или я должен просто определить модель для моих WishListItems (на данный момент это сводная таблица, поэтому модель не определена), сделать так, чтобы все мои продаваемые модели расширяли супермодель, и попытаться связать отношения вместе?

Спасибо за вклад!

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
2 239
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Решение "по умолчанию" - это средство доступа, которое объединяет две (или более) коллекции:

public function getWishListItemsAttribute()
{
    return $this->wishListProducts->toBase()->merge($this->wishListMerchandises);
}

// $user->wishListItems

+++ ОБНОВЛЕНИЕ +++

Я создал пакет для объединения отношений с использованием представлений:
https://github.com/staudenmeir/laravel-merged-relations

Сначала создайте представление слияния в миграции:

use Staudenmeir\LaravelMergedRelations\Facades\Schema;

Schema::createMergeView(
    'wish_list_items', [(new User)->wishListMerchandises(), (new User)->wishListProducts()]
);

Затем определите отношения:

class User extends Model
{
    use \Staudenmeir\LaravelMergedRelations\Eloquent\HasMergedRelationships;

    public function wishListItems()
    {
        return $this->mergedRelation('wish_list_items');
    }
}

Используйте его как любые другие отношения:

$user->wishListItems;

$user->wishListItems()->paginate();

User::with('wishListItems')->get();

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

Ours 18.10.2018 18:11

Я создал пакет для объединения отношений и добавил его в свой ответ.

Jonas Staudenmeir 26.06.2019 21:59

Другие вопросы по теме