首頁 >php框架 >Laravel >Laravel權限功能的技巧:如何實現權限繼承與繼承關係管理

Laravel權限功能的技巧:如何實現權限繼承與繼承關係管理

PHPz
PHPz原創
2023-11-04 09:28:49879瀏覽

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 如何實現繼承關係管理。

繼承關係管理

在某些情況下,有必要建立繼承關係,並在應用程式中使用它們。例如,如果我們有一個部門管理應用程序,則每個部門都可以有管理者。而管理者與該部門之間的關係可以透過繼承關係來建立。

在 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權限功能的技巧:如何實現權限繼承與繼承關係管理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn