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

Viewed 12537

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?

6 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.

I believe the accepted answer is missing one important fact that may mislead some: you cannot run loadMissing($relation) on a collection.

This is important because most use cases of lazy eager loading relationships are when you already have a collection and you don't want to commit the n+1 sin - i.e. unnecessarily hit the DB multiple times in a loop.

So while you can use load($relation) on a collection, if you only want to do it if the relationships haven't already been loaded before, you're out of luck.

Very useful for APIs

The use of with, loadMissing or load can has more importance when use it in API environment, where the results are passed to json. On this case, lazy loading hasn't any effect.

its mean do not repeat the query to be clear about it if you use : load() 2 times the query will repeat even if the relationships exists

while : loadMissing() is check if the relationship has loaded . it will not repeat the query . beacuse it has already loaded before by [ load() or with() ] = egear load

    DB::enableQueryLog();

    $user = User::find(1);

    // see the query 

    $user->load('posts');   
    $user->load('posts');  
    $user->loadMissing('posts'); // put it on top to see the difference 

    dd(DB::getQueryLog());

that's what i think its purpose

Lets say you have multiple relationships.

book belongs to an author and book belongs to a publisher.

so first you might load it with one relationship.

$books->load('author');

and later on certain condition you want to load another relationship into it.

$book->loadMissing('publisher');

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?

Suppose say

public function format(Book $book)
{
    //book will not have the author relationship yet  

    return [
        'name' => $book->name, //book will not have the author relationship loaded yet  
        'author' => $book->author->name //book will now have the author relationship 
    ];
}

Difference between above and below code is when will the relationship be loaded and how much control you have over the property.

public function format(Book $book)
{
    $book->loadMissing('author'); // book will now have the author relationship

    return [
        'name' => $book->name, // book have the author relationship loaded
        'author' => $book->author->name // book have the author relationship loaded
    ];
}
Related