この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: 管理者ユーザーの作成/判定と管理画面
SEOタイトル: Laravel で管理者ユーザーを作る方法 (is_admin / roles / Gate / Middleware

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li><strong>最小実装</strong>: <code>users</code> テーブルに <code>is_admin</code> カラムを追加</li><li><strong>柔軟な実装</strong>: <code>roles</code> / <code>role_user</code> テーブルで多対多 → Spatie Laravel-Permission</li><li><strong>判定</strong>: <code>Gate::define</code> + <code>@can("admin")</code> Blade ディレクティブ</li><li><strong>ルート保護</strong>: <code>middleware(["auth", "admin"])</code></li><li><strong>管理画面</strong>: Filament / Backpack / Voyager から選ぶ</li></ul></td></tr></table>
<h2>最小実装: is_admin カラム</h2>

<p>Laravel で 1 種類しか管理者がいない(一般 / 管理者の 2 値)場合の最速パターン:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// database/migrations/xxxx_add_is_admin_to_users.php
public function up(): void
{
    Schema::table(&apos;users&apos;, function (Blueprint $table) {
        $table->boolean(&apos;is_admin&apos;)->default(false)->after(&apos;email&apos;);
    });
}

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

    public function isAdmin(): bool
    {
        return (bool) $this->is_admin;
    }
}</code></pre>
<h2>判定: Gate</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// app/Providers/AuthServiceProvider.php
public function boot(): void
{
    Gate::define(&apos;admin&apos;, function (User $user) {
        return $user->isAdmin();
    });

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

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

// もしくは
if (Gate::allows(&apos;admin&apos;)) { ... }
if ($request->user()->can(&apos;admin&apos;)) { ... }</code></pre>
<h2>判定: Blade @can</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">{{-- resources/views/layouts/app.blade.php --}}
<nav>
    <a href="/">トップ</a>
    @auth
        <a href="/mypage">マイページ</a>
        @can(&apos;admin&apos;)
            <a href="/admin">管理画面</a>
        @endcan
        <form action="/logout" method="post">
            @csrf
            <button>ログアウト</button>
        </form>
    @else
        <a href="/login">ログイン</a>
    @endauth
</nav></code></pre>
<h2>ルート保護: Middleware</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash">php artisan make:middleware AdminMiddleware</code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// app/Http/Middleware/AdminMiddleware.php
public function handle(Request $request, Closure $next): Response
{
    if (!$request->user() || !$request->user()->isAdmin()) {
        abort(403, &apos;管理者権限が必要です&apos;);
    }
    return $next($request);
}

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

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

// routes/web.php
Route::middleware([&apos;auth&apos;, &apos;admin&apos;])->prefix(&apos;admin&apos;)->group(function () {
    Route::get(&apos;/&apos;,          [AdminController::class, &apos;index&apos;]);
    Route::resource(&apos;users&apos;, \App\Http\Controllers\Admin\UserController::class);
});</code></pre>
<h2>多役割パターン: roles テーブル</h2>

<p>管理者・編集者・閲覧者など複数の役割が必要なら、<strong>roles</strong> + <strong>role_user</strong> の多対多にする:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// migration
Schema::create(&apos;roles&apos;, function (Blueprint $table) {
    $table->id();
    $table->string(&apos;name&apos;)->unique();   // admin, editor, viewer
    $table->string(&apos;display_name&apos;);
    $table->timestamps();
});

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

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

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

public function isAdmin(): bool
{
    return $this->hasRole(&apos;admin&apos;);
}</code></pre>
<h2>Spatie Laravel-Permission (推奨)</h2>

<p>自前で roles/permissions を作るより<strong>Spatie のパッケージ</strong>が圧倒的に楽:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash">composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate</code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// User モデル
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable {
    use HasRoles;
}

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

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

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

// Middleware
Route::middleware([&apos;role:admin&apos;])->group(...);
Route::middleware([&apos;permission:edit articles&apos;])->group(...);</code></pre>
<h2>管理者アカウントの作成 (Seeder)</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// database/seeders/AdminUserSeeder.php
public function run(): void
{
    User::firstOrCreate(
        [&apos;email&apos; => &apos;admin@example.com&apos;],
        [
            &apos;name&apos;     => &apos;Admin&apos;,
            &apos;password&apos; => bcrypt(&apos;S3curePassw0rd!&apos;),
            &apos;is_admin&apos; => true,
        ]
    );
}

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

// 実行
// php artisan db:seed
// 本番では Artisan コマンド経由がおすすめ</code></pre>
<h2>管理画面パッケージ比較</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>パッケージ</th><th>特徴</th><th>向いてる用途</th></tr></thead>
<tbody>
<tr><td><strong>Filament</strong></td><td>Livewire ベース。最新・高機能。Resource 自動生成</td><td>新規プロジェクト・複雑な管理画面</td></tr>
<tr><td><strong>Laravel Nova</strong></td><td>公式有償。$199/site。安定</td><td>商用・サポート重視</td></tr>
<tr><td><strong>Backpack</strong></td><td>有償あり。CRUD パネル特化</td><td>シンプルな CRUD 中心</td></tr>
<tr><td><strong>Voyager</strong></td><td>無償。GUI で完結。メンテ停滞気味</td><td>WordPress ライクな感覚</td></tr>
<tr><td><strong>自前で作る</strong></td><td>Bootstrap / Tailwind + Blade</td><td>カスタム要件が強い場合</td></tr>
</tbody>
</table>

<h2>Filament を入れる例</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash">composer require filament/filament
php artisan filament:install --panels
php artisan make:filament-user</code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// 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();
    }
}</code></pre>
<h2>FAQ</h2>

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

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

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