The first sentence of the Eager Loading section from the Laravel docs is:
When accessing Eloquent relationships as properties, the relationship data is “lazy loaded”. This means the relationship data is not actually loaded until you first access the property.
In the last paragraph of this section it is stated:
To load a relationship only when it has not already been loaded, use the loadMissing method:
public function format(Book $book) { $book->loadMissing('author'); return [ 'name' => $book->name, 'author' => $book->author->name ]; }
But I don’t see the purpose of $book->loadMissing('author')
. Is it doing anything here?
What would be the difference if I just remove this line? According to the first sentence, the author in $book->author->name
would be lazy-loaded anyway, right?
Advertisement
Answer
Very good question; there are subtle differences which are not getting reflected instantly by reading through the documentation.
You are comparing “Lazy Eager Loading” using loadMissing()
to “Lazy Loading” using magic properties on the model.
The only difference, as the name suggests, is that:
- “Lazy loading” only happens upon the relation usage.
- “Eager lazy loading” can happen before the usage.
So, practically, there’s no difference unless you want to explicitly load the relation before its usage.
It also worths a note that both load
and loadMissing
methods give you the opportunity to customize the relation loading logic by passing a closure which is not an option when using magic properties.
$book->loadMissing(['author' => function (Builder $query) { $query->where('approved', true); }]);
Which translates to “Load missing approved author if not already loaded” which is not achievable using $book->author
unless you define an approvedAuthor
relation on the model (which is a better practice, though).
To answer your question directly; yeah, there won’t be any difference if you remove:
$book->loadMissing('author');
in that particular example as it’s being used right after the loading. However, there might be few use cases where one wants to load the relation before its being used.
So, to overview how relation loading methods work:
Eager loading
Through the usage of with()
you can “eager load” relationships at the time you query the parent model:
$book = Book::with('author')->find($id);
Lazy eager loading
To eager load a relationship after the parent model has already been retrieved:
$book->load('author');
Which also might be used in a way to only eager load missing ones:
$book->loadMissing('author');
Contrary to the load()
method, loadMissing()
method filters through the given relations and lazily “eager” loads them only if not already loaded.
Through accepting closures, both methods support custom relation loading logics.
Lazy loading
Lazy loading which happens through the usage of magic properties, is there for developer’s convenience. It loads the relation upon its usage, so that you won’t be needing to load it beforehand.
@rzb has mentioned a very good point in his answer as well. Have a look.