Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel: What is the purpose of the `loadMissing` function?

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?

like image 780
Adam Avatar asked Nov 11 '17 14:11

Adam


People also ask

What is with function in Laravel?

with() is generally used with eager loading, which is a quick way to pull related models. Basically, it means that, along with the main model, Laravel will preload the listed relationship(s). This is beneficial when you need to load additional data and want to avoid making N+1 DB bad practices.

What is eager loading in Laravel?

Eager loading is super simple using Laravel and basically prevents you from encountering the N+1 problem with your data. This problem is caused by making N+1 queries to the database, where N is the number of items being fetched from the database.

What is relationship in Laravel?

Defining Relationships. Eloquent relationships are defined as methods on your Eloquent model classes. Since relationships also serve as powerful query builders, defining relationships as methods provides powerful method chaining and querying capabilities.

What is polymorphic relationship in Laravel?

A one-to-one polymorphic relationship is a situation where one model can belong to more than one type of model but on only one association. A typical example of this is featured images on a post and an avatar for a user. The only thing that changes however is how we get the associated model by using morphOne instead.


1 Answers

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.

like image 182
sepehr Avatar answered Oct 16 '22 06:10

sepehr