【PHP】Laravelでミドルウェアを実装する方法

対象バージョン: Laravel 13.x / PHP 8.3+(2026年時点のシリーズ基準)
一次ソース: Middleware / Routing / Release Notes

こんにちは。この記事では、Laravel 13.x で ミドルウェアを実装する基本 を、現行の公式ドキュメントに沿って整理します。作成(make:middleware)、handle での前後処理、bootstrap/app.php への登録、ルート割り当て、パラメータまでを通します。認証設計や API 全体の話は扱いません。まずは「自分で作ったミドルウェアを、正しい場所に登録してルートに掛けられる」状態を目指します。

この記事で分かること

  • ミドルウェアの役割(HTTP リクエストの検査・フィルタ)
  • php artisan make:middleware と handle の書き方(before / after)
  • Laravel 13.x の登録場所(bootstrap/app.php の withMiddleware)
  • ルートへの割り当てとパラメータ付きミドルウェア
  • Laravel 10 時代の Kernel.php とのよくある落とし穴

対象バージョンと前提

本記事の前提は Laravel 13.x / PHP 8.3+ です。Laravel 13.x は PHP 8.3 以上を要求し、フレームワーク本体の composer.json も "php": "^8.3" です(Release Notes)。調査時点で確認した laravel/framework 13.x の最新 stable は v13.34.0(2026-09-29)です。

登録の正本は bootstrap/app.php の withMiddleware です。 laravel/laravel 13.x のスケルトンには app/Http/Kernel.php がなく、app/Http 配下は主に Controllers です。古い記事の Kernel.php 前提は、現行手順として使わないでください(差分は後半で短く触れます)。


ミドルウェアとは何か

ミドルウェアは、アプリケーションに入ってくる HTTP リクエストを検査・フィルタするための仕組み です。たとえばトークンの確認、ロケールの設定、レスポンスヘッダの付与など、「コントローラの手前(または直後)で毎回やりたいこと」を分離するのに向いています。

イメージとしては、リクエストがコントローラに届くまでのレイヤーです。通過させてよければ次へ渡し、ダメならここでレスポンスを返して止めます。ユーザー定義のミドルウェアは、通常 app/Http/Middleware に置きます。


ミドルウェアの作成(make:middleware)

新しいクラスは Artisan で生成します。

php artisan make:middleware EnsureTokenIsValid

app/Http/Middleware/EnsureTokenIsValid.php が作られます。中心は handle メソッドです。型ヒント例は公式どおり、戻り値を Response にします。

<?php

namespace App\Http\Middleware;

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

class EnsureTokenIsValid
{
    /**
     * Handle an incoming request.
     */
    public function handle(Request $request, Closure $next): Response
    {
        if ($request->input('token') !== 'my-secret-token') {
            return response('Invalid token.', 401);
        }

        return $next($request);
    }
}

リクエストを先に進めるときは $next($request) を返します。止めるときは、ここでレスポンスを返して $next を呼びません。ミドルウェアはサービスコンテナ経由で解決されるため、コンストラクタでの依存注入も使えます。


リクエスト前後の処理

Before(コントローラの前)

$next($request) を呼ぶ 前 に処理を書くと、リクエストがアプリケーション本体に入る前に実行されます。上のトークン例がこれです。

After(コントローラの後)

先に $response = $next($request) で先を実行し、返ってきたレスポンスに手を加えてから返すと、後処理になります。

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

    $response->headers->set('X-Example', 'Middleware');

    return $response;
}

登録方法(bootstrap/app.php)

Laravel 13.x では、ミドルウェアの登録・エイリアス・グループへの追加を bootstrap/app.php の withMiddleware で行います。スケルトンには空のコールバックが用意されています。

->withMiddleware(function (Middleware $middleware): void {
    //
})

グローバル(すべての HTTP リクエスト)

すべてのリクエストで動かしたい場合は append / prepend します。

->withMiddleware(function (Middleware $middleware): void {
    $middleware->append(\App\Http\Middleware\EnsureTokenIsValid::class);
    // 先頭に入れたい場合
    // $middleware->prepend(\App\Http\Middleware\EnsureTokenIsValid::class);
})

既定のグローバルスタックを自分で並べ替える場合は $middleware->use([...]) も使えます(必要なときだけ)。

エイリアス

短い名前でルートに掛けたいときは alias を登録します。

->withMiddleware(function (Middleware $middleware): void {
    $middleware->alias([
        'token.valid' => \App\Http\Middleware\EnsureTokenIsValid::class,
    ]);
})

組み込みでも、例えば auth / auth.basic / can / guest / signed / throttle / verified などが既定でエイリアスされています。

web / api グループ

Laravel にはあらかじめ web と api のミドルウェアグループがあります。routes/web.php と routes/api.php のルートには、それぞれ自動で適用されます。既定グループに自分のクラスを足す例です。

->withMiddleware(function (Middleware $middleware): void {
    $middleware->web(append: [
        \App\Http\Middleware\EnsureTokenIsValid::class,
    ]);

    $middleware->api(prepend: [
        \App\Http\Middleware\EnsureTokenIsValid::class,
    ]);
})

独自グループは appendToGroup / prependToGroup で定義し、ルートでは ->middleware('group-name') のように使います。

$middleware->appendToGroup('custom', [
    \App\Http\Middleware\EnsureTokenIsValid::class,
]);

ルートへの割り当て

特定ルートだけに掛ける場合は、ルート定義で middleware を指定します。

use App\Http\Middleware\EnsureTokenIsValid;

Route::get('/profile', function () {
    // ...
})->middleware(EnsureTokenIsValid::class);

Route::get('/dashboard', function () {
    // ...
})->middleware([EnsureTokenIsValid::class, 'auth']);

エイリアス名でもクラス名でも構いません。複数は配列で並べます。

withoutMiddleware の注意

ルートからミドルウェアを外すときは withoutMiddleware([...]) を使います。ただし 外せるのはルートに割り当てたミドルウェアだけ で、グローバルスタックには効きません。

Route::get('/public', function () {
    // ...
})->withoutMiddleware([EnsureTokenIsValid::class]);

ミドルウェアパラメータ

handle の $next のあとに追加引数を取れます。ルート側では、クラス名(またはエイリアス)の後ろに :値 を付けます。複数はカンマ区切りです。

public function handle(Request $request, Closure $next, string $role): Response
{
    if (! $request->user() || ! $request->user()->hasRole($role)) {
        abort(403);
    }

    return $next($request);
}
Route::put('/post/{id}', function (string $id) {
    // ...
})->middleware(\App\Http\Middleware\EnsureUserHasRole::class.':editor');

(任意)優先順位と Terminable

ルートへの並び以外で実行順を細かく決めたいときは、bootstrap/app.php で $middleware->priority([...]) や prependToPriorityList / appendToPriorityList を使えます。入門では、まずルート配列の順序で足りることが多いです。

レスポンス送信後に後始末したい場合は、terminate(Request $request, Response $response): void を定義できます。Web サーバが FastCGI のとき、レスポンス送信後に自動で呼ばれます。詳細は公式の Terminable Middleware を参照してください。本記事では深掘りしません。


Laravel 10 とのよくある落とし穴

Laravel 10.x 頃 Laravel 11+ / 13.x
app/Http/Kernel.php の $middleware / $middlewareAliases / $middlewareGroups bootstrap/app.php の withMiddleware
スケルトンに Kernel.php がある前提の解説が多い 13.x スケルトンに Kernel.php は無い(URL も 404)

古いチュートリアルを写すと「Kernel.php が見つからない」になりがちです。現行は bootstrap/app.php だけを主経路にしてください。


まとめ

  • ミドルウェアは HTTP リクエストの検査・フィルタ用レイヤー
  • 作成は php artisan make:middleware、処理の中心は handle と $next($request)
  • before は $next の前、after は $response = $next($request) の後
  • Laravel 13.x の登録は bootstrap/app.php の withMiddleware(グローバル / エイリアス / web・api)
  • ルートは ->middleware(...)。withoutMiddleware はグローバルには効かない
  • パラメータは Class::class.':param'
  • Kernel.php を現行の主教材にしない

参考リンク

コメントする