如何在laravel中的多个关系上具有withCount的总和

时间:2019-05-21 11:31:09

标签: laravel

我有一个基本的三个表,用户,来宾和帖子

我还有一个名为user_views的表: 存储帖子的唯一用户视图

post_id   user_id
1         10002
2         10003
3         10011

另一个名为guest_views的表: 存储访客唯一的帖子视图

post_id   guest_id
1         10002
2         10003
3         10011

在Post模型中,我有:

public function user_views()
{
    return $this->hasMany('App\Models\PostUserView');
}

public function guest_views()
{
    return $this->hasMany('App\Models\PostGuestView');
}

在下面的代码中,使用两个不同的键可以获得正确的结果。

$posts = Post::all()
            ->withCount('user_views')
            ->withCount('guest_views')

我想到将user_views和guest_views合并,然后按如下方式计算计数,但结果仅包括user_views的计数

public function views()
{
    return $this->user_views()->unionAll($this->guest_views());
}

执行以下代码后

$posts = Post::all()
            ->withCount('views')
            ->withCount('user_views')
            ->withCount('guest_views')

我得到这个结果

"views_count": 5, 
"user_views_count": 5,
"guest_views_count": 2,

示例示例的预期结果是:

"views_count": 7, 
"user_views_count": 5,
"guest_views_count": 2,

我也尝试按照以下方式使用sql查询

public function views()
{
    return DB::raw("(select * from post_views) union all (select * from post_guest_views)");
}

但是得到

"Call to undefined method Illuminate\Database\Query\Expression::getRelationExistenceCountQuery()"

因此,我想获取每个帖子的所有用户和来宾的总观看次数。

3 个答案:

答案 0 :(得分:1)

在您的发布模型中

public function user_views()
{
    return $this->hasMany('App\Models\PostUserView','user_id','id');
}

public function guest_views()
{
    return $this->hasMany('App\Models\PostGuestView','user_id','id');
}

public function views() 
{
   return $this->user_views()->unionAll($this->guest_views()); 
}

现在您可以访问

$posts = Post::withCount(['user_views','guest_views','views'])->get()

注意

  

withCount()方法中指定的每个参数都变为   主对象的_count属性。所以在这种情况下,我们将拥有   $ posts-> guest_views_count,$ posts-> views_count和   $ posts-> user_views_count变量。

希望它对您有用。

答案 1 :(得分:0)

您可以使用join()获得观看次数。下面是代码示例:-

$posts = Post::join('user_views as uv', function($q) {
    $q->on('uv.post_id', '=', 'posts.id');
})
->join('guest_views as gv', function($q) {
    $q->on('gv.post_id', '=', 'posts.id');
})
->selectRaw("posts.*, COUNT(uv.id) as user_views_count, COUNT(gv.id) guest_views_count, SUM(COUNT(uv.id) + COUNT(gv.id)) as views_count")
->groupBy("posts.id")
->get();

尝试一下。

答案 2 :(得分:0)

您可以按照以下方法使用reduce的收集方法:

$posts->reduce(function($carry,$item){
  return $carry+$item->user_views_count;
},0);

有关更多信息,请查看reduce文档:https://laravel.com/docs/6.x/collections#method-reduce