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

Laravel 9中如何仅通过中间表外键实现HasManyThrough关联?

原生Laravel实现方案

针对你的两个需求,利用Laravel原生的belongsToMany关联即可实现,无需依赖外部扩展。本质上用户与商品是多对多关系,订单表作为中间关联表承载两者的关联关系及额外订单字段。

1. 获取指定用户的所有下单商品

在User模型中定义与Item的多对多关联,指定订单表作为中间表:

// app/Models/User.php
public function orderedItems()
{
    return $this->belongsToMany(Item::class, 'orders', 'user_id', 'item_id')
                ->using(Order::class) // 关联中间模型Order
                ->withPivot('id', 'created_at', 'quantity') // 按需携带订单表字段
                ->distinct(); // 去重,避免同一商品因多次购买重复出现
}

查询示例:

// 获取ID为1的用户所有下单商品
$user = User::find(1);
$orderedItems = $user->orderedItems;

// 带条件查询(比如筛选30天内下单的商品)
$recentOrderedItems = $user->orderedItems()
    ->where('orders.created_at', '>=', now()->subDays(30))
    ->get();

2. 获取指定商品的所有下单用户

在Item模型中定义与User的反向多对多关联:

// app/Models/Item.php
public function buyers()
{
    return $this->belongsToMany(User::class, 'orders', 'item_id', 'user_id')
                ->using(Order::class)
                ->withPivot('id', 'created_at', 'quantity')
                ->distinct();
}

查询示例:

// 获取ID为5的商品所有下单用户
$item = Item::find(5);
$buyers = $item->buyers;

// 带条件查询(比如筛选已支付的下单用户)
$paidBuyers = $item->buyers()
    ->where('orders.is_paid', true)
    ->get();

方案优势

  • 完全基于Laravel原生关联,无需引入外部依赖
  • 支持关联缓存、链式查询、预加载等Eloquent特性,性能更优
  • 通过withPivot可直接获取订单表的额外字段,满足业务扩展需求
  • 若无需去重(如统计用户重复购买记录),只需移除distinct()方法即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 01:37:17