0

0

Laravel权限功能的技巧:如何实现权限继承和继承关系管理

PHPz

PHPz

发布时间:2023-11-04 09:28:49

|

923人浏览过

|

来源于php中文网

原创

laravel权限功能的技巧:如何实现权限继承和继承关系管理

Laravel 是一框架,它有丰富的特性能够快速开发 Web 应用程序。其权限功能是其中之一。在本文中,我们将开始学习 Laravel 权限系统的两个关键问题:权限继承和继承关系管理,并将实现功能代码的演示。

权限继承

权限继承是指将权限从一个角色传递到另一个角色。在某些情况下,有必要将权限分配给一个角色,然后将这些权限传递给更具体的角色。例如,如果我们要管理某个单位的权限,则可以授予单位管理员所有的单位权限。而不必为每个员工分配权限。

Laravel 提供了「权限继承」功能,我们可以使用它将权限从一个角色传递到另一个角色。让我们开始学习如何实现这个功能。

在开始之前,我们需要建立数据库。我们将创建两个表:roles 和 permissions。

CREATE TABLE `roles` (
  `id` int(10) UNSIGNED NOT NULL,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `parent_id` int(10) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE `permissions` (
  `id` int(10) UNSIGNED NOT NULL,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

我们将创建 roles 表来存储角色,包括 id、name 和 parent_id 字段。id 字段是一个主键,必须唯一。name 字段将存储角色名称。parent_id 字段是可选的,它表示该角色的父角色。我们还将创建 permissions 表,其中包括 id 和 name 字段。id 字段是一个主键,必须唯一。name 字段将存储权限名称。

下面是 roles 表的示例数据:

INSERT INTO `roles` (`id`, `name`, `parent_id`) VALUES
(1, 'Admin', NULL),
(2, 'Manager', 1),
(3, 'User', 2);

在以上示例数据中,我们创建了三个角色,第一个角色称为「Admin」,它没有父角色;第二个角色称为「Manager」,它的父角色是「Admin」;第三个角色称为「User」,它的父角色是「Manager」。

现在,我们要实现权限继承功能。为此,我们需要创建一个函数,该函数将接收一个角色 ID,找到该角色的所有父角色,并返回这些角色的权限。我们还将实现另一个函数,该函数将接收一个角色 ID 和一个权限名称,并检查该角色是否具有该权限,无论是直接授予该权限还是通过继承该权限。

下面是获取角色的所有父角色的函数:

public function getPermissionsByRoleId($roleId) {
    $permissions = [];
    $role = Role::find($roleId);
    while($role) {
        $parent = Role::find($role->parent_id);
        if($parent) {
            $permissions = array_merge($permissions, $parent->permissions);
        }
        $role = $parent;
    }
    return $permissions;
}

以上代码创建了一个 $permissions 数组,并从指定的角色开始遍历角色的父角色。当找到父角色时,将其所有权限添加到 $permissions 数组中。如果找不到父角色,while 循环将终止,并返回 $permissions 数组。

现在,我们将实现另一个函数,该函数将接收角色 ID 和权限名称,并检查该角色是否具有该权限。以下是该函数的代码:

public function hasRolePermission($roleId, $permissionName) {
    $permissions = $this->getPermissionsByRoleId($roleId);
    foreach($permissions as $permission) {
        if($permission->name == $permissionName) {
            return true;
        }
    }
    return false;
}

以上代码调用了 getPermissionsByRoleId 函数以获取角色的所有权限,并将其迭代以找到指定的权限。如果找到该权限,该函数将返回 true。否则,它将返回 false。

现在我们已经学会了如何实现权限继承,接下来重点学习 Laravel 如何实现继承关系管理。

继承关系管理

在某些情况下,有必要创建继承关系,并在应用程序中使用它们。例如,如果我们有一个部门管理应用程序,则每个部门都可以有一个管理者。而管理者与该部门之间的关系可以通过继承关系建立。

DreamGen
DreamGen

一个AI驱动的角色扮演和故事写作的平台

下载

在 Laravel 中,我们可以使用「多态关联」功能建立继承关系。让我们开始学习如何实现它。

我们将创建一个 departments 数据表。departments 表将表示应用程序中的部门,包括 id、name 和 parent_id 字段。id 字段是一个主键,必须唯一。name 字段名称将存储部门名称。parent_id 字段是可选的,它表示该部门的父部门。此外,我们还将创建一个 users 表。此表包含了一个用户的基本信息,包括 id 和 name 字段。我们还需要创建一个 userables 表。该表将包含 user_id、userable_id 和 userable_type 字段。其中,user_id 字段是外键,指向 users 表中的 id 字段。userable_id 和 userable_type 字段是多态字段,它们表示用户与其相关联的任何模型。

下面是所需数据表结构和示例数据:

CREATE TABLE `departments` (
  `id` int(10) UNSIGNED NOT NULL,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `parent_id` int(10) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE `users` (
  `id` int(10) UNSIGNED NOT NULL,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE `userables` (
  `id` int(10) UNSIGNED NOT NULL,
  `user_id` int(10) UNSIGNED NOT NULL,
  `userable_id` int(10) UNSIGNED NOT NULL,
  `userable_type` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `departments` (`id`, `name`, `parent_id`) VALUES
(1, 'Administration', NULL),
(2, 'Finance', 1),
(3, 'Sales', 1),
(4, 'IT', 1),
(5, 'Accounts Payable', 2),
(6, 'Accounts Receivable', 2),
(7, 'Engineering', 4),
(8, 'Development', 7),
(9, 'Testing', 7);

INSERT INTO `users` (`id`, `name`) VALUES
(1, 'User One'),
(2, 'User Two'),
(3, 'User Three');

INSERT INTO `userables` (`id`, `user_id`, `userable_id`, `userable_type`) VALUES
(1, 1, 1, 'Department'),
(2, 1, 2, 'Department'),
(3, 2, 3, 'Department'),
(4, 3, 9, 'Department');

以上示例数据中,我们创建了一个名为「Administration」的部门,它没有父部门;名为「Finance」、「Sales」、「IT」的部门有「Administration」部门作为他们的父部门。另外,名为「Accounts Payable」和「Accounts Receivable」部门有「Finance」部门作为他们的父部门。名为「Engineering」的部门有「IT」部门作为它的父部门。「Development」和「Testing」部门有「Engineering」部门作为他们的父级部门。

我们将使用这些部门和用户数据来建立继承关系。

下面是 userables 表与部门之间的多态关联:

class Userable extends Model {
    public function userable() {
        return $this->morphTo();
    }

    public function user() {
        return $this->belongsTo(User::class);
    }
}

以上代码定义了 userable 函数。该函数返回与 userable 模型相关联的模型。在我们的情况下,userable 将返回 Department 模型或任何其他相关模型。

接下来,我们定义 Department 模型:

class Department extends Model {
    public function users() {
        return $this->morphMany(Userable::class, 'userable');
    }

    public function parent() {
        return $this->belongsTo(Department::class, 'parent_id');
    }

    public function children() {
        return $this->hasMany(Department::class, 'parent_id');
    }
}

以上代码定义了三个函数。users 函数返回将 Userable id 与当前模型实例相关联的所有 User 实例。parent 函数返回这个部门的一个父级部门。children 函数返回所有直接关联的部门。

现在,我们可以使用这些函数来获取一个部门的所有直接用户。以下是 getAllUsers 函数。

public function getAllUsers() {
    $users = [];
    foreach($this->users as $user) {
        $users[] = $user->user;
    }
    return $users;
}

此函数将从当前部门中检索所有用户,并返回一个数组,其中包含这些用户。

最后,我们将定义 User 模型:

class User extends Model {
    public function userables() {
        return $this->hasMany(Userable::class);
    }

    public function departments() {
        return $this->morphToMany(Department::class, 'userable');
    }

    public function getDepartmentAttribute() {
        $department = null;
        foreach($this->userables as $userable) {
            if($userable->userable_type == 'Department') {
                $department = $userable->userable;
                break;
            }
        }
        return $department;
    }
}

以上代码定义了三个函数。userables 函数返回该用户的所有可关联实例。departments 函数返回与此用户相关联的所有部门。getDepartmentAttribute 函数将从 userables 中找到所有 Department 实例,并返回它们中的第一个。

以上所有代码示例可以一起使用,以计划实现 Laravel 权限系统的两个主要问题:权限继承和继承关系管理。

相关专题

更多
laravel组件介绍
laravel组件介绍

laravel 提供了丰富的组件,包括身份验证、模板引擎、缓存、命令行工具、数据库交互、对象关系映射器、事件处理、文件操作、电子邮件发送、队列管理和数据验证。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

314

2024.04.09

laravel中间件介绍
laravel中间件介绍

laravel 中间件分为五种类型:全局、路由、组、终止和自定。想了解更多laravel中间件的相关内容,可以阅读本专题下面的文章。

270

2024.04.09

laravel使用的设计模式有哪些
laravel使用的设计模式有哪些

laravel使用的设计模式有:1、单例模式;2、工厂方法模式;3、建造者模式;4、适配器模式;5、装饰器模式;6、策略模式;7、观察者模式。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

363

2024.04.09

thinkphp和laravel哪个简单
thinkphp和laravel哪个简单

对于初学者来说,laravel 的入门门槛较低,更易上手,原因包括:1. 更简单的安装和配置;2. 丰富的文档和社区支持;3. 简洁易懂的语法和 api;4. 平缓的学习曲线。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

363

2024.04.10

laravel入门教程
laravel入门教程

本专题整合了laravel入门教程,想了解更多详细内容,请阅读专题下面的文章。

80

2025.08.05

laravel实战教程
laravel实战教程

本专题整合了laravel实战教程,阅读专题下面的文章了解更多详细内容。

63

2025.08.05

laravel面试题
laravel面试题

本专题整合了laravel面试题相关内容,阅读专题下面的文章了解更多详细内容。

62

2025.08.05

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

81

2023.09.25

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

74

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Laravel---API接口
Laravel---API接口

共7课时 | 0.6万人学习

ThinkPHP配置开发与CMS后台实战
ThinkPHP配置开发与CMS后台实战

共87课时 | 8.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号