Как объединить 3 таблицы с Eloquent отношениями Laravel с Eager Loading?

Итак, order имеет внешний_ключ offer_id.

И offer имеет внешний_ключ item_id.

Товар может быть в нескольких предложениях. Но в каждом предложении есть один пункт.

Предложение может быть в нескольких заказах. Но каждый заказ имеет одно предложение.

Когда я делаю это:

$orders = Auth::user()->orders()
            ->with('offer')
            ->get();

Я получаю это:

id: 3,
user_id: 1,
offer_id: 5,
created_at: "2019-02-15 00:40:31",
updated_at: "2019-02-15 00:40:31",
offer: {
    id: 5,
    item_id: 3,
    created_at: "2019-02-15 00:39:40",
    updated_at: "2019-02-15 00:39:40"
}

Как видите, за это предложение я могу получить item_id: 3 Но я хочу получить весь товар целиком; все его столбцы, а не только идентификатор.

Обычно вы должны соединить эти две таблицы. Как это сделать с помощью Eloquent?

Вот мои красноречивые отношения:

Заказать

public function offer()
{
    return $this->belongsTo(Offer::class);
}

Предложение

public function orders()
{
    return $this->hasMany(Order::class);
}

public function item()
{
    return $this->hasOne(Item::class);
}

Элемент

public function offers()
{
    return $this->belongsToMany(Offer::class);
}

person padawanTony    schedule 15.02.2019    source источник


Ответы (3)


Laravel Eager Загрузка

Ниже вы найдете вложенную нетерпеливую загрузку:

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

$books = App\Book::with('author.contacts')->get();

В вашем случае мы можем получить вложенные, используя точечную запись между отношениями.

$orders = Auth::user()->orders()
            ->with(['offer', 'offer.item'])
            ->get();
person Community    schedule 15.02.2019
comment
Вы имеете в виду offer.items, а не offer.orders, верно? Все равно не работает - RelationNotFoundException Call to undefined relationship [items] on model [App\Offer]. - person padawanTony; 15.02.2019
comment
Вы сказали, что в предложении есть заказы, в заказе есть товары. Так что было бы offer.orders.items получать предметы. В вашей модели заказа вы должны определить свое отношение к модели товара. Что было бы $this->hasMany() кажется. Если заказы могут иметь много элементов. - person ; 15.02.2019
comment
Нет. В заказе есть предложение, а в предложении есть товар. Взгляните на внешние ключи, которые я дал в первых двух строках моего описания, пока я обновляю его, чтобы включить отношения, которые у меня есть в моем коде. - person padawanTony; 15.02.2019
comment
Плохо, я неправильно прочитал, так что это будет order.offers.items. Я обновил свой ответ выше, это должно работать нормально. Пока ваша модель предложения имеет отношение к элементам. - person ; 15.02.2019
comment
@padawanTony Это будут не предметы, а просто предметы, поскольку ваши отношения - HasOne. Поэтому, пожалуйста, посмотрите на мой обновленный ответ. - person ; 15.02.2019
comment
Все еще не работает: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'items.offer_id' in 'where clause' (SQL: select * from items`, где items.offer_id в (2, 4, 5))` Из того, что я вижу, он пытается найти offer_id в items, которого не существует. Должно быть наоборот. Так может отношения неправильные? - person padawanTony; 15.02.2019

Если под едой вы подразумеваете товары в заказе, как насчет:

$orders = Auth::user()->orders()
            ->with('offer', 'offer.orders', 'offer.item')
            ->get();
person Mihir Bhende    schedule 15.02.2019
comment
Я получаю RelationNotFoundException Call to undefined relationship [items] on model [App\Order]. - person padawanTony; 15.02.2019
comment
Где находится отношение элементов в вашем проекте, это модель заказа? - person Mihir Bhende; 15.02.2019
comment
Пожалуйста, смотрите обновленное описание. Я добавил отношения. - person padawanTony; 15.02.2019
comment
Все еще не работает: SQLSTATE [42S22]: столбец не найден: 1054 Неизвестный столбец «items.offer_id» в «предложении where» (SQL: выберите * из элементов, где items.offer_id в (2, 4, 5)) `От чего Я вижу, он пытается найти offer_id в товарах, которых не существует. Должно быть наоборот. Так может отношения неправильные? - person padawanTony; 15.02.2019
comment
Вы указали отношение в своей модели предложения к ожидаемому столбцу item_id. Какова структура таблицы? - person Mihir Bhende; 15.02.2019
comment
Да. Итак, таблица orders имеет внешний ключ offer_id. И таблица offers имеет внешний_ключ item_id. Это все. Товар может быть в нескольких предложениях. Но в каждом предложении есть один пункт. Предложение может быть в нескольких заказах. Но каждый заказ имеет одно предложение. - person padawanTony; 15.02.2019
comment
Решил это. Отношения между item и offer должны были измениться на противоположные. Спасибо, что указали мне правильный путь. - person padawanTony; 15.02.2019

Ответы как @MihirBhende, так и @swonder указывали на правильный путь.

Это действительно должно быть:

$orders = Auth::user()->orders()
            ->with('venue')
            ->with('offer.item')
            ->get();

или (то же самое):

$orders = Auth::user()->orders()
            ->with(['venue', 'offer.food'])
            ->get();

Но отношения моделей Offer и Item должны быть обратными:

Предложение

public function item()
{
    return $this->belongsTo(Item::class);
}

Элемент

public function offers()
{
    return $this->hasMany(Offer::class);
}
person padawanTony    schedule 15.02.2019