VOOZH about

URL: https://deepwiki.com/hypervel/permission/2.2-hasrole-trait

⇱ HasRole Trait | hypervel/permission | DeepWiki


Loading...
Menu

HasRole Trait

This document details the HasRole trait, which provides role management capabilities for owner models. The trait enables models to have roles assigned to them, check role membership, and manage role assignments with automatic cache invalidation.

For direct permission management without roles, see HasPermission Trait. For information on how the Role model is structured, see Role Model. For HTTP-level role enforcement, see Role Middleware.


Overview

The HasRole trait is located at src/Traits/HasRole.php1-307 and provides a complete role-based authorization system. It includes the HasPermission trait src/Traits/HasRole.php27 meaning any model using HasRole automatically gains both role and permission capabilities.

The trait supports:

  • Polymorphic many-to-many role relationships
  • Multiple role checking strategies (any, all, intersection)
  • Role assignment, removal, and synchronization
  • Type-safe role identifiers (int, string, enums)
  • Automatic cache invalidation on role changes
  • Integration with the PermissionManager for caching

Sources: src/Traits/HasRole.php1-307


Class Structure and Dependencies

The following diagram shows the HasRole trait's structure and its relationships with other components:


Sources: src/Traits/HasRole.php27 src/Traits/HasRole.php43-46 src/Traits/HasRole.php87-96


Role Relationship

The trait defines a polymorphic many-to-many relationship to the Role model through the roles() method src/Traits/HasRole.php87-96:

Configuration KeyPurposeDefault Value
permission.models.roleRole model classHypervel\Permission\Models\Role
permission.table_names.owner_nameMorph nameowner
permission.table_names.owner_has_rolesPivot tableowner_has_roles
permission.column_names.owner_morph_keyOwner ID columnowner_id
permission.column_names.role_pivot_keyRole ID columnrole_id

The relationship is configured via the morphToMany() method, which creates a polymorphic relationship allowing any owner type (e.g., User, Team) to have roles. The role class is resolved via getRoleClass() src/Traits/HasRole.php31-38 which retrieves the configured class from the PermissionManager.

Sources: src/Traits/HasRole.php87-96 src/Traits/HasRole.php31-38


Role Checking Methods

The trait provides three primary role checking methods with automatic caching support:

Role Check Flow


Sources: src/Traits/HasRole.php59-82 src/Traits/HasRole.php101-108

hasRole()

Checks if the owner has a specific role src/Traits/HasRole.php101-108:


The method:

  1. Retrieves cached roles via getCachedRoles() src/Traits/HasRole.php103
  2. Normalizes the role value to a field/value pair src/Traits/HasRole.php105
  3. Checks if the collection contains the role src/Traits/HasRole.php107

The role can be specified by ID (int) or name (string), and the method automatically determines which field to check.

Sources: src/Traits/HasRole.php101-108

hasAnyRoles()

Checks if the owner has any of the specified roles src/Traits/HasRole.php178-187:


This method is used by RoleMiddleware src/Middleware/RoleMiddleware.php to enforce role-based access control. It returns true if at least one role matches.

Sources: src/Traits/HasRole.php178-187

hasAllRoles()

Checks if the owner has all of the specified roles src/Traits/HasRole.php194-203:


Returns true only if every role in the input array is assigned to the owner.

Sources: src/Traits/HasRole.php194-203

onlyRoles()

Returns the intersection of assigned roles and specified roles src/Traits/HasRole.php210-228:


This method:

  1. Separates input roles into IDs and names src/Traits/HasRole.php214
  2. Intersects with owner's role IDs and names src/Traits/HasRole.php220-221
  3. Filters and returns matching roles src/Traits/HasRole.php223-227

Sources: src/Traits/HasRole.php210-228


Role Assignment Methods

All role assignment methods automatically clear the owner's cache to ensure consistency:


Sources: src/Traits/HasRole.php233-278

assignRole()

Assigns one or more roles to the owner src/Traits/HasRole.php233-248:


The method:

  1. Loads existing roles src/Traits/HasRole.php235
  2. Collects and resolves role IDs src/Traits/HasRole.php236
  3. Calculates the diff to avoid duplicate attachments src/Traits/HasRole.php239-240
  4. Attaches only new roles src/Traits/HasRole.php240
  5. Unsets the relationship src/Traits/HasRole.php242
  6. Clears the owner cache src/Traits/HasRole.php245

Sources: src/Traits/HasRole.php233-248

removeRole()

Removes one or more roles from the owner src/Traits/HasRole.php253-263:


The method collects role IDs and detaches them from the relationship, then clears the cache src/Traits/HasRole.php255-260

Sources: src/Traits/HasRole.php253-263

syncRoles()

Synchronizes the owner's roles with the given list src/Traits/HasRole.php268-278:


This method performs a complete synchronization, attaching new roles and detaching roles not in the list. It returns the sync result array (attached, detached, updated) src/Traits/HasRole.php272

Sources: src/Traits/HasRole.php268-278


Type Support and Normalization

The trait supports multiple role identifier types and automatically normalizes them:

Supported Types

TypeExampleExtracted ValueField
int11id (primary key)
string'admin''admin'name
BackedEnum (int)RoleEnum::ADMIN (value: 1)1id
BackedEnum (string)RoleEnum::ADMIN (value: 'admin')'admin'name
UnitEnumRoleEnum::ADMIN'ADMIN'name

Sources: src/Traits/HasRole.php126-133 src/Traits/HasRole.php140-148

Type Normalization Process


Sources: src/Traits/HasRole.php113-121 src/Traits/HasRole.php126-148

extractRoleValue()

Extracts the actual value from any supported role type src/Traits/HasRole.php126-133:


Sources: src/Traits/HasRole.php126-133

isRoleIdType()

Determines whether a role should be treated as an ID or name src/Traits/HasRole.php140-148:

  • Returns true for: int values, BackedEnum with int value
  • Returns false for: string values, UnitEnum, BackedEnum with string value
  • Throws InvalidArgumentException for unsupported types

Sources: src/Traits/HasRole.php140-148

separateRolesByType()

Separates an array of mixed-type roles into two collections src/Traits/HasRole.php155-171:


Returns [$roleIds, $roleNames] where:

  • $roleIds: Collection of integer IDs
  • $roleNames: Collection of string names

This is used by onlyRoles() and collectRoles() to efficiently query the database.

Sources: src/Traits/HasRole.php155-171


Caching Behavior

The trait implements a sophisticated caching strategy through integration with PermissionManager:

Cache Keys

The cache keys are generated using the following pattern src/PermissionManager.php124-127:

{prefix}:{ownerType}:{ownerId}

Where:

  • prefix: Configured via permission.cache.keys.owner_roles (default: "owner_roles")
  • ownerType: Owner class name (e.g., App\Models\User)
  • ownerId: Owner's primary key value

Sources: src/PermissionManager.php124-127 src/Traits/HasRole.php49-54

getCachedRoles()

Retrieves roles with caching src/Traits/HasRole.php59-82:


Sources: src/Traits/HasRole.php59-82 src/PermissionManager.php185-191

The method:

  1. Requests cached data from PermissionManager src/Traits/HasRole.php62
  2. If cache exists, hydrates models from the array src/Traits/HasRole.php64-68
  3. If cache is empty, loads from database src/Traits/HasRole.php71
  4. Caches the fresh data via PermissionManager src/Traits/HasRole.php75-79

Sources: src/Traits/HasRole.php59-82

Cache Invalidation

Cache is automatically cleared when roles are modified src/Traits/HasRole.php245 src/Traits/HasRole.php260 src/Traits/HasRole.php275 All three mutation methods (assignRole, removeRole, syncRoles) call:


This clears both the owner's roles cache and permissions cache, as role changes affect computed permissions. See Permission Manager for details on cache management.

Sources: src/Traits/HasRole.php245 src/Traits/HasRole.php260 src/Traits/HasRole.php275 src/PermissionManager.php216-223


Integration with HasPermission

The HasRole trait includes HasPermission src/Traits/HasRole.php27 which means:

  1. Owner models get both traits: Any model using HasRole automatically has all HasPermission methods available
  2. Permissions via roles: Roles have permissions assigned to them via the role_has_permissions pivot table
  3. Permission checking includes roles: The HasPermission trait's permission checking methods consider both direct permissions and permissions inherited through roles
  4. Shared caching: Both traits use the same PermissionManager instance and cache clearing affects both roles and permissions

This design allows a layered authorization model:

  • Direct permissions (owner → permission)
  • Role-based permissions (owner → role → permission)
  • Forbidden permissions (explicit denials at any level)

For details on how permissions are checked and how roles contribute to permission calculation, see HasPermission Trait.

Sources: src/Traits/HasRole.php27


Helper Methods

getRoleClass()

Retrieves the configured role model class src/Traits/HasRole.php31-38:


The class is cached in the trait instance src/Traits/HasRole.php29 and retrieved from PermissionManager on first access src/Traits/HasRole.php34

Sources: src/Traits/HasRole.php31-38

getPermissionManager()

Returns the PermissionManager singleton instance src/Traits/HasRole.php43-46:


This method provides access to caching and model resolution services.

Sources: src/Traits/HasRole.php43-46

getOwnerType()

Returns the owner's class name for cache key generation src/Traits/HasRole.php51-54:


Uses static::class to ensure the correct class name is used when the trait is applied to different model types.

Sources: src/Traits/HasRole.php51-54

collectRoles()

Converts variadic role arguments to an array of role IDs src/Traits/HasRole.php283-305:


The method:

  1. Flattens the input arguments src/Traits/HasRole.php285-288
  2. Separates roles by type (IDs vs names) src/Traits/HasRole.php289
  3. Queries the database for matching roles src/Traits/HasRole.php291-302
  4. Returns an array of role IDs src/Traits/HasRole.php304

This method is used internally by all assignment methods to normalize input roles before database operations.

Sources: src/Traits/HasRole.php283-305


Property Documentation

The trait adds the following property to owner models via @property-read annotation src/Traits/HasRole.php23:

PropertyTypeDescription
$rolesCollection<Role>Collection of roles assigned to the owner

This property is accessed via the roles() relationship method and is lazy-loaded on first access.

Sources: src/Traits/HasRole.php23