我真的试图理解with()
方法和load()
方法之间的区别,但无法理解。
我认为,使用with()
方法是“更好”,因为我急于加载关系。似乎如果我使用load()
我加载关系就好像我会使用hasMany()
(或任何其他与对象之间的关系相关的方法)。
我弄错了吗?
答案 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;
}
因此,如果我们分别加载它们,则下次其中一些更新时,您需要清除特定的关系缓存并再次获取它。无需一遍又一遍地获取帖子,标签,图像等。