Laravel 中间件指南

创建、注册和应用 Laravel 中间件:HTTP 过滤器、认证守卫、限流、可终止中间件和组配置。

1. 创建中间件

// php artisan make:middleware EnsureApiKey

class EnsureApiKey
{
    public function handle(Request $request, Closure $next): Response
    {
        $key = $request->header('X-API-Key') ?? $request->query('api_key');

        if (! $key || ! ApiKey::where('key', $key)->where('is_active', true)->exists()) {
            return response()->json(['error' => 'API 密钥无效'], 403);
        }

        return $next($request);
    }
}

// 带参数的中间件
class RequireRole
{
    public function handle(Request $request, Closure $next, string ...$roles): Response
    {
        if (! in_array($request->user()->role, $roles)) {
            abort(403, '权限不足');
        }
        return $next($request);
    }
}

2. 注册中间件 (Laravel 11+)

// bootstrap/app.php
return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->alias([
            'role'    => RequireRole::class,
            'api.key' => EnsureApiKey::class,
        ]);
        $middleware->appendToGroup('api', [EnsureApiKey::class]);
    })->create();

3. 路由中间件应用

Route::get('/admin', AdminController::class)->middleware('auth', 'role:admin');

Route::middleware(['auth', 'verified'])->group(function () {
    Route::resource('articles', ArticleController::class);
});

4. 可终止中间件

class LogResponseTime implements TerminableMiddleware
{
    private float $startTime;

    public function handle(Request $request, Closure $next): Response
    {
        $this->startTime = microtime(true);
        return $next($request);
    }

    // 响应发送给客户端后调用
    public function terminate(Request $request, Response $response): void
    {
        $duration = (microtime(true) - $this->startTime) * 1000;
        RequestLog::create([
            'path'     => $request->path(),
            'status'   => $response->getStatusCode(),
            'duration' => round($duration),
        ]);
    }
}