0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Laravel 11/Middleware】実用的なカスタムミドルウェアの作成と活用例

Last updated at Posted at 2025-02-06

Laravel 11.x では、ミドルウェアの登録が従来の app/Http/Kernel.php ではなく、bootstrap/app.php に記述されるようになりました。
また、サービスプロバイダも artisan make:provider コマンドで生成すると、自動的に bootstrap/providers.php に登録されるようになっています。
ここでは、実際の開発現場で役立つカスタムミドルウェアのサンプルコードを充実させて解説します。


1. カスタムミドルウェアの基本と実用例

まずは、ユーザーが利用停止(banned)状態の場合に、ログイン後の画面へアクセスさせず、専用の通知ページへリダイレクトするミドルウェアのサンプルを見ていきます。

1-1. 利用停止ユーザーのチェックミドルウェア(CheckUserStatus)

作成コマンド:

php artisan make:middleware CheckUserStatus

生成されるファイル:
app/Http/Middleware/CheckUserStatus.php

サンプルコード:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CheckUserStatus
{
    /**
     * Handle an incoming request.
     *
     * ユーザーが利用停止状態の場合、専用の通知ページへリダイレクトする
     *
     * @param  \Illuminate\Http\Request  $request  現在の HTTP リクエスト
     * @param  \Closure  $next  次に実行すべき処理
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        // リクエスト前の処理
        $user = Auth::user();

        // ログイン済みかつ利用停止状態の場合(例として、Userモデルに isBanned() メソッドがある)
        if ($user && $user->isBanned()) {
            // 利用停止の通知ページへリダイレクト
            return redirect()->route('banned.notice');
        }

        // 次のミドルウェアまたはコントローラにリクエストを渡す
        $response = $next($request);

        // レスポンス後の処理:レスポンスヘッダーにカスタム情報を追加
        $response->headers->set('X-User-Status', $user ? 'active' : 'guest');

        return $response;
    }
}

補足:

  • Auth::user() を利用して現在のユーザー情報を取得。
  • ユーザーがログインしている場合に、isBanned()(Userモデルに実装していると仮定)で利用停止状態かチェック。
  • 利用停止の場合、redirect()->route('banned.notice') で専用ページへ誘導しています。
  • レスポンス後の処理で、X-User-Status ヘッダーを追加しているのは、後からデバッグやフロントエンド側で確認するための例です。

2. パラメータ付きミドルウェアの実用例

次に、ユーザーのロール(権限)をチェックするミドルウェアのサンプルです。
たとえば、管理者専用のルートにアクセスさせる前に、ユーザーが admin ロールを持っているかをチェックします。

2-1. ユーザーロールチェックミドルウェア(CheckUserRole)

作成コマンド:

php artisan make:middleware CheckUserRole

生成されるファイル:
app/Http/Middleware/CheckUserRole.php

サンプルコード:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CheckUserRole
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string  $role  期待するユーザーロール(例:"admin")
     * @return mixed
     */
    public function handle(Request $request, Closure $next, $role)
    {
        $user = Auth::user();

        // ユーザーがログインしていない、もしくは期待するロールを持っていない場合
        if (! $user || ! $user->hasRole($role)) {
            // 403エラーを返すか、または特定のページへリダイレクトする
            abort(403, 'この操作は許可されていません。');
        }

        return $next($request);
    }
}

補足:

  • $role はルート定義時にミドルウェアへ渡すパラメータです。
  • ユーザーがログインしていない場合や、Userモデルに実装した hasRole() メソッドで期待するロールを持っていない場合は、HTTP 403 エラーを返します。
  • もちろん、必要に応じてリダイレクト処理に変更することも可能です。

3. ミドルウェアの登録(Laravel 11.x ~ bootstrap/app.php)

Laravel 11.x では、ミドルウェアは bootstrap/app.php に登録します。
以下は、グローバルミドルウェアとルートミドルウェアの登録例です。

3-1. グローバルミドルウェアの登録例

// bootstrap/app.php

$app->middleware([
    // すべてのリクエストに適用するミドルウェア
    App\Http\Middleware\CheckForMaintenanceMode::class,
    App\Http\Middleware\CheckUserStatus::class, // 先ほど作成した利用停止ユーザーチェック
]);

3-2. ルートミドルウェアの登録例

// bootstrap/app.php

$app->routeMiddleware([
    'auth'   => App\Http\Middleware\Authenticate::class,
    'role'   => App\Http\Middleware\CheckUserRole::class, // パラメータ付きミドルウェア
    'sample' => App\Http\Middleware\SampleMiddleware::class,
]);

4. ルート定義と実用的な使用例

実際のルート定義において、上記のミドルウェアをどのように活用するかを見てみましょう。

4-1. 利用停止ユーザーのリダイレクト例

利用停止ユーザー向けの通知ページ(例:banned.notice)があると仮定します。

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\NoticeController;

Route::group(['prefix' => 'admin'], function () {
    // ログイン関連のルート(ミドルウェア不要)
    Route::get('/login', [LoginController::class, 'showLoginForm'])->name('login');
    Route::post('/login', [LoginController::class, 'login']);

    // 通知ページ:利用停止ユーザー向け
    Route::get('/banned', [NoticeController::class, 'banned'])->name('banned.notice');

    // 認証済みユーザー向けのルートグループ
    Route::group(['middleware' => 'auth'], function () {
        // 利用停止チェックミドルウェアはグローバルに登録済み

        // 管理者のみアクセス可能なルート
        Route::group(['middleware' => 'role:admin'], function () {
            Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
        });
    });
});

ポイント:

  • /admin/banned には、利用停止状態のユーザーがリダイレクトされます(CheckUserStatus ミドルウェアが働く)。
  • /admin/dashboard は、authrole:admin のミドルウェアが両方適用され、ログイン済みかつ管理者権限を持つユーザーのみアクセス可能です。

5. サービスプロバイダの自動登録とその違い

Laravel 11.x では、サービスプロバイダを作成すると自動的に bootstrap/providers.php に登録されるようになりました。
サービスプロバイダは、アプリケーション起動時に一度だけ実行され、以下のような初期化処理を担当します。

5-1. サービスプロバイダ作成の例

php artisan make:provider CustomServiceProvider

生成されたサービスプロバイダは、以前は手動で config/app.phpproviders 配列に追加する必要がありましたが、Laravel 11.x では自動で bootstrap/providers.php に登録されます。

サービスプロバイダとミドルウェアの違い:

  • ミドルウェア:
    → 各リクエストごとに実行される処理(例:認証、権限チェック、CSRF 保護)
    bootstrap/app.php でグローバルまたはルート単位で登録
  • サービスプロバイダ:
    → アプリケーション起動時の初期化処理(例:サービスバインディング、イベントリスナー登録)
    → 作成時に自動で bootstrap/providers.php に登録され、アプリ全体の基盤を構築

6. まとめ

  • カスタムミドルウェアの作成:
    Artisan コマンドで生成し、handle メソッド内でリクエスト前後の処理を実装。
    実用例として、利用停止ユーザーのリダイレクト(CheckUserStatus)やパラメータ付きのロールチェック(CheckUserRole)を紹介。

  • Laravel 11.x の登録方式:
    ミドルウェアは bootstrap/app.php でグローバルおよびルートミドルウェアとして登録。
    サービスプロバイダは作成時に自動で bootstrap/providers.php に登録され、手動設定が不要に。

  • 実用的なサンプルコード:
    ルート定義例やコントローラと連携した利用例を充実させ、実際のアプリケーションでの利用イメージを明確化。

これらを活用することで、堅牢で保守性の高い Laravel アプリケーションを構築できるでしょう。
ぜひ、自分のプロジェクトに合わせたカスタムミドルウェアを作成し、柔軟なリクエスト制御を実現してください!


参考リンク


以上、実用的なカスタムミドルウェアの作成と活用例についての解説でした。
ご質問やコメントがあれば、お気軽にお寄せください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?