NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Require the package. The service provider and the Permissions facade alias are auto-discovered — no manual registration:

composer require roundly-consulting/permissions-for-laravel

Publish the config before anything else. The holder key type is baked into the schema, so decide between bigint, UUID and ULID keys now (see Database schema & key types):

php artisan vendor:publish --tag="permissions-config"

Then publish and run the migrations:

php artisan vendor:publish --tag="permissions-migrations"
php artisan migrate

Publish-only migrations

The package never loads its migrations, so php artisan migrate creates nothing until you have published them into your app’s database/migrations. The eight migrations land timestamped and in dependency order — permissions, roles, permission_role, model_roles, model_permissions, then the three 2.1 ones: add_owner_to_roles_table, create_role_assignments_table and create_permission_assignments_table — and publishing again overwrites them in place rather than adding a second copy.

The only publish tags the package exposes are permissions-config and permissions-migrations.

Upgrading from 2.0

Nothing changes until you opt in: with permissions.assignments.enabled off, 2.1 sends exactly the 2.0 queries and never reads the new tables or columns, so you can update before you migrate. To use scoped and time-boxed grants or owned roles:

  • If your scope models — projects, teams, tenants — use another key type than your holders, set permissions.assignments.scope_key_type first.
  • Publish the migrations again and migrate: the three new files are added, the five you have are overwritten in place. add_owner_to_roles_table drops the roles name index by its Laravel-derived name (<roles table>_name_unique) after creating the new one — if you renamed that index by hand, adjust the published migration.
  • Set PERMISSIONS_ASSIGNMENTS=true. There is no data migration: your 2.0 grants keep working as unscoped, permanent grants.
  • Optionally call Permissions::forgetScope() from your scope models’ deleting hooks and schedule permissions:prune-expired — see Scoped & time-boxed grants.

Next steps

  • Add the HasRoles trait to your user model.
  • Create your roles and permissions — ideally in an idempotent seeder.
  • Protect routes with the native can: middleware.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.