如何使用 Laravel 的 Eloquent 关系与 Eager Loading 连接 3 个表?

Posted

技术标签:

【中文标题】如何使用 Laravel 的 Eloquent 关系与 Eager Loading 连接 3 个表?【英文标题】:How to join 3 tables with Laravel's Eloquent relationships with Eager Loading? 【发布时间】:2019-07-09 03:04:06 【问题描述】:

所以,order 有一个 foreign_key offer_id

offer 有一个foreign_key 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 获得此优惠 但我想得到整个项目;它的所有列,而不仅仅是 id。

通常,您会加入这两个表。 如何用 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);

【问题讨论】:

【参考方案1】:

@MihirBhende 和@swonder 的答案指出了正确的方向。

确实应该是:

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

或(同样的事情):

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

OfferItem 模型的关系应该颠倒:

优惠

public function item()

    return $this->belongsTo(Item::class);

物品

public function offers()

    return $this->hasMany(Offer::class);

【讨论】:

【参考方案2】:

如果你所说的食物是指订单中的物品,那么:

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

【讨论】:

我收到了RelationNotFoundException Call to undefined relationship [items] on model [App\Order]. 你的项目中的items关系在哪里,是订单模型吗? 请查看更新后的描述。我添加了关系。 仍然无法正常工作:SQLSTATE[42S22]:找不到列:1054 'where 子句'中的未知列 'items.offer_id'(SQL:select * from items` where items.offer_id in (2, 4, 5))` 就我所见,它试图在 items 中寻找一个不存在的 offer_id。应该反过来。那么也许关系是错误的? 您在报价模型中指定了一个关系,即预期 item_id 列。表结构是什么样的?【参考方案3】:

Laravel Eager Loading

在下面你会发现嵌套的急切加载:

要急切加载嵌套关系,您可以使用“点”语法。例如,让我们在一个 Eloquent 语句中急切地加载本书的所有作者和作者的所有个人联系人:

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

在您的情况下,我们可以使用关系之间的点表示法获得嵌套的。

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

【讨论】:

你的意思是offer.items 不是offer.orders,对吗?它仍然无法正常工作 - RelationNotFoundException Call to undefined relationship [items] on model [App\Offer]. 你说offer有订单,order有商品。所以它会是offer.orders.items 来获取物品。在您的订单模型上,您必须定义与 Item 模型的关系。这似乎是$this->hasMany()。如果订单可以有很多项目。 没有。订单有报价,报价有商品。看看我在描述的前两行中给出的外键,同时我更新它以包含我在代码中的关系。 对不起,我读错了,所以应该是order.offers.items。我已经更新了上面的答案,应该可以正常工作。只要您的 Offer 模型与商品有关系。 @padawanTony 这不是物品,它只是物品,因为您的关系是 HasOne。所以请看我更新的答案。

以上是关于如何使用 Laravel 的 Eloquent 关系与 Eager Loading 连接 3 个表?的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5:如何使用 'where' 或 'orderBy' 使用 eloquent?

如何使用 eloquent 在 laravel 中编写多个连接

Laravel Eloquent - orWhereHas 方法 - 何时使用以及如何使用

如何使用 Laravel 4 Eloquent 连接列?

如何在 Laravel 5.8 中使用 Eloquent 进行查询?

如何在 Laravel/Eloquent 中获得完整的关系