在PHP开发中,获取当前域名是一项常见需求,无论是生成动态链接、处理跨域请求,还是构建绝对路径,都离不开对域名的准确获取,由于服务器环境、协议类型、端口配置等因素的差异,获取域名时需要兼顾多种场景,本文将详细介绍PHP中获取当前域名的核心方法、注意事项及实际应用技巧,帮助开发者写出健壮、可靠的代码。

基础方法:$_SERVER超全局变量
PHP提供了$_SERVER超全局变量,其中存储了服务器和执行环境的信息,获取当前域名主要依赖以下几个关键元素:
$_SERVER['HTTP_HOST']:客户端请求的Host头信息,包含域名和端口号(如example.com或localhost:8080),直接反映用户访问的域名,是最常用的获取方式。$_SERVER['SERVER_NAME']:服务器配置的主机名(如虚拟主机中设置的ServerName),通常与HTTP_HOST一致,但在某些情况下(如重定向)可能不同,需结合场景使用。$_SERVER['REQUEST_URI']:请求的URI路径(如/index.php),虽不直接包含域名,但可用于拼接完整URL。
获取基础域名可直接使用:
$domain = $_SERVER['HTTP_HOST']; // 输出:example.com 或 localhost:8080
处理HTTPS与HTTP协议
现代Web应用普遍支持HTTPS协议,因此获取域名时需同时判断当前协议类型,PHP中可通过$_SERVER['HTTPS']变量判断:
- 若值为
"on"或1,表示当前为HTTPS协议; - 若值为空或
"off",表示为HTTP协议。
结合协议和域名,可构建完整的带协议的URL:
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; $fullDomain = $protocol . '://' . $_SERVER['HTTP_HOST']; // 输出:https://example.com
注意:默认情况下,HTTP使用80端口,HTTPS使用443端口,若端口号为默认值,无需额外拼接,避免URL冗余(如https://example.com:443)。

获取子域名与主域名
实际开发中,有时需要分离子域名和主域名(如从sub.example.com中提取example.com),可通过parse_url()和explode()组合实现:
- 使用
parse_url()解析域名部分:$host = parse_url($_SERVER['HTTP_HOST'], PHP_URL_HOST); // 去除可能的端口
- 通过分割域名数组,取最后两部分作为主域名:
$hostParts = explode('.', $host); $mainDomain = $hostParts[count($hostParts)-2] . '.' . $hostParts[count($hostParts)-1]; // 输出:example.com若需获取子域名(如
sub),则取数组前面的部分:$subdomain = count($hostParts) > 2 ? implode('.', array_slice($hostParts, 0, -2)) : ''; // 输出:sub
处理端口信息
当服务器使用非默认端口(如8080、8443)时,HTTP_HOST会包含端口号(如localhost:8080),若需在URL中显示端口,可通过$_SERVER['SERVER_PORT']判断:
$port = $_SERVER['SERVER_PORT']; $portStr = ($port == 80 || $port == 443) ? '' : ':' . $port; // 默认端口不显示 $fullUrl = $protocol . '://' . $_SERVER['HTTP_HOST'] . $portStr . $_SERVER['REQUEST_URI']; // 完整URL
常见问题与解决方案
-
本地开发环境差异
本地开发时,可能使用localhost、0.0.1或自定义域名(如dev.local),且可能带端口号,此时HTTP_HOST能准确反映访问地址,无需特殊处理,但需注意配置文件(如hosts)与服务器配置的一致性。 -
CDN或反向代理环境
当网站通过CDN(如Cloudflare)或反向代理(如Nginx)访问时,HTTP_HOST可能返回CDN的域名,而非真实服务器域名,此时需检查请求头中的X-Forwarded-Host或X-Forwarded-For,获取原始域名:
$host = isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : $_SERVER['HTTP_HOST'];
-
服务器配置差异
不同服务器(Apache/Nginx)对$_SERVER变量的支持可能不同,某些环境下HTTP_HOST可能未定义,需回退到SERVER_NAME:$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
代码示例与最佳实践
以下是一个综合函数,可获取当前域名、主域名、子域名及完整URL,兼容多数场景:
function getCurrentDomainInfo() {
// 协议判断
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
// 域名获取(兼容CDN)
$host = isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] :
(isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']);
// 解析域名和端口
$parsedHost = parse_url('http://' . $host);
$domain = $parsedHost['host'];
$port = $parsedHost['port'] ?? ($protocol === 'https' ? 443 : 80);
// 主域名和子域名
$hostParts = explode('.', $domain);
$mainDomain = $hostParts[count($hostParts)-2] . '.' . $hostParts[count($hostParts)-1];
$subdomain = count($hostParts) > 2 ? implode('.', array_slice($hostParts, 0, -2)) : '';
// 完整URL(不含端口,若为默认)
$fullUrl = $protocol . '://' . $domain .
($port == 80 || $port == 443 ? '' : ':' . $port) .
($_SERVER['REQUEST_URI'] ?? '');
return [
'protocol' => $protocol,
'domain' => $domain,
'main_domain' => $mainDomain,
'subdomain' => $subdomain,
'full_url' => $fullUrl
];
}
// 使用示例
$domainInfo = getCurrentDomainInfo();
echo "主域名:" . $domainInfo['main_domain']; // 输出:example.com
echo "完整URL:" . $domainInfo['full_url']; // 输出:https://example.com/path/to/page
在PHP中获取当前域名,需以$_SERVER['HTTP_HOST']为核心,结合协议判断、端口处理及服务器环境兼容性,对于复杂场景(如CDN、多级域名),需通过额外请求头或字符串解析获取准确信息,开发者应根据实际需求选择合适的方法,并注意代码的健壮性,确保在不同环境下均能正确获取域名信息,为后续开发奠定坚实基础。


















