ミドルウェアとは何か
LaravelのMiddleware(ミドルウェア)は、HTTPリクエストがアプリケーションに到達する前後に処理を挟み込む仕組みです。
たとえば以下のような用途に使われます。
- ログインしているかどうかの認証チェック
- リクエストのロギング
- CORS(クロスオリジン)ヘッダーの付与
- レスポンスの圧縮
リクエストが「コントローラ」に届く前に、いくつかのミドルウェアを通過するイメージです。
リクエスト → [ミドルウェアA] → [ミドルウェアB] → コントローラ → レスポンス
Laravelには最初からいくつかのミドルウェアが組み込まれており、app/Http/Middleware ディレクトリに配置されています。
カスタムミドルウェアを作る
まずはArtisanコマンドでミドルウェアを生成します。
php artisan make:middleware CheckAge
app/Http/Middleware/CheckAge.php が作成されます。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class CheckAge
{
public function handle(Request $request, Closure $next): Response
{
// リクエストが届いたときの処理(Before)
if ($request->age < 18) {
return redirect('/home')->with('error', '18歳以上のみアクセスできます');
}
// 次のミドルウェア or コントローラへ処理を渡す
$response = $next($request);
// レスポンスが返ってきたあとの処理(After)
// ここでレスポンスヘッダーの付与なども可能
return $response;
}
}
$next($request) を呼び出すことで、次のミドルウェアまたはコントローラへ処理が渡されます。これを呼ばなければリクエストをそこで止めることができます。
ミドルウェアを登録する
作ったミドルウェアはLaravelに登録する必要があります。Laravel 11以降は bootstrap/app.php で設定します。
グローバルミドルウェア(すべてのリクエストに適用)
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->append(\App\Http\Middleware\CheckAge::class);
})
エイリアスを設定してルートで使う
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
'check.age' => \App\Http\Middleware\CheckAge::class,
]);
})
ルートへのミドルウェア適用
エイリアスを設定したら、ルートに適用できます。
// routes/web.php
// 単一ルートに適用
Route::get('/adult-content', [ContentController::class, 'index'])
->middleware('check.age');
// 複数のミドルウェアを指定
Route::get('/dashboard', [DashboardController::class, 'index'])
->middleware(['auth', 'check.age']);
// グループ全体に適用
Route::middleware(['auth', 'check.age'])->group(function () {
Route::get('/profile', [ProfileController::class, 'show']);
Route::get('/settings', [SettingsController::class, 'show']);
});
実践例:アクセスログを記録するミドルウェア
実際によく使われるパターンとして、リクエストのアクセスログを記録するミドルウェアを作ってみましょう。
php artisan make:middleware AccessLog
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;
class AccessLog
{
public function handle(Request $request, Closure $next): Response
{
// リクエスト前:情報を記録
$startTime = microtime(true);
$response = $next($request);
// レスポンス後:処理時間とステータスを記録
$duration = round((microtime(true) - $startTime) * 1000, 2);
Log::info('Access Log', [
'method' => $request->method(),
'url' => $request->fullUrl(),
'ip' => $request->ip(),
'status' => $response->getStatusCode(),
'duration' => $duration . 'ms',
]);
return $response;
}
}
このミドルウェアをグローバルに登録しておけば、すべてのリクエストに対してアクセスログが storage/logs/laravel.log に記録されます。
ミドルウェアにパラメータを渡す
ミドルウェアには引数を渡すこともできます。たとえば「ロールに応じてアクセス制限する」ミドルウェアを作ってみます。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class CheckRole
{
public function handle(Request $request, Closure $next, string $role): Response
{
if (! $request->user() || $request->user()->role !== $role) {
abort(403, 'このページへのアクセス権がありません');
}
return $next($request);
}
}
ルートでは : のあとにパラメータを渡します。
Route::get('/admin', [AdminController::class, 'index'])
->middleware('check.role:admin');
Route::get('/editor', [EditorController::class, 'index'])
->middleware('check.role:editor');
まとめ
Laravelのミドルウェアの基本をまとめます。
| 項目 | 内容 |
|---|---|
| 作成 | php artisan make:middleware 名前 |
| 処理タイミング | $next($request) の前後で制御 |
| 登録場所 | bootstrap/app.php |
| 適用範囲 | グローバル・単一ルート・グループ |
| パラメータ | middleware('名前:値') で渡せる |
ミドルウェアを活用することで、認証・ロギング・アクセス制御といった横断的な処理をコントローラとは分離して書くことができます。コードの責務が明確になり、保守性が大きく向上します。ぜひ自作ミドルウェアを試してみてください。