TP5获取当前网站完整域名带端口,优先用Request::instance()->domain()拿到“协议+Host”,再用SERVER_PORT或X-Forwarded-Port补全端口;在反向代理和HTTPS环境里,单靠SERVER_NAME往往会丢端口。 下面按可直接复制的代码、常见场景和排查路径展开。
TP5获取当前域名带端口的方法
控制器里先拿基础值
在TP5项目中,最直接的方式是引入think\Request。domain()返回当前包含协议和域名的URL,多数情况下Host里已经带了端口,例如本地环境会得到http://localhost:8080。
use think\Request; $request = Request::instance(); $fullDomain = $request->domain();
如果只是拼资源地址、回调地址或跳转地址,这个值可以先用,但生产环境要留意两点:反向代理可能改写Host头,HTTPS可能在代理层终止,这两点都会让domain()拿到http而不是https,或者只拿到域名没有端口。
写一个可复用的辅助函数
TP5.0可放在application/common.php,TP5.1可放在app/common.php,函数先取框架的scheme()、host()、port(),再判断Host里是否已有端口,避免重复拼接。
function current_full_domain()
{
$request = \think\Request::instance();
$scheme = $request->scheme();
$host = $request->host();
$port = (int) $request->port();
if (!preg_match('/:\d+$/', $host) && !in_array($port, [80, 443], true)) {
$host .= ':' . $port;
}
return $scheme . '://' . $host;
}
调用时直接写$url = current_full_domain();,本地localhost:8080会得到http://localhost:8080,自定义HTTPS端口8443会得到https://www.example.com:8443。80和443是默认端口,浏览器通常会省略,代码里也不必强行补上。
反向代理场景要读转发头
Nginx、CDN和负载均衡常见做法是把请求转发给PHP-FPM,此时REMOTE_ADDR和SERVER_PORT可能变成内网地址与内部端口,可以在辅助函数里优先读取X-Forwarded-Proto、X-Forwarded-Host、X-Forwarded-Port,但只应在可信代理后面使用。
function current_full_domain()
{
$request = \think\Request::instance();
$scheme = $request->header('x-forwarded-proto') ?: $request->scheme();
$host = $request->header('x-forwarded-host') ?: $request->host();
$port = (int) ($request->header('x-forwarded-port') ?: $request->port());
if (!preg_match('/:\d+$/', $host) && !in_array($port, [80, 443], true)) {
$host .= ':' . $port;
}
return $scheme . '://' . $host;
}
Nginx侧可以这样配置,宝塔面板可在“网站-设置-反向代理-配置文件”里检查:
proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port;
这里用$http_host而不是$host,是因为$host在部分配置下会丢掉非标准端口,改完后用nginx -t检查,再重载Nginx。
TP5获取当前域名带端口与Request::url区别对比
不少项目会把domain()和url(true)混着用,两者目标不同:前者偏“站点根地址”,后者偏“当前请求地址”,下面这张表按实际输出做对比。
| 方法或变量 | 示例输出 | 端口表现 | 适用场景 |
|---|---|---|---|
Request::instance()->domain() |
https://www.example.com:8443 |
通常跟随Host头,可能含端口 | 拼资源地址、站点根地址 |
Request::instance()->url(true) |
https://www.example.com:8443/news/1.html?id=2 |
跟随Host头,通常含端口 | 当前页面完整地址 |
$_SERVER['HTTP_HOST'] |
www.example.com:8080 |
通常含端口 | 快速取Host,但要校验 |
$_SERVER['SERVER_NAME'] |
www.example.com |
通常不带端口 | 服务器配置名,不适合单独拼完整域名 |
$_SERVER['SERVER_PORT'] |
8080 |
纯端口数字 | 配合协议补全端口 |
本地开发TP5获取当前域名带端口为什么少了端口
本地用php -S 0.0.0.0:8080或Apache虚拟主机时,浏览器访问地址是http://localhost:8080,HTTP_HOST一般会带8080,如果代码只取了SERVER_NAME,结果就是localhost,端口自然消失,另一种情况是框架或中间件里把Host固定成了配置域名,也会覆盖真实端口,排查时先打印$_SERVER['HTTP_HOST']、$_SERVER['SERVER_PORT']和$request->host(),看端口丢在哪一层,需要验证代理转发时,可以用命令模拟:
curl -H "Host: demo.com:8080" http://127.0.0.1:8080/index/index/domain
返回结果里应出现demo.com:8080,如果只出现demo.com,说明入口或代理层改写了Host。
国内服务器宝塔面板部署TP5获取完整域名带端口的检查点
国内服务器常见“Nginx+宝塔+TP5”组合,检查顺序可以按下面走:
- 站点配置里的
server_name是否只写了域名,是否漏了非标准端口。 - 反向代理配置是否使用
$http_host,是否传递了X-Forwarded-Port。 - PHP-FPM是否收到正确的
HTTP_HOST,可在控制器临时输出$request->host()。 - 是否启用了CDN或WAF,回源端口和回源Host是否被改写。
- HTTPS证书是否在代理层终止,若是,PHP侧要读
X-Forwarded-Proto。
据PHP官方文档,HTTP_HOST来自客户端请求头,不能默认当作可信输入,业内专家指出,凡是把域名用于支付回调、密码重置链接的场景,都要对Host头做白名单校验,避免请求头被伪造后生成错误链接。
TP5获取当前域名带端口需要付费扩展吗
这类基础URL获取不需要购买付费扩展。TP5自带的Request类与$_SERVER变量已经够用,真正要投入的是代理配置、HTTPS判断和域名白名单校验,行业共识认为,付费插件更适合复杂路由、权限或后台生态,单纯取“协议+域名+端口”没必要额外引入依赖,若项目已有统一URL生成服务,把辅助函数放进公共文件或中间件即可,后续换框架也容易迁移。
收束
把流程收束成一句话:先用Request::instance()->domain()拿协议和Host,再用SERVER_PORT或X-Forwarded-Port补端口,最后做Host白名单校验,生产环境不要把HTTP_HOST直接拼进支付回调或密码重置链接。
TP5获取当前网站完整域名带端口的常见问答
TP5获取当前网站完整域名带端口时,domain()和HTTP_HOST选哪个?
看场景,只要站点根地址、且代理配置规范,用domain()更省事;需要自己控制端口补全和代理头时,用HTTP_HOST配合SERVER_PORT更透明,两者都要做Host校验。
为什么线上HTTPS获取到的是http,而且没有端口?
常见原因是HTTPS在Nginx或CDN终止,PHP侧只看到内部HTTP请求,让代理传递X-Forwarded-Proto和X-Forwarded-Port,代码里优先读这两个头,若端口是443,浏览器本来就会省略,不需要强行显示。
TP5获取当前网站完整域名带端口需要改框架源码吗?
不需要,把辅助函数放在application/common.php或app/common.php,或在中间件里统一赋值给模板即可,结论是:优先用Request::instance()->domain(),再用SERVER_PORT和代理头补全,生产环境同时做Host白名单校验。