为 BelongsToMany 关系的 Pivot 表的查询添加括号
今天在实现一个多对多关联查询的时候遇到以下问题:
用户模型 User
通过 shopRoles
多对多关联店铺角色模型 ShopRole
其中的中间表有字段 shop_id
进行区分用户拥有哪些门店的角色,当 shop_id
为 null
值的时候代表对所有门店授权。
另外不太重要的是 ShopRole
模型同时关联 ShopPermission
模型,我们要通过 ShopPermission
模型的 is_super
字段判断 User
模型是否有超管权限。
一开始写了如下代码:
/**
* 是否为超级管理员
*
* @param int|null $shopId 商店ID 为空时差全局超级管理员
*
* @return bool
*/
public function isSuper(?int $shopId = null): bool
{
return $this->shopRoles()
->where(
fn(Builder $query) => $query
// 未指定店铺ID时,查询空店铺ID
->wherePivotNull('shop_id')
->when(
$shopId !== null,
// 店铺ID不为空时,查询指定店铺ID
fn (Builder $query) => $query
->orWherePivot('shop_id', $shopId)
)
)
->whereHas('shopPermissions', fn ($query) => $query->where('is_super', true))
->exists();
}
这段代码会触发一个错误: Illuminate\Database\Eloquent\Builder::wherePivotNull()
方法不存在。
但我又需要使用 where(Closure $callback)
为查询中的或逻辑添加括号。
于是我翻了一下 Illuminate\Database\Eloquent\Relations\BelongsToMany
的代码中 wherePivot
的实现后将代码改成如下方式进行查询通过了测试。
/**
* 是否为超级管理员
*
* @param int|null $shopId 商店ID 为空时差全局超级管理员
*
* @return bool
*/
public function isSuper(?int $shopId = null): bool
{
$relation = $this->shopRoles();
return $relation
->where(
fn(Builder $query) => $query
// 未指定店铺ID时,查询空店铺ID
->whereNull($relation->qualifyPivotColumn('shop_id'))
->when(
$shopId !== null,
// 店铺ID不为空时,查询指定店铺ID
fn (Builder $query) => $query
->orWhere($relation->qualifyPivotColumn('shop_id'), $shopId)
)
)
->whereHas('shopPermissions', fn ($query) => $query->where('is_super', true))
->exists();
}
推荐文章: