Eager loading relationships in Laravel makes it
really easy to avoid N+1 query problems. This occurs when you run an additional query for each result in a previous
query. Take for example a model Post
that has a hasOne
relationship with User
.
$posts = Post::all();
foreach ($posts as $post) {
// Retrieve the post author
echo $post->user->name;
}
This would run an additional query for each post author. To avoid this we use eager loading. This essentially lazy loads the relationship into one extra query.
$posts = Post::with('user')->get();
Now imagine the reverse of that example. You want to query all users and get their latest post. Easy we use eager
loading to lazy load the posts
relationship.
$users = User::with('posts')->get();
In this case eager loading causes to load all posts for every user. This is bad because we only need the latest post.
Because the user model has a hasMany
relationship with posts, all posts are eager loaded for every user. To solve this
you might think a simple ->limit(1)
would do the
trick. But that does not work.
The solution is actually pretty simple. In order to load the latest post you can simply create a new hasOne
relationship on the User
model.
public function latestPost()
{
return $this->hasOne(Post::class)->latest();
}
When you use this relationship with eager loading only one post will be queried per user.
$users = User::with('latestPost')->get();
foreach ($users as $user) {
// Retrieve the latest post
echo $user->latestPost->title;
}
If you're wondering how you can easily keep track of how many queries are run I highly recommend you install barryvdh/laravel-debugbar.