Laravel 工程化实战:把中间件写成一条可组合的请求管道
test12026-09-253 次阅读
中间件就是管道的一环
Laravel 的中间件在请求进入控制器之前、响应返回客户端之前各有一道处理机会。把鉴权、限流、CORS、响应压缩这类横切关注点收进中间件,控制器就能只关心业务。多个中间件按顺序串成管道,前一个的输出是后一个的输入。
写一个带短路逻辑的中间件
下面这个中间件做 API 令牌校验,失败直接返回 401,根本不会走到控制器:
// app/Http/Middleware/CheckApiToken.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class CheckApiToken
{
public function handle(Request $request, Closure $next): Response
{
$token = $request->header('X-Api-Token');
if ($token !== config('app.api_token')) {
return response()->json(['code' => 401, 'message' => 'unauthorized'], 401);
}
// 往后续环节注入信息
$request->attributes->set('client', 'partner-a');
return $next($request);
}
}
在 Kernel 里编排顺序
全局中间件对所有请求生效,路由中间件可按需挂载,顺序就是管道顺序:
// app/Http/Kernel.php
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckApiToken::class, // 先鉴权
\Illuminate\Http\Middleware\HandleCors::class,
];
protected $middlewareGroups = [
'api' => [
'throttle:api', // 再限流
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
响应阶段也能改:terminable 中间件
如果要在响应发给客户端之后做点事(如写日志、压缩),实现 Terminable 接口:
use Symfony\Component\HttpKernel\TerminableInterface;
class CompressResponse implements TerminableInterface
{
public function handle($request, $next)
{
return $next($request);
}
public function terminate($request, $response)
{
// 响应已发出,这里做收尾,不影响用户等待
logger()->info('done', ['path' => $request->path()]);
}
}
工程化要点
- 中间件顺序有依赖:鉴权必须先于业务,CORS 通常要尽早,避免被前面的短路挡掉。
- 不要在中间件里堆业务逻辑,它只该做"请求/响应级别"的横切处理,否则难以测试和维护。
- 需要按条件跳过某个中间件时,用 $request->route()->withoutMiddleware(...) 或在路由上用 except。
- 中间件本身也要有单测:用 Router 或 handle() 直接调用,断言短路与透传两种分支。
把横切逻辑下沉到中间件,控制器保持瘦,是整个 Laravel 项目可维护性的关键一步。当管道里鉴权、限流、CORS、压缩各司其职且顺序正确时,新增业务接口几乎不用再碰这些通用代码。
T
test1
文章作者
中间件就是管道的一环 Laravel 的中间件在请求进入控制器之前、响应返回客户端之前各有一道处理机会。把鉴权、限流、...
- 分类
- 技术
- 发布时间
- 2026-09-25
- 字数
- 约 1941 字
- 阅读
- 3 次
