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

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」部門作為它的父部門?!窪evelopment」和「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 權限系統的兩個主要問題:權限繼承和繼承關系管理。

? 版權聲明
THE END
喜歡就支持一下吧
點贊11 分享