同时拥有admin与support角色时无法查询数据行的问题解决
Laravel查询构建器多角色权限逻辑修正
问题场景
现有Laravel查询构建器代码如下,用于根据用户角色过滤runs数据:
return $builder ->when($authUser->hasRole('admin'), function (Builder $q) use ($authUser) { $q->whereHas('users', function (Builder $builder) use ($authUser) { $builder->where('users.id', $authUser->id); }); }) ->when($authUser->hasRole('support'), function (Builder $q) { $q->whereHas('users', function (Builder $q2) { $q2->where('support_access', true); }); }) ->when($authUser->hasRole('owner'), function (Builder $q) use ($authUser) { $q ->where(function (Builder $builder) use ($authUser) { $builder ->whereIn('device_id', $authUser->company->devices->pluck('id')) ->orWhereIn('id', $authUser->runs()->pluck('runs.id')); }); }) ->when($authUser->hasRole('viewer'), function (Builder $q) use ($authUser) { $q->whereIn('id', $authUser->runs->pluck('id')); });
预期逻辑:
- 用户仅拥有
admin角色时,获取关联自己的runs数据 - 用户仅拥有
support角色时,获取所有support_access=true的runs数据 - 用户同时拥有
admin和support角色时,优先获取support_access=true的runs数据 - 其他角色逻辑保持不变
当前问题:单独拥有admin或support角色时逻辑正常,但同时拥有两个角色时返回空数据。
问题原因
当用户同时拥有admin和support角色时,两个when条件都会触发,查询会同时添加两个且关系的过滤条件:
runs必须关联当前用户(admin逻辑)runs必须关联support_access=true的用户(support逻辑)
两种条件叠加后没有符合要求的数据,因此返回空结果。
解决方案
调整admin角色的when触发条件,仅当用户是admin且不具备support角色时,才执行admin对应的过滤逻辑。修改后的代码如下:
return $builder // 仅当用户是admin且无support角色时,执行admin专属过滤 ->when($authUser->hasRole('admin') && !$authUser->hasRole('support'), function (Builder $q) use ($authUser) { $q->whereHas('users', function (Builder $builder) use ($authUser) { $builder->where('users.id', $authUser->id); }); }) // 只要用户有support角色,就执行support逻辑 ->when($authUser->hasRole('support'), function (Builder $q) { $q->whereHas('users', function (Builder $q2) { $q2->where('support_access', true); }); }) ->when($authUser->hasRole('owner'), function (Builder $q) use ($authUser) { $q ->where(function (Builder $builder) use ($authUser) { $builder ->whereIn('device_id', $authUser->company->devices->pluck('id')) ->orWhereIn('id', $authUser->runs()->pluck('runs.id')); }); }) ->when($authUser->hasRole('viewer'), function (Builder $q) use ($authUser) { $q->whereIn('id', $authUser->runs->pluck('id')); });
逻辑说明
- 当用户同时拥有
admin和support角色时,admin的when条件不满足(!$authUser->hasRole('support')为false),仅执行support的过滤逻辑,返回所有support_access=true的runs数据 - 当用户仅拥有
admin角色时,admin的when条件满足,执行原有的关联用户过滤逻辑 - 其他角色的逻辑保持不变,不受影响
内容的提问来源于stack exchange,提问作者Jesse Schoonveld
相关产品推荐
相关产品推荐

