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
Laravel count column of related model
提问by JasonK
I want to count the number of upvotes and downvotes from ScripRating
for 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 upvotes
and downvotes
, so you'll need to query your relationship by a group by
clause.
但是,您感兴趣的是将评分分组到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 1
and -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 loading
or 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 loading
or 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.php
model 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 Script
model 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 }}