【Laravel】 ミドルウェアの使い方と作り方
ミドルウェアは、リクエストを検査したりユーザ認証をチェックして弾く、アクセスに関する詳細なログを記録するといった、メインの処理を行う前のタスクを実行するのに使用します。
最初からあるミドルウェア
Laravelでは、いくつかのミドルウェアが最初から定義されています。ミドルウェアは、app/Http/Middleware/
ディレクトリ内にあります。いずれのミドルウェアもアプリケーションのメインロジック (要はControllerのメソッド) に入る前に処理されるものです。
フォームから送信した際のCSRFの防止(VerifyCsrfToken)、ログイン認証(Authenticate)、入力された情報のトリム (文字列の前後のスペース削除) (TrimStrings) といったものが並んでいます。

ミドルウェアを使う
用意されているミドルウェアや自作したミドルウェアは、app/Http/Kernel.php
に登録することで使用、またはルーティング側に設定することで使用できます。
Kernelで設定
Kernelでは、どのルートでも使用するミドルウェアを$middleware
に、ルーティングのグループごとに使い分けるミドルウェアを$middlewareGroups
に入れます。いくつかは最初から定義されていますね。
前者の、どのルートでも使用するミドルウェアは、グローバルミドルウェアと呼びます。
ここにあるルートのグループというのは、app/Providers/RouteServiceProvider.php
のboot()
内でどれがどのグループに属するかが定義されています。
// どのページでも使用したいミドルウェアのクラスを並べる protected $middleware = [ \App\Http\Middleware\PreventRequestsDuringMaintenance::class, // ... ]; // ルートのグループごとに使用したいミドルウェアを並べる protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\VerifyCsrfToken::class, // ... ], 'api' => [ // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
ルートごとに指定
特定のルートにミドルウェアを適用したい場合、Kernel.php
の$routeMiddleware
に並べ、そのキーを使ってroutes
側の定義にメソッドチェーンで->middleware('キー')
のようにします。
protected $routeMiddleware = [ 'hoge' => \App\Http\Middleware\Authenticate::class, ];
// $routeMiddlewareのキーと、ここのmiddlewareをあわせる Route::get('/hoge', [HelloController::class, 'index']) ->middleware('hoge'); // 配列でもOK // Route::get('/hoge', [HelloController::class, 'index']) // ->middleware(['hoge']);
ミドルウェアの適用から除外
特定のルートで特定のミドルウェアを適用したくない場合、ルート側でwithoutMiddleware
を設定します。引数にはクラスを入れます。
Route::post('/home', [HelloController::class, 'hoge']) ->withoutMiddleware([\App\Http\Middleware\TrimStrings::class]);
グローバルミドルウェアとして登録されているミドルウェアは、withoutMiddleware
を設定しても適用外になりません。
ミドルウェアを作る
ミドルウェアを作る場合、まずはartisan
でファイルを作成しましょう。
php artisan make:middleware IpRestriction
そうすると、app/Http/Middleware/
ディレクトリ内に指定した名前のファイルが作成されています。
public function handle(Request $request, Closure $next) { return $next($request); }
にあるRequest
は、コントローラに設定したRequest
と同じです。$request->input('hoge')
のようにして、リクエストボディやクエリストリングの値を取得できます。
ルートパラメータを取得したい場合、$request->route()->parameter('userId')
のようにします。
use Illuminate\Support\Facades\Log; public function handle(Request $request, Closure $next) { Log::debug($request->route()->parameter('id')); // 172.22.0.1 return $next($request); }
$next
は、今後の処理を行うためのものです。その今後の処理の中には、コントローラのメソッドを実行するなども含まれています。そのため、
public function handle(Request $request, Closure $next) { $response = $next($request); // 処理 return $response; }
のように、先に$next
を実行すると、コントローラなどの処理後に実行するミドルウェアを作成できます。
実際に作ってみる
実際にミドルウェアを1つ作ってみましょう。今回はIP制限を行うミドルウェアを作成してみます。
php artisan make:middleware IpRestriction
IPアドレスは$request->ip()
で取得できます。これを使って特定のIPのみページを表示し、それ以外のIPはエラーページに飛ばす処理を作ってみます。
public function handle(Request $request, Closure $next) { Log::debug($request->ip()); // 172.22.0.1など return $next($request); }
リダイレクトするには、redirect('path', statusCode)
関数を用います。
public function handle(Request $request, Closure $next) { if ($request->ip() === '172.22.0.1') { // 続きの処理を実行 return $next($request); } // 172.22.0.1以外は /err に移動 (302でリダイレクト) return redirect('/err'); }
完成しました!
172.22.0.1
はdocker経由でアクセスしたときの値です。
まとめ
ミドルウェアを使用することで、メインの処理を行う前に様々な処理を行うことができます。ユーザ権限を使用した制限やロギングといった、メインロジックとは少し離れた、複数のページで共通して使うような処理によく利用されます。
ミドルウェアを活用して、コントローラが肥大化しないようにしていきましょう!
