在PHP中获取当前域名,最核心的方案就是读取预定义变量$_SERVER['HTTP_HOST'],但严格来说还需要结合$_SERVER['SERVER_NAME']做安全兜底,或者用parse_url()从完整URL中提取,不同场景取舍不同。 下面我聊一下实际项目中常用的几种写法,以及你迟早会踩到的坑。
php获取当前域名的方法有哪些?直接给你能跑的代码
用$_SERVER['HTTP_HOST']取域名(最直接)
这个变量返回的是HTTP请求头里的Host字段,比如你在浏览器打开https://blog.example.com/article/1,它就会输出blog.example.com。
<?php $host = $_SERVER['HTTP_HOST']; echo $host; // 输出 blog.example.com
注意:如果当前请求不是通过Web服务器发起的,比如你用命令行跑脚本,$_SERVER['HTTP_HOST']可能不存在,这个值如果用户手动构造请求头,是可以被伪造的,后面我会专门说安全问题。
用$_SERVER['SERVER_NAME']取域名(更稳定但有小坑)
SERVER_NAME来自服务器配置中的ServerName指令,一般不会被客户端请求头直接影响,同样输出blog.example.com,但它通常不包含端口号。
<?php echo $_SERVER['SERVER_NAME'];
不过有两点要注意:如果服务器配置的是IP地址,它就会输出IP;如果虚拟主机配置里写死了其他域名,也会跟着走,所以在多数场景下,HTTP_HOST更贴近用户实际访问的地址。
用parse_url()从完整URL里提取(最通用)
有时候你已经拿到了完整的URL,比如https://example.com/path?query=1,这时候直接让parse_url()干活就行。
<?php $url = 'https://user:pass@example.com:8080/path?arg=1#hash'; $parts = parse_url($url); echo $parts['host']; // example.com
这个方法在反向代理、URL重写或者你手动拼接地址时特别有用,也是业内比较推荐的做法。
三种方法怎么选?对比一下
| 方法 | 包含端口? | 安全性 | 适用场景 | |
|---|---|---|---|---|
$_SERVER['HTTP_HOST'] |
请求头中的Host | 可能包含 | 低,可伪造 | 快速输出完整域名 |
$_SERVER['SERVER_NAME'] |
服务器配置名称 | 不含 | 较高 | 后台脚本、CLI |
parse_url() |
从完整URL提取 | 不包含 | 取决于输入源 | 已有URL时解析 |
行业共识认为,前后端分离或接口开发时,最好把HTTP_HOST当作“用户看到什么就返回什么”的参考,而SERVER_NAME当作“服务器认为你是谁”的参考。
php获取当前域名和路径的实用技巧
如果你不只是想要域名,还想带上路径、协议甚至端口,那就得组合几个$_SERVER变量,我经常这么干:
拼出完整的当前URL
<?php
$isHttps = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|| ($_SERVER['SERVER_PORT'] ?? 443) == 443;
$protocol = $isHttps ? 'https://' : 'http://';
$host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'];
$uri = $_SERVER['REQUEST_URI'] ?? '';
$fullUrl = $protocol . $host . $uri;
echo $fullUrl;
这样就能同时拿到协议、域名和请求路径,注意REQUEST_URI会包含查询字符串,比如/article/1?page=2,如果你只想要路径部分,可以用strtok($uri, '?')分割。
区分域名、路径和查询参数
几个常见变量各司其职,新手容易搞混:
HTTP_HOST:域名(可能带端口)REQUEST_URI:路径+查询字符串SCRIPT_NAME:入口文件路径PHP_SELF:入口文件路径(相对document root)QUERY_STRING:查询字符串,比如page=2
举例:访问http://localhost:8080/index.php?page=2时,HTTP_HOST是localhost:8080,REQUEST_URI是/index.php?page=2,SCRIPT_NAME是/index.php,QUERY_STRING是page=2。
处理子目录和伪静态的干扰
如果你的站点部署在子目录,比如http://example.com/blog/,用REQUEST_URI取到的路径会包含/blog前缀,这时候别急着拼接,先判断项目根目录的位置,一个比较稳妥的做法是用dirname($_SERVER['SCRIPT_NAME'])获取当前脚本所在目录,但如果你用了路由重写,SCRIPT_NAME可能指向index.php,目录结构并不等于用户看到的路径。
多数情况下,真正要用的域名就是HTTP_HOST加上协议,路径交给路由去解析,别自己瞎拼。
php获取当前域名不带http的纯域名写法
很多场景只需要域名本体,比如生成二维码、设置cookie或做跨域白名单,这时候你需要把http://和端口都剥掉。
从

HTTP_HOST
直接去掉端口

HTTP_HOST
<?php$host = $_SERVER['HTTP_HOST'];$domain = preg_replace('/:d+$/', '', $host);echo $domain; // example.com如果HTTP_HOST里没有端口,正则也不会误伤,用explode也行:explode(':', $host)[0],但有IPv6地址的时候会翻车,比如[::1]:8080,所以更推荐正则。
去掉www前缀获取顶级域名
做站时经常需要把www.example.com归一化成example.com,可以用str_replace或正则:
<?php
$host = 'www.example.com';
$mainDomain = preg_replace('/^www./i', '', $host);
echo $mainDomain;
注意:这只是把www去掉,不适用于blog.example.com这类二级域名,如果你想要“真正的顶级域名”(比如从news.example.co.uk提取example.co.uk),那就得维护一份公共后缀列表,光靠PHP代码处理不了。
本地环境怎么兼容?
本地开发时,HTTP_HOST经常是localhost或0.0.1,有时还带着端口,如果你想区分本地和线上,可以这样写:
<?php
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$host = preg_replace('/:d+$/', '', $host);
if (in_array($host, ['localhost', '127.0.0.1'], true)) {
// 本地环境,走测试逻辑
} else {
// 线上环境
}
这样就能安全地在本地和线上之间切换,不会因为localhost误判成线上域名。
实际项目中的安全防护与框架姿势
别直接把HTTP_HOST输出到页面或SQL里
HTTP_HOST是客户端可控的,攻击者可以发送一个恶意Host请求头,引发缓存投毒或者密码重置链接污染,业内专家指出,最有效的办法是配置一个“合法域名白名单”,校验不过就抛异常。
<?php
$allowedHosts = ['www.example.com', 'example.com'];
$host = $_SERVER['HTTP_HOST'] ?? '';
if (!in_array($host, $allowedHosts, true)) {
header('HTTP/1.1 400 Bad Request');
exit('Invalid Host');
}
如果站点有很多域名,可以把白名单放到环境变量或配置文件中,别硬编码在业务代码里。
在Laravel和ThinkPHP里怎么取域名?
Laravel提供了request()->getHost()和request()->getHttpHost(),前者返回不带端口的域名,后者返回带端口的域名,你还可以用request()->secure()

判断是否HTTPS。
ThinkPHP则可以用request()->domain()获取当前域名(不带端口和协议),用request()->url()获取完整URL,实际开发中,建议直接用框架封装的方法,别碰原生$_SERVER,因为框架已经处理了反向代理和CLI的兼容问题。
从PHP 7.0到现在,函数有什么变化?
PHP自带函数里其实没有专门的getCurrentDomain(),所以社区惯例就是用$_SERVER组合,近年来PHP版本迭代很快,但$_SERVER这套机制一直没变,你可以放心用,唯一需要注意的是在CLI模式下,$_SERVER里通常没有HTTP_HOST,这时要主动判断一下。
写到最后,别忽略一个小细节
无论你用哪种方法,获取到的都是“用户请求时携带的域名”,如果你用了CDN或负载均衡,HTTP_HOST仍然能用,但HTTPS状态可能藏在X-Forwarded-Proto头里,这时候判断协议就要多检查一层:
<?php
$isHttps = ($_SERVER['HTTPS'] ?? 'off') !== 'off'
|| ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https';
所以最稳的组合拳是:用HTTP_HOST做输出参考,用SERVER_NAME做内部校验,用parse_url()处理已有URL,记住这句话,基本就能应付大多数需求了。
关于php获取当前域名的三个高频疑问
问:php获取当前域名时,$_SERVER['HTTP_HOST']为什么可能不安全?
因为HTTP_HOST直接来自请求头,客户端可以任意修改它,如果后端用它生成链接、设置cookie或拼接SQL,攻击者就能提交一个伪造的Host来污染结果,解决办法是维护白名单,服务器配置里也尽量把ServerName设置成固定值。
问:php获取当前域名如何排除端口号?
用preg_replace('/:d+$/', '', $_SERVER['HTTP_HOST'])就可以去掉末尾的端口,注意这个正则要求IP是IPv4格式,如果遇到IPv6地址,HTTP_HOST会像[::1]:8080,正则匹配不到端口,最好先用strrpos配合str_replace处理。
问:php获取当前域名在命令行CLI模式下为什么拿不到?
CLI模式下没有HTTP请求,自然也没有Host头,$_SERVER['HTTP_HOST']未定义,如果需要支持CLI,可以先用$_SERVER['SERVER_NAME']兜底,或者定义常量来手动指定当前域名,网上有些代码直接写$_SERVER['HTTP_HOST']不做判断,跑CLI脚本时就会报未定义索引,所以建议始终用运算符给出默认值。
图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/775246.html

