Laravel is a framework with rich features for rapid development of web applications. Its permissions feature is one of them. In this article, we will start to learn two key issues of Laravel's permission system: permission inheritance and inheritance relationship management, and will implement a demonstration of functional code.
Permission inheritance
Permission inheritance refers to passing permissions from one role to another role. In some cases, it is necessary to assign permissions to a role and then pass those permissions to more specific roles. For example, if we want to manage permissions for an organization, we can grant the unit administrator all organization permissions. Rather than having to assign permissions to each employee.
Laravel provides the "permission inheritance" function, which we can use to pass permissions from one role to another. Let's start learning how to implement this functionality.
Before we start, we need to create a database. We will create two tables: roles and 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;
We will create the roles table to store the roles, including the id, name and parent_id fields. The id field is a primary key and must be unique. The name field will store the role name. The parent_id field is optional and represents the parent role of this role. We will also create the permissions table, which includes id and name fields. The id field is a primary key and must be unique. The name field will store the permission name.
The following is sample data from the roles table:
INSERT INTO `roles` (`id`, `name`, `parent_id`) VALUES (1, 'Admin', NULL), (2, 'Manager', 1), (3, 'User', 2);
In the above sample data, we created three roles. The first role is called "Admin", which has no parent role; The second role is called "Manager", and its parent role is "Admin"; the third role is called "User", and its parent role is "Manager".
Now, we need to implement the permission inheritance function. To do this, we need to create a function that will receive a role ID, find all the parent roles of that role, and return the permissions for those roles. We'll also implement another function that will receive a role ID and a permission name and check whether the role has that permission, either by granting it directly or by inheriting it.
The following is a function to get all the parent roles of a role:
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; }
The above code creates a $permissions array and traverses the parent roles of the role starting from the specified role. When the parent role is found, add all its permissions to the $permissions array. If the parent role is not found, the while loop terminates and the $permissions array is returned.
Now we will implement another function that will receive the role ID and permission name and check if the role has that permission. Here is the code for the function:
public function hasRolePermission($roleId, $permissionName) { $permissions = $this->getPermissionsByRoleId($roleId); foreach($permissions as $permission) { if($permission->name == $permissionName) { return true; } } return false; }
The above code calls the getPermissionsByRoleId function to get all the permissions for the role and iterates it to find the specified permission. If the permission is found, the function returns true. Otherwise, it returns false.
Now that we have learned how to implement permission inheritance, let’s focus on learning how Laravel implements inheritance relationship management.
Inheritance relationship management
In some cases, it is necessary to create inheritance relationships and use them in the application. For example, if we have a department management application, each department can have a manager. The relationship between the manager and the department can be established through inheritance.
In Laravel, we can use the "polymorphic association" function to establish inheritance relationships. Let's start learning how to implement it.
We will create a departments data table. The departments table will represent the departments in the application and includes the id, name, and parent_id fields. The id field is a primary key and must be unique. The name field name will store the department name. The parent_id field is optional and represents the parent department of this department. Additionally, we will create a users table. This table contains basic information about a user, including the id and name fields. We also need to create a userables table. The table will contain user_id, userable_id, and userable_type fields. Among them, the user_id field is a foreign key pointing to the id field in the users table. The userable_id and userable_type fields are polymorphic fields that represent whatever model the user is associated with.
The following is the required data table structure and sample data:
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');
In the above sample data, we created a department named "Administration", which has no parent department; it is named "Finance" ”, “Sales”, and “IT” departments have the “Administration” department as their parent department. Additionally, departments named "Accounts Payable" and "Accounts Receivable" have the "Finance" department as their parent department. A department named "Engineering" has the "IT" department as its parent department. The "Development" and "Testing" departments have the "Engineering" department as their parent department.
We will use these department and user data to establish inheritance relationships.
The following is the polymorphic association between the userables table and the department:
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 above is the detailed content of Tips on Laravel permission function: How to implement permission inheritance and inheritance relationship management. For more information, please follow other related articles on the PHP Chinese website!