Laravel预加载时如何排除calculationBusSizes关联为空的Program?
解决Laravel预加载嵌套关联后仍返回空关联的问题
你遇到的核心问题是:has('calculation.calculationBusSizes')仅验证关联关系的存在性,不会考虑你在预加载闭包中添加的bus_company_id过滤条件。也就是说,只要program关联的calculation下存在任意calculationBusSizes记录(不管是否匹配bus_company_id),就会被查询出来,但预加载时会过滤掉不匹配的记录,导致最终返回的calculationBusSizes为空数组。
要解决这个问题,需要用whereHas替代has,并在嵌套关联的闭包中加入相同的bus_company_id条件,确保查询和预加载的过滤逻辑一致:
$programs = Program::query() ->where('has_programs_id', '=', $offer->id) ->where('has_programs_type', '=', 'App\Models\Offer') ->with(['calculation.calculationBusSizes' => function($query) use ($company){ $query->where('bus_company_id', '=', $company->id); }]) ->whereHas('calculation.calculationBusSizes', function($query) use ($company){ $query->where('bus_company_id', '=', $company->id); }) ->get();
代码说明
whereHas('calculation.calculationBusSizes', ...):在查询program时,直接通过关联表筛选出拥有符合bus_company_id条件的calculationBusSizes记录的program,从根源排除了没有匹配关联的结果。- 预加载的闭包保持和
whereHas一致的过滤条件,确保最终加载的calculationBusSizes数据都是符合要求的,不会出现空数组。
如果想避免重复编写过滤逻辑,可以将条件抽离为独立闭包:
$busCompanyFilter = function($query) use ($company) { $query->where('bus_company_id', '=', $company->id); }; $programs = Program::query() ->where('has_programs_id', '=', $offer->id) ->where('has_programs_type', '=', 'App\Models\Offer') ->with(['calculation.calculationBusSizes' => $busCompanyFilter]) ->whereHas('calculation.calculationBusSizes', $busCompanyFilter) ->get();
内容的提问来源于stack exchange,提问作者Telexx
相关产品推荐
相关产品推荐

