Open source June 2025

Larallow

Larallow is a roles-and-permissions package for Laravel where permissions are declared in code, scoped to a tenant or resource, and granted to any actor model.

Spatie's package is excellent and covers the common case well. Larallow exists for the projects where scopes and multiple actor types are the point rather than an afterthought.

Installation

composer require edulazaro/larallow
php artisan vendor:publish --tag=larallow
php artisan migrate

Declaring permissions

Permissions are defined in a service provider, the way routes are, rather than inserted into a table.

use EduLazaro\Larallow\Permission;

Permission::create([
    'manage-office' => 'Manage office',
])->for(User::class)->on(Office::class);
Method Meaning
for() Which actor models may hold the permission
on() Which scope models it is granted within
implies() A broader handle automatically carries a narrower one
Permission::create('manage-clients')
    ->for(User::class)
    ->on([Office::class, Group::class])
    ->implies('handle-clients');

Handles can be plain strings or enum values. Labels can go through your translation layer, so a permission list renders in the user's language.

Granting

Add the traits to any actor model:

use EduLazaro\Larallow\Concerns\HasPermissions;
use EduLazaro\Larallow\Concerns\HasRoles;

class User extends Authenticatable
{
    use HasPermissions, HasRoles;
}

Granting takes a scope, so the same permission can be true in one office and false in another:

$user->allow('manage-office', $office);

Checking

There are two levels, and the difference matters:

$user->hasPermission('manage-office');                  // direct grants only
$user->permissions('manage-office')->on($office)->check(); // direct or via a role

In Blade:

@permissions('manage-office', $office)
    <button>Manage office</button>
@endpermissions

Roles

Roles live in the database and bundle permissions. A user is assigned roles, optionally within a scope.

use EduLazaro\Larallow\Models\Role;

$role = Role::create(['handle' => 'office-manager', 'name' => 'Office Manager']);
$role->addPermission('manage-office');

$user->assignRole($role, $office);

Tenant-owned roles

A role can belong to a tenant, so one workspace's "Office Manager" is not another's. A model that owns roles gets the IsRoleTenant trait. Role names carry their own translations without a second package.

Query scopes

User::withPermission('manage-office', $office);

Returns every user who can manage that office, implications included.

built and maintained by Edu Lazaro · MIT license