Eloquent深层关联查询问题:按Production条件筛选ProductionProducts
问题描述
我需要获取supplier_id匹配指定ID的ProductionProducts列表,但仅包含满足delivery_date小于当前日期且status=1的Production对应的产品。现有三个模型关联关系:1个Production对应多个ProductionPackages,1个ProductionPackages对应多个ProductionProducts。当前代码使用with闭包筛选Production条件,但未生效,仍返回status=0的Production对应的产品,代码如下:
public function productEntryInput($supplierId){ $supplier = Supplier::find($supplierId); $productions = ProductionProducts::with(['productionPackage', 'productionPackage.production' => function ($query) use ($supplier) { $inputDate = Date('Y-m-d'); $query->where('status', 1)->where('packing_plant_id', Session::get('user_packingPlant')) ->whereDate('delivery_date', '<',$inputDate); }]) ->where('supplier_id', $supplier->id) ->get(); dd($productions); }
错误原因及解决方案
错误核心
你用with()的闭包只是筛选了关联加载的Production数据,并没有过滤掉那些不符合条件的ProductionProducts本身。也就是说,即使某个ProductionProducts对应的Production不满足status=1和日期条件,这个ProductionProducts仍然会被查询出来,只是它关联的production数据会是null或者空集合而已。
解决办法
要过滤掉不符合条件的ProductionProducts,需要用whereHas()来嵌套查询关联模型的条件,whereHas()会直接限制主模型(ProductionProducts)的结果集,只保留那些存在符合条件的关联模型的记录。
修正后的代码如下:
public function productEntryInput($supplierId){ $supplier = Supplier::findOrFail($supplierId); // 用findOrFail避免supplier不存在时的null问题 $inputDate = Date('Y-m-d'); $products = ProductionProducts::with(['productionPackage.production' => function ($query) use ($inputDate) { // 保留with闭包,只加载符合条件的关联数据,减少冗余 $query->where('status', 1) ->where('packing_plant_id', Session::get('user_packingPlant')) ->whereDate('delivery_date', '<', $inputDate); }]) ->where('supplier_id', $supplier->id) // 嵌套whereHas,逐层校验关联的ProductionPackage和Production的条件 ->whereHas('productionPackage.production', function ($query) use ($inputDate) { $query->where('status', 1) ->where('packing_plant_id', Session::get('user_packingPlant')) ->whereDate('delivery_date', '<', $inputDate); }) ->get(); dd($products); }
关键说明
with()的作用是预加载关联数据,可筛选要加载的关联内容,但不影响主模型的查询结果集。whereHas()的作用是过滤主模型结果,只保留存在符合条件关联模型的记录,这才是实现需求的核心逻辑。- 原代码里的
use ($supplier)是多余的,闭包未用到该变量,改为use ($inputDate)更合理。
内容的提问来源于stack exchange,提问作者luukd
相关产品推荐
相关产品推荐

