23.

Laravel で管理者ユーザーを作る方法 (is_admin / roles / Gate / Middleware

編集
この記事の要点
  • 最小実装: users テーブルに is_admin カラムを追加
  • 柔軟な実装: roles / role_user テーブルで多対多 → Spatie Laravel-Permission
  • 判定: Gate::define + @can("admin") Blade ディレクティブ
  • ルート保護: middleware(["auth", "admin"])
  • 管理画面: Filament / Backpack / Voyager から選ぶ

最小実装: is_admin カラム

Laravel で 1 種類しか管理者がいない(一般 / 管理者の 2 値)場合の最速パターン:

// database/migrations/xxxx_add_is_admin_to_users.php
public function up(): void
{
    Schema::table('users', function (Blueprint $table) {
        $table->boolean('is_admin')->default(false)->after('email');
    });
}

// User モデル
class User extends Authenticatable
{
    protected $casts = [
        'is_admin' => 'boolean',
    ];

    public function isAdmin(): bool
    {
        return (bool) $this->is_admin;
    }
}

判定: Gate

// app/Providers/AuthServiceProvider.php
public function boot(): void
{
    Gate::define('admin', function (User $user) {
        return $user->isAdmin();
    });

    Gate::define('manage-articles', function (User $user) {
        return $user->isAdmin() || $user->hasRole('editor');
    });
}

// コントローラで利用
public function destroy(Article $article)
{
    Gate::authorize('admin');  // 失敗時 403
    $article->delete();
    return redirect('/admin/articles');
}

// もしくは
if (Gate::allows('admin')) { ... }
if ($request->user()->can('admin')) { ... }

判定: Blade @can

{{-- resources/views/layouts/app.blade.php --}}

ルート保護: Middleware

php artisan make:middleware AdminMiddleware
// app/Http/Middleware/AdminMiddleware.php
public function handle(Request $request, Closure $next): Response
{
    if (!$request->user() || !$request->user()->isAdmin()) {
        abort(403, '管理者権限が必要です');
    }
    return $next($request);
}

// app/Http/Kernel.php (Laravel 10 まで)
protected $middlewareAliases = [
    'admin' => \App\Http\Middleware\AdminMiddleware::class,
];

// bootstrap/app.php (Laravel 11+)
->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'admin' => \App\Http\Middleware\AdminMiddleware::class,
    ]);
})

// routes/web.php
Route::middleware(['auth', 'admin'])->prefix('admin')->group(function () {
    Route::get('/',          [AdminController::class, 'index']);
    Route::resource('users', \App\Http\Controllers\Admin\UserController::class);
});

多役割パターン: roles テーブル

管理者・編集者・閲覧者など複数の役割が必要なら、roles + role_user の多対多にする:

// migration
Schema::create('roles', function (Blueprint $table) {
    $table->id();
    $table->string('name')->unique();   // admin, editor, viewer
    $table->string('display_name');
    $table->timestamps();
});

Schema::create('role_user', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->foreignId('role_id')->constrained()->cascadeOnDelete();
    $table->primary(['user_id', 'role_id']);
});

// User モデル
public function roles(): BelongsToMany
{
    return $this->belongsToMany(Role::class);
}

public function hasRole(string $name): bool
{
    return $this->roles->contains('name', $name);
}

public function isAdmin(): bool
{
    return $this->hasRole('admin');
}

Spatie Laravel-Permission (推奨)

自前で roles/permissions を作るよりSpatie のパッケージが圧倒的に楽:

composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
// User モデル
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable {
    use HasRoles;
}

// 役割と権限の作成
$role = Role::create(['name' => 'admin']);
$permission = Permission::create(['name' => 'edit articles']);
$role->givePermissionTo($permission);

// 付与
$user->assignRole('admin');
$user->givePermissionTo('edit articles');

// 判定
$user->hasRole('admin');
$user->can('edit articles');

// Middleware
Route::middleware(['role:admin'])->group(...);
Route::middleware(['permission:edit articles'])->group(...);

管理者アカウントの作成 (Seeder)

// database/seeders/AdminUserSeeder.php
public function run(): void
{
    User::firstOrCreate(
        ['email' => 'admin@example.com'],
        [
            'name'     => 'Admin',
            'password' => bcrypt('S3curePassw0rd!'),
            'is_admin' => true,
        ]
    );
}

// DatabaseSeeder.php
$this->call(AdminUserSeeder::class);

// 実行
// php artisan db:seed
// 本番では Artisan コマンド経由がおすすめ

管理画面パッケージ比較

パッケージ特徴向いてる用途
FilamentLivewire ベース。最新・高機能。Resource 自動生成新規プロジェクト・複雑な管理画面
Laravel Nova公式有償。$199/site。安定商用・サポート重視
Backpack有償あり。CRUD パネル特化シンプルな CRUD 中心
Voyager無償。GUI で完結。メンテ停滞気味WordPress ライクな感覚
自前で作るBootstrap / Tailwind + Bladeカスタム要件が強い場合

Filament を入れる例

composer require filament/filament
php artisan filament:install --panels
php artisan make:filament-user
// User モデルに FilamentUser を実装
use Filament\Models\Contracts\FilamentUser;
use Filament\Panel;

class User extends Authenticatable implements FilamentUser
{
    public function canAccessPanel(Panel $panel): bool
    {
        return $this->isAdmin();
    }
}

FAQ

Q: is_adminroles どちらを使うべき?
A: ユーザー数少 + 役割 2 種類なら is_admin。役割が増える / 権限が細かいなら Spatie 一択。

Q: 管理画面の URL は隠すべき?
A: /admin 自体は隠しても効果薄。強パスワード + 2FA + IP 制限を組み合わせるのが本筋。

Q: 管理者の操作ログを残したい
A: Spatie laravel-activitylog パッケージで Eloquent モデルの変更を自動記録。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 環境構築とプロジェクト/アプリの作成
  2. MVC(MVT)のそれぞれの使い方と説明
  3. データベースへの接続と操作
  4. Django Administration
  5. git管理
  6. エラー一覧
  7. バージョンの確認方法
  8. ログ出力方法
  9. SQLのログ出力方法
  10. ログのローテート設定
  11. settings.pyの定数にアクセスする方法
  12. 本番環境へのインストールとアプリのデプロイ(apache編)
  13. 本番環境へのインストールとアプリのデプロイ(nginx編)
  14. djangoアプリの本番の開始URLを変更する
  15. 静的(static)ファイルの置き場所と読み込み(画像、css、js )
  16. CSRFトークンをAjaxで使用する方法
  17. ajaxの使用例(POST編)
  18. ファイルのアップロードとファイルの名前
  19. クイックスタート/チュートリアル
  20. ログイン機能
  21. テンプレート側のログイン判定
  22. ビュー側のログイン判定
  23. 管理者ユーザーの作成/判定と管理画面
  24. モデルのjson化とレスポンス
  25. runserverでポートを指定する方法
  26. cronによるバッチ実行
  27. テンプレートで利用する共通のcontextを定義する方法
  28. プログラムが本番サーバーで反映されない場合の対処法
  29. APIの作成
  30. cron用コマンド・ファイルの作成