【laravel】ミドルウェアの実行の順番の制御方法

laravelのミドルウェアを使用していて

「この処理を一番最初に通したい」や「最後に実行したい」と思ったことはありませんか?

  • ミドルウェアを先に実行した・最後に実行したいがやり方がわからない
  • 認証前やレスポンス返却後など、処理のタイミングが制御できず困っている
  • ミドルウェアを追加したら、想定と違う順番で実行されてしまった

本記事では、ミドルウェアを最初・最後に実行する方法を実際の設定例を交えて紹介します。
また、実際の開発現場で認証前に必ず通したい処理最後にログを残したい処理を実装する際に使用した方法となります。ぜひ参考にしてみてください。
※今回紹介するのはlaravel9となります。laravel10ではkernelに追加する場所が変わっています。
laravel11以降はちょっと方法が変わっておりますので公式ドキュメントをご参照ください。

  • ミドルウェアを最初・最後に実行する設定方法が分かる
  • 処理の流れを理解したうえで、意図した順番でミドルウェアを実行できる
  • 実行順が原因の不具合を事前に防げるようになる

ミドルウェアは一度作るとそのあとはあまり触ることはなく、設定方法を忘れがちですが、すぐ見返せるように簡潔になるよう書いております。

目次

実装

実装する流れ

  • コマンドを使用してミドルウェアのファイルを作成する
  • Kernel.phpに作成したミドルウェアを追加する
  • web.phpにKernelで定義したミドルウェアを設定する
  • ミドルウェアのロジックを作成する

コマンドでミドルウェアファイルを作成する

user2:laravel$ php artisan make:middleware testMiddleware

   INFO  Middleware [app/Http/Middleware/testMiddleware.php] created successfully.  

Kernel.phpにミドルウェアを追加

//~~~~~省略~~~~~
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
    'signed' => \App\Http\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    'CheckGroup' => \App\Http\Middleware\CheckGroup::class,
    // ↓コマンドで作成したファイルを追加し、名前を設定する
    'testCheck' => \App\Http\Middleware\testMiddleware::class,
];

web.phpにミドルウェアを設定

web.phpにkernel.phpで設定したミドルウェアの名前を追記し、適用させる範囲を設定します。

//~~~~~省略~~~~~
// ミドルウェアの適用
Route::group(['middleware' => ['auth','testCheck']], function () {
    // 適用範囲
    Route::get('/', [App\Http\Controllers\EventController::class, 'eventList'])->name('eventList_get');
}

ミドルウェアを最初に実行するパターン

laravelがリクエストを受け取った直後に実行され、コントローラの処理が走る前にアクセスログに登録する前処理を行います。
ほかにも、「リクエストヘッダのチェックを最初に行いたい」や「認証より前に処理をしたい」などのケースでも使用できます。

実装上は、「$next($request)」を呼び出す前に処理を書きます。
この位置に処理を書くことで、最初に実行されるミドルウェアとして機能します。

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\DB;
use App\Models\t_access_log;
use App\Repositories\accesslogRegisterRepository;
use App\libs\Logging;
use Illuminate\Support\Facades\Log;

class testMiddleware
{
    protected $accesslogRegisterRepository;

    public function __construct(accesslogRegisterRepository $accesslogRegisterRepository)
    {
        $this->accesslogRegisterRepository = $accesslogRegisterRepository;
    }

    /**
    * Handle an incoming request.
    *
    * @param \Illuminate\Http\Request $request
    * @param \Closure $next
    * @return mixed
    */
    public function handle($request, Closure $next)
    {
        try {
            // アクセスログに登録
            DB::beginTransaction();

            $this->accesslogRegisterRepository->accesslogInsert();
            DB::commit();
        } catch (\Exception $e) {
            DB::rollback();
        }
        
        return $next($request);  // 最後にcontroller等の処理を行う
    }
}

ミドルウェアを最後に実行させるパターン

「リクエスト → コントローラ処理 → レスポンス生成 → ミドルウェア後処理」という流れで、レスポンスを返す前にアクセスログ登録が実行されるミドルウェアです。

実装上は、「$next($request)」の後に処理を書きます。最後に、「return」することを忘れないようにしましょう。

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\DB;
use App\Models\t_access_log;
use App\Repositories\accesslogRegisterRepository;
use App\libs\Logging;
use Illuminate\Support\Facades\Log;

class testMiddleware
{
    protected $accesslogRegisterRepository;

    public function __construct(accesslogRegisterRepository $accesslogRegisterRepository)
    {
        $this->accesslogRegisterRepository = $accesslogRegisterRepository;
    }

    /**
    * Handle an incoming request.
    *
    * @param \Illuminate\Http\Request $request
    * @param \Closure $next
    * @return mixed
    */
    public function handle($request, Closure $next)
    {
        $response = $next($request); // 先にcontroller等の処理を行う

        // その後の処理
        try {
            // アクセスログに登録
            DB::beginTransaction();

            $this->accesslogRegisterRepository->accesslogInsert();
            DB::commit();
        } catch (\Exception $e) {
            DB::rollback();
        }
        
        return $response;
    }
}

まとめ

laravelのミドルウェアは非常に簡単に実装できますが、どのタイミングで実行されるのかを把握しておくことが大切です。

最初・最後に実行するパターンの2つを押さえておくことで、リクエスト処理とレスポンス処理の流れが理解しやすくなったと思います。
共通処理もミドルウェアで順番を柔軟にコントロールすることができ、簡単に可読性と保守性を上げることができます。

  • URLをコピーしました!
目次