The Problem
// This causes N+1 queries!
$posts = Post::all();
foreach ($posts as $post) {
echo $post->author->name; // Query for EACH post
}
100 posts = 101 queries!
Solution: Eager Loading
Basic Eager Loading
// Only 2 queries now!
$posts = Post::with('author')->get();
foreach ($posts as $post) {
echo $post->author->name; // No extra query
}
Multiple Relationships
$posts = Post::with(['author', 'comments', 'tags'])->get();
Nested Relationships
$posts = Post::with('comments.user')->get();
Conditional Eager Loading
$posts = Post::with(['comments' => function ($query) {
$query->where('approved', true)
->orderBy('created_at', 'desc');
}])->get();
Detecting N+1 Problems
Method 1: Laravel Debugbar
composer require barryvdh/laravel-debugbar --dev
Method 2: Prevent Lazy Loading
// AppServiceProvider.php
public function boot()
{
Model::preventLazyLoading(!app()->isProduction());
}
Method 3: Query Log
DB::enableQueryLog();
// Your code here
dd(DB::getQueryLog());
Other Optimization Tips
// Select only needed columns
Post::with('author:id,name')->select('id', 'title', 'author_id')->get();
// Use lazy eager loading when needed
$posts = Post::all();
if ($needAuthors) {
$posts->load('author');
}
// Count without loading
$post->comments()->count();
// Instead of
$post->comments->count();
Comments (0)
Leave a Comment
No comments yet. Be the first to share your thoughts!