0

我有一个简单的结构,一个帖子有很多票。投票具有“值”属性,即 1 或 -1

在阅读所有帖子时,我很乐意为每个帖子选择这个总和到帖子级别的自定义属性中。目前我这样做

    $posts = Post::where('published_at', '<=', $date)
        ->orderBy('published_at', 'desc')
        ->simplePaginate(20);

    $posts->each(function($post) {
        $post->overallRating = $post->getRating();
    });

这是完全有效的,但是我认为对数据库进行 20 次查询以读取评级并不是那么好。有没有办法在实际获取帖子时简化这一点?

public function getRating()
{
    return $this->votes->sum('value');
}
4

2 回答 2

2

如果您想将选票保留在分页结果中,那么我建议添加with('votes'),以便它们至少是急切加载的,即

$posts = Post::with('votes')
    ->where('published_at', '<=', $date)
    ->orderBy('published_at', 'desc')
    ->simplePaginate(20);

但是,如果您不想/不介意获得投票并且只想要每个帖子的评级,您可以将以下范围添加到您的Post模型中:

public function scopeWithRating(Builder $query)
{
    if (is_null($query->getQuery()->columns)) {
        $query->select([$query->getQuery()->from . '.*']);
    }

    $query->selectSub(
        $this->votes()->getRelationExistenceQuery(
            $this->votes()->getRelated()->newQuery(), $query, new Expression('sum(value)')
        )->toBase(),
        'rating'
    );
}

然后:

$posts = Post::withRating()
    ->where('published_at', '<=', $date)
    ->orderBy('published_at', 'desc')
    ->simplePaginate(20);

希望这可以帮助!

于 2017-02-08T22:37:26.083 回答
0

尝试这个:

$posts = Post::where('published_at', '<=', $date)
        ->orderBy('published_at', 'desc')
        ->with(['votes' => function($query) {
            $query->sum('value');
        }])->simplePaginate(20);
于 2017-02-08T17:59:40.833 回答