Laravel:`loadMissing`函数的目的是什么?

Ada*_*dam 6 php mysql laravel laravel-5

Laravel文档中Eager Loading部分的第一句是:

当访问Eloquent关系作为属性时,关系数据是"延迟加载".这意味着在您首次访问该属性之前,实际上不会加载关系数据.

在本节的最后一段中说明:

要仅在尚未加载关系时加载关系,请使用loadMissing方法:

public function format(Book $book)
{
    $book->loadMissing('author');

    return [
        'name' => $book->name,
        'author' => $book->author->name
    ];
}
Run Code Online (Sandbox Code Playgroud)

但我没有看到目的$book->loadMissing('author').这是在做什么吗?

如果我删除这一行会有什么区别?根据第一句话,无论如何,作者$book->author->name都是懒惰的,对吧?

sep*_*ehr 8

非常好的问题; 通过阅读文档可以立即反映出微妙的差异.

您正在使用模型上的魔术属性将" Lazy Eager Loading " loadMissing()用于"延迟加载" .

顾名思义,唯一的区别是:

  • "延迟加载"仅在关系使用时发生.
  • "急切加载"可能会在使用前发生.

因此,实际上,除非您希望在使用之前显式加载关系,否则没有区别.

值得注意的是,两者loadloadMissing方法都为您提供了通过传递闭包来自定义关系加载逻辑的机会,该闭包在使用魔术属性时不是一个选项.

$book->loadMissing(['author' => function (Builder $query) {
    $query->where('approved', true);
}]);
Run Code Online (Sandbox Code Playgroud)

除非您在模型上定义关系(这是更好的做法),否则这将转换为"加载缺少已批准的作者(如果尚未加载"),这是无法实现的.$book->authorapprovedAuthor


直接回答你的问题; 是的,如果你删除将没有任何区别:

$book->loadMissing('author'); 
Run Code Online (Sandbox Code Playgroud)

在该特定示例中,因为它在加载后立即使用.但是,可能很少有用户希望在使用之前加载关系.


因此,要概述关系加载方法的工作原理:

渴望加载

通过使用,with()您可以在查询父模型时"急切加载"关系:

$book = Book::with('author')->find($id);
Run Code Online (Sandbox Code Playgroud)

懒惰的渴望加载

在已经检索父模型之后急切地加载关系:

$book->load('author');
Run Code Online (Sandbox Code Playgroud)

这也可能只用于加载遗漏的方法:

$book->loadMissing('author');
Run Code Online (Sandbox Code Playgroud)

与该load()方法相反,loadMissing()方法通过给定关系过滤并且懒洋洋地"急切"加载它们仅在尚未加载时加载它们.

通过接受闭包,这两种方法都支持自定义关系加载逻辑.

懒加载

通过使用魔法属性实现的延迟加载是为了方便开发人员.它会根据其使用情况加载关系,这样您就不需要事先加载它.


@rzb也在他的回答中提到了一个非常好的观点.看一看.


rzb*_*rzb 5

我相信已接受的答案遗漏了一个可能误导某些人的重要事实:您不能loadMissing($relation)在集合上运行。

这很重要,因为延迟预加载关系的大多数用例是当您已经有一个集合并且您不想提交 n+1 罪 - 即在循环中多次不必要地访问数据库。

因此,虽然您可以load($relation)在集合上使用,但如果您只想在之前尚未加载关系的情况下使用它,那么您就不走运了。

  • 从 5.6.22 开始,您现在可以对集合运行 loadMissing。https://medium.com/laravel-announcements/laravel-v5-6-22-released-5a3c821eebf7 (3认同)