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

Laravel中如何不使用JOIN通过Eloquent附加子模型字段到父模型

Eloquent 父子关联字段平铺挂载方案

核心结论

Eloquent原生支持该需求,不需要使用JOIN查询,实现逻辑和已有的withCount()方法完全同源,最终可实现子表字段与父模型字段平级挂载,无嵌套关联结构。

实现方式

Laravel 9 及以上版本(原生便捷方法)

直接调用withCount()底层的通用关联聚合方法withAggregate()即可,用法和withCount()几乎一致,支持直接提取子表任意字段挂载到父模型顶层属性:

// 需提前在Types模型中定义好typeChild关联(hasOne/belongsTo类单结果关联)
Types::query()
    ->withAggregate('typeChild', 'rank as child_rank')
    ->get()

该方法底层生成的是关联相关子查询,和withCount()的执行逻辑完全相同,不会产生JOIN语句。返回结果中child_rank字段会和Types模型自身的id、名称等原生字段平级,不会嵌套在typeChild关联数组下,完全符合平级挂载的结构要求。

Laravel 8 及更早版本

低版本没有内置withAggregate()方法时,可直接通过查询构造器的addSelect()方法手动追加关联子查询,同样不依赖JOIN,实现效果完全一致:

Types::query()
    ->addSelect([
        'child_rank' => function ($query) {
            // 直接复用模型内已定义的typeChild关联逻辑,无需重复编写外键匹配条件
            return (new Types())->typeChild()
                ->getQuery()
                ->select('rank')
                ->limit(1);
        }
    ])
    ->get()

注意事项

  • 若typeChild是hasMany一对多关联,需要在子查询中增加orderBy()等筛选规则,明确指定要取哪一条子记录的字段,避免子查询返回多行触发SQL错误
  • 如果不需要调用完整的子关联数据,无需额外调用with()做预加载,子查询可独立完成字段取值
  • 该方案的性能表现和withCount()完全一致,无额外性能开销

内容的提问来源于stack exchange,提问作者Aleks

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:07:04