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

Database schema & key types

Five tables back the package. Table names come from table_names; column names are fixed:

TableColumnsKeys
permissionsid, name (unique), description (jsonb, nullable), timestampsAuto-incrementing id.
rolesid, name (unique), description (jsonb, nullable), timestampsAuto-incrementing id.
permission_rolepermission_id, role_idBoth foreign keys cascade on delete; primary key (permission_id, role_id).
model_rolesrole_id, model_type, model_idrole_id cascades on delete; index (model_id, model_type); primary key (role_id, model_id, model_type).
model_permissionspermission_id, model_type, model_idpermission_id cascades on delete; index (model_id, model_type); primary key (permission_id, model_id, model_type).

Holder links are polymorphic (model_type + model_id), so any Eloquent model can hold roles and permissions — not just users. Custom morph-map aliases are stored in the pivots as they are everywhere else in Laravel.

Holder key type

key_type describes the models that hold roles and permissions — never this package’s own tables, which always keep an auto-incrementing key. It types the model_id column on the two polymorphic pivots:

key_typemodel_id columnUse when your holders…
bigintunsignedBigIntegeruse Laravel’s default auto-incrementing keys (the default)
uuiduuiduse HasUuids
uliduliduse HasUlids

Set it before you publish and run the migrations — the schema freezes at release:

PERMISSIONS_KEY_TYPE=uuid
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Foundation\Auth\User as Authenticatable;
use RoundlyConsulting\Permissions\Concerns\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
    use HasUuids; // pairs with PERMISSIONS_KEY_TYPE=uuid
}

Unset or blank reads as bigint; an unrecognized value throws the toolkit’s InvalidConfigurationException rather than silently building bigint keys.

Hard deletes by design

Roles and permissions do not use soft deletes: the unique name index would clash with soft-deleted rows, and every pivot cascades on delete — removing a role or permission removes its grants with it.

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.