Laravel四层嵌套hasmany关联在最下级子模型加where条件返回正向嵌套JSON
解决方案
修正后完整实现代码
以下是ModelA中thedata静态方法的正确实现,可同时满足末级筛选、正向嵌套结构返回、父级指定字段查询需求:
public static function thedata($string) { return self::whereHas('modelb.modelc.modeld', function ($query) use ($string) { // 筛选存在符合条件ModelD的顶层ModelA $query->where('column', 'like', "%{$string}%") ->whereColumn('modelc.column2', 'modeld.column2') ->whereColumn('modelc.column3', 'modeld.column3'); }) ->with([ // 指定ModelB返回字段,必须带主键id和关联父级的外键modela_id 'modelb:id,modela_id,field1,field2', // 指定ModelC返回字段,必须带主键id和关联父级的外键modelb_id 'modelb.modelc:id,modelb_id,column2,column3,field1', // 过滤末级ModelD,指定返回字段需带关联父级的外键modelc_id 'modelb.modelc.modeld' => function ($query) use ($string) { $query->where('column', 'like', "%{$string}%"); } ]) ->get(); }
关联定义优化建议
建议将ModelC和ModelD的跨表匹配条件放到关联方法中,避免重复编码:
// ModelC.php public function modeld() { return $this->hasMany(ModelD::class) ->whereColumn('modelc.column2', 'modeld.column2') ->whereColumn('modelc.column3', 'modeld.column3'); }
优化后thedata方法中的两个查询闭包都可以删除whereColumn相关代码,逻辑更简洁。
逻辑说明
whereHas('modelb.modelc.modeld')的作用是筛选顶层ModelA:仅保留子孙层级中存在符合筛选条件ModelD的顶层模型,过滤无匹配数据的父级记录- 带闭包的
with预加载的作用:- 按
ModelA->ModelB->ModelC->ModelD的正向结构组装嵌套数据 - 仅返回符合筛选条件的末级
ModelD,不会返回同层级下其他不符合条件的子记录 - 支持自定义各级关联返回的字段,注意每级字段必须包含自身主键和指向父级的外键,否则关联关系无法正常绑定
- 按
内容的提问来源于stack exchange,提问作者jdeliver
相关产品推荐
相关产品推荐

