DEV Community

Morcos Gad
Morcos Gad

Posted on

5 2

Eloquent Performance - N+1 Query Problems - Laravel

I knew that this problem N+1 is one of the problems that affect the performance of my project and I found this article that contains the reasons https://laravel-news.com/laravel-n1-query-problems and solution to this problem and I wanted to share it with you because of the importance of this topic

Four cases to clarify the problem and solve it

  • Case 1. "Regular" N+1 Query
// app/Models/Book.php
class Book extends Model
{
    public function author()
    {
        return $this->belongsTo(Author::class);
    }
}
// Then, in some Controller:
$books = Book::all();
foreach ($books as $book) {
    echo $book->author->name;
}
Enter fullscreen mode Exit fullscreen mode

fix

// Instead of
$books = Book::all();
// You should do
$books = Book::with('author')->get();
Enter fullscreen mode Exit fullscreen mode
  • Case 2. Two Important Symbols
public function index()
{
    $authors = Author::with('books')->get();
    return view('authors.index', compact('authors'));
}

// Blade
@foreach($authors as $author)
    <tr>
        <td>{{ $author->name }}</td>
        <td>{{ $author->books()->count() }}</td>
    </tr>
@endforeach
Enter fullscreen mode Exit fullscreen mode

So, the method of relation would query the database for each author. But if you load the data, without () symbols, it will successfully use the eager loaded data $author->books
fix

// Controller
$authors = Author::withCount('books')->get();
// Blade
{{ $author->books_count }}
Enter fullscreen mode Exit fullscreen mode
  • Case 3. "Hidden" Relationship in Accessor
// Controller
public function index()
{
    $authors = Author::all();
    return view('authors.index', compact('authors'));
}

// Blade
@foreach($authors as $author)
    <tr>
        <td>{{ $author->name }}</td>
        <td>{{ $author->is_active ? 'Yes' : 'No' }}</td>
    </tr>
@endforeach
Enter fullscreen mode Exit fullscreen mode

That "is_active" is defined in the Eloquent model

use Illuminate\Database\Eloquent\Casts\Attribute;
class Author extends Model
{
    public function isActive(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->books->count() > 0,
        );
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Case 4. Be Careful with Packages

Laravel has a great ecosystem of packages, but sometimes it's dangerous to use their features "blindly". You can run into unexpected N+1 queries if you're not careful.

  • The Built-In Solution Against N+1 Query

since Laravel 8.43, the framework https://laravel-news.com/disable-eloquent-lazy-loading-during-development

In addition to the Laravel Debugbar for inspection, you can add a code to the prevention of this problem

You need to add two lines of code to app/Providers/AppServiceProvider.php

use Illuminate\Database\Eloquent\Model;
class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Model::preventLazyLoading(! app()->isProduction());
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, if you launch any page that contains an N+1 Query problem, you will see an error page

I have explained only the important points, but to go deeper, the article must be increased and benefited from.

API Trace View

Struggling with slow API calls?

Dan Mindru walks through how he used Sentry's new Trace View feature to shave off 22.3 seconds from an API call.

Get a practical walkthrough of how to identify bottlenecks, split tasks into multiple parallel tasks, identify slow AI model calls, and more.

Read more →

Top comments (0)

Cloudinary image

Optimize, customize, deliver, manage and analyze your images.

Remove background in all your web images at the same time, use outpainting to expand images with matching content, remove objects via open-set object detection and fill, recolor, crop, resize... Discover these and hundreds more ways to manage your web images and videos on a scale.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay