Laravel如何在whereHas中对pivot中间表加where条件查询未关联指定Item的商品
解决方案
核心思路
- 你需要查询不存在与指定Item的关联关系的Product,对应Eloquent的
whereDoesntHave方法,而非whereHas - 在关联闭包内可以直接引用中间表的字段名做条件筛选
- 需先修正关联定义,适配Item模型非默认的主键字段
步骤1:修正Product模型的关联定义
因为你的Item模型主键为item_id而非默认的id,需要在关联方法中指定关联外键,否则关联查询会出错:
// Product模型 public function items(){ return $this->belongsToMany(Item::class,'product_items', 'product_id', 'item_id'); }
步骤2:实现查询作用域
// Product模型中新增本地作用域 public function scopeGetProductThatIsNotOccupiedByItem($query, ?int $itemId = null) { return $query->when($itemId, function ($query) use ($itemId) { $query->whereDoesntHave('items', function ($q) use ($itemId) { // 直接对中间表product_items的字段做条件判断 $q->where('product_items.item_id', $itemId); }); }); }
使用示例
// 查询未被item_id=5关联的商品 $products = Product::getProductThatIsNotOccupiedByItem(5)->get(); // 不传参数时返回所有商品,符合「指定Item未关联任何商品时返回全部」的需求 $allProducts = Product::getProductThatIsNotOccupiedByItem()->get();
补充说明
如果需要在whereHas场景下筛选中间表条件,写法和上面一致,直接在闭包内指定中间表字段即可:
// 示例:查询已经和指定Item关联的商品 $occupiedProducts = Product::whereHas('items', function ($q) use ($itemId) { $q->where('product_items.item_id', $itemId); })->get();
内容的提问来源于stack exchange,提问作者Miracle Hades
相关产品推荐
相关产品推荐

