编程

Laravel Permission v7 发布

10 2026-02-16 01:04:00

当权限在代码中定义时,Laravel 内置的授权功能非常强大。借助门控和策略,你可以编写如下逻辑:

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

但在某些项目中,角色和权限是动态的:由用户创建、通过管理面板管理,或者在运行时无需部署代码即可更改。我们的 Laravel Permission 包可以帮助你动态创建角色和权限。

 v7 版本刚刚发布了,虽然没有带来任何新功能,但清理了内部代码并使其现代化。接下来,我将为你详细介绍该包的功能。

使用该包

该软件包用户模型添加了一个 HasRoles 特性。通过该特性,你可以创建角色和权限、分配角色和权限,并检查访问权限:

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

所有数据都存储在数据库中。用户或管理员面板可以在运行时创建新的角色和权限,无需部署。

该软件包附带用于保护路由的中间件:

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']);
});

在 Blade 模板中,你可以使用 @role@can 指令:

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

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

所有方法都返回模型实例,这样你就可以链式调用:

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

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

v7 版本新增内容

该包现在需要 PHP 8.4+ 和 Laravel 12+。为了更清晰地命名,新版本重命名了模型类:Role 现在是 RoleModelPermission 现在是 PermissionModel。旧名称仍然可以作为别名使用,因此不会破坏你现有的代码。

所有方法签名现在都完全类型安全,使用联合类型并返回 static 对象,以确保正确的链式调用。内部实现基于 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

另外新版本还用 Pest 重写了整个测试套件。这样也方便你测试自己的权限逻辑:

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();
});

小结

如果你是从 v6 版本升级而来,升级应该很容易。旧的类名仍然可以作为别名使用,公共 API 也未发生变化。请查看升级指南了解完整详情。

你可以在 GitHub 上找到该软件包的代码。官方网站上也提供了丰富的文档。

 

下一篇