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

Laravel角色层级排序与用户创建角色权限控制方案咨询

嘿,针对你要实现的角色层级排序+权限限制分配的需求,这里有几个落地性很强的方案,结合你现有的Role模型来逐一说明:

方案1:给角色添加层级字段(最直观的轻量方案)

这是最简单直接的方式,核心思路是给每个角色定义一个层级值,通过数值大小来判断角色的上下级关系,进而限制分配权限。

步骤1:修改Role模型

给roles表新增一个level字段(建议用整数类型),然后在模型的$fillable里添加这个字段:

class Role extends Model { 
    use Notifiable; 
    /** 
    * The attribute that are mass assignable. 
    * 
    * @var array 
    */ 
    protected $fillable = [ 'name', 'description', 'level' ]; 

    public function permissions() { 
        return $this->hasOne(Permissions::class); 
    } 
}

比如可以这样定义层级数值:

  • 管理员:level = 3
  • 版主:level = 2
  • 普通用户:level = 1

步骤2:添加分配权限校验逻辑

在创建用户的控制器方法里,先获取当前登录用户的角色层级,然后只允许选择层级值小于当前用户角色层级的角色:

// 获取当前登录用户的角色层级
$currentUserRoleLevel = auth()->user()->role->level;

// 查询可分配的角色(仅层级更低的角色)
$assignableRoles = Role::where('level', '<', $currentUserRoleLevel)->get();

同时一定要在后端做参数验证,防止前端篡改请求:

$this->validate($request, [
    'role_id' => [
        'required',
        Rule::exists('roles', 'id'),
        function ($attribute, $value, $fail) {
            $currentLevel = auth()->user()->role->level;
            $targetLevel = Role::find($value)->level;
            if ($targetLevel >= $currentLevel) {
                $fail('你没有权限分配该角色');
            }
        },
    ],
]);
方案2:建立角色自关联(适合复杂层级关系)

如果你的角色层级可能有多层级(比如超级管理员→管理员→分区版主→普通用户),或者需要更灵活的上下级关联,那可以用角色自关联的方式,让每个角色拥有父角色和子角色。

步骤1:修改Role模型和数据表

给roles表新增parent_id字段(外键关联自身的id),然后在模型里添加自关联方法:

class Role extends Model { 
    use Notifiable; 
    protected $fillable = [ 'name', 'description', 'parent_id' ]; 

    public function permissions() { 
        return $this->hasOne(Permissions::class); 
    }

    // 关联父角色
    public function parent() {
        return $this->belongsTo(Role::class, 'parent_id');
    }

    // 关联子角色
    public function children() {
        return $this->hasMany(Role::class, 'parent_id');
    }
}

比如数据可以这样存储:

  • 管理员(id=1):parent_id = null
  • 版主(id=2):parent_id = 1
  • 普通用户(id=3):parent_id = 2

步骤2:查询可分配的角色

如果需要获取当前角色下所有层级的子角色(比如版主能分配普通用户),可以递归查询所有后代角色。这里给个基础的递归查询示例:

// 递归获取当前角色的所有子角色ID
function getAllDescendantRoleIds($roleId) {
    $children = Role::where('parent_id', $roleId)->pluck('id')->toArray();
    foreach ($children as $childId) {
        $children = array_merge($children, getAllDescendantRoleIds($childId));
    }
    return $children;
}

// 在控制器里使用
$currentRoleId = auth()->user()->role->id;
$assignableRoleIds = getAllDescendantRoleIds($currentRoleId);
$assignableRoles = Role::whereIn('id', $assignableRoleIds)->get();

这样版主就能分配所有属于自己下级的角色,而不能分配管理员或者同级的版主角色。

方案3:基于权限模型的细粒度控制

因为你已经给每个角色关联了Permissions模型,那可以把“可分配角色列表”直接配置到权限里,实现更灵活的自定义权限控制。

步骤1:修改Permissions模型

给permissions表新增assignable_role_ids字段(可以用JSON类型或者文本存储,比如存逗号分隔的角色ID),如果用JSON类型,记得开启数组转换:

class Permissions extends Model {
    // 把JSON字段自动转换为数组
    protected $casts = [
        'assignable_role_ids' => 'array',
    ];
}

比如给版主的权限配置assignable_role_ids: [3](3是普通用户的角色ID),管理员的配置assignable_role_ids: [2,3]。

步骤2:校验分配权限

在创建用户时,直接读取当前用户角色关联的权限里的可分配角色ID列表,然后过滤可选角色:

// 获取当前用户角色允许分配的角色ID
$assignableRoleIds = auth()->user()->role->permissions->assignable_role_ids;

// 查询可分配的角色
$assignableRoles = Role::whereIn('id', $assignableRoleIds)->get();

这种方式的好处是不需要依赖层级数值或者固定的上下级关系,完全可以根据业务需求灵活配置每个角色能分配的范围,比如某些特殊版主可以分配特定的子角色。


额外注意点

  • 前端后端双重校验:前端可以先过滤掉不可选的角色,但一定要在后端做最终校验,防止恶意请求绕过前端限制。
  • 逻辑复用:可以把角色权限校验的逻辑封装成自定义请求类、中间件或者Traits,避免在多个控制器里重复写代码。
  • 性能优化:如果角色层级或可分配列表不常变动,可以把查询结果缓存起来,减少数据库查询次数。

内容的提问来源于stack exchange,提问作者Petoux

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:15:02