You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 10中如何通过Eloquent关联获取订单商品的最新库存?

用Eloquent关联实现订单商品对应店铺的最新库存(解决N+1问题)

问题场景

在Laravel 10项目中,存在三张数据表:

  • orders(订单表):包含id、shop_id字段
  • orders_products(订单商品表):包含order_id、product_id字段
  • remainings(库存表):包含date、shop_id、product_id、remaining字段

需要在OrdersProduct模型中定义Eloquent关联,获取对应product_id、对应店铺(通过orders表关联shop_id)的最新日期库存。原hasOneThrough写法会触发N+1查询问题,现需改用支持预加载的Eloquent关联实现。

原代码问题分析

原hasOneThrough关联中使用了whereProductId($this->product_id),该条件依赖当前模型实例的属性,导致Laravel无法将其合并到预加载查询中,只能在每个OrdersProduct实例单独调用时触发子查询,进而引发N+1问题。

解决方案:可预加载的Eloquent关联

方案一:调整hasOneThrough关联,使用字段级条件

在OrdersProduct模型中定义如下关联,通过whereColumn关联表字段而非实例属性,确保关联支持预加载:

use Illuminate\Database\Eloquent\Relations\HasOneThrough;

public function latestRemaining(): HasOneThrough
{
    return $this->hasOneThrough(
        Remaining::class,
        Order::class,
        'id',               // 中间表orders的外键,对应orders_products的order_id
        'shop_id',          // 目标表remainings的外键,对应orders的shop_id
        'order_id',         // 当前表orders_products的本地键,对应orders的id
        'shop_id'           // 中间表orders的本地键,对应remainings的shop_id
    )->whereColumn('remainings.product_id', 'orders_products.product_id')
        ->orderByDesc('date');
}

方案二:使用hasOne结合关联查询

如果觉得hasOneThrough的外键映射容易混淆,也可以用hasOne直接关联Remaining,并通过join关联orders表匹配店铺:

use Illuminate\Database\Eloquent\Relations\HasOne;

public function latestRemaining(): HasOne
{
    return $this->hasOne(Remaining::class)
        ->join('orders', 'orders.shop_id', '=', 'remainings.shop_id')
        ->whereColumn('orders.id', '=', 'orders_products.order_id')
        ->whereColumn('remainings.product_id', '=', 'orders_products.product_id')
        ->orderByDesc('remainings.date')
        ->limit(1);
}

使用方式

通过with()预加载关联,彻底避免N+1查询:

$orderProducts = OrdersProduct::with('latestRemaining')->get();

foreach ($orderProducts as $orderProduct) {
    // 获取最新库存值,注意处理null情况
    $latestRemaining = $orderProduct->latestRemaining?->remaining;
}

执行时只会生成两条查询:一条获取所有订单商品,另一条批量获取对应商品和店铺的最新库存记录。

内容的提问来源于stack exchange,提问作者user618383

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 03:22:22