Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon Can you provide an example of using the whenLoaded() method to avoid N 1 queries


Can you provide an example of using the whenLoaded() method to avoid N 1 queries


Certainly! The `whenLoaded()` method is a useful tool in Laravel's Eloquent ORM to safely access relationships without triggering additional database queries, which helps avoid the notorious N+1 query problem.

Understanding the N+1 Query Problem

The N+1 query problem occurs when you load a collection of models and then access a related model for each item individually. For example, if you have 10 posts and you access the author for each post without eager loading, Laravel will execute 1 query to get the posts plus 10 additional queries to get each author - hence N+1 queries.

How `whenLoaded()` Helps

The `whenLoaded()` method checks if a relationship is already loaded (usually via eager loading) before trying to access it. If the relationship is not loaded, it avoids triggering a lazy load query, which helps prevent unexpected queries and improves performance.

Example Scenario

Suppose you have two models: `Post` and `Author`. Each post belongs to an author.

Models

php
class Post extends Model
{
    public function author()
    {
        return $this->belongsTo(Author::class);
    }
}

class Author extends Model
{
    // Author model details
}

Problematic Code (Causing N+1 Queries)

php
$posts = Post::all();

foreach ($posts as $post) {
    echo $post->author->name; // This triggers a query for each post's author
}

Here, `Post::all()` fetches all posts in one query, but `$post->author` triggers a query per post to fetch the author, causing N+1 queries.

Using `whenLoaded()` to Avoid N+1 Queries

Step 1: Eager Load the Relationship

php
$posts = Post::with('author')->get();

This loads all posts and their authors in just two queries.

Step 2: Use `whenLoaded()` to Safely Access the Relationship

php
foreach ($posts as $post) {
    echo $post->whenLoaded('author', function ($author) {
        return $author->name;
    }, 'Author not loaded');
}

Explanation

- The `whenLoaded('author', $callback, $default)` method checks if the `author` relationship is already loaded.
- If loaded, it passes the related model (`Author`) to the callback, allowing you to safely access its properties without triggering a new query.
- If not loaded, it returns the default value (`'Author not loaded'`), preventing accidental lazy loading.

Why This Is Useful

- Prevents accidental lazy loading: If you forget to eager load the relationship, your code won’t trigger extra queries unexpectedly.
- Improves performance: Ensures your code only runs queries you explicitly want.
- Makes your code more robust: You can provide fallback behavior if the relationship isn’t loaded.

Summary

- Use `with()` to eager load relationships and avoid N+1 queries.
- Use `whenLoaded()` to safely access relationships only if they are loaded.
- This combination helps write efficient and clean Eloquent code.

If you want, I can provide a more complex example or demonstrate how to use `whenLoaded()` with nested relationships!