PHP code example of scabarcas / laravel-permissions-redis

1. Go to this page and download the library: Download scabarcas/laravel-permissions-redis library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

scabarcas / laravel-permissions-redis example snippets


// .env
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=null



namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Scabarcas\LaravelPermissionsRedis\Traits\HasRedisPermissions;

class User extends Authenticatable
{
    use HasRedisPermissions;
}

// config/permissions-redis.php
'user_model' => [
    App\Models\User::class,
    App\Models\Admin::class,
],

use Scabarcas\LaravelPermissionsRedis\Models\Permission;
use Scabarcas\LaravelPermissionsRedis\Models\Role;

// Create permissions
$createPosts = Permission::findOrCreate('posts.create');
$editPosts   = Permission::findOrCreate('posts.edit');
$deletePosts = Permission::findOrCreate('posts.delete');

// Create with group
$manageUsers = Permission::findOrCreate('users.manage', 'web', 'user-management');

// Create roles
$admin  = Role::findOrCreate('admin');
$editor = Role::findOrCreate('editor');

// Assign permissions to a role
$editor->syncPermissions(['posts.create', 'posts.edit']);

// Or add permissions individually
$editor->givePermissionTo('posts.create', 'posts.edit');

// Remove permissions
$editor->revokePermissionTo('posts.delete');

// Check whether a role grants a specific permission (reads Redis)
$editor->hasPermission('posts.create');          // bool
$editor->hasPermission('reports.export', 'api'); // optional guard

$user = User::find(1);

// Assign roles (additive, does not remove existing roles)
$user->assignRole('admin');
$user->assignRole('editor', 'moderator');

// Replace all roles
$user->syncRoles('editor');

// Remove a role
$user->removeRole('moderator');

// Give direct permissions (in addition to role-inherited permissions)
$user->givePermissionTo('reports.export', 'reports.view');

// Revoke direct permissions
$user->revokePermissionTo('reports.export');

// Replace all direct permissions
$user->syncPermissions(['reports.view']);

// Single permission check
$user->hasPermissionTo('posts.edit');        // bool

// Any of multiple permissions
$user->hasAnyPermission('posts.edit', 'posts.delete');  // bool

// All permissions / bool

// All roles adata (e.g., "user-management", "billing")
$user->getAllPermissions()->groupBy('group');

// Get permission names only
$user->getPermissionNames();    // Collection<string>

// Get role names
$user->getRoleNames();          // Collection<string>

// Find users with a specific role (SQL query)
User::role('admin')->get();

// Find users with a specific permission (SQL query)
User::permission('posts.edit')->get();

// Single permission
Route::get('/posts/create', [PostController::class, 'create'])
    ->middleware('permission:posts.create');

// OR (user needs ANY of these)
Route::get('/posts', [PostController::class, 'index'])
    ->middleware('permission:posts.view|posts.manage');

// AND (user needs ALL of these)
Route::put('/posts/{id}/publish', [PostController::class, 'publish'])
    ->middleware('permission:posts.edit&posts.publish');

// Single role
Route::get('/admin', [AdminController::class, 'index'])
    ->middleware('role:admin');

// OR (user needs ANY role)
Route::get('/dashboard', [DashboardController::class, 'index'])
    ->middleware('role:admin|editor');

// AND (user needs ALL roles)
Route::get('/super', [SuperController::class, 'index'])
    ->middleware('role:admin&super_admin');

Route::get('/reports', [ReportController::class, 'index'])
    ->middleware('role_or_permission:admin|reports.view');

// In controllers
$this->authorize('posts.edit');

// In policies
Gate::allows('posts.edit');

// In Blade
@can('posts.edit')
    <button>Edit</button>
@endcan

$admin = Role::findOrCreate('admin');
$wildcard = Permission::findOrCreate('users.*');

$admin->permissions()->sync([$wildcard->id]);
$user->assignRole('admin');

// All these return true:
$user->hasPermissionTo('users.create');  // matched by users.*
$user->hasPermissionTo('users.edit');    // matched by users.*
$user->hasPermissionTo('users.delete');  // matched by users.*

// This returns false:
$user->hasPermissionTo('posts.create');  // no match

Role::findOrCreate('super_admin');
$user->assignRole('super_admin');

// All permission checks return true, no actual lookup needed
$user->hasPermissionTo('anything.at.all'); // true

use Scabarcas\LaravelPermissionsRedis\Cache\AuthorizationCacheManager;

$manager = app(AuthorizationCacheManager::class);

$manager->warmAll();            // Full cache rebuild (flush + warm)
$manager->rewarmAll();          // Rewarm without flushing
$manager->warmUser($userId);    // Warm specific user
$manager->warmRole($roleId);    // Warm specific role
$manager->evictUser($userId);   // Remove user from cache
$manager->evictRole($roleId);   // Remove role from cache

// Targeted warming after permission changes
$manager->warmPermissionAffectedUsers($permissionId);

use Scabarcas\LaravelPermissionsRedis\Traits\DispatchesPermissionEvents;

class User extends Authenticatable
{
    use HasRedisPermissions, DispatchesPermissionEvents;
}

// config/permissions-redis.php
'seed' => [
    'roles' => [
        'admin'  => ['users.*', 'posts.*', 'settings.update'],
        'editor' => ['posts.create', 'posts.edit', 'posts.delete'],
        'viewer' => ['posts.view', 'reports.view'],
    ],
    'permissions' => [
        'reports.export',  // standalone permissions not tied to any role
    ],
],

// config/permissions-redis.php
'model_morph_key_type' => env('PERMISSIONS_REDIS_MORPH_KEY_TYPE', 'int'),

// Works the same regardless of ID type
$user->assignRole('admin');
$user->hasPermissionTo('posts.create'); // true

// config/permissions-redis.php
'octane' => [
    'reset_on_request' => true,
],

// config/permissions-redis.php
'tenancy' => [
    'enabled'  => true,
    'resolver' => 'stancl', // or a custom class
],

namespace App\Tenancy;

class TenantResolver
{
    public function __invoke(): string|int|null
    {
        return session('tenant_id');
    }
}

'tenancy' => [
    'enabled'  => true,
    'resolver' => \App\Tenancy\TenantResolver::class,
],

// In a controller, checks Redis first, then PostPolicy::update()
$this->authorize('posts.edit', $post);

// In Blade, same behavior
@can('posts.edit', $post)
    <button>Edit</button>
@endcan

class PostPolicy
{
    // Only called if user does NOT have 'posts.edit' in Redis
    public function update(User $user, Post $post): bool
    {
        return $post->user_id === $user->id; // fallback: owners can edit
    }
}

Route::middleware(['auth:sanctum', 'permission:posts.create'])
    ->post('/posts', [PostController::class, 'store']);

Permission::findOrCreate('posts.create', 'web', 'content');
Permission::findOrCreate('posts.edit', 'web', 'content');
Permission::findOrCreate('users.manage', 'web', 'administration');

Permission::findOrCreate('api.access', 'api');
Role::findOrCreate('api_consumer', 'api');

$user->hasPermissionTo('api.access', 'api');
$user->hasRole('api_consumer', 'api');

$user->forGuard('api')->hasPermissionTo('api.access');
$user->forGuard('api')->getAllPermissions();
$user->forGuard('api')->getRoleNames();

enum Permission: string
{
    case CreatePost = 'posts.create';
    case EditPost   = 'posts.edit';
    case DeletePost = 'posts.delete';
}

$user->hasPermissionTo(Permission::EditPost);
$user->givePermissionTo(Permission::CreatePost, Permission::EditPost);

$user->hasPermissionTo('posts.edit');                       // true
$user->hasPermissionTo(Permission::EditPost);               // true (BackedEnum)
$user->hasAnyPermission('posts.edit', 'posts.delete');      // true (has at least one)
$user->hasAllPermissions('posts.edit', 'posts.delete');     // false (missing one)
$user->hasRole('admin');                                    // true
$user->hasRole(['admin', 'editor']);                         // true (has at least one)
$user->hasAnyRole('admin', 'editor');                       // true
$user->hasAllRoles('admin', 'editor');                      // false (missing one)

$user->getAllPermissions();
// Collection [PermissionDTO { name: 'posts.edit', group: 'content', guard: 'web' }, ...]

$user->getPermissionNames();            // Collection ['posts.edit', 'posts.create']
$user->getRoleNames();                  // Collection ['admin', 'editor']

$user->forGuard('api')->getRoleNames(); // Collection ['api_consumer']

// SQL reads (Eloquent relations), return Permission models, not DTOs.
// For admin screens and business logic, not hot authorization paths.
$user->getDirectPermissions();          // Collection [Permission { name: 'reports.export' }]
$user->getPermissionsViaRoles();        // Collection [Permission { name: 'posts.edit' }, ...]

$user->assignRole('admin', 'editor');           // additive
$user->syncRoles('editor');                     // replaces all, user now has only 'editor'
$user->removeRole('editor');                    // removes 'editor'

$user->givePermissionTo('reports.export');      // direct permission
$user->revokePermissionTo('reports.export');    // revoke
$user->syncPermissions('reports.view');         // replace all direct permissions
$user->syncPermissions(['reports.view']);       // array form works too

User::role('admin')->get();             // all admins
User::role(['admin', 'editor'])->get(); // users with admin OR editor
User::permission('posts.edit')->get();  // users who can edit posts (direct or via role)

$role = Role::findOrCreate('editor');
$role->syncPermissions('posts.create', 'posts.edit');    // replace (array form works too)
$role->givePermissionTo('posts.publish');                // additive
$role->revokePermissionTo('posts.publish');              // remove

$perm = Permission::findOrCreate('posts.create');                      // default guard 'web'
$perm = Permission::findOrCreate('api.access', 'api');                 // custom guard
$perm = Permission::findOrCreate('posts.edit', 'web', 'content');      // with group

$manager = app(AuthorizationCacheManager::class);

$manager->warmAll();                                // full rebuild
$manager->warmUser($user->id);                      // single user
$manager->evictUser($user->id);                     // remove from cache
$manager->warmPermissionAffectedUsers($perm->id);   // rewarm after manual DB change

try {
    // middleware check
} catch (UnauthorizedException $e) {
    $e->getStatusCode();     // 403
    $e->getMessage();        // 'User does not have the 

// Listen to events in your app
use Scabarcas\LaravelPermissionsRedis\Events\RolesAssigned;

Event::listen(RolesAssigned::class, function (RolesAssigned $event) {
    Log::info("Roles changed for user {$event->user->id}");
});

// Manually dispatch UserDeleted when deleting users
use Scabarcas\LaravelPermissionsRedis\Events\UserDeleted;

User::deleted(function (User $user) {
    event(new UserDeleted($user->id));
});

use Scabarcas\LaravelPermissionsRedis\Testing\WithPermissions;

class PostControllerTest extends TestCase
{
    use WithPermissions;

    public function test_admin_can_create_posts(): void
    {
        $user = User::factory()->create();

        // Seeds permissions + assigns them + acts as the user
        $this->actingAsWithPermissions($user, ['posts.create', 'posts.edit'])
            ->post('/posts', ['title' => 'Hello'])
            ->assertStatus(201);
    }

    public function test_editor_role_can_edit(): void
    {
        $user = User::factory()->create();

        // Seeds role + assigns it + acts as the user
        $this->actingAsWithRoles($user, ['editor'])
            ->put('/posts/1', ['title' => 'Updated'])
            ->assertOk();
    }
}

use Scabarcas\LaravelPermissionsRedis\Testing\WithPermissions;

uses(WithPermissions::class);

it('allows admins to manage users', function () {
    $user = User::factory()->create();

    $this->actingAsWithRoles($user, ['admin'])
        ->get('/admin/users')
        ->assertOk();
});

use Scabarcas\LaravelPermissionsRedis\Contracts\PermissionRepositoryInterface;
use Scabarcas\LaravelPermissionsRedis\Testing\InMemoryPermissionRepository;

// In your TestCase::setUp()
$this->app->singleton(
    PermissionRepositoryInterface::class,
    InMemoryPermissionRepository::class,
);

   // config/permissions-redis.php
   'redis_connection' => env('PERMISSIONS_REDIS_CONNECTION', 'default'),
   

   // This will NOT invalidate cache:
   Model::withoutEvents(fn () => $user->roles()->attach($roleId));

   // This WILL invalidate cache (use the trait method):
   $user->assignRole('admin');
   

   // Created with 'web' guard (default)
   Permission::findOrCreate('posts.edit');

   // Checking from 'api' guard, won't find it!
   $user->hasPermissionTo('posts.edit', 'api'); // false

   // Fix: create the permission for the correct guard
   Permission::findOrCreate('posts.edit', 'api');

   // Or use forGuard() to check explicitly
   $user->forGuard('web')->hasPermissionTo('posts.edit'); // true
   

   $role = Role::findOrCreate('editor');
   $role->syncPermissions(['posts.create']); // 'posts.edit' is not here
   $user->assignRole('editor');
   $user->hasPermissionTo('posts.edit'); // false, not in role
   

   return [
       // ...
       Scabarcas\LaravelPermissionsRedis\PermissionsRedisServiceProvider::class,
   ];
   
mermaid
flowchart TD
    A["hasPermissionTo('posts.edit')"] --> B{In-memory\ncache?}
    B -- "Hit" --> C["Return cached result"]
    B -- "Miss" --> D{"Redis\nSISMEMBER?"}
    D -- "Hit" --> E["Cache in memory\nand return"]
    D -- "Miss" --> F{"User cache\nexists in Redis?"}
    F -- "Yes" --> K{"Wildcard\nenabled?"}
    F -- "No (cold start)" --> H["AuthorizationCacheManager\n::warmUser()"]
    H --> I["Query DB:\ndirect perms + role perms"]
    I --> J["Write merged SETs\nto Redis"]
    J --> D

    K -- "No" --> L["Permission denied"]
    K -- "Yes" --> M["fnmatch() scan\nall user perms"]
    M -- "Match" --> N["Return true"]
    M -- "No match" --> L

bash
php artisan vendor:publish --provider="Scabarcas\LaravelPermissionsRedis\PermissionsRedisServiceProvider"
bash
php artisan migrate
bash
php artisan permissions-redis:warm
bash
   php artisan permissions-redis:warm-user {userId}
   
bash
   php artisan permissions-redis:warm-user {userId}
   
bash
   php artisan permissions-redis:stats
   
bash
   composer remove spatie/laravel-permission
   php artisan config:clear
   php artisan cache:clear
   php artisan route:clear
   
bash
   rm config/permission.php
   
bash
   grep -r "Spatie\\\\Permission" app/ config/ routes/ --
bash
   php artisan package:discover
   
bash
   php artisan vendor:publish --tag=permissions-redis-config
   php artisan vendor:publish --tag=permissions-redis-migrations