with() 必须在 get() 等执行方法前调用,否则无效;正确写法是 User::with('posts')->get(),错误写法如 User::all()->with('posts') 会报错或返回空关联,因 all() 已执行查询并返回 Collection,无法再链式调用 with()。

with() 必须在 get() 之前调用
预加载不是“查完再补”,而是“查的时候就一起拿”。with() 返回的是查询构建器实例,只有调用 get()、first() 或 find() 这类执行方法时,Laravel 才真正发起 SQL。如果写成 User::all()->with('posts'),all() 已经执行了查询,with() 就只是个无效链式调用。
常见错误现象:Call to undefined method Illuminate\Database\Eloquent\Collection::with() 或数据里 $user->posts 仍是空集合,但 SQL 日志里只有一条查 users 的语句。
- ✅ 正确:
User::with('posts')->get()、User::with('posts')->find(1) - ❌ 错误:
User::all()->with('posts')、User::get()->with('posts') - ⚠️ 注意:
load()是给已有模型集合补查关联的,比如$users = User::get(); $users->load('posts');—— 它不解决 N+1,只是把 N 次懒加载延迟到统一时刻,仍会发 N 条 SQL
嵌套预加载要传数组,别链式 with()
想同时加载 User → posts → comments,不能写两次 with(),否则后一次会覆盖前一次。Laravel 不支持链式叠加,必须一次性声明完整路径。
使用场景:用户列表页既要显示每人的文章数,又要展示每篇文章的最新三条评论。
- ✅ 正确:
User::with(['posts.comments' => function ($q) { $q->latest()->limit(3); }])->get() - ❌ 错误:
User::with('posts')->with('posts.comments')->get()(只生效posts.comments) - ⚠️ 性能影响:嵌套层级越深,SQL JOIN 越复杂;若某层无数据(如用户没文章),Laravel 仍会保留主记录,但关联属性为集合或 null,需在 Blade 中用
optional($post->comments)->count()或空值判断
带条件的预加载必须用闭包,不能 where()
直接在 with() 里加 where() 是无效的——那只是给查询构建器加条件,不会作用于预加载子查询。Eloquent 预加载的子查询是独立执行的,必须显式通过闭包传入约束逻辑。
常见错误现象:写了 User::with('posts')->where('posts.status', 'published')->get(),结果报错 Unknown column 'posts.status',因为主查询是 users 表,posts 并不在 SELECT 范围内。
- ✅ 正确:
User::with(['posts' => function ($q) { $q->where('status', 'published'); }])->get() - ✅ 带别名计数:
User::withCount(['posts as published_posts' => function ($q) { $q->where('status', 'published'); }])->get() - ⚠️ 注意:闭包里的
$q是针对关联模型(Post)的查询构建器,字段名按 Post 表来写,不是 users 表
外键命名不标准时,hasMany 和 with 都会失效
预加载依赖关系定义正确。如果 Post 表的外键叫 author_id 而不是默认的 user_id,但 User 模型里还用 hasMany(Post::class),那么 with('posts') 查出来的永远是空集合——因为 Laravel 默认按 user_id 匹配,根本找不到数据。
容易被忽略的地方:错误不会报异常,只会静默返回空,调试时容易误判为数据缺失或权限问题。
- ✅ 修正关系:
public function posts() { return $this->hasMany(Post::class, 'author_id'); } - ✅ 同时确认
Post模型的反向关系:public function user() { return $this->belongsTo(User::class, 'author_id'); } - ⚠️ 验证方式:用
dd(User::with('posts')->first())看 SQL 日志,检查预加载语句中 WHERE 条件是否用了author_id IN (...),而不是user_id IN (...)


















