最可靠方式是优先用$_SERVER['HTTP_HOST']并结合$_SERVER['HTTPS']判断协议,因它直接来自请求头、反映真实访问域名;若为空则fallback到$_SERVER['SERVER_NAME'],并手动剥离端口,同时需校验域名合法性。

PHP 获取当前访问域名,最可靠的方式是组合 $_SERVER['HTTP_HOST'] 和 $_SERVER['HTTPS'] 判断,而不是依赖 $_SERVER['SERVER_NAME'] 或拼接 REQUEST_URI。
为什么 $_SERVER['HTTP_HOST'] 是首选
它直接来自 HTTP 请求头的 Host 字段,反映客户端实际访问的域名(含端口),不受服务器配置影响。而 $_SERVER['SERVER_NAME'] 取自 Apache/Nginx 配置,可能和用户访问地址不一致(比如泛解析、反向代理场景下容易出错)。
- 如果请求是
https://api.example.com:8080,$_SERVER['HTTP_HOST']返回api.example.com:8080 - 如果 Nginx 配置了
server_name *.example.com,$_SERVER['SERVER_NAME']可能只返回example.com,丢失子域 - 某些 CDN 或代理未透传
Host头时,HTTP_HOST会为空 —— 这时需 fallback 到SERVER_NAME,但必须加判断
如何安全提取纯域名(不含端口和协议)
直接用 parse_url() 解析 HTTP_HOST 不行(它不是完整 URL),得手动处理端口。推荐写一个简明函数:
function get_current_domain() {
$host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';
// 去掉端口(如果有)
if (($pos = strpos($host, ':')) !== false) {
$host = substr($host, 0, $pos);
}
return $host;
}
注意:$_SERVER['HTTP_HOST'] 可能被恶意构造(如伪造 Host 头),若用于白名单校验,务必配合 filter_var($host, FILTER_VALIDATE_DOMAIN) 或正则校验。
立即学习“PHP免费学习笔记(深入)”;
需要带协议和端口的完整访问地址?别硬拼 REQUEST_URI
常见错误是这样拼:$_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] —— 但 REQUEST_SCHEME 并非所有环境都存在(尤其 PHP-FPM + Nginx 场景)。更稳的做法:
- 协议:检查
$_SERVER['HTTPS'] === 'on'或$_SERVER['SERVER_PORT'] == 443 - 端口:仅当非标准端口(80/443)时才显式拼入
- 完整 URL 示例:
($is_https ? 'https' : 'http') . '://' . get_current_domain() . ($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443 ? ':' . $_SERVER['SERVER_PORT'] : '')
真正容易被忽略的是反向代理环境 —— 如果你的 PHP 运行在 Docker 容器或 behind Nginx,HTTP_HOST 通常没问题,但 SERVER_PORT 和 HTTPS 状态可能不准,此时应优先信任 X-Forwarded-Proto 和 X-Forwarded-Host(前提是代理明确设置了它们且你信任该代理)。











