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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 13:57:25