Laravel雄辩的联盟关系模型

时间:2020-08-21 15:24:14

标签: sql laravel eloquent laravel-7.x

我有一个用户可以召开来自不同关系的会议。他可以直接分配给具有多个关系的会议,他可以具有具有太多关系的用户组,可以拥有具有太多关系的会议,他可以负责一对多关系的会议。
我想让一个用户参加所有会议。我不想合并集合,因为我希望能够直接在数据库中使用where之类的功能。我的尝试是合并所有会议ID,然后通过“ whereIn”获取会议。

$ids = $this->meetings()->select('meetings.id')
    ->union($this->meetingsFromGroups()->select('meetings.id'))
    ->union($this->responsibleMeetings()->select('meetings.id'));

return Meeting::whereIn('id', $ids)->get();

执行此操作时,出现此错误:

“ SQLSTATE [42000]:语法错误或访问冲突:1064您的SQL语法有错误;请查看与您的MySQL服务器版本相对应的手册,以在'union'附近使用正确的语法(选择” meetings“。第1行中来自“会议”内部联接“会议_用户_组”上的“ id”(SQL:...)” 执行的SQL:

select *
from `meetings`
where `id` in (
        (
            select `meetings`.`id`
            from `meetings`
                inner join `meeting_user` on `meetings`.`id` = `meeting_user`.`meeting_id`
            where `meeting_user`.`user_id` = 1
        )
        union
        (
            select `meetings`.`id`
            from `meetings`
                inner join `meeting_user_group` on `meeting_user_group`.`meeting_id` = `meetings`.`id`
                inner join `user_groups` on `user_groups`.`id` = `meeting_user_group`.`user_group_id`
                inner join `user_user_group` on `user_user_group`.`user_group_id` = `user_groups`.`id`
            where `user_user_group`.`user_id` = 1
        )
        union
        (
            select `meetings`.`id`
            from `meetings`
            where `meetings`.`responsible_id` = 1
                and `meetings`.`responsible_id` is not null
        )
    )

关系:

    public function responsibleMeetings(): HasMany {
        return $this->hasMany(Meeting::class, 'responsible_id');
    }

    public function meetings(): BelongsToMany {
        return $this->belongsToMany(Meeting::class)->withTimestamps();
    }

    public function meetingsFromGroups(): HasManyDeep {
        return $this->hasManyDeepFromRelations($this->userGroups(), (new UserGroup())->meetings());
    }

我正在使用Staudenmeir\EloquentHasManyDeep的软件包meetingsFromGroups

我不能在整个会议中使用union,因为那样我会得到

SQLSTATE [21000]:违反基数:1222使用的SELECT语句具有不同的列数

由于枢轴字段。

如何更改SQL才能使其正常工作,我如何用Eloquent做到这一点?

1 个答案:

答案 0 :(得分:1)

默认情况下,whereIn期望数组对数组项执行IN()子句,但是在您的情况下,您正在发送联合查询,这就是它引发错误的原因。

$ids = $this->meetings()->select('meetings.id')
    ->union($this->meetingsFromGroups()->select('meetings.id'))
    ->union($this->responsibleMeetings()->select('meetings.id'))
    ->pluck('id')->all();

return Meeting::whereIn('id', $ids)->get();

此外,whereIn也接受闭包方法,但不确定在闭包内部如何称呼这些相关对象$this->meetings()$this->meetingsFromGroups()$this->responsibleMeetings()

return Meeting::whereIn('id', function($query){
    $query->select('...')
    ...;
})->get();