Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Acl Laravel Package

kodeine/laravel-acl

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require kodeine/laravel-acl
    

    Run migrations:

    php artisan migrate
    

    Publish config (optional):

    php artisan vendor:publish --provider="Kodeine\Acl\AclServiceProvider"
    
  2. First Use Case:

    • Define Roles & Permissions:

      // In a seeder or migration
      use Kodeine\Acl\Models\Role;
      use Kodeine\Acl\Models\Permission;
      
      $adminRole = Role::create(['name' => 'admin']);
      $userRole  = Role::create(['name' => 'user']);
      
      $createPostPermission = Permission::create(['name' => 'posts.create']);
      $editPostPermission   = Permission::create(['name' => 'posts.edit']);
      
      $adminRole->attachPermission($createPostPermission);
      $adminRole->attachPermission($editPostPermission);
      
    • Assign Roles to Users:

      $user = User::find(1);
      $user->attachRole($adminRole);
      
    • Protect Routes:

      Route::get('/admin/dashboard', function () {
          return view('admin.dashboard');
      })->middleware('can:posts.create'); // Requires 'posts.create' permission
      
    • Protect Controller Methods:

      use Kodeine\Acl\Middleware\AclMiddleware;
      
      class PostController extends Controller
      {
          public function __construct()
          {
              $this->middleware('can:posts.create')->only(['store']);
              $this->middleware('can:posts.edit')->only(['edit', 'update']);
          }
      }
      
  3. Quick Check: Use Tinker to verify permissions:

    php artisan tinker
    
    $user = User::find(1);
    $user->can('posts.create'); // Returns boolean
    

Implementation Patterns

Core Workflows

  1. Role-Permission Assignment:

    • Bulk Attach:
      $role = Role::find(1);
      $permissions = Permission::whereIn('name', ['posts.create', 'posts.edit'])->get();
      $role->attachPermissions($permissions);
      
    • Detach:
      $role->detachPermission($editPostPermission);
      
  2. Dynamic Permission Checks:

    • Middleware:
      Route::get('/admin/posts', function () {
          return view('posts.index');
      })->middleware('can:posts.index');
      
    • Policy Integration (Laravel 5.5+):
      use Kodeine\Acl\Policies\AclPolicy;
      
      class PostPolicy extends AclPolicy
      {
          public function viewAny(User $user)
          {
              return $user->can('posts.index');
          }
      }
      
  3. CRUD Controller Protection:

    • Base Controller:
      use Kodeine\Acl\Traits\AclCrudTrait;
      
      class PostController extends Controller
      {
          use AclCrudTrait;
      
          protected $permissionPrefix = 'posts';
          protected $crudPermissions = ['index', 'create', 'store', 'edit', 'update', 'destroy'];
      }
      
    • Automatically maps methods to permissions (e.g., index()posts.index).
  4. User-Specific Checks:

    • In Blade:
      @can('posts.create')
          <a href="{{ route('posts.create') }}">Create Post</a>
      @endcan
      
    • In Controllers:
      if ($user->can('posts.destroy')) {
          $post->delete();
      }
      
  5. Role-Based Redirects:

    • Middleware for Role Checks:
      Route::get('/admin', function () {
          return view('admin.dashboard');
      })->middleware('role:admin');
      

Integration Tips

  1. Seeding Roles/Permissions:

    • Use a RoleSeeder to predefine roles and permissions:
      public function run()
      {
          $adminRole = Role::create(['name' => 'admin']);
          $userRole  = Role::create(['name' => 'user']);
      
          Permission::create(['name' => 'posts.*'])->roles()->attach($adminRole);
          Permission::create(['name' => 'users.manage'])->roles()->attach($adminRole);
      }
      
  2. Wildcard Permissions:

    • Use * for bulk permission assignment:
      $adminRole->attachPermission(Permission::create(['name' => 'posts.*']));
      
    • Grants access to all posts.* permissions (e.g., posts.create, posts.edit).
  3. Custom Permission Logic:

    • Extend Kodeine\Acl\Contracts\Permission for custom logic:
      class CustomPermission implements Permission
      {
          public function userCan(User $user, $ability)
          {
              // Custom logic here
              return $user->isAdmin();
          }
      }
      
  4. API Resource Protection:

    • Protect API routes with can middleware:
      Route::apiResource('posts', PostController::class)->middleware('can:posts.*');
      
  5. Caching Permissions:

    • Enable caching in config/acl.php:
      'cache' => [
          'enabled' => true,
          'driver'  => 'file', // or 'redis', 'database'
      ],
      
    • Reduces database queries for frequent permission checks.

Gotchas and Tips

Pitfalls

  1. Permission Caching Issues:

    • Problem: Cached permissions may not update immediately after role/permission changes.
    • Fix: Clear the cache:
      php artisan cache:clear
      
      Or manually clear the ACL cache:
      \Kodeine\Acl\Facades\Acl::clearCache();
      
  2. Wildcard Permission Conflicts:

    • Problem: posts.* might override more specific permissions (e.g., posts.create).
    • Fix: Ensure wildcard permissions are attached to roles after specific permissions.
  3. Middleware Order Matters:

    • Problem: can middleware must run after auth middleware.
    • Fix: Define middleware in app/Http/Kernel.php:
      protected $middleware = [
          // ...
          \Illuminate\Auth\Middleware\Authenticate::class,
          \Kodeine\Acl\Middleware\AclMiddleware::class,
      ];
      
  4. Mass Assignment Risks:

    • Problem: Directly attaching permissions/roles without validation.
    • Fix: Use syncPermissions/syncRoles instead of attach to avoid duplicates:
      $role->syncPermissions([$permission1, $permission2]);
      
  5. Database Schema Changes:

    • Problem: Migrations may fail if the acl_roles, acl_permissions, or pivot tables are manually altered.
    • Fix: Always run php artisan migrate after updating the package.

Debugging

  1. Permission Check Logging:

    • Enable debug mode in config/acl.php:
      'debug' => true,
      
    • Logs permission checks to storage/logs/laravel.log.
  2. Common Errors:

    • Class 'Kodeine\Acl\Models\Role' not found:
      • Ensure the service provider is registered in config/app.php.
    • Call to undefined method:
      • Verify you’re using the correct package version (v2.x for Laravel 9+).
    • Middleware not working:
      • Check Route::middleware() vs. Route::group(['middleware' => ...]).
  3. Permission Hierarchy Issues:

    • Use Acl::getUserPermissions($user) to inspect a user’s permissions:
      $permissions = \Kodeine\Acl\Facades\Acl::getUserPermissions(auth()->user());
      dd($permissions);
      

Extension Points

  1. Custom Permission Providers:

    • Implement Kodeine\Acl\Contracts\PermissionProvider to fetch permissions from external sources (e.g., API):
      class ApiPermissionProvider implements PermissionProvider
      {
          public function getPermissions()
          {
              return Cache::remember('api-permissions', 60, function () {
                  return Http::get('https://api.example.com/permissions')->json();
              });
          }
      }
      
    • Register in config/acl.php:
      'permission_provider' => \App\Providers\ApiPermissionProvider::class,
      
  2. Event Listeners:

    • Listen for role/permission changes:
      // In EventServiceProvider
      protected $listen = [
          'Kodeine\Acl\Events\PermissionAttached' => [
              \App\Listeners\LogPermissionChange::class,
          ],
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope
nawasara/auth-primitives
adhocrat-io/arkhe-main
make-dev/orca-harpoon
itsemon245/lamet
baks-dev/dashboard
amoifr/pickle-panther-bundle
make-dev/orca
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle