Weave 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 Permission Laravel Package

amir/laravel-permission

Role and permission management for Laravel apps, with migrations, middleware, Blade directives, and Eloquent traits for assigning roles and abilities to users.

View on GitHub
Deep Wiki
Context7

Getting Started

Before writing any application code, confirm what this package actually is. amir/laravel-permission is a small, low-adoption package (47 stars, no dependents) that overlaps in name — but not necessarily in API — with the far more common spatie/laravel-permission. Do not assume Spatie's method names, config keys, or table schema carry over. Open the repository README and src/ first and note the exact facade, trait, middleware alias, and config filename.

Minimal install path:

  1. composer require amir/laravel-permission
  2. Publish and inspect the package's config and migrations before running them — check the table names to avoid colliding with any existing roles/permissions tables.
  3. Run php artisan migrate.
  4. Add the package's trait to your User model. The trait name is the single most important thing to verify; it is what gives you roles, permissions, and the check methods.
  5. Seed a small, realistic permission set rather than creating records by hand.

First use case: gate one route behind one permission and prove the whole loop works end to end — seed a posts.edit permission, attach it to an editor role, assign that role to a user, then protect the route with the package's middleware and assert a 403 for a plain user. If that single flow is clean, the package is viable for the rest of the app.

Where to look first, in order: the migration stubs (schema shape tells you whether roles and permissions are many-to-many, whether teams/scopes exist, and whether there is a pivot for direct user permissions), the config file (guard names, cache settings, table names), then the service provider (what middleware aliases and Blade directives are registered).

Implementation Patterns

Seed permissions as a fixed catalogue, roles as config. Keep permission names in a single PHP array or enum so they are greppable and testable. Roles become seeders that reference those names. This makes permission drift visible in code review instead of discovered in production.

Prefer permission checks in code, role checks in administration. Call the permission check (can, hasPermissionTo, or whatever the package exposes) in controllers, policies, and Blade. Check roles only in admin screens that assign them. Role names change with org structure; permission names should be stable and tied to features.

Wrap the package in one application-level abstraction. A Gate::before hook for super-admins and a thin Permissions helper service give you a single place to swap the package out. Given the low adoption rate and the risk of the maintainer going quiet, this is not over-engineering — it is the difference between a one-evening migration and a two-week one.

// AppServiceProvider::boot()
Gate::before(function ($user, $ability) {
    return $user->isSuperAdmin() ? true : null;
});

Route middleware for coarse gates, policies for row-level rules. Use the package's permission middleware for posts.create, and keep ownership/state logic in policies. Mixing the two leads to permission names like posts.edit.own and an explosion of the catalogue.

Multi-guard apps need explicit guard wiring. If you have web and admin guards with separate user models, verify how the package resolves the guard — usually via config guard_name or a model property. Set it per model; do not rely on a default that silently uses web.

Test the permission layer directly. Use RefreshDatabase, call the seeders in setUp, and assert both the positive and negative path. A test that only asserts "editor can edit" will not catch a super-admin bypass that returns true for everything.

Gotchas and Tips

Name collision with Spatie. The most likely day-to-day failure is a developer (or an LLM, or a tutorial) applying Spatie idioms to this package. The middleware alias permission:, the trait name, the HasRoles interface, and the cache-flush command may all differ. Put a one-line note in your team README stating which package is installed and which method names are canonical.

Permission caching is the classic trap. If the package caches the user's permission set (most do), a role change made directly in the database or via a seeder will not appear until the cache is cleared or the user re-authenticates. Always mutate permissions through the package's API, and if you must touch the tables directly, flush the cache in the same deployment step. Write down the flush command — you will need it at 2 a.m.

Guard name mismatches produce silent denials. A role created with guard_name = 'web' will never satisfy a check made on the admin guard. When seeding, set the guard explicitly rather than trusting the default.

Check migration indexes. A package this small may not index the pivot tables well. On a users table above a few hundred thousand rows, an unindexed model_has_roles join can dominate request time. Add indexes if they are missing; it is a safe, non-breaking change.

Eager-load before rendering lists. Rendering a user index page that calls can() per row will N+1 on roles and permissions. Eager-load the relations the package defines, or pre-compute a permission array per user.

Pin the version. With a single maintainer and infrequent releases, a ^1.0 constraint combined with a composer update during an unrelated deployment is a real risk. Pin to the exact minor and review the changelog before bumping.

Extension points are thin, so keep your own seam. If the package lacks teams, scopes, or wildcard permissions, do not patch vendor/. Fork it, or implement the missing layer in your own Gate::before / policy logic and treat the package purely as storage for role-permission assignments.

Have an exit plan. Before committing, write the users, roles, permissions, and pivot tables to a short schema note and confirm the data is portable. Spatie uses similar table names; if the schemas line up, migrating later is mostly a code swap behind your abstraction layer, not a data migration.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console