laravel-permission-development について
spatie/laravel-permission を使う Laravel 開発者向けの開発スキルです。ロールと権限の管理、認可チェック、ミドルウェア、Blade ディレクティブ、チーム設定を扱います。
主な機能
- 01ロールと権限の作成・割り当て
- 02Gate による権限チェック
- 03ルートミドルウェアと Blade ディレクティブ
- 04チーム単位の権限設定
- 05権限キャッシュと Seeder の管理
活用シーン
- 01ユーザーへのロールと権限の割り当て
- 02ルートや Blade ビューでの認可
- 03Super Admin とチーム権限の設定
- 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()を使用し、その後キャッシュをフラッシュします。