Laravel 中应统一使用 request()->header() 获取请求头,它自动处理大小写不敏感、代理头标准化及环境兼容性;自定义响应头须通过中间件设置 Response 实例;队列任务中无法访问请求头,需提前提取关键值传参;Nginx/Apache 配置(如 underscores_in_headers on)直接影响 header 透传。

直接用 request()->header() 拿请求头,别碰 $_SERVER
Laravel 的 request()->header() 是唯一推荐方式。它自动处理大小写不敏感、X-Forwarded-For 等代理头的标准化,而直接读 $_SERVER['HTTP_X_CUSTOM_HEADER'] 会漏掉被 Apache/Nginx 重写的头(比如把 X-Api-Key 变成 HTTP_X_API_KEY),且在 CLI 或 Swoole 环境下行为不一致。
常见错误现象:request()->header('X-Api-Key') 返回 null,但 Postman 明明发了——大概率是 Nginx 默认剥离了带下划线的 header,或用了 fastcgi_param 未显式透传。
- 用
request()->header('X-Api-Key'),不是request()->headers->get('X-Api-Key')(后者也能用,但前者更直觉、自动 trim) - 所有 header 名不区分大小写,
request()->header('x-api-key')和request()->header('X-API-KEY')效果一样 - 如果 header 值是数组(如多个
Cookie),request()->header()默认只返回第一个;要全量用request()->header('Cookie', null, true)(第三个参数设为true)
自定义 Header 必须在中间件里加,不能在控制器里 header()
Laravel 响应头必须通过 Response 实例设置,控制器里调 header('X-Trace-ID', 'abc123') 是无效的——PHP 的原生 header() 在 Laravel 的响应生命周期中早已失效,甚至可能触发 “headers already sent” 错误。
使用场景:需要统一加审计 ID、版本标识、CSP 策略等全局响应头。
- 新建中间件:
php artisan make:middleware AddCustomHeader - 在
handle()里写:$response = $next($request); $response->headers->set('X-Trace-ID', Str::uuid()); return $response; - 注册到
$middlewareGroups['web']或$middleware,取决于是否需要对 API 路由生效 - 避免在中间件里做耗时操作(比如查 DB 生成 header 值),否则拖慢所有请求
Request::header() 在队列任务里拿不到,因为没 HTTP 上下文
队列任务运行在 CLI 进程,没有原始请求头。哪怕你把 Request 对象序列化传进去,header() 方法也会返回空——这不是 Bug,是设计使然。试图在 Job 构造函数里接收 Request 并缓存 header,等于埋雷。
正确做法是在发起队列前,把真正需要的 header 值抽出来,作为参数显式传入:
- 比如需要记录请求来源:
ProcessOrderJob::dispatch($order, request()->header('X-Forwarded-For')) - 不要传整个
request()或$request->all(),容易序列化失败或泄露敏感字段 - 如果 header 值本身依赖运行时计算(如签名验证结果),应在 dispatch 前完成验证,再把结果传入
Nginx/Apache 配置影响 header 透传,特别是带下划线的 key
Apache 默认丢弃含下划线的 header(如 X_Api_Key),Nginx 默认把下划线转为短横线,还可能因 underscores_in_headers off 直接忽略。这是线上环境最常被忽略的环节——代码没问题,配置卡脖子。
典型错误现象:本地开发能拿到 X-Auth-Token,上线后始终 null;或者 curl -H "X_Api_Key: abc" ... 在服务器上完全收不到。
- Nginx:确保配置中有
underscores_in_headers on;,并在location块里显式透传:proxy_set_header X-Api-Key $http_x_api_key; - Apache:在虚拟主机里加
SetEnvIfNoCase ^X-Api-Key$ ^(.*)$ X_API_KEY=$1,再在 Laravel 中用request()->server('HTTP_X_API_KEY')(不推荐,仅作兜底) - 测试是否生效:用
curl -I -H "X-Test: 123" https://yoursite.com,然后在控制器里Log::info(request()->header('X-Test'))查日志










