如何在自定义Join查询中实现Laravel Eager Load(预加载)?
在自定义Join查询中实现Laravel预加载(Eager Load)
你之前的写法问题出在with('tasks')之后多余调用了query(),因为with()方法已经返回Eloquent查询构造器实例,再调用query()会重置之前的预加载配置,导致预加载失效。
正确写法
$projects = Project::with('tasks') ->select('projects.*') ->join('tasks', 'projects.id', '=', 'tasks.project_id') ->groupBy('projects.id') ->get();
更简洁的替代方案
如果你的需求只是获取存在关联任务的项目,完全可以用Eloquent的has()方法替代手动join+groupBy,写法更优雅且性能相当:
$projects = Project::with('tasks') ->has('tasks') ->get();
原理说明
- 第一种写法:先执行join分组查询拿到符合条件的项目集合,再自动执行一次
SELECT * FROM tasks WHERE project_id IN (...)的查询,将任务关联到对应项目,避免N+1查询问题。 - 第二种写法:
has('tasks')底层会生成EXISTS子查询来过滤存在任务的项目,配合with('tasks')同样实现预加载,代码更符合Eloquent的设计理念。
内容的提问来源于stack exchange,提问作者inf3rno
相关产品推荐
相关产品推荐

