laravel 相关模型的Laravel计数列

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26104008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 10:12:17  来源:igfitidea点击:

Laravel count column of related model

laravelmodelcounteloquentrelationship

提问by JasonK

I want to count the number of upvotes and downvotes from ScripRatingfor a certain Script.

我想计算ScripRating某个Script.

Script.php:

脚本.php:

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

ScriptRating.php:

ScriptRating.php:

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

The script_rating database table:

script_rating 数据库表:

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

To retrieve a script and display the ratings:

要检索脚本并显示评级:

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

This works fine, it returns an array: [{"id":1,"script_id":1,"rating":1}]. But at this point I'm stuck. How could I count the total upvotes and downvotes for a certain script?

这工作正常,它返回一个数组:[{"id":1,"script_id":1,"rating":1}]。但在这一点上我被卡住了。我如何计算某个脚本的总赞成票和反对票?

I also have one more small question what I'm finding confusing. This does the same as the code above:

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

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

What is the difference between these two methods and which one should I use?

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

Thanks in advance!

提前致谢!

Edit

编辑

I made three scopes:

我做了三个范围:

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

And display them as following:

并将它们显示如下:

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

回答by Steve Bauman

You can use

您可以使用

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

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

This will display the number total ratings a script has.

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

However what you're interested in doing is grouping the ratings into upvotesand downvotes, so you'll need to query your relationship by a group byclause.

但是,您感兴趣的是将评分分组到upvotes和 中downvotes,因此您需要通过group by子句查询您的关系。

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

I believe the collection returned should be now grouped by 1and -1. Let me know of the results!

我相信返回的集合现在应该按1和分组-1。让我知道结果!

EDIT: You can also take a look here at the documentation on querying relationships:

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

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

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

EDIT for response:

编辑响应:

The simplest way to do this without using group by would be separate queries:

不使用 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();
}

Also the difference between your scripts mentioned is called eager loadingor lazy loading. When you specify ->with()in your query, this is called eager loading. If you don't do this, the query will be ran when you specify $script->ratings

此外,您提到的脚本之间的差异称为eager loadingor lazy loading。当您->with()在查询中指定时,这称为预先加载。如果你不这样做,查询将在你指定时运行$script->ratings

More about eager/lazy loading here:

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

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

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

Edit for another response:

编辑另一个回复:

You would use the ->whereHas('ratings')function if you want to gather scripts that onlyhave ratings. You can also check the existence of the script having ratings by doing an if statement:

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

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

If you don't want to keep repeating this code you could always put a function inside your Script.phpmodel by using the following:

如果您不想继续重复此代码,您可以始终Script.php使用以下方法在模型中放置一个函数:

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

Then you can do:

然后你可以这样做:

if ($script->hasRatings())

if ($script->hasRatings())

回答by Marcin Nabia?ek

You can add to the Scriptmodel class those 2 functions:

您可以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;
}

and now display sum using:

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

{{ $script->rating_sum }}