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

Laravel中通过whereHas筛选中间表条件,实现仅展示当前用户未选择产品的技术问询

解决方案:修正关联与查询作用域

首先,先纠正你现有代码里的两处小问题,再完善核心查询逻辑:

1. 修正Product模型的items关联

你当前的items()关联写错了目标模型,应该关联Item::class而非Product::class;另外因为中间表名不是Laravel默认的复数组合形式,需要手动指定中间表和外键;如果后续需要访问中间表的user_id字段,还要加上withPivot:

public function items()
{
    return $this->belongsToMany(Item::class, 'product_item', 'product_id', 'item_id')
                ->withPivot('user_id'); // 允许访问中间表的user_id字段
}

2. 完善查询作用域逻辑

你的核心需求是获取当前用户从未选择过的产品,本质是筛选出所有Product中,在product_item表内没有和当前用户ID关联的记录。我们可以用Laravel的whereDoesntHave方法实现这个“不存在关联”的查询,同时按照Laravel作用域规范,方法名需要以scope开头:

public function scopeShowNonSelectedItem($query, $userId)
{
    return $query->when($userId, function ($query) use ($userId) {
        // 筛选逻辑:不存在与当前用户绑定的product_item记录的Product
        $query->whereDoesntHave('items', function ($q) use ($userId) {
            $q->wherePivot('user_id', $userId);
        });
    });
}

逻辑说明

  • whereDoesntHave('items', ...):检查当前Product是否不存在满足条件的items关联记录
  • wherePivot('user_id', $userId):指定关联的中间表(product_item)中user_id等于当前传入的用户ID
  • 最终效果:只保留那些没有被当前用户在product_item表中关联过的Product,完全不受其他用户的关联记录影响

调用示例

你可以在控制器里这样使用这个作用域:

// 获取user_id=2未选择的产品
$products = Product::showNonSelectedItem(2)->get();

// 获取user_id=3未选择的产品
$products = Product::showNonSelectedItem(3)->get();

验证测试数据

  • 当user_id=2时,product_item表中只有product_id=1的记录属于该用户,所以返回product_id=2、3,符合预期
  • 当user_id=3时,product_item表中product_id=1、2的记录属于该用户,所以返回product_id=3,符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 03:52:35