我有两个模型,Box和BoxLocations。 Box
与hasMany
有BoxLocations
关系,BoxLocations
与belongsTo
有Box
关系。
BoxLocations
还有一个附加到模型的属性,该属性需要来自Box关系的单条信息。
我注意到,在调用Box::with(['BoxLocations']->)all();
时,我看到BoxLocations
模型正在重新加载Box关系。这发生在每个BoxLocation
(50多次)
laravel是否跟踪Box已从最初的Box::with(['BoxLocations']->)all();
请求加载,然后将其传递给BelongsTo关系?
我正在尝试优化一个Web系统,并且当加载了take属性时(每次加载时都需要它),它会导致已经加载的相同Box模型的50多次点击到数据库。
如果laravel没有这样做 - 是否有更好的方法来实现上述目标?
当你使用eager loading方法时,Laravel使用with()
。
当访问Eloquent关系作为属性时,关系数据是“延迟加载”。这意味着在您首次访问该属性之前,实际上不会加载关系数据。但是,Eloquent可以在您查询父模型时“急切加载”关系。急切加载缓解了N + 1查询问题。
所以,如果你这样做:
$boxes = Box::with('BoxLocations')->get();
它会加载关系,但让我们说你这样做:
$boxes = Box::all();
foreach($boxes as $box)
{
echo box->boxlocation->name;
}
如果你有50个Box,这个循环将运行51个查询。
但是当你使用with
方法并急切加载关系时,这个循环只会运行2个查询。
您也可以使用Lazy Eager Loading并决定何时加载关系