不需要重写CorsMiddleware类,但需检查app/middleware.php注册方式、确保其置于数组首位、在app.php中配置method_filter或allow_method、在handle()中先判OPTIONS并返回204响应、动态设置CORS头须在$next()后一次性写入Response对象。

ThinkPHP 6.0 升级到 6.1 后 CorsMiddleware 是否需要重写
不需要重写中间件类本身,但必须检查 app/middleware.php 中的注册方式和执行顺序——6.1 对中间件生命周期更严格,旧写法容易被跳过或覆盖。
升级后 OPTIONS 预检请求突然 405 或无响应
6.1 默认加强了 method_filter 检查,即使中间件里写了 $request->isOptions() 判断,若没在 app/config/app.php 中显式放行 OPTIONS,框架会在路由前就拦截并返回 405。
- 打开
app/config/app.php,确认'method_filter' => false,或至少把'OPTIONS'加进'allow_method'数组 - 中间件 handle() 开头仍需保留
if ($request->isOptions()) { return response('', 204); },不能只依赖配置 - 用
curl -X OPTIONS -I http://your-api.com/api/test验证真实响应状态码,别信浏览器 Network 的“预检被缓存”假象
Access-Control-Allow-Origin 动态白名单在 6.1 中失效
6.1 的 Response 对象对 header 写入时机更敏感,如果中间件里先调了 $next($request) 再设 header,响应头大概率被丢弃——必须在 $response = $next($request) 之后、return 之前一次性设置全部 CORS 头。
- 错误写法:
header('Access-Control-Allow-Origin: *');—— 6.1 下完全无效,且可能触发headers already sent - 正确写法:
$response->header('Access-Control-Allow-Origin', $origin);,其中$origin必须来自$request->header('origin')并做过白名单校验 - 如果启用了
credentials,$origin不能是*,也不能是空字符串或未校验的原始值
为什么升级后跨域只对 GET 有效,POST/PUT 仍失败
不是中间件逻辑变了,而是 6.1 默认禁用了路由自动 fallback 到 OPTIONS —— 如果你原来靠 Route::get() + allowCrossDomain() 混用,升级后这部分逻辑不再兜底。
立即学习“PHP免费学习笔记(深入)”;
- 确保所有需要跨域的非 GET 路由都显式声明了允许方法:
->allowCrossDomain(['https://a.com'], true)或统一走中间件 - 检查是否误删了
app/middleware.php中的中间件类引用,6.1 不再从配置文件自动加载未注册的中间件 - 若用了多应用模式,确认每个应用目录下的
middleware.php都同步更新,6.1 不再继承全局中间件配置
最常被忽略的一点:6.1 的中间件执行链一旦遇到 return response() 就彻底终止,不会再走后续中间件。所以 CorsMiddleware 必须放在 app/middleware.php 数组的第一位,且内部不能有未捕获的异常——否则连 204 都发不出去。



















