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

Laravel Eloquent嵌套With关联查询:如何将父模型列值作为子查询Where条件

解决Laravel嵌套关联查询中传递父模型列到子查询的问题

没问题,我完全理解你想要高效获取Category->Brands->Items嵌套结构的需求——循环逐个查询确实太低效了,咱们可以用Laravel的关联约束特性来实现批量、高效的查询,不用走N+1的弯路。

首先,你当前尝试的whereColumn('category_id', 'categories.id')思路是对的,但需要注意嵌套关联中的查询上下文,我来给你调整出正确的写法:

Category::with(['brands' => function ($brandQuery) {
    // 预加载每个品牌下,属于当前分类的商品
    $brandQuery->with(['items' => function ($itemQuery) {
        // 通过whereColumn关联外层分类表的id和商品的category_id
        // 这里Laravel会自动处理表的关联关系,确保每个商品都属于当前父分类
        $itemQuery->whereColumn('items.category_id', 'categories.id');
    }]);
    
    // 可选:如果你只想保留那些有对应分类商品的品牌,加上这个whereHas约束
    $brandQuery->whereHas('items', function ($itemQuery) {
        $itemQuery->whereColumn('items.category_id', 'categories.id');
    });
}])->get();

为什么这个方案高效?

这个写法只会执行3次数据库查询:

  1. 先获取所有目标分类
  2. 批量获取这些分类关联的所有品牌
  3. 批量获取这些品牌下、对应所属分类的商品

完全避免了循环查询带来的N+1性能问题,和你之前的低效方案比,性能提升非常明显。

额外优化:指定需要的字段

如果不需要模型的所有字段,还可以通过select指定需要的列,进一步减少数据传输量:

Category::select('id', 'name') // 只选择分类的必要字段
    ->with(['brands' => function ($brandQuery) {
        $brandQuery->select('id', 'name')
            ->with(['items' => function ($itemQuery) {
                $itemQuery->select('id', 'name', 'brand_id', 'category_id')
                    ->whereColumn('items.category_id', 'categories.id');
            }]);
    }])->get();

原理说明

whereColumn在这里的作用是比较两个表的列值,而不是用固定值去匹配。在嵌套预加载的上下文里,Laravel会自动处理外层categories表和内层items表的关联,确保每个分类下的商品都属于该分类,完美实现你想要的嵌套数据结构。

这样写出来的结果就是每个Category对象下,包含关联的Brands,每个Brand下又只包含属于当前Category的Items,完全符合你的需求。

内容的提问来源于stack exchange,提问作者Анжел Миленов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 14:42:46