TP8中间件必须实现PSR-15原生接口,显式use PsrHttpServerMiddlewareInterface并定义process()方法,参数与返回类型须严格匹配;文件名、类名、命名空间须完全一致,否则静默失效。

中间件类必须实现 PSR-15 接口
TP8 不再识别仅含 handle() 方法的类,哪怕它继承自旧版 thinkMiddleware。容器在反射时会直接跳过未实现 PsrHttpServerMiddlewareInterface 的类,导致中间件静默失效——请求不经过、也不报错,排查时容易误判为路由或控制器问题。
正确写法需显式 use 并 implements:
namespace appmiddleware;
use PsrHttpServerMiddlewareInterface;
use PsrHttpMessageServerRequestInterface;
use PsrHttpServerRequestHandlerInterface;
use PsrHttpMessageResponseInterface;
class Auth implements MiddlewareInterface
{
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
// 你的逻辑
return $handler->handle($request);
}
}
- 接口名、方法名、参数类型、返回类型缺一不可;
- 别用
thinkcontractMiddlewareInterface—— TP8 已弃用该路径,只认 PSR 原生接口; - 若类中已有同名但签名不符的
handle(),必须删掉,否则 PHP 8.1+ 会因方法重载冲突报Fatal error。
构造函数参数必须带类型且可被容器解析
TP8 容器依赖 PHP 8 的反射能力自动注入依赖,但前提是构造函数参数有明确类型声明。如果中间件需要日志、配置或数据库实例,不能靠运行时手动 new,得让容器来配。
错误示例:public function __construct($logger) —— $logger 无类型,容器无法判断该注入哪个实现,最终传入 null 或抛出 No entry found for ... 错误。
正确做法:
- 所有参数加类型:例如
private PsrLogLoggerInterface $logger; - 确保该类型已在容器中注册(如
config/log.php中'default'驱动名有效); - 避免在构造函数里做耗时操作(如连接数据库),TP8 中间件实例在请求前就已创建,频繁初始化会拖慢整个管道。
别在中间件里调用 session() 或 $request->param()
TP8 的 ServerRequestInterface 是不可变对象,$request->param() 这类 TP6 风格的方法已被移除。而 session() 函数底层依赖全局状态,在 PSR-15 管道中可能尚未初始化或已被重置,调用后大概率返回空或触发 RuntimeException。
替代方案:
- 取 POST 数据:
$request->getParsedBody()(已解析的数组)或$request->getBody()->getContents()(原始字符串); - 取 GET 参数:
$request->getQueryParams(); - 存取 session:改用
$request->getAttribute('session'),前提是已在前置中间件中通过withAttribute('session', $session)注入; - 若必须用 session,建议把相关逻辑下沉到控制器或服务层,中间件只做轻量校验。
文件名与类名必须严格一致且路径匹配 PSR-4
TP8 的自动加载完全依赖 composer.json 中的 psr-4 映射。如果中间件文件叫 Auth.php,但类定义是 class CheckAuth,或者文件放在 app/middleware/v1/ 却没在 autoload 里声明该子命名空间,Composer 就找不到这个类,容器自然无法实例化。
检查步骤:
- 确认
composer.json的autoload.psr-4包含"app\middleware\": "app/middleware/"; - 文件路径必须为
app/middleware/Auth.php,类名为appmiddlewareAuth; - 执行
composer dump-autoload -o强制刷新映射,别依赖自动触发; - 升级后若发现中间件突然不执行,优先
php -r "var_dump(class_exists('app\middleware\Auth'));"验证类是否能被加载。
最常被忽略的是 autoload 映射未更新或文件名大小写不一致(尤其在 Linux 生产环境),这类问题不会报错,只会让中间件彻底消失。

















