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

时间:2014-09-23 22:56:41

标签: laravel laravel-4

我真的试图理解with()方法和load()方法之间的区别,但无法理解。

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

我弄错了吗?

3 个答案:

答案 0 :(得分:73)

两者都实现了相同的最终结果 - 渴望将相关模型加载到第一个结果上。实际上,它们都运行完全相同的两个查询。关键区别在于with() eager在初始查询之后立即加载相关模型(例如all()first()find(x));使用load()时,首先运行初始查询,然后在稍后的某个时刻急切加载关系。

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


使用with()

加载

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

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

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

select * from `users`
select * from `comments` where `comments`.`user_id` in (1, 2, 3, 4, 5)

...我们最终得到了一组模型,这些模型的注释附加到用户模型,因此我们可以执行$users->comments->first()->body之类的操作。


使用load()

加载“懒惰”

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

$users = User::all();

运行:

    select * from `users`

之后,如果我们认为我们需要为所有这些用户提供相关评论,我们可以在事后加急加载:

$users = $users->load('comments');
运行第二个查询的

    select * from `comments` where `comments`.`user_id` in (1, 2, 3, 4, 5)

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


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


其中任何一个的替代方案是循环遍历初始结果集并查询每个项目的hasMany()关系。这将最终运行 n + 1 查询,或在此示例中运行 6 。无论是使用with()还是稍后使用load()预先完成加载,都只需加载 2 查询。

答案 1 :(得分:2)

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

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

例如:

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

答案 2 :(得分:1)

@damiani也说明了 signingConfigs { release { keyAlias 'akeyalias' keyPassword '*******' storeFile file("apath") storePassword '********' } } load()之间的区别,但他说with()不可缓存,所以我想说几句话。

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

load()

但是,如果有新评论,并且我们想立即显示,则必须清除帖子缓存,然后再次获取帖子和评论。这会导致不必要的查询。让我们考虑对标签,媒体,帖子的提供者等进行其他查询。这将增加资源使用量。

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

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

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

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

    return $this;
}

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