Laravel Builder Scope与Union和多对多关系

时间:2017-11-10 18:04:06

标签: php laravel eloquent union query-builder


我有一个通知表(和型号)
因此通知表列:

id
title
body
is_public
...

我还有一个用户表(和型号)
用户表列:

id
username
...

我还有一个pivot notification_user表
列:

user_id
notification_id

因此在Notification和User模型上设置了多对多关系:

  

Notification.php

public function users()
{
    return $this->belongsToMany('App\Api\V1\Models\User');
}
  

user.php的

public function notifications() 
{
    return $this->belongsToMany('App\Api\V1\Models\Notification');      
}

现在在Notification.php内我想设置一个范围。在范围内,我需要获取公共通知和当前用户 单个SQL查询中的私有通知。从我的表结构中,公共通知是在哪里is_public == 1.私人通知在数据透视表上关联。

要实现这一点,在我的Notification.php内,我也有这个设置:

public function scopePublicAndPrivate(Builder $query)
{
    return $this->public($query)->union($this->private($query));
}
public function scopePublic(Builder $query)
{
    return $query->where('is_public', 1);
}
public function scopePrivate(Builder $query)
{
    $user = JWTAuth::parseToken()->authenticate(); //using JWT to get a user.
    return $user->notifications();
}

现在当我在控制器中尝试Notification::publicAndPrivate()->get()时,我得到:

Illuminate\Database\QueryException with message 'SQLSTATE[21000]: Cardinality violation: 1222 The used SELECT statements have a different number of columns (SQL: (select * from `notifications` where `is_public` = 1) union (select * from `notifications` inner join `notification_user` on `notifications`.`id` = `notification_user`.`notification_id` where `notification_user`.`user_id` = 1))

请相信我们可以帮助您实现这一目标或提供更好的解决方案。

1 个答案:

答案 0 :(得分:1)

我相信你应该改变:

返回$ user-> notifications();

以其他方式,例如:

return $query->where('user_id', $user->id);

或者

return $query->whereHas('users', function($q) use ($user) {
   $q->where('id', $user->id);
});   

这是因为在一个查询中,您没有使用任何连接,而在第二个查询中,您将获得不同数量的联合部件列。