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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 22:24:08