👻

[Laravel]Middlewareを活用し特定APIリクエストにだけ追加処理を行う

2024/08/23に公開
2

この記事を3行でまとめる

  • 特定のAPIリクエストにだけ追加で処理を行いたい
  • 既存の処理には手を加えずに実施したい
  • LaravelのMiddlewareを使って実現する

前提

  • この記事はLaravelが既に動作する状態にあることを前提に記載しています
  • Laravelのインストールなどは公式サイトなどを参考に行ってください

https://readouble.com/laravel/10.x/ja/installation.html

Middleware

https://readouble.com/laravel/10.x/ja/middleware.html

  • HTTPリクエストに対して検査やフィルタリングするための便利なメカニズム
  • すごくザックリとしたイメージ図ですが、以下の赤枠が「Middleware」となります

  • Request の後、Response の前に処理を挟み込むことが可能となります
  • Laravelの初期状態でも幾つものMiddlewareが搭載されています
    • app/Http/Middleware 配下

構築するもの

  • 今回は以下2つのMiddlewareを作成し動作を見ていきます
  1. Controller の前段で動作するMiddleware
  2. Controller の後段で動作するMiddleware

Controller の前段で動作するMiddleware

  1. artisan コマンドを使ってMiddlewareを作成
php artisan make:middleware BeforeSampleMiddleware

# 以下が出力されればOK
 INFO  Middleware [app/Http/Middleware/BeforeSampleMiddleware.php] created successfully.
  1. Middlewareを開き確認用コードを書く

app/Http/Middleware/BeforeSampleMiddleware.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class BeforeSampleMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
     */
    public function handle(Request $request, Closure $next)
    {
        \Log::info('BeforeSampleMiddleware');

        # ここよりも前に処理を描くと「前段」で動作するMiddlewareとなる
        return $next($request);
    }
}

  1. Middlewareを kernel.php に「ルートに対する」Middlewareとして登録する

app/Http/Kernel.php

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{

...

    protected $middlewareAliases = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
...
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
        # ここに追加
        'sample.before' => \Illuminate\Auth\Middleware\BeforeSampleMiddleware::class,
    ];
}
  1. ルートにMiddlewareを設定する

routes/web.php

Route::get('/', function () {
    \Log::info('welcome');
    return view('welcome');
})->middleware('sample.before');

※上記はLaravel初期状態を想定して設定していいます

  1. APIリクエストを行いMiddlewareが動作しているか確認する

  2. サイトにアクセスする

  3. Laravelのログを確認する

  4. BeforeSampleMiddleware が先で welcome が後に出力されていればOK

Controller の後段で動作するMiddleware

  1. artisan コマンドを使ってMiddlewareを作成
php artisan make:middleware AfterSampleMiddleware

# 以下が出力されればOK
 INFO  Middleware [app/Http/Middleware/AfterSampleMiddleware.php] created successfully.
  1. Middlewareを開き確認用コードを書く

app/Http/Middleware/AfterSampleMiddleware.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class AfterSampleMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
     */
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);
        # ここよりも後に処理を描くと「後段」で動作するMiddlewareとなる

        \Log::info('AfterSampleMiddleware');

        return $response
    }
}
  1. Middlewareを kernel.php に「ルートに対する」Middlewareとして登録する

app/Http/Kernel.php

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{

...

    protected $middlewareAliases = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
...
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
        'sample.before' => \Illuminate\Auth\Middleware\BeforeSampleMiddleware::class,
        # ここに追加
        'sample.after' => \Illuminate\Auth\Middleware\AfterSampleMiddleware::class,
    ];
}
  1. ルートにMiddlewareを設定する

routes/web.php

Route::get('/', function () {
    \Log::info('welcome');
    return view('welcome');
})->middleware('sample.after');

※上記はLaravel初期状態を想定して設定していいます

  1. APIリクエストを行いMiddlewareが動作しているか確認する

  2. サイトにアクセスする

  3. Laravelのログを確認する

  4. welcome が先で AfterSampleMiddleware が後に出力されていればOK

まとめ

いかがでしたでしょうか?
Middlewareを活用することでメインの処理を変更せずとも特定の処理を追加することができます
また、複数個所への処理追加をMiddlewareに寄せることで、
Controllerへのテスト負荷や確認作業も軽減させることが可能となります。

活用次第でメリットが多くあるMiddleware、ぜひとも活用していきたいですね。

株式会社THIRD エンジニアブログ

Discussion

MaruMaru

突然のコメント失礼します。

    public function handle(Request $request, Closure $next)
    {
        return $next($request);
        # ここよりも後に処理を描くと「後段」で動作するMiddlewareとなる

        \Log::info('AfterSampleMiddleware');
    }

上記のコード例ですが、return以降は実行されないと思うので、正しくは以下ではないでしょうか?

    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);
        # ここよりも後に処理を描くと「後段」で動作するMiddlewareとなる
        \Log::info('AfterSampleMiddleware');

        return $response
    }

https://laravel.com/docs/11.x/middleware#middleware-and-responses

zenn_kurarazenn_kurara

@Maru さん
おぉ、本当ですね。
完全にミスってます。
ご指摘ありがとうございます!