request()->host() 是最稳妥获取请求Host值的方式,它自动处理反向代理场景并校验可信IP,而 $_SERVER['HTTP_HOST'] 易被伪造、domain() 返回带协议字符串且不走代理信任链,子域名提取应结合根域名后缀匹配而非硬切字符串。

request()->host() 是最常用也最稳妥的方式
直接调用 request()->host() 就能拿到请求头里的 Host 值(如 api.example.com 或 admin.example.com:8080),它已自动处理常见反向代理场景(比如 Nginx 终结 HTTPS 后传 X-Forwarded-Host),前提是你的 trust_host 配置正确(例如设为 ['127.0.0.1', '10.0.0.0/8'])。
别用 $_SERVER['HTTP_HOST'] 手动读取——它可能被伪造、在 CLI 下为空、在容器或 CDN 后拿到的是内网地址(如 172.18.0.3:9000),而 host() 内部做了白名单校验和 fallback 逻辑。
- 返回值不含协议,也不自动去掉端口;若需纯域名(无端口),得自己处理:
parse_url($request->host(), PHP_URL_HOST) - 在 Swoole 或 CLI 环境下,
host()可能返回空或抛异常,务必先判断:if (!$request->isCli() && !$request->isSwoole()) { ... } - 如果你启用了多域名路由绑定(
route_domain),host()返回的是原始请求头值,不是匹配到的路由域名;要拿绑定域名,得用$request->routeInfo()['__domain__'] ?? null,且必须在路由中间件之后执行
为什么 request()->domain() 不适合取 Host
request()->domain() 返回的是带协议的完整字符串(如 https://example.com),它底层只清洗 HTTP_HOST,不走代理头信任链。在接口统计、日志记录、子域名识别等场景下,它会漏掉反向代理、CDN、WAF 修改后的实际入口域名。
- 典型错误现象:Nginx 配置了
proxy_set_header Host api.example.com;,但 PHP 层仍收到localhost:8080——此时domain()返回http://localhost:8080,而host()在配置 trust_host 后可正确 fallback 到api.example.com - 多域名绑定时,用户访问
shop.example.com,但路由规则匹配到admin.example.com的分组,domain()仍返回shop.example.com,无法反映业务上下文 - CLI 调用时
domain()直接报错,host()至少能返回空或触发默认逻辑
需要子域名时别硬切字符串
想提取 admin.example.com 中的 admin,不要用 explode('.', $host)[0] 这类写法——它在 www.example.com、example.com、test.co.uk 场景下全错。
- ThinkPHP 提供了
$request->subDomain(),但它依赖url_domain_deploy配置开启,且只对一级子域有效(admin.example.com→admin),二级子域(dev.admin.example.com)需手动处理 - 更可控的做法是:先用
$request->host()拿到完整 host,再结合已知根域名做后缀匹配,例如str_replace('.example.com', '', $host),并加长度和字符合法性校验(只允许字母、数字、下划线) - 如果用于商户系统识别,务必查库验证该子域名是否启用,不能仅靠字符串存在就放行
真实入口域名统计必须结合 X-Forwarded-Host
接口请求统计要求“用户真正看到的域名”,这时单靠 host() 还不够——某些 CDN 或 WAF 会清空 Host 头,但保留 X-Forwarded-Host。
- 标准做法是:
$request->header('x-forwarded-host') ?: $request->host(),但必须配合trust_host白名单,否则X-Forwarded-Host可被恶意伪造 - 线上部署时,Nginx 必须显式透传:
proxy_set_header X-Forwarded-Host $host;,且确保只从可信上游传入 - 别混淆
X-Forwarded-For和X-Forwarded-Host:前者是客户端 IP,后者才是原始 Host,两者信任链要分开配置
实际拼完整 URL 时,scheme() + host() + url() 是最可控组合,但注意 url() 不含锚点、不包含子目录前缀(如部署在 /admin/ 下),这些细节在生成跳转链接或资源路径时最容易出错。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











