These are not my insights but rather a good explanation on Stack Overflow about the difference between the with() and load() methods for eager loading relationships.
Essentially they are the same thing, each one just has a different use case.
Post on SO: laravel with() method versus load() method
Both accomplish the same end results—eager loading a related model onto the first. In fact, they both run exactly the same two queries. The key difference is that
with() eager loads the related model up front, immediately after the initial query (
find(x), for example); when using
load(), you run the initial query first, and then eager load the relation at some later point.
“Eager” here means that we’re associating all the related models for a particular result set using just one query, as opposed to having to run n queries, where n is the number of items in the initial set.
Eager loading using
If we eager load using
with(), for example:
$users = User::with('comments')->get();
…if we have 5 users, the following two queries get run immediately:
select * from `users` select * from `comments` where `comments`.`user_id` in (1, 2, 3, 4, 5)
…and we end up with a collection of models that have the comments attached to the user model, so we can do something like
“Lazy” eager loading using
Or, we can separate the two queries, first by getting the initial result:
$users = User::all();
select * from `users`
And later, if we decide that we need the related comments for all these users, we can eager load them after the fact:
$users = $users->load('comments');
which runs the 2nd query:
select * from `comments` where `comments`.`user_id` in (1, 2, 3, 4, 5)
…and we end up with the same result, just split into two steps. Again, we can call
$users->comments->first()->body to get to the related model for any item.
load() gives you the option of deciding later, based on some dynamic condition, whether or not you need to run the 2nd query. If, however, there’s no question that you’ll need to access all the related items, use
with(). (The docs also reference a caching benefit to using load(), but I’m not familiar with that; in fact, I believe the results of
load() are not cacheable.)
The alternative to either of these would be looping through the initial result set and querying a
hasMany() relation for each item. This would end up running n+1 queries, or 6 in this example. Eager loading, regardless of whether it’s done up-front with
with() or later with
load(), only runs 2 queries.