thinkphp 5.1+ 的 request()->header() 键名统一为小写且连字符转下划线,如 content-type → content_type;需用 dump(request()->header()) 查看实际可用键名,不可用 http_ 前缀或原始大小写形式。
header键名怎么写">
ThinkPHP 的 request()->header() 键名是小写且用下划线分隔
ThinkPHP 5.1+ 对 HTTP 请求头做了标准化处理:所有 header 键名被自动转为小写,并将连字符(-)替换为下划线(_)。这意味着原始请求中的 Content-Type 会变成 content_type,X-Requested-With 变成 x_requested_with。
这是框架内部调用 getallheaders() 后统一 normalize 的结果,不是你手写错了,而是它本来就这样设计。
-
request()->header('user_agent')✅ 正确(对应User-Agent) -
request()->header('HTTP_USER_AGENT')❌ 错误(TP 不识别 CGI 风格前缀) -
request()->header('User-Agent')❌ 错误(大小写和连字符不匹配 normalize 规则) -
request()->header('authorization')✅ 正确(对应Authorization)
如何快速确认当前请求里有哪些可用 header 键
别猜,直接 dump 出来看。在控制器里加一行:
dump(request()->header());
你会看到一个关联数组,键全是小写下划线格式,比如:
[ 'host' => 'localhost:8000', 'connection' => 'keep-alive', 'authorization' => 'Bearer abc123', 'x_token' => 'xxx' ]
这个输出就是你后续调用的合法键名来源 —— 它取决于实际请求发了什么,也受服务器配置影响(如 Nginx 默认不透传 X-* 头,需显式配置 proxy_set_header X-Token $http_x_token;)。
自定义 header(如 X-App-Version)取不到?检查中间件和 Web 服务器
TP 能读到 header 的前提是:该 header 真的到达了 PHP-FPM 或 CLI 环境。常见断点有:
- Nginx/Apache 没有透传自定义头(尤其
X-开头),需在配置中显式放行 - Swoole 模式下,
request()->header()行为与 FPM 一致,但某些代理层(如 Cloudflare)可能过滤或重命名 header - 浏览器发起的跨域请求(CORS),若未在
Access-Control-Allow-Headers中声明,该 header 根本不会发送到后端 - TP 的
Header中间件默认启用,但如果你手动覆盖了Request实例或用了非标准初始化方式,header 可能为空
想兼容原始大小写或连字符?别绕路,直接用 $_SERVER
如果某个场景必须按原样读(比如对接遗留系统、调试时比对 raw header),可以绕过 TP 封装:
// 原始 CGI 格式(注意 HTTP_ 前缀 + 大写 + 下划线)
$raw = $_SERVER['HTTP_X_APP_VERSION'] ?? null;
// 或者遍历所有 SERVER 变量找
$headers = array_filter($_SERVER, function($k) {
return substr($k, 0, 5) === 'HTTP_';
}, ARRAY_FILTER_USE_KEY);
但要注意:$_SERVER 在 CLI/Swoole 下行为不一致,且部分环境(如某些 FastCGI 配置)会丢弃 HTTP_*;而 request()->header() 是 TP 统一抽象后的稳定接口,日常开发优先用它。
真正容易被忽略的是:header 键名 normalize 发生在 Request 初始化阶段,一旦 request 实例创建完成,header 就固定了 —— 所以不要试图在中间件里“动态注入” header 到 request()->header(),那只会失败。需要改 header,得从入口或前置服务层下手。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











