Laravel は、Web アプリケーションを迅速に開発するための豊富な機能を備えたフレームワークです。その権限機能もその 1 つです。この記事では、Laravel のパーミッション システムの 2 つの重要な問題、パーミッションの継承と継承関係の管理について学習し、機能コードのデモンストレーションを実装します。
権限の継承
権限の継承とは、あるロールから別のロールに権限を渡すことを指します。場合によっては、ロールにアクセス許可を割り当ててから、そのアクセス許可をより具体的なロールに渡すことが必要になります。たとえば、組織の権限を管理したい場合、部門管理者に組織のすべての権限を付与できます。各従業員に権限を割り当てる必要がなくなります。
Laravel は、あるロールから別のロールにアクセス許可を渡すために使用できる「アクセス許可の継承」機能を提供します。この機能を実装する方法を学び始めましょう。
始める前に、データベースを作成する必要があります。ロールと権限という 2 つのテーブルを作成します。
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;
id、name、parent_id フィールドを含むロールを保存するロール テーブルを作成します。 id フィールドは主キーであり、一意である必要があります。名前フィールドにはロール名が保存されます。 parent_id フィールドはオプションで、このロールの親ロールを表します。 ID フィールドと名前フィールドを含む権限テーブルも作成します。 id フィールドは主キーであり、一意である必要があります。名前フィールドには権限名が保存されます。
次は、ロール テーブルのサンプル データです:
INSERT INTO `roles` (`id`, `name`, `parent_id`) VALUES (1, 'Admin', NULL), (2, 'Manager', 1), (3, 'User', 2);
上記のサンプル データでは、3 つのロールを作成しました。最初のロールは「Admin」と呼ばれ、親ロールはありません。 2 番目のロールは「Manager」と呼ばれ、その親ロールは「Admin」です。3 番目のロールは「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 では、「ポリモーフィック関連付け」機能を使用して継承関係を確立できます。実装方法を学び始めましょう。
部門データテーブルを作成します。部門テーブルはアプリケーション内の部門を表し、id、name、parent_id フィールドが含まれます。 id フィールドは主キーであり、一意である必要があります。名前フィールド名には部署名が格納されます。 parent_id フィールドはオプションで、この部門の親部門を表します。さらに、users テーブルを作成します。このテーブルには、id フィールドや名前フィールドなど、ユーザーに関する基本情報が含まれています。 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');
上記のサンプル データでは、親部門を持たない「管理」という名前の部門を作成しました。「」という名前です。財務「 」、「営業」、および「IT」部門は、親部門として「管理」部門を持ちます。さらに、「買掛金」および「売掛金」という名前の部門には、親部門として「財務」部門があります。 「エンジニアリング」という名前の部門は、親部門として「IT」部門を持っています。 「開発」部門と「テスト」部門は、「エンジニアリング」部門を親部門としています。
これらの部門とユーザーのデータを使用して、継承関係を確立します。
次は、ユーザー可能テーブルと部門の間の多態性の関連付けです:
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パーミッション機能のTips:パーミッション継承と継承関係管理の実装方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。