mcpField
L
laravel-permission-development

laravel-permission-development

github.com/spatie開発13.0k301 回インストール6 日前に更新
リポジトリ

laravel-permission-development について

spatie/laravel-permission を使う Laravel 開発者向けの開発スキルです。ロールと権限の管理、認可チェック、ミドルウェア、Blade ディレクティブ、チーム設定を扱います。

主な機能

  1. 01ロールと権限の作成・割り当て
  2. 02Gate による権限チェック
  3. 03ルートミドルウェアと Blade ディレクティブ
  4. 04チーム単位の権限設定
  5. 05権限キャッシュと Seeder の管理

活用シーン

  1. 01ユーザーへのロールと権限の割り当て
  2. 02ルートや Blade ビューでの認可
  3. 03Super Admin とチーム権限の設定
  4. 04ロールと権限の Seeder 作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/spatie/laravel-permission --skill laravel-permission-development

インストール後、Claude Code で/laravel-permission-developmentを入力して読み込まれたか確認します。

詳細

Laravel 権限開発

このスキルを使用する場面

spatie/laravel-permission を使用して、認可、ロール、権限、アクセス制御、ミドルウェアのガード、Blade の権限ディレクティブを扱う場合に、このスキルを使用します。

中核となる概念

  • ユーザーにはロールがあり、ロールには権限があり、アプリは権限をチェックします(ロールではありません)。
  • ユーザーに直接権限を付与するのはアンチパターンです。代わりに、ロールに権限を割り当てます。
  • すべての認可チェックには $user->can('permission-name') を使用します(Gate を介して Super Admin に対応します)。
  • HasRoles トレイト(HasPermissions を含む)を User モデルに追加します。

セットアップ

User モデルに HasRoles トレイトを追加します。

use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
}

ロールと権限の作成

use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

$role = Role::create(['name' => 'writer']);
$permission = Permission::create(['name' => 'edit articles']);

// findOrCreate is idempotent (safe for seeders)
$role = Role::findOrCreate('writer', 'web');
$permission = Permission::findOrCreate('edit articles', 'web');

ロールと権限の割り当て

// Assign roles to users
$user->assignRole('writer');
$user->assignRole('writer', 'admin');
$user->assignRole(['writer', 'admin']);
$user->syncRoles(['writer', 'admin']); // replaces all
$user->removeRole('writer');

// Assign permissions to roles (preferred)
$role->givePermissionTo('edit articles');
$role->givePermissionTo(['edit articles', 'delete articles']);
$role->syncPermissions(['edit articles', 'delete articles']);
$role->revokePermissionTo('edit articles');

// Reverse assignment
$permission->assignRole('writer');
$permission->syncRoles(['writer', 'editor']);
$permission->removeRole('writer');

ロールと権限のチェック

// Permission checks (preferred - supports Super Admin via Gate)
$user->can('edit articles');
$user->canAny(['edit articles', 'delete articles']);

// Direct package methods (bypass Gate, no Super Admin support)
$user->hasPermissionTo('edit articles');
$user->hasAnyPermission(['edit articles', 'publish articles']);
$user->hasAllPermissions(['edit articles', 'publish articles']);
$user->hasDirectPermission('edit articles');

// Role checks
$user->hasRole('writer');
$user->hasAnyRole(['writer', 'editor']);
$user->hasAllRoles(['writer', 'editor']);
$user->hasExactRoles(['writer', 'editor']);

// Get assigned roles and permissions
$user->getRoleNames();           // Collection of role name strings
$user->getPermissionNames();     // Collection of permission name strings
$user->getDirectPermissions();   // Direct permissions only
$user->getPermissionsViaRoles(); // Inherited via roles
$user->getAllPermissions();      // Both direct and inherited

クエリスコープ

$users = User::role('writer')->get();
$users = User::withoutRole('writer')->get();
$users = User::permission('edit articles')->get();
$users = User::withoutPermission('edit articles')->get();

ミドルウェア

bootstrap/app.php でミドルウェアのエイリアスを登録します。

->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'role' => \Spatie\Permission\Middleware\RoleMiddleware::class,
        'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class,
        'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class,
    ]);
})

ルートで使用します(OR ロジックにはパイプ | を使います)。

Route::middleware(['permission:edit articles'])->group(function () { ... });
Route::middleware(['role:manager|writer'])->group(function () { ... });
Route::middleware(['role_or_permission:manager|edit articles'])->group(function () { ... });

// With specific guard
Route::middleware(['role:manager,api'])->group(function () { ... });

単一の権限には、Laravel に組み込まれている can ミドルウェアも使用できます。

Route::middleware(['can:edit articles'])->group(function () { ... });

Blade ディレクティブ

@role(ロールベース)よりも @can(権限ベース)を優先します。

@can('edit articles')
    {{-- User can edit articles (supports Super Admin) --}}
@endcan

@canany(['edit articles', 'delete articles'])
    {{-- User can do at least one --}}
@endcanany

@role('admin')
    {{-- Only use for super-admin type checks --}}
@endrole

@hasanyrole('writer|admin')
    {{-- Has writer or admin --}}
@endhasanyrole

Super Admin

AppServiceProvider::boot() で Gate::before を使用します。

use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    Gate::before(function ($user, $ability) {
        return $user->hasRole('Super Admin') ? true : null;
    });
}

これにより、Super Admin に対して $user->can() と @can が常に true を返します。ほかのユーザーに対する通常のチェックを許可するには、false ではなく null を返す必要があります。

ポリシー

ポリシーメソッド内で $user->can() を使用して権限をチェックします。

class PostPolicy
{
    public function update(User $user, Post $post): bool
    {
        if ($user->can('edit all posts')) {
            return true;
        }

        return $user->can('edit own posts') && $user->id === $post->user_id;
    }
}

列挙型

enum RolesEnum: string
{
    case WRITER = 'writer';
    case EDITOR = 'editor';
}

enum PermissionsEnum: string
{
    case EDIT_POSTS = 'edit posts';
    case DELETE_POSTS = 'delete posts';
}

// Most methods accept enums directly
Permission::findOrCreate(PermissionsEnum::EDIT_POSTS, 'web');
$user->assignRole(RolesEnum::WRITER);
$user->hasRole(RolesEnum::WRITER);
$role->givePermissionTo(PermissionsEnum::EDIT_POSTS);
$user->hasPermissionTo(PermissionsEnum::EDIT_POSTS);

シーディング

シーディング時は、必ず権限キャッシュをフラッシュします。

class RolesAndPermissionsSeeder extends Seeder
{
    public function run(): void
    {
        // Reset cache
        app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();

        // Create permissions
        Permission::findOrCreate('edit articles', 'web');
        Permission::findOrCreate('delete articles', 'web');

        // Create roles and assign permissions
        Role::findOrCreate('writer', 'web')
            ->givePermissionTo(['edit articles']);

        Role::findOrCreate('admin', 'web')
            ->givePermissionTo(Permission::all());
    }
}

チーム(マルチテナンシー)

マイグレーションを実行する前に、config/permission.php で有効にします。

'teams' => true,

ミドルウェアでアクティブなチームを設定します。

setPermissionsTeamId($teamId);

チームを切り替える際は、キャッシュされたリレーションを解除します。

$user->unsetRelation('roles')->unsetRelation('permissions');

イベント

config/permission.php で有効にします。

'events_enabled' => true,

利用可能なイベント:Spatie\Permission\Events 名前空間の RoleAttachedEvent、RoleDetachedEvent、PermissionAttachedEvent、PermissionDetachedEvent。

パフォーマンス

  • 権限は自動的にキャッシュされます。パッケージのメソッドを使ってロールや権限を変更すると、キャッシュがフラッシュされます。
  • DB を直接操作した後は、手動でキャッシュをフラッシュします:app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions()
  • 一括シーディングでは、速度向上のために Permission::insert() を使用し、その後キャッシュをフラッシュします。

コメント