kfi*_*rba 41 laravel laravel-4
我真的试图理解with()方法和load()方法之间的区别,但无法理解.
我认为,使用该with()方法"更好",因为我急切地加载关系.似乎如果我使用load()我加载关系就好像我会使用hasMany()(或任何其他与对象之间的关系相关的方法).
我弄错了吗?
dam*_*ani 83
两者都实现了相同的最终结果 - 渴望将相关模型加载到第一个结果上.实际上,它们都运行完全相同的两个查询.关键的区别是,with()急于载荷相关的示范前面,立即初始查询后(all(),first(),或find(x),例如); 在使用时load(),首先运行初始查询,然后在稍后的某个时刻急切加载关系.
这里的"Eager"意味着我们只使用一个查询来关联特定结果集的所有相关模型,而不必运行n个查询,其中n是初始集合中的项目数.
渴望加载使用 with()
如果我们急于加载使用with(),例如:
$users = User::with('comments')->get();
Run Code Online (Sandbox Code Playgroud)
...如果我们有5个用户,则立即运行以下两个查询:
select * from `users`
select * from `comments` where `comments`.`user_id` in (1, 2, 3, 4, 5)
Run Code Online (Sandbox Code Playgroud)
...我们最终得到了一些模型,这些模型的注释附加在用户模型上,因此我们可以做类似的事情$users->comments->first()->body.
"懒惰"急切加载使用 load()
或者,我们可以将两个查询分开,首先获取初始结果:
$users = User::all();
Run Code Online (Sandbox Code Playgroud)
运行:
select * from `users`
Run Code Online (Sandbox Code Playgroud)
后来,如果我们决定需要所有这些用户的相关评论,我们可以在事后加急加载:
$users = $users->load('comments');
Run Code Online (Sandbox Code Playgroud)
运行第二个查询:
select * from `comments` where `comments`.`user_id` in (1, 2, 3, 4, 5)
Run Code Online (Sandbox Code Playgroud)
......我们最终得到了相同的结果,只分成两步.同样,我们可以调用$users->comments->first()->body以获取任何项目的相关模型.
为何使用load()vs. with()?load()根据某些动态条件,您可以选择稍后决定是否需要运行第二个查询.但是,如果您无需访问所有相关项目,请使用with().(文档也引用了使用load()的缓存优势,但我对此并不熟悉;事实上,我认为结果load()不可缓存.)
其中任何一个的替代方案是循环遍历初始结果集并查询hasMany()每个项目的关系.这将最终运行n + 1个查询,或者在此示例中为6.无论是预先加载with()还是以后加载,都load()只需运行2次查询即可.
Rad*_*rma 13
正如 @damiani 所说,两者都实现了相同的最终结果\xe2\x80\x94eager 将相关模型加载到第一个模型上。事实上,它们都运行完全相同的两个查询。关键区别在于 with() 在初始查询之后立即预先加载相关模型(例如 all()、first() 或 find(x));使用 load() 时,您首先运行初始查询,然后在稍后的某个时刻预先加载关系。
\n\nWith() 和 load() 之间还有一个区别,使用 with() 时可以添加条件,但在 load() 中则不能这样做
\n\n例如:
\n\nProductCategory::with('children')\n ->with(['products' => function ($q) use($SpecificID) {\n $q->whereHas('types', function($q) use($SpecificID) {\n $q->where('types.id', $SpecificID)\n });\n }])\n ->get(); \nRun Code Online (Sandbox Code Playgroud)\n
load()@damiani 也解释了和with()之间的区别,但他说load()不可缓存,所以我想对此说几句话。
假设我们有一篇博客文章并与评论相关。我们一起获取并缓存它。
$post = Cache::remember("post.".$slug,720,function()use($slug){
return Post::whereSlug($slug)->with("comments")->first();
});
Run Code Online (Sandbox Code Playgroud)
但是,如果有新评论并且我们想立即显示它,我们必须清除帖子缓存并再次一起获取帖子和评论。这会导致不必要的查询。让我们假设还有对标签、媒体、帖子贡献者等的其他查询。这会增加资源使用量。
public function load($relations)
{
$query = $this->newQueryWithoutRelationships()->with(
is_string($relations) ? func_get_args() : $relations
);
$query->eagerLoadRelations([$this]);
return $this;
}
Run Code Online (Sandbox Code Playgroud)
正如您在上面看到的,当我们使用该方法时,它会加载给定的关系并返回具有获取的关系的模型。所以你可以在回调之外返回它。
$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");
});
Run Code Online (Sandbox Code Playgroud)
因此,如果我们单独加载它们,下次当其中一些更新时,您需要清除特定关系缓存并再次获取它。无需一遍又一遍地获取帖子、标签、图像等。
| 归档时间: |
|
| 查看次数: |
59008 次 |
| 最近记录: |