Oh Dear is the all-in-one monitoring tool for your entire website. We monitor uptime, SSL certificates, broken links, scheduled tasks and more. You'll get a notifications for us when something's wrong. All that paired with a developer friendly API and kick-ass documentation. O, and you'll also be able to create a public status page under a minute. Start monitoring using our free trial now.

Laravel Permission v7 has been launched

Original – by Freek Van der Herten – 3 minute read

Laravel's built-in authorization is great when permissions are defined in code. With gates and policies, you can write logic like this:

// Defined in code, requires a deploy to change
Gate::define('edit-posts', function (User $user) {
    return $user->is_admin;
});

But in some projects roles and permissions are dynamic: created by users, managed through an admin panel, or changed at runtime without deploying code. Our Laravel Permission package can help you dynamically create roles and permissions.

We just released v7 which doesn't bring any new features, but cleans up the internal code and modernizes it. Let me walk you through what the package can do.

Using the package

The package adds a HasRoles trait to your User model. From there, you can create roles and permissions, assign them, and check access:

use Spatie\Permission\Models\RoleModel;
use Spatie\Permission\Models\PermissionModel;

$role = RoleModel::create(['name' => 'editor']);
$permission = PermissionModel::create(['name' => 'edit posts']);

$role->givePermissionTo('edit posts');

$user->assignRole('editor');
$user->givePermissionTo('publish posts');

$user->hasRole('editor'); // true
$user->can('edit posts'); // true

Everything is stored in the database. Your users or admin panel can create new roles and permissions at runtime, no deploy needed.

The package ships with middleware to protect routes:

Route::group(['middleware' => ['role:editor']], function () {
    Route::get('/posts/create', [PostController::class, 'create']);
});

Route::group(['middleware' => ['permission:publish posts']], function () {
    Route::post('/posts/{post}/publish', [PostController::class, 'publish']);
});

In your Blade templates, you can use the @role and @can directives:

@role('editor')
    <a href="/posts/create">Write a new post</a>
@endrole

@can('publish posts')
    <button>Publish</button>
@endcan

All methods return the model instance, so you can chain calls together:

$user
    ->assignRole('editor')
    ->givePermissionTo('edit posts')
    ->givePermissionTo('publish posts');

$user->hasAllPermissions('edit posts', 'publish posts'); // true
$user->hasAnyPermission('delete posts', 'edit posts'); // true

What's new in v7

The package now requires PHP 8.4+ and Laravel 12+. We've renamed the model classes for clarity: Role is now RoleModel and Permission is now PermissionModel. The old names still work as aliases, so this won't break your existing code.

All method signatures are now fully type-safe, using union types and returning static for proper chaining. The internals have been rebuilt on top of our laravel-package-tools PackageServiceProvider.

public function assignRole(string|RoleModel ...$roles): static
public function givePermissionTo(string|PermissionModel ...$permissions): static
public function hasRole(string|RoleModel $role): bool

We've also rewritten the entire test suite in Pest. This makes it easy to test your own permission logic too:

use Spatie\Permission\Models\RoleModel;

it('can assign a role to a user', function () {
    $role = RoleModel::create(['name' => 'editor']);

    $this->user->assignRole($role);

    expect($this->user->hasRole('editor'))->toBeTrue();
});

it('can check permissions via role', function () {
    $this->user->assignRole('editor');

    expect($this->user->can('edit posts'))->toBeTrue();
    expect($this->user->can('delete posts'))->toBeFalse();
});

In closing

If you're coming from v6, the upgrade should be easy. The old class names still work as aliases, and the public API hasn't changed. Check out the upgrade guide for the full details.

You can find the code of the package on GitHub. We also have extensive docs on our website.

This is one of the many packages we've created at Spatie. If you want to support our open source work, consider picking up one of our paid products.

Stay up to date with all things Laravel, PHP, and JavaScript.

You can follow me on these platforms:

On all these platforms, regularly share programming tips, and what I myself have learned in ongoing projects.

Every month I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.