【问题标题】:Laravel count column of related model相关模型的 Laravel 计数列
【发布时间】:2014-11-24 02:07:29
【问题描述】:

我想统计某个Script 中来自ScripRating 的赞成票和反对票的数量。

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) }}

【问题讨论】:

    标签: laravel model count eloquent relationship


    【解决方案1】:

    你可以使用

    {{ $script-&gt;ratings-&gt;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。当您在查询中指定 -&gt;with() 时,这称为预加载。如果你不这样做,查询将在你指定$script-&gt;ratings时运行

    更多关于急切/延迟加载的信息:

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

    编辑其他回复:

    如果您想收集有评级的脚本,您可以使用-&gt;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-&gt;hasRatings())

    【讨论】:

    • 感谢您的评论。我尝试了上面的代码,但我不知道如何使用它。如何检索反对/赞成票?另外,你知道我第二个问题的答案吗?
    • 谢谢!你可以在我的第一篇文章中看到我做了什么。我现在遇到的唯一问题是这个错误:Object of class Illuminate\Database\Eloquent\Builder could not be converted to string 当脚本没有任何评级时会发生这种情况。你知道如何解决这个问题吗?
    【解决方案2】:

    您可以将这 2 个函数添加到 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 }}
    

    【讨论】:

    • 我确实做到了,但它给了我 SQL 语法错误。另外,如果我理解这一点,这将返回反对票和赞成票的总和。我需要这些数据,但我也需要单独的赞成票和反对票。请原谅我的英语不好。
    • @JasonK 有一个错字。现在看,如果你有错误,你应该总是提供完整的错误信息
    • 是的,我已经注意到 't' 不见了。语法错误:near '*) as sum from script_rating where script_rating.script_id = ? group by ' at line 1 (SQL: select script_id, sum(*) as sum from script_rating where script_rating.script_id = 1 group by script_id limit 1) (View: C:\xampp\htdocs\laravel\laravel\app\views\script.blade.php)
    • @JasonK 我已经更改了答案 - 将 as sum`` 更改为 as sum_all 并在第二个函数中相同
    • 仍然出现语法错误:) as sum_all from script_rating where script_rating.script_id = ? group b' at line 1 (SQL: select script_id, sum() as sum_all from script_rating where script_rating.script_id = 1 group by script_id limit 1
    猜你喜欢
    • 2014-10-29
    • 1970-01-01
    • 2019-05-16
    • 2013-08-07
    • 2019-02-03
    • 2017-09-10
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    相关资源
    最近更新 更多