Laravel - 预加载
Laravel - Eager Loading
我正在尝试使用 Laravel 来理解预加载以避免生成大量不必要的查询。我想获得最后添加的 15 个 Posts 并从我的费率 table 的关系中获得他们的费率(在我得到 Posts 之前,后来在 foreach 中我要求 $item- >avgRate() 创建了 15 个额外的查询 :S).
我的Post模特:
public function rates()
{
return $this->hasMany(Rate::class);
}
public function scopeLastAdded($query, $limit = 15)
{
return $query->latest()->limit($limit)->with('rates')->get();
}
这有效,对于每个 post,我也得到所有费率,但主要目标是创建一些函数来计算每个 post 的平均费率,而不是检索所有费率。我创建了一个新方法:
public function avgRate()
{
return number_format($this->rates()->avg('rate'), 1, '.', '');
}
当我使用 with('avgRate')
时,我的模型失败了:
Call to a member function addEagerConstraints() on string
我怎样才能用我最后的 15 Post 以某种干净的方式获得 avgRate 以仅执行 2 个查询而不是 16 个?
预期输出:
// Post view
@foreach ($posts as $post)
<div>{{ $post->title }}</div>
<div>{{ $post->avgRate }}</div> //I want to get data without performing 15 queries
@endforeach
我会使用子查询来实现这一点。此外,为了让事情更清晰一些,您可以创建一个范围来获取评分:
public function scopeWithRating($query)
{
$rating = Rate::selectRaw('AVG(rate)')
->whereColumn('post_id', 'posts.id')
->getQuery();
$query->select('posts.*')
->selectSub($rating, 'rating');
}
...要使用它,您需要:
Post::withRating()->get();
现在,您的 Post
对象也将包含一列 rating
,并且基本上是通过单个查询完成的。
这里有一个 example 来说明这一点。
我正在尝试使用 Laravel 来理解预加载以避免生成大量不必要的查询。我想获得最后添加的 15 个 Posts 并从我的费率 table 的关系中获得他们的费率(在我得到 Posts 之前,后来在 foreach 中我要求 $item- >avgRate() 创建了 15 个额外的查询 :S).
我的Post模特:
public function rates()
{
return $this->hasMany(Rate::class);
}
public function scopeLastAdded($query, $limit = 15)
{
return $query->latest()->limit($limit)->with('rates')->get();
}
这有效,对于每个 post,我也得到所有费率,但主要目标是创建一些函数来计算每个 post 的平均费率,而不是检索所有费率。我创建了一个新方法:
public function avgRate()
{
return number_format($this->rates()->avg('rate'), 1, '.', '');
}
当我使用 with('avgRate')
时,我的模型失败了:
Call to a member function addEagerConstraints() on string
我怎样才能用我最后的 15 Post 以某种干净的方式获得 avgRate 以仅执行 2 个查询而不是 16 个?
预期输出:
// Post view
@foreach ($posts as $post)
<div>{{ $post->title }}</div>
<div>{{ $post->avgRate }}</div> //I want to get data without performing 15 queries
@endforeach
我会使用子查询来实现这一点。此外,为了让事情更清晰一些,您可以创建一个范围来获取评分:
public function scopeWithRating($query)
{
$rating = Rate::selectRaw('AVG(rate)')
->whereColumn('post_id', 'posts.id')
->getQuery();
$query->select('posts.*')
->selectSub($rating, 'rating');
}
...要使用它,您需要:
Post::withRating()->get();
现在,您的 Post
对象也将包含一列 rating
,并且基本上是通过单个查询完成的。
这里有一个 example 来说明这一点。