Laravelのミドルウェアについてのまとめ

Laravel Laravel

Laravelのミドルウェア(middleware)についてまとめています。
Laravel11で確認しています。

公式ページ

Laravelでのミドルウェア(middleware)とは?

ブラウザなどからリクエストを受けて処理する前に何か処理したり、
リクエストの処理が終わった後に何か処理をするようにプログラムを書けるファイルになります。

Qiitaのこちらの記事がイメージ付きでわかりやすいです!

ミドルウェア(middleware)を作る

artisanの下記コマンドで作成することができます。

php artisan make:middleware [ミドルウェア名] 

リクエスト前処理を書く場合

作成したミドルウェアクラスのhandleメソッドで処理できます。
$next()を呼ぶ前に処理を書くと、リクエスト前処理が書けます。

public function handle(Request $request, Closure $next): Response
{
    // TODO: リクエストが処理される前の処理を書く
    return $next($request);
}

リクエスト後処理を書く場合

こちらも作成したミドルウェアクラスのhandleメソッドで処理できます。

$next()を呼んだ後に、やりたい処理を書くと、リクエスト後処理が書けます。
$next()でコントローラーのロジックを呼んで、responseを取得して返しています。

返す前に処理を書くことで、リクエスト後処理になります。

public function handle(Request $request, Closure $next): Response
{
    $response = $next($request);

    // TODO: リクエストが処理された後の処理を書く

    return $response;
}

ミドルウェアの登録

作ったミドルウェアは、Laravelに定義して処理をすることが可能になります。

Laravel11で登録する

Laravel11からbootstrap/app.phpファイルで登録できるようになりました。

グローバル登録

withMiddlewareメソッドの中で、引数の$middlewareからappendメソッドを使って、グローバル登録できます。
この方法で登録すると、すべてのルートに適用されます。

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        // ミドルウェアを追加して、自動的に全体に適用する
        $middleware->append(Logger::class);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

エイリアス登録

同じようにwithMiddlewareメソッドの中で、aliasメソッドを使って、登録する方法があります。
Loggerというミドルウェアを作成している場合は、下記のようにloggerという別名で登録することができます。

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        // Loggerミドルウェアに別名'logger'をつける(自動的に使われることはない)
        $middleware->alias(['logger' => Logger::class]);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

Laravel10以前の登録方法

Laravel10以前はapp/Http/Kernel.phpに作ったミドルウェアを追加します。

グローバル登録

HTTPリクエスト全体で動くミドルウェアになります。
app/Http/Kernel.phpの$middleware配列に作ったクラスを追加します。

protected $middleware = [ 
    \App\Http\Middleware\TrustProxies::class,
    \App\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    // TODO: 作ったミドルウェア追加
];

エイリアス登録

指定したルーティングで定義しているURLにアクセスした時にだけ動くミドルウェアを作ることができます。
ログインしているユーザーだけとか、指定することができます。

ルーティングファイル(web.php)に定義するためにapp/Http/Kernel.phpに連想配列の形式で、$routeMiddleware配列に追加します。

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    // TODO: 作ったミドルウェア追加
];

ミドルウェアを割り当てる

グローバルで登録していないミドルウェアは、ルーティングファイルに記載して割り当てることができます。

直接指定で割り当て

定義したルートから、middlewareメソッドを呼び出して割り当てることができます。
bootstrap/app.phpに書いてなくても使えます。

// 直接指定で割り当て
Route::get('/middleware-test-output', [MiddlewareTestController::class, 'output'])->middleware(Logger::class);

エイリアスを指定して割り当て

bootstrap/app.phpにエイリアス登録したものを指定して、割り当てることができます。

// エイリアス指定で割り当て
Route::get('/middleware-test-output', [MiddlewareTestController::class, 'output'])->middleware('logger');

ルーティンググループへの割り当て

直接ミドルウェアを指定して、下記のようにグループ化したルートに適用することができます。

Route::middleware([Logger::class, Hello::class])->group(function () {
    Route::get('/middleware-test1', function () {
        logger()->info('test1');
    });

    Route::get('/middleware-test2', function () {
        logger()->info('test2');
    });
});

エイリアスを使って適用するには、class指定していたところを、登録したエイリアスを指定するだけです。

Route::middleware(['logger', 'hello'])->group(function () {
    Route::get('/middleware-test1', function () {
        logger()->info('test1');
    });

    Route::get('/middleware-test2', function () {
        logger()->info('test2');
    });
});

実際に作ってみる

artisanコマンドでLoggerミドルウェアを作ってみました。

$ php artisan make:middleware Logger

ミドルウェアのソース

新しくミドルウェアを作ると、app/Http/Middlewareにファイルができます。

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class Logger
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        \Log::info('[middleware] start run logger');
        $this->outputRequest($request);
        $response = $next($request);
        \Log::info('[middleware] end run logger');

        return $response;
    }

    /**
     * リクエストパラメータ出力.
     * @param Request $request
     */
    private function outputRequest(Request $request)
    {
        $requestMethod = $request->method();
        $requestParams = json_encode($request->all());
        \Log::info("{$requestMethod} : {$requestParams}");
    }
}

中身を上記のように書きました。
受け取ったリクエストをoutputRequestメソッドでログに出力するようにしています。

$request->method()でGETやPOSTなどのメソッド名が取得できて、
$request->all())でパラメータが全部取得できます。(POSTやPUTなどのパラメータも取れます)

ミドルウェア登録

bootstrap/app.phpにルート登録しました。

<?php
use App\Http\Middleware\Logger;
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) {
        // Loggerミドルウェアに別名'logger'をつける(自動的に使われることはない)
        $middleware->alias([
            'logger' => Logger::class,
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

web.phpを修正

前述したようにルートに対して、ミドルウェアを指定する方法がいくつかあります。
今回は、下記のように指定しました。

Route::get('/middleware-test-output', [MiddlewareTestController::class, 'output'])->middleware('logger');

動作確認

ブラウザにパラメータを付けてアクセスすると…
LaravelのMiddlewareの動作確認

ログ出力されました!

024-03-23 08:58:58] local.INFO: [middleware] start run logger  
[2024-03-23 08:58:58] local.INFO: GET : {"text":"hello","hoge":"123"}  
[2024-03-23 08:58:58] local.INFO: [middleware] end run logger  

ソースはこちら

おわりに

特に難しいことなく、リクエストの後に処理をはさむことができました。

業務ロジックなどを書いているそれぞれのコントローラーに処理を書かずに
簡単に共通処理をかけるのでいいですね!

コメント

タイトルとURLをコピーしました