Laravel Eloquent嵌套关联中使用without()方法排除指定关联的问题
解决Laravel中嵌套预加载的排除问题
你的问题其实是Laravel的without()方法和模型全局预加载($with属性)的优先级导致的,下面给你两个可行的解决方案:
方法一:加载关联时显式排除嵌套关联
既然Customer模型的$with里默认预加载了address,你需要在加载customer关联时,通过闭包覆盖它的全局预加载,手动排除address:
return response()->json( Ticket::where('status_id', '!=', 5) ->with(['customer' => function ($query) { // 排除Customer模型默认预加载的address $query->without('address'); }]) ->get() );
这个方法的核心是:当加载customer关联时,主动告诉查询构建器不要加载Customer模型自带的address关联,这样就能得到只包含customer但不包含customer.address的Ticket数据。
方法二:临时禁用模型的全局预加载
如果你不想每次都写闭包,也可以临时清空Customer模型的全局预加载配置:
return response()->json( Ticket::where('status_id', '!=', 5) ->with(['customer' => function ($query) { $query->setEagerLoads([]); // 清空Customer的所有全局预加载 }]) ->get() );
不过这种方法会清空Customer的所有全局预加载,如果你后续给Customer添加了其他全局预加载,可能会影响预期结果,所以更推荐第一种方法。
为什么你的原方法不生效?
你之前用的without(['customer.address'])没效果,是因为without()只能排除**当前模型(Ticket)**定义的预加载关联,而address是Customer模型自己的全局预加载。当Ticket加载customer时,Customer会自动触发自身的$with属性加载address,Ticket的without无法直接干预这个过程。而without(['customer'])能生效,是因为它直接排除了Ticket的customer关联,自然也就不会加载后续的嵌套关联了。
内容的提问来源于stack exchange,提问作者Cas Bekhuis
相关产品推荐
相关产品推荐

