Slim 4中间件必须是实现MiddlewareInterface的类,process方法须返回ResponseInterface实例,否则TypeError;注册顺序决定洋葱模型层级,CORS中间件需在addRoutingMiddleware前注册。

Slim 4 中间件不是“加了就能用”,必须是类、实现 MiddlewareInterface、返回 ResponseInterface,否则直接 TypeError 报错。
中间件必须是类,不能是闭包或函数
Slim 4 彻底弃用 Slim 3 风格的 function ($request, $response, $next) 写法。任何非类形式的中间件(包括匿名函数、静态方法、全局函数)传给 $app->add() 都会触发 TypeError: Argument 1 passed to Slim\App::add() must be an instance of Psr\Http\Server\MiddlewareInterface。
- 必须用
class MyMiddleware implements Psr\Http\Server\MiddlewareInterface -
process()方法签名严格为:public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface - 别在构造函数里做 heavy 初始化——容器可能还没 ready,依赖注入应走
ContainerInterface而非$app
process() 里必须调用 $handler->handle($request),不能 return 数组或字符串
常见错误是把中间件当控制器写:return ['error' => 'forbidden'] 或 echo '403',结果抛出 TypeError: Return value of MyMiddleware::process() must be an instance of Psr\Http\Message\ResponseInterface。
- 所有响应都得是
ResponseInterface实例,例如用$responseFactory->createResponse(403)创建 - 要写 JSON?先
$response->withHeader('Content-Type', 'application/json'),再$response->getBody()->write(json_encode([...])) - 别复用参数里的
$response——它只是占位符;PSR-7 不可变,必须用工厂新建 - 想中断流程?直接返回响应对象即可,
$handler->handle($request)就不执行了
注册位置决定作用域和执行顺序
中间件不是“全局生效”或“自动扫描”,add() 的调用位置和顺序直接决定洋葱模型的包裹层级。
立即学习“PHP免费学习笔记(深入)”;
- 全局:
$app->add(new AuthMiddleware())→ 包裹所有路由,包括 404 - 路由组:
$app->group('/api', ...)->add(new JwtMiddleware())→ 只对/api/**生效 - 单个路由:
$app->get('/admin', ...)->add(new AdminOnlyMiddleware())→ 最内层,最后进、最先出 - 多个
add()按代码顺序从上到下执行,不是倒序
CORS 中间件必须在 $app->addRoutingMiddleware() 之前注册
如果 CorsMiddleware 没生效,大概率是因为它被加在了路由解析之后,导致 OPTIONS 预检请求根本没走到它那里。
- 正确顺序:
$app->add(new Tuupola\Middleware\CorsMiddleware([...]))→$app->addRoutingMiddleware() - 别用
Slim\Middleware\CorsMiddleware——Slim 官方没这个类;必须装tuupola/cors-middleware - 生产环境禁用
"origin" => ["*"];若设"credentials" => true,"origin"必须是单个具体域名 - 测试预检:用
curl -I -X OPTIONS https://yoursite.com/api/user看响应头有没有Access-Control-Allow-Origin
最易忽略的一点:Slim 4 的中间件链不接受任何“隐式返回”。每个 process() 都必须显式返回 ResponseInterface,哪怕只是透传;少一个 return,或返回了 null,整个管道就崩在那儿了。



















