You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化两层多对多关联下的用户权限校验实现代码

现有实现存在的问题
  • 关联预加载不完整:仅加载了roles关联,未嵌套加载roles.permissions,遍历角色权限时会产生N+1次SQL查询,性能损耗大
  • 存在逻辑bug:代码中遗留的dd('hier 2')调试语句,会在第一个权限匹配失败时直接终止程序运行,导致后续权限校验逻辑完全无法执行
  • 时间复杂度高:两层foreach循环加上每次遍历都调用array_filter遍历待校验权限数组,时间复杂度达到O(mnk)(m为用户所属角色数、n为单角色对应权限数、k为待校验权限数),效率极低
  • 封装冗余:自定义的getFilteredArray过滤方法完全可以用PHP内置的in_array方法替代,不需要单独封装做遍历过滤
优化方案

从代码特征判断你使用的是Laravel框架的Eloquent模型,以下提供两种适配不同场景的优化实现:

方案1:基于集合的内存校验(适合中小权限量级场景)

优化后代码:

public function hasPermissions(array $permissions = []): bool
{
    // 空权限入参可根据业务需求调整返回值,此处和原逻辑对齐返回false
    if (empty($permissions)) {
        return false;
    }

    // 一次性预加载所有嵌套关联,仅执行2次SQL查询
    $this->loadMissing('roles.permissions');

    // 拍平所有角色的权限,直接判断和待校验权限是否有交集
    return $this->roles
        ->pluck('permissions')
        ->flatten(1)
        ->pluck('permission')
        ->intersect($permissions)
        ->isNotEmpty();
}

优化点说明:

  • 嵌套关联预加载避免了N+1查询问题
  • 去掉所有手写循环,用Laravel内置集合方法完成权限提取和匹配,逻辑简洁可读性高
  • 时间复杂度降低为O(m*n + k),性能提升明显

方案2:数据库层直接校验(适合大权限量级场景)

如果用户关联的角色和权限量级很大,不需要把所有权限加载到内存处理,可以直接通过EXISTS查询完成校验,性能最高:

public function hasPermissions(array $permissions = []): bool
{
    if (empty($permissions)) {
        return false;
    }

    // 仅执行1次EXISTS查询,无需返回任何权限数据
    return $this->roles()->whereHas('permissions', function ($query) use ($permissions) {
        $query->whereIn('permission', $permissions);
    })->exists();
}

如果你的业务需求是校验用户拥有所有传入的权限,只需将方案1的交集判断改为intersect($permissions)->count() === count($permissions),方案2则改为统计匹配的权限数量和传入权限数量是否相等即可。

内容的提问来源于stack exchange,提问作者GekkeGlenn-Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 02:42:03