laravel with() 方法与 load() 方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26005994/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 16:44:57  来源:igfitidea点击:

laravel with() method versus load() method

laravellaravel-4

提问by kfirba

I really tried to understand the difference between the with()method and the load()method, but couldn't really understand.

我真的很想了解with()方法和load()方法之间的区别,但无法真正理解。

As I see it, using the with()method is "better" since I eager load the relation. It seems that if I use load()I load the relation just as if I would use the hasMany()(or any other method that relates to the relation between objects).

在我看来,使用该with()方法“更好”,因为我急切地加载关系。似乎如果我使用load()我加载关系就像我会使用hasMany()(或任何其他与对象之间的关系相关的方法)。

Do I get it wrong?

我理解错了吗?

回答by damiani

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 (all(), first(), or find(x), for example); when using load(), you run the initial query first, and then eager load the relation at some later point.

两者都实现了相同的最终结果——急切地将相关模型加载到第一个上。事实上,它们都运行完全相同的两个查询。关键的区别是,with()急于载荷相关的示范前面,初始查询后立即(all()first(),或find(x),例如); 使用时load(),您首先运行初始查询,然后在稍后的某个时刻预先加载关系。

"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 nqueries, where nis the number of items in the initial set.

“急切”在这里意味着我们只使用一个查询将特定结果集的所有相关模型关联起来而不是必须运行n 个查询,其中n是初始集中的项目数。



Eager loading using with()

急切加载使用 with()

If we eager load using with(), for example:

如果我们急切加载使用with(),例如:

$users = User::with('comments')->get(); 

...if we have 5 users, the following two queries get run immediately:

...如果我们有 5 个用户,则会立即运行以下两个查询:

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 $users->comments->first()->body.

...我们最终得到了一个模型集合,这些模型将注释附加到用户模型上,因此我们可以执行类似$users->comments->first()->body.



"Lazy" eager loading using load()

“懒惰”急切加载使用 load()

Or, we can separate the two queries, first by getting the initial result:

或者,我们可以将两个查询分开,首先通过获取初始结果:

$users = User::all();

which runs:

运行:

    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()->bodyto get to the related model for any item.

...我们最终得到相同的结果,只是分为两个步骤。同样,我们可以调用$users->comments->first()->body以获取任何项目的相关模型。



Why use load()vs. with()? 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.)

为什么使用load()vs with()load()为您提供稍后根据某些动态条件决定是否需要运行第二个查询的选项。但是,如果毫无疑问您需要访问所有相关项目,请使用with(). (文档还提到了使用 load() 的缓存优势,但我对此并不熟悉;事实上,我相信结果load()是不可缓存的。)



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+1queries, or 6in this example. Eager loading, regardless of whether it's done up-front with with()or later with load(), only runs 2queries.

这两种方法的替代方法是循环遍历初始结果集并查询hasMany()每个项目的关系。这最终会运行n+1 个查询,或者在这个例子中运行6 个。急切加载,无论是使用 预先完成with()还是稍后使用load(),都只运行2 个查询。

回答by Teoman T?ng?r

@damiani Explanied difference between load()and with()as well but he said load()is not cacheable so I wanna say couple words about it.

@damiani 解释了load()和之间的区别,with()但他说load()不可缓存,所以我想说几句。

Let assume we have a blog post and related with comments. And we're fetching together and caching it.

假设我们有一篇博客文章并与评论相关。我们正在一起获取并缓存它。

$post = Cache::remember("post.".$slug,720,function()use($slug){
   return Post::whereSlug($slug)->with("comments")->first();
});

But if there is a new comment and we want to display it immediately, we have to clear post cache and fetch post and comments together again. And that causes unnecessary queries. Lets think there are another queries for tags, media, contributors of the post etc. it will increase amount of resource usage..

但是如果有新的评论并且我们想立即显示它,我们必须清除帖子缓存并再次一起获取帖子和评论。这会导致不必要的查询。让我们认为还有另一个对标签、媒体、帖子贡献者等的查询。它会增加资源使用量。

public function load($relations)
{
    $query = $this->newQueryWithoutRelationships()->with(
        is_string($relations) ? func_get_args() : $relations
    );

    $query->eagerLoadRelations([$this]);

    return $this;
}

As you can see above when we use the method it loads given relation and returns model with fetched relation. So you can return it outside of a callback.

正如您在上面看到的,当我们使用该方法时,它会加载给定的关系并返回具有获取关系的模型。所以你可以在回调之外返回它。

$post = Cache::remember("post.".$slug,720,function()use($slug){
   return Post::whereSlug($slug)->first();
});

$post = Cache::remember("post.relation.images.".$slug,720,function()use($post){
  return $post->load("images");
});

$post = Cache::remember("post.relation.comments".$slug,720,function()use($post){
   return $post->load("comments");
});

So if we load them seperatly, next time when some of them updated all you need to do clear specific relation cache and fetch it again. No need to fetch post, tags, images etc. over and over.

因此,如果我们单独加载它们,下次当其中一些更新时,您需要清除特定的关系缓存并再次获取它。无需一遍又一遍地获取帖子、标签、图像等。

回答by Radhe Shyam sharma

As @damiani said, 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 (all(), first(), or find(x), for example); when using load(), you run the initial query first, and then eager load the relation at some later point.

正如@damiani 所说,两者都实现了相同的最终结果——渴望将相关模型加载到第一个上。事实上,它们都运行完全相同的两个查询。主要区别在于 with() 在初始查询之后立即加载相关模型(例如,all()、first() 或 find(x));使用 load() 时,您首先运行初始查询,然后在稍后的某个时刻预先加载关系。

There is one more difference between With() & load(), you can put the conditions when using with() but you can't do the same in case of load()

With() 和 load() 之间还有一个区别,你可以在使用 with() 时放置条件,但在 load() 的情况下不能这样做

For example:

例如:

ProductCategory::with('children')
        ->with(['products' => function ($q) use($SpecificID) {
            $q->whereHas('types', function($q) use($SpecificID) {
                $q->where('types.id', $SpecificID)
            });
        }])
        ->get();