【问题标题】:Laravel Builder Scope with Union and many-to-many relationship具有联合和多对多关系的 Laravel Builder 范围
【发布时间】:2018-04-24 00:44:31
【问题描述】:


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

id
title
body
is_public
...

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

id
username
...

我还有一个数据透视表 notification_user 表
列:

user_id
notification_id

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

Notification.php

public function users()
{
    return $this->belongsToMany('App\Api\V1\Models\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))

如果能帮我解决这个问题或提供更好的解决方案,我将不胜感激。

【问题讨论】:

    标签: php laravel eloquent union query-builder


    【解决方案1】:

    我认为你应该改变:

    return $user->notifications();

    到别的东西,例如:

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

    或许

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

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

    【讨论】:

    • 非常感谢@Marcin,第二个建议非常有效。第一个不应该在这种情况下适用,因为我们将在 'notifications' 表中查询不存在的 'user_id' 列。请同时将'user' 编辑为'users' 以匹配初始关系。
    猜你喜欢
    • 1970-01-01
    • 2020-06-14
    • 2021-09-06
    • 1970-01-01
    • 2019-10-12
    • 2019-01-26
    • 2023-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多