Eloquent 的 with() 预加载可避免 N+1 查询,通过 2 条 SQL 一次性加载关联数据;支持嵌套、字段筛选(需含外键)、正确关联定义及 whereHas/约束 with 区分使用场景,慎用深层嵌套以防笛卡尔积。
用 Eloquent 的 with() 预加载避免 N+1 查询
直接在查询中调用关联属性(比如 $user->posts)会触发懒加载,每查一个模型就额外发起一次 SQL,100 个用户就会执行 100 次 SELECT * FROM posts WHERE user_id = ? —— 这是性能杀手。
正确做法是用 with() 一次性预加载:
$users = User::with('posts')->get();
foreach ($users as $user) {
echo $user->name;
foreach ($user->posts as $post) { // 此处不再查库
echo $post->title;
}
}
-
with('posts')底层生成一条 JOIN 或独立的SELECT ... WHERE id IN (...),只发 2 条 SQL - 支持嵌套:例如
with('posts.comments')加载三级关联 - 如果只想要部分字段,用
with(['posts' => function ($q) { $q->select('id', 'title', 'user_id'); }]),但注意必须包含外键字段(如user_id),否则关联会断
关联方法定义要匹配实际外键和本地键
模型里写错 belongsTo() 或 hasMany() 的参数,会导致 with() 查不到数据或报错,但错误不明显。
常见陷阱:
立即学习“PHP免费学习笔记(深入)”;