Laravel计数相关模型列

时间:2014-09-29 15:56:18

标签: laravel model count eloquent relationship

我想计算某ScripRating Script的{​​0}投票数和投票数。

的script.php:

public function ratings()
{
    return $this->hasMany('ScriptRating');
}

ScriptRating.php:

public function script()
{
    return $this->belongsTo('Script');
}

script_rating数据库表:

id (primary, increments)
script_id(integer)
rating(integer) <-- Can be either 1 (upvote) or -1 (downvote)

检索脚本并显示评分:

$script = Script::where('title', '=', $title)->get();
{{ $script->ratings }}

这很好用,它返回一个数组:[{"id":1,"script_id":1,"rating":1}]。但此时我被困住了。我怎么能算出某个剧本的总票数和票数呢?

我还有一个小问题,我发现我感到困惑。这与上面的代码相同:

$script = Script::where('title', '=', $title)->with('ratings')->get();
{{ $script->ratings }}

这两种方法之间有什么区别,我应该使用哪种方法?

提前致谢!

修改

我做了三个范围:

public function scopeTotalRating($query, $scriptId) {
    return $query->where('script_id', $scriptId)->get()->sum('rating');
}

public function scopeThumbsUp($query, $scriptId) {
    return $query->where('script_id', $scriptId)->having('rating', '=', 1)->get()->sum('rating');
}

public function scopeThumbsDown($query, $scriptId) {
    return $query->where('script_id', $scriptId)->having('rating', '=', -1)->get()->sum('rating');
}

并显示如下:

{{ ScriptRating::thumbsUp($script->id) }}

2 个答案:

答案 0 :(得分:4)

您可以使用

{{ $script->ratings->count() }}

这将显示脚本的总评分数。

但是,您感兴趣的是将评分分组为upvotesdownvotes,因此您需要通过group by子句查询您的关系。

Script::where('title', '=', $title)->with([
    'ratings' => function($query) {
        $query->groupBy('rating');
    })
])->get();

我认为现在返回的集合应按1-1分组。让我知道结果!

编辑:您还可以查看有关查询关系的文档:

http://laravel.com/docs/4.2/eloquent#querying-relations

编辑回复:

不使用group by的最简单方法是单独查询:

$script = Script::where('title', $title)->first();

if ($script) {
    $upvotes = ScriptRating::where('script_id', $script->id)->having('rating', '>', 0)->get()->count();

    $downvotes = ScriptRating::where('script_id', $script->id)->having('rating', '<', 0)->get()->count();
}

您提到的脚本之间的区别也称为eager loadinglazy loading。在查询中指定->with()时,这称为预先加载。如果您不这样做,则在指定$script->ratings

时将运行查询

有关热切/延迟加载的更多信息:

http://laravel.com/docs/4.2/eloquent#eager-loading

编辑其他回复:

如果您想收集具有评分的脚本,您可以使用->whereHas('ratings')功能。您还可以通过执行if语句来检查具有评级的脚本是否存在:

if ($script->ratings->count() > 0) { 
    // The script has ratings
} else {
    // The script does not have ratings
}

如果您不想继续重复此代码,可以使用以下内容将功能放在Script.php模型中:

public function hasRatings()
{
    return $this->ratings->count() > 0;
}

然后你可以这样做:

if ($script->hasRatings())

答案 1 :(得分:1)

您可以向Script模型类添加这两个函数:

public function ratingsSumRelation()
{
    return $this->hasOne('ScriptRating')->selectRaw('script_id, sum(rating) as sum_all')
        ->groupBy('script_id');
}

public function getRatingSumAttribute()
{

    return $this->ratingsSumRelation ?
        $this->ratingsSumRelation->sum_all: 0;
}

现在使用以下方式显示总和:

{{ $script->rating_sum }}