TP6/TP8中间件必须用\think\middleware\AllowCrossDomain::class格式,开头反斜杠和::class缺一不可;执行顺序影响CORS与Session生效,需AllowCrossDomain在SessionInit之前;TP8不支持路由传参及protected $except,须改用配置或容器注入。

中间件类名写法必须带反斜杠前缀
TP6/TP8 都不接受字符串形式的类名,'think\middleware\AllowCrossDomain' 会直接报错 Class not found。框架加载时把没加反斜杠的字符串当作当前命名空间下的类去查,而它根本不存在。
正确写法只有一种:\think\middleware\AllowCrossDomain::class。注意开头的 \ 不能省,::class 也不能漏。
常见错误包括:
- 在
app/middleware.php里写use think\middleware\AllowCrossDomain—— 该文件是纯配置脚本,use完全被忽略 - 写成
'\think\middleware\AllowCrossDomain'(字符串)—— PHP 不会自动解析为类引用,实例化失败 - 多应用项目中只在主应用配了中间件,子应用(如
app/api/middleware.php)没单独加,导致接口层中间件不生效
中间件执行顺序决定 CORS 和 Session 是否起作用
CORS 头被覆盖、Session 设了取不到,十有八九是中间件位置错了。TP6/TP8 的中间件链是严格顺序执行的,AllowCrossDomain 必须比 SessionInit 更早,否则跨域响应头可能被后续中间件或控制器输出覆盖;而 SessionInit 又必须在路由解析之前,否则无法读取 Cookie 中的 session_id。
推荐顺序(从上到下):
\think\middleware\AllowCrossDomain::class\think\middleware\SessionInit::class-
\think\middleware\LoadLangPack::class(TP6)或\think\middleware\Lang::class(TP8) - 你自定义的鉴权、日志等中间件
如果用了自定义 CORS 中间件,务必在开头加 if ($request->isOptions()) { return response('', 204); } 拦住预检请求,否则 OPTIONS 请求会穿透到路由层,返回 404 或空内容。
TP8 中间件注册后仍不执行?检查 PHP 版本与反射兼容性
TP8 在 PHP 8.1+ 环境下对中间件类的反射更严格。如果中间件类没有声明命名空间,或者构造函数参数类型与框架期望不匹配(比如老插件里写了 public function __construct(Request $request, $config = [])),实例化时会抛出 BindingResolutionException,且默认静默跳过,不报错也不执行。
排查方法:
- 确认中间件类以
namespace app\middleware;开头(非全局命名空间) - 构造函数参数尽量精简,TP8 推荐只保留
Request和必要配置,避免可变参数或未声明类型的变量 - 临时在中间件
handle()开头加throw new \Exception('hit');,看是否触发 —— 不触发就说明根本没实例化成功 - 运行
php -d display_errors=1 -d error_reporting=-1 think console,观察启动阶段是否有反射异常
中间件传参方式在 TP8 中已失效
TP6 支持在路由分组里用 ->middleware([CheckAuth::class, ['admin']]) 传参,TP8 已移除该机制。所有中间件参数必须通过配置文件或依赖注入传递,硬编码进路由链的参数会被忽略。
替代方案有两种:
- 把参数写进配置,例如
config/auth.php里设'roles' => ['admin', 'editor'],中间件内用config('auth.roles')读取 - 改用容器绑定:在
app/provider.php中写$app->bind(CheckAuth::class, function ($app) { return new CheckAuth(['admin']); });
特别注意:TP8 不再支持中间件类里用 protected $except = ['login']; 做排除列表,这类逻辑必须移到中间件内部手动判断 $request->url(),否则配置无效。
中间件不是“配完就跑”,TP8 对类加载、反射、执行时机的要求明显收紧。最容易被忽略的是:你以为中间件在运行,其实它连构造函数都没进去过 —— 先验证实例化,再谈逻辑。

















