Laravel:具有 whereHas 和多对多关系的全局范围

Posted

技术标签:

【中文标题】Laravel:具有 whereHas 和多对多关系的全局范围【英文标题】:Laravel: Global scope with whereHas and many-to-many relationshipi 【发布时间】:2016-05-12 17:16:56 【问题描述】:

我想通过关系的字段进行全局范围过滤。

// The *apply* method of VersionScope file is:
$builder->whereHas('versions', function ($query) 
    return $query->where('version_id', '=', version()->id);
);

// Users'boot method has this line after parent:boot();
static::addGlobalScope(new VersionScope);

versions 是 BelongsToMany 关系,version() 返回一个 Version 对象。

但是我记录了查询并显示如下内容:

select * 
from users 
where users.id = ?
where exists (
    select *
    from versions
    inner join user_version on user_version.version_id = versions.id
    where user_version.user_id = users.id
    and user_version.version_id = ?
)

如果 EXISTS 子查询是第一个关系,则它可以正常工作,例如:

id|user_id|version_id
1 |1      |1
2 |1      |2

如果 version_id = 1,查询工作正常,但如果 version_id = 2,我得到空结果。我不是 mysql 专家,所以我不太了解 EXISTS 子查询如何工作,其中包含 JOIN。

但我看看我是否执行下一个代码之类的操作一切正常。但我需要过滤所有查询,所以我认为我需要一个全局范围。

User::whereHas('versions', function($query) 
    return $query->where('version_id', version()->id)
);

有什么想法吗?

【问题讨论】:

尝试将whereHas('version_id'<...>改为简单的where('version_id'<...> 哎呀,对不起。原始代码是“where”而不是“whereHas”,我在发布代码时犯了一个错误。更新中 【参考方案1】:

我还没有解决这个问题,但我已经找到了避免它的方法。我不知道为什么会这样:

如果我有以下查询并且 id 是唯一的,我不会得到任何结果。但是,如果 id 不是 UNIQUE 我会得到预期的结果;所以我决定删除唯一的,直到我找到另一个解决方案。

select * 
from users 
where users.id = ?
where exists (
    select *
    from versions
    inner join user_version on user_version.version_id = versions.id
    where user_version.user_id = users.id
    and user_version.version_id = ?
)

我不知道这是 EXISTS 子查询的限制还是 MySQL 5.7.12 的错误

【讨论】:

以上是关于Laravel:具有 whereHas 和多对多关系的全局范围的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 多对多使用WhereHas搜索,中间表和要搜索表的字段重合时

HasManyThrough 具有多态和多对多关系

Laravel whereHas on Many-to-Many 关系

具有一对多和多对多关系的 JOOQ pojos

具有外键和多对多关系的 Django 模型与同一模型

QueryDSL 和多对多关系