【第四弾】Laravel入門資料
- コース紹介
- Windows環境構築
- Mac環境構築
- Laravelとは
- ルーティング
- ビュー
- コントローラ
- マイグレーション
- モデル
- ここまでの知識の実践
- 検索・フィルタ
- ソフトデリート
- ページネーション
- 画像アップロード
- 認証ライブラリ
- 認証実装
- ミドルウェア・ロール
- 総合実践
📚 Laravel公式ドキュメント - Middleware / Authorization
https://laravel.com/docs/12.x/middleware https://laravel.com/docs/12.x/authorization
💡 この講座では、上記の公式ドキュメントを基に解説していきます。
公式ドキュメントは初学者には内容が難しいため、エッセンスを優しく噛み砕いて解説していきます。
ミドルウェアと権限管理
認証機能だけでは不十分です。誰が何をできるかを管理する権限管理(認可)が必要です。
この章では、ミドルウェアとロールを使った権限管理を学びます。
認証と認可の違い
前章で学んだのは認証(Authentication)です。
この章で学ぶのは認可(Authorization)です。
認証(Authentication)
「あなたは誰ですか?」を確認すること。
ログイン機能がこれにあたります。
// 認証:ログインしているか確認
if (auth()->check()) {
echo 'ログインしています';
}
// 誰がログインしているか
echo auth()->user()->name; // 「田中太郎」
認可(Authorization)
「あなたには権限がありますか?」を確認すること。
管理者のみアクセス可能なページを作る機能がこれにあたります。
// 認可:管理者権限を持っているか確認
if (auth()->user()->isAdmin()) {
echo '管理者です';
}
// 特定のロールを持っているか
if (auth()->user()->hasRole('admin')) {
echo '管理者権限があります';
}
具体例で理解しよう
会社のオフィスに例えると:
-
認証: 社員証でゲートを通る
→ 「あなたは社員である」ことを確認 -
認可: 役職によって入れる部屋が異なる
→ 「一般社員は会議室Aにアクセスできるが、役員会議室には入れない」
Webアプリケーションの例
| ページ | 認証 | 認可 |
|---|---|---|
| トップページ | 不要 | 不要 |
| ダッシュボード | 必要(ログイン必須) | 不要 |
| 記事編集 | 必要(ログイン必須) | 必要(編集者または管理者) |
| ユーザー管理 | 必要(ログイン必須) | 必要(管理者のみ) |
✅ 認証と認可の違いが理解できました!
ミドルウェアの仕組み
ミドルウェアは、コントローラーが実行される前にチェックを行う「番人」のような仕組みです。
ミドルウェアファイルの構造
まず、ミドルウェアファイルがどう書かれているか見てみましょう。
// app/Http/Middleware/Authenticate.php (Laravel標準のミドルウェア)
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class Authenticate
{
public function handle(Request $request, Closure $next)
{
// ログインしているかチェック
if (!auth()->check()) {
// ログインしていない → ログインページへリダイレクト
return redirect('/login');
}
// ログインしている → 次の処理(コントローラー)へ進む
return $next($request);
}
}
📝 コードの構造
- • ミドルウェアは必ず
handle()メソッドを持つ - • 第1引数
$request: ユーザーからのリクエスト情報 - • 第2引数
$next: 次の処理(コントローラー)を実行する関数
$next($request) の意味
ミドルウェアの2つの選択肢:
ユーザーがアクセス
↓
[ミドルウェアの handle() メソッドが実行される]
↓
条件チェック
↓
✅ OK → return $next($request); ← コントローラーへ進む
❌ NG → return redirect('/login'); ← ここで処理を止める
💡 重要ポイント
- •
return $next($request);→ 次の処理(コントローラー)へ進む - •
return redirect();→ 処理を止めてリダイレクト - •
return abort(403);→ 処理を止めてエラー表示
なぜ $next を使うの?
Laravelのミドルウェアは必ず $next($request) を使う設計です。
これは「次に何が実行されるか(別のミドルウェアかコントローラーか)をミドルウェア自身は知らない」ためです。
$next($request) で次に渡すのが標準的な書き方です。
具体例: 管理者チェックのミドルウェア
// app/Http/Middleware/IsAdmin.php
class IsAdmin
{
public function handle(Request $request, Closure $next)
{
// 1. ログインしているかチェック
if (!auth()->check()) {
return redirect('/login'); // ← ここで止まる
}
// 2. 管理者かチェック
if (!auth()->user()->isAdmin()) {
return abort(403); // ← ここで止まる
}
// 3. 両方OKならコントローラーへ
return $next($request); // ← コントローラー実行
}
}
📝 補足: レスポンス後の処理も可能
ミドルウェアはレスポンスを返した後の処理も書けます(例: アクセスログの記録)。
ただし今回は使わないので、「リクエスト前のチェック」だけ覚えておけばOKです。
public function handle(Request $request, Closure $next)
{
// リクエスト前の処理(今回使う)
$response = $next($request); // コントローラー実行
// レスポンス後の処理(今回は使わない)
// 例: Log::info('アクセスログ');
return $response;
}
Laravelの標準ミドルウェア
| ミドルウェア | 役割 |
|---|---|
auth |
ログインしているかチェック(認証) |
guest |
ログインしていないかチェック |
verified |
メール認証済みかチェック |
throttle |
レート制限(アクセス回数制限) |
authミドルウェアの使い方
// routes/web.php
// 方法1: 個別のルートに適用
Route::get('/dashboard', [DashboardController::class, 'index'])
->middleware('auth');
// 方法2: 複数のルートにまとめて適用
Route::middleware(['auth'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
Route::get('/profile', [ProfileController::class, 'show']);
Route::get('/settings', [SettingsController::class, 'index']);
});
// 方法3: コントローラーで適用
class DashboardController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('dashboard');
}
}
authミドルウェアの動き:
- ログインしている → コントローラー処理を続行
- ログインしていない →
/loginにリダイレクト
✅ ミドルウェアの仕組みが理解できました!
ロールテーブルの設計
まずは、usersテーブルにroleカラムを追加するシンプルな方法を学びます。
ステップ1: マイグレーション作成
# マイグレーション作成
php artisan make:migration add_role_to_users_table
// database/migrations/xxxx_add_role_to_users_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->enum('role', ['admin', 'user'])->default('user')->after('name');
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('role');
});
}
};
# マイグレーション実行
php artisan migrate
想定するロール:
'user'- 一般ユーザー(デフォルト)'admin'- 管理者(全ての操作が可能)
ステップ2: Userモデルにメソッド追加
// app/Models/User.php
class User extends Authenticatable
{
protected $fillable = [
'name',
'email',
'password',
'role', // ← 追加
];
/**
* 管理者かどうか
*/
public function isAdmin(): bool
{
return $this->role === 'admin';
}
/**
* 特定のロールを持っているかチェック
*/
public function hasRole(string $role): bool
{
return $this->role === $role;
}
/**
* いずれかのロールを持っているかチェック
*/
public function hasAnyRole(array $roles): bool
{
return in_array($this->role, $roles);
}
}
ステップ3: Tinkerでロールを設定してみよう
# Tinkerを起動
php artisan tinker
// ユーザーを取得
$user = User::find(1);
// 現在のロールを確認
$user->role;
// => "user"(デフォルト)
// 管理者に昇格
$user->role = 'admin';
$user->save();
// 管理者かどうか確認
$user->isAdmin();
// => true
$user->hasRole('admin');
// => true
// 一般ユーザーを作成
$normalUser = User::create([
'name' => '一般ユーザー',
'email' => 'user@example.com',
'password' => 'password',
'role' => 'user', // デフォルトは'user'なので省略可
]);
$normalUser->isAdmin();
// => false
$normalUser->hasRole('user');
// => true
✅ Tinkerで確認したこと:
- ロールの変更と保存
- isAdmin()での判定
- hasRole()での特定ロールチェック
- hasAnyRole()での複数ロールチェック
✅ シンプルなロール管理が実装できました!
カスタムミドルウェアの作成
管理者のみアクセス可能なページを作るため、カスタムミドルウェアを作成します。
ステップ1: ミドルウェア作成
# ミドルウェア作成
php artisan make:middleware IsAdmin
// app/Http/Middleware/IsAdmin.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class IsAdmin
{
/**
* Handle an incoming request.
*/
public function handle(Request $request, Closure $next): Response
{
// ログインしているか確認
if (!auth()->check()) {
return redirect('/login');
}
// 管理者かどうか確認
if (!auth()->user()->isAdmin()) {
abort(403, 'このページにアクセスする権限がありません。');
}
// 管理者なら次の処理へ
return $next($request);
}
}
ミドルウェアの動き:
- ログインしていない →
/loginにリダイレクト - ログインしているが管理者ではない → 403エラー(Forbidden)
- 管理者 → 次の処理(コントローラー)へ
ステップ2: ミドルウェアを登録
// bootstrap/app.php (Laravel 12)
use App\Http\Middleware\IsAdmin;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware): void {
// ミドルウェアのエイリアスを登録
$middleware->alias([
'admin' => IsAdmin::class,
]);
})
->withExceptions(function (Exceptions $exceptions): void {
//
})->create();
💡 ポイント
- • Laravel 11以降は
bootstrap/app.phpのwithMiddleware()でミドルウェアを登録します - •
$middleware->alias()で短い名前(例: 'admin')とクラスを紐づけます - • ルートで
->middleware('admin')と書くことで適用できます
ステップ3: ルートに適用
認証セクションで作成した dashboard ルートを管理者専用に改修します。
// routes/web.php
// 管理者専用ページ (adminミドルウェアでグループ化)
Route::middleware(['admin'])->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
});
ポイント:
middleware(['admin'])->group()でグループ化すると、複数のルートにまとめて適用できる- 認証セクションで作成したdashboardルートを管理者専用に変更
- adminミドルウェア内でログインチェックもしているので、
'auth'は不要
💡 複数のミドルウェアも設定可能
今回は['admin']だけですが、複数のミドルウェアも指定できます:
// 複数のミドルウェアを適用する例
Route::middleware(['auth', 'verified', 'admin'])->group(function () {
// このグループ内のルートは3つのミドルウェアを通過する
});
配列の順番通りに実行されます。今回は必要ないので覚えておくだけでOKです。
実践: 実際にアクセスしてテストしてみよう
ステップ1: Tinkerでユーザーを作成
php artisan tinker
// 管理者を作成
User::create([
'name' => '管理者',
'email' => 'admin@example.com',
'password' => bcrypt('password'),
'role' => 'admin',
]);
// 一般ユーザーを作成
User::create([
'name' => '一般ユーザー',
'email' => 'user@example.com',
'password' => bcrypt('password'),
'role' => 'user',
]);
ステップ2: ブラウザでアクセスして確認
1️⃣ 管理者でログイン
- •
http://localhost/loginにアクセス - • Email:
admin@example.com - • Password:
password
2️⃣ ダッシュボードにアクセス
- • ログイン後、自動的に
http://localhost/dashboardへリダイレクト - • ✅ 管理者なのでアクセスできる!
3️⃣ ログアウトして一般ユーザーでログイン
- • Email:
user@example.com - • ログイン後、
http://localhost/dashboardへ自動リダイレクト - • ❌ 403エラー表示! (一般ユーザーはアクセスできない)
🎓 何が起きたか?
- ✅ 管理者:
isAdmin()がtrue→ ミドルウェア通過 → ページ表示 - ❌ 一般ユーザー:
isAdmin()がfalse→ ミドルウェアでabort(403)→ エラー画面
✅ カスタムミドルウェアで権限管理ができました!
一般ユーザー用の画面を作成
管理者以外の一般ユーザーもログイン後にアクセスできる画面を作成しましょう。
ステップ1: 一般ユーザー用ビューの作成
<!-- resources/views/home.blade.php -->
<h1>ホーム画面</h1>
<p>ようこそ、{{ auth()->user()->name }}さん</p>
<p>あなたは一般ユーザーです。</p>
ステップ2: ルートの追加
// routes/web.php
// 管理者専用ページ
Route::middleware(['admin'])->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
});
// 一般ユーザー用ページ (認証のみ必要)
Route::middleware(['auth'])->group(function () {
Route::get('/home', function () {
return view('home');
})->name('home');
});
ポイント:
/dashboard- 管理者専用 (adminミドルウェア)/home- 一般ユーザー用 (authミドルウェアのみ)- 役割によって画面を分けることで、権限管理が明確になる
ステップ3: ログイン後の振り分け
ログイン後に役割に応じて適切な画面へリダイレクトするように、LoginControllerを修正します。
// app/Http/Controllers/Auth/LoginController.php
public function login(Request $request)
{
$credentials = $request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
// 管理者なら /dashboard へ、一般ユーザーなら /home へ
if (auth()->user()->isAdmin()) {
return redirect()->route('dashboard');
}
return redirect()->route('home');
}
return back()->withErrors([
'email' => 'メールアドレスまたはパスワードが正しくありません。',
])->onlyInput('email');
}
💡 何が起きるか?
- ✅ 管理者: ログイン後 →
/dashboardへ自動リダイレクト - ✅ 一般ユーザー: ログイン後 →
/homeへ自動リダイレクト - ✅ 一般ユーザーが
/dashboardに直接アクセス → 403エラー
実践: 動作確認
1️⃣ 管理者でログイン
- • Email:
admin@example.com - • ログイン後 → /dashboard へ自動リダイレクト
2️⃣ 一般ユーザーでログイン
- • Email:
user@example.com - • ログイン後 → /home へ自動リダイレクト
3️⃣ 一般ユーザーが /dashboard にアクセスしようとすると
- • URLに直接
http://localhost/dashboardを入力 - • 403エラー! 管理者専用のため
✅ 役割に応じた画面の振り分けが実装できました!
まとめ
この章で学んだこと
- 認証と認可の違い - 「あなたは誰?」と「あなたには権限がある?」
- ミドルウェアの仕組み - コントローラー実行前のチェック、
$next($request)で進む - ミドルウェアファイルの構造 -
handle()メソッド、$requestと$next - enum型でロール管理 -
enum('role', ['admin', 'user'])で型安全に - カスタムミドルウェア作成 -
php artisan make:middleware IsAdmin - ミドルウェア登録 -
bootstrap/app.phpのwithMiddleware()でalias()登録 - ルートへの適用 -
Route::middleware(['admin'])->group()でグループ化 - 役割別画面の振り分け - 管理者は
/dashboard、一般ユーザーは/home - ログイン後のリダイレクト -
LoginControllerでisAdmin()判定して振り分け
重要なポイント
1. ミドルウェアは「番人」
条件を満たせばreturn $next($request)で次へ、満たさなければreturn redirect()やabort()で止める
2. adminミドルウェアでログインチェックも行う
middleware(['admin'])だけで、ログインチェック+管理者チェックの両方を実行
3. group()でまとめて適用
複数のルートに同じミドルウェアを適用する場合はRoute::middleware()->group()を使う
実践で身につけたスキル
usersテーブルにenum型のroleカラムを追加UserモデルにisAdmin()メソッドを追加IsAdminミドルウェアでログイン・管理者チェックを実装bootstrap/app.phpで'admin' => IsAdmin::classと登録routes/web.phpで管理者用・一般ユーザー用ルートを分離LoginControllerで役割に応じたリダイレクト先を振り分け- ブラウザで403エラーを確認して権限管理の動作を体験
🎉 ミドルウェアによる権限管理が完璧に理解できました!