Grace Michelle Grace Michelle - 1 month ago 14
PHP Question

Eager Loading, Constraining Eager Loads, Lazy Eager Loading

I'm learning Laravel, and I'm using Laravel 5.2. I want to know about Eager Loading, Constraining Eager Loads, and Lazy Eager Loading. What are the similarities and differences between those three? Can you give an example for each of them? I have read Laravel documentation, but I still don't understand. I hope you can give clearer explanation. Thanks.

Answer

Nutshell:

Eager Loading allows you to get the relationships for some Models efficiently.

Constraining Eager Loads Again makes it efficient but you can limit your results e.g. date range, specific id etc

Lazy Eager Loading Is for when you already have your parent models loaded

Example:

Ok, lets say you're making a Blog where you will have Posts and those post can have comments and likes.

Scenario 1:

You want to get all the Posts with their Comments and their Likes. Would you load all the Posst and then loop through them and get there comments and likes? Well, you could but this could end up being very expensive as it could end up performing many, many queries. Or you could load the posts and then get their ids and load all the comments that you need for those ids and the same for there likes as well. This is essentially what Laravel does with eager loading.

Scenario 2 (a real world example of Scenario 1):

You're creating you feed for the posts. So, you've loaded up all your Posts and then you want to show how many likes and comments it has so you would have something like (very basic):

Controller:

$posts = App\Post::all();

return view('posts.index', compact('posts'));

blade file:

@foreach($posts as $post)

    <h2>{{ $post->title }}</h2>

    <p>{{ $post->description }}</p>

    <p>
        Likes: {{ $post->likes->count() }} <br>
        Comments: {{ $post->comments->count() }}
    </p>

@endforeach

The above would work but for every loop it would actually be querying the database. Changing your controller to:

$posts = App\Post::with('likes', 'comments')->get();

return view('posts.index', compact('posts'));

Will then get the comments and likes for all of the Posts beforehand saving the database and making your application much more efficient.

Scenario 3

I want to show the Posts but I only want to show the last 3 comments that were made.

$posts = App\Post::with(['comments' => function ($query) {

        $query->limit(3);

    }]);

Lazy Eager Loading is for when you've already loaded your Posts and you then need to get all the comments or likes after the fact. Same principle but you would use load instead of with. Another reason you might use load is if you using Route model binding for your controllers so the Post will have already been retrieved but you still want to get it's relationships.

Hope this help!