一、前言

在PHP开发中,获取当前域名是一个常见的需求,比如用于生成完整URL、判断当前环境、做域名授权验证、记录来源信息等。本文将总结多种PHP获取当前域名的方法,包括获取主域名、顶级域名、完整URL路径、端口等实用技巧。

主要获取主域名,自动识别证书,例如:https://www.csdn.net/,可以当作普通函数使用,或者在框架中添加函数使用。

二、获取当前域名(自动识别HTTPS)

这是最常用的方法,可以自动判断当前是HTTP还是HTTPS协议:

<?php
function getHostDomain()
{
    return getHttpType() . $_SERVER['SERVER_NAME'];
}

/**
 * 获取 HTTPS协议类型
 * @return string
 */
function getHttpType()
{
    return $type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';
}

// 使用示例
echo getHostDomain(); // 输出:https://www.example.com

说明:

  • $_SERVER['HTTPS']:判断是否启用了HTTPS
  • $_SERVER['HTTP_X_FORWARDED_PROTO']:用于反向代理(如Nginx代理)场景下判断协议
  • $_SERVER['SERVER_NAME']:获取服务器域名(不含端口号)

三、$_SERVER变量获取域名相关

PHP的$_SERVER超全局变量包含了大量服务器和环境信息,以下是获取域名相关的常用键值:

<?php
// 获取当前域名(不含端口号)
echo $_SERVER['SERVER_NAME'];  // www.example.com

// 获取当前域名(含端口号)
echo $_SERVER['HTTP_HOST'];    // www.example.com:8080

// 获取当前请求URI
echo $_SERVER['REQUEST_URI'];  // /index.php?id=123

// 获取当前完整URL
$protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$url = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
echo $url; // https://www.example.com/index.php?id=123

四、获取完整URL(包含路径和参数)

有时候我们需要获取包含路径和参数的完整URL:

<?php
/**
 * 获取当前页面完整URL
 * @return string
 */
function getFullUrl()
{
    $protocol = isHttps() ? 'https://' : 'http://';
    return $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}

/**
 * 判断是否为HTTPS
 * @return bool
 */
function isHttps()
{
    if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
        return true;
    }
    if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
        return true;
    }
    if ($_SERVER['SERVER_PORT'] == 443) {
        return true;
    }
    return false;
}

// 使用示例
echo getFullUrl();

五、获取域名的各个部分

通过parse_url函数可以解析URL的各个组成部分:

<?php
$url = 'https://www.example.com:8080/path/page.html?id=123#anchor';

$parts = parse_url($url);
print_r($parts);

// 输出结果:
// Array
// (
//     [scheme] => https        // 协议
//     [host] => www.example.com // 域名
//     [port] => 8080            // 端口
//     [path] => /path/page.html // 路径
//     [query] => id=123         // 查询参数
//     [fragment] => anchor      // 锚点
// )

// 获取域名
echo $parts['host'];  // www.example.com

// 获取端口
echo $parts['port'];  // 8080

六、获取主域名(根域名)

从完整域名中提取主域名(如从www.example.com获取example.com):

<?php
/**
 * 获取主域名(根域名)
 * @param string $domain 完整域名
 * @return string
 */
function getMainDomain($domain)
{
    // 定义顶级域名列表
    $tlds = [
        'com.cn', 'net.cn', 'org.cn', 'gov.cn', 'co.uk', 'co.jp',
        'com.tw', 'com.hk', 'com.ru', 'net.tw', 'net.hk'
    ];
    
    // 分割域名
    $parts = explode('.', $domain);
    $count = count($parts);
    
    // 检查是否是带国别后缀的顶级域名
    $lastTwo = $parts[$count-2] . '.' . $parts[$count-1];
    if (in_array($lastTwo, $tlds)) {
        // 如 xxx.com.cn 返回倒数第三部分+倒数第二部分+最后一部分
        return $parts[$count-3] . '.' . $lastTwo;
    }
    
    // 普通情况返回后两部分
    return $parts[$count-2] . '.' . $parts[$count-1];
}

// 使用示例
echo getMainDomain('www.example.com');      // example.com
echo getMainDomain('blog.example.com.cn');   // example.com.cn
echo getMainDomain('www.csdn.net');          // csdn.net

七、获取二级域名前缀

获取域名的子域名部分:

<?php
/**
 * 获取二级域名前缀
 * @return string
 */
function getSubDomain()
{
    $host = $_SERVER['HTTP_HOST']; // www.example.com
    $parts = explode('.', $host);
    
    if (count($parts) >= 3) {
        return $parts[0]; // www
    }
    
    return '';
}

// 使用示例
echo getSubDomain(); // 如 www.example.com 返回 www

八、获取当前域名端口

<?php
/**
 * 获取当前域名端口
 * @return int|string
 */
function getDomainPort()
{
    return $_SERVER['SERVER_PORT']; // 80 或 443
}

// 获取端口号
echo getDomainPort();

九、获取顶级域名

从域名中提取顶级域名部分:

<?php
/**
 * 获取顶级域名(如 .com, .cn, .net)
 * @param string $domain
 * @return string
 */
function getTopLevelDomain($domain)
{
    $parts = explode('.', $domain);
    return end($parts);
}

// 使用示例
echo getTopLevelDomain('www.example.com'); // com
echo getTopLevelDomain('www.example.cn');  // cn
echo getTopLevelDomain('www.example.org'); // org

十、常用场景汇总

场景1:判断当前是否为HTTPS

<?php
function checkHttps()
{
    if ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')
        || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')
        || (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443)) {
        return true;
    }
    return false;
}

场景2:获取域名的多种写法汇总

<?php
// 获取协议+域名
$domain = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'];
echo $domain; // https://www.example.com

// 获取域名(不含www)
$host = $_SERVER['HTTP_HOST'];
$domainNoWww = preg_replace('/^www\./', '', $host);
echo $domainNoWww; // example.com

// 获取完整URL含参数
$fullUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://') 
         . $_SERVER['HTTP_HOST'] 
         . $_SERVER['REQUEST_URI'];
echo $fullUrl; // https://www.example.com/page?id=1

场景3:Laravel框架中获取域名

<?php
// Laravel中获取当前URL
url()->current();           // 当前URL(不含参数)
url()->full();              // 完整URL(含参数)
url()->previous();          // 上一页URL

// 获取域名
request()->getHost();       // www.example.com
request()->getHttpHost();   // www.example.com:8080
request()->root();          // https://www.example.com

// 判断HTTPS
request()->secure();        // true 或 false

十一、注意事项

  1. 安全性$_SERVER['HTTP_HOST']来自HTTP请求头,可能被伪造,不要用于安全敏感场景
  2. 反向代理:使用了Nginx等反向代理时,需要通过HTTP_X_FORWARDED_PROTO判断真实协议
  3. 端口问题SERVER_NAME不含端口,HTTP_HOST包含端口号
  4. 框架使用:在Laravel、ThinkPHP等框架中,建议使用框架提供的方法获取

十二、完整工具函数

<?php
/**
 * 域名获取工具类
 */
class DomainHelper
{
    /**
     * 获取当前完整URL
     */
    public static function fullUrl()
    {
        return self::scheme() . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    }
    
    /**
     * 获取当前域名(不含路径)
     */
    public static function domain()
    {
        return self::scheme() . $_SERVER['HTTP_HOST'];
    }
    
    /**
     * 获取主域名
     */
    public static function mainDomain()
    {
        $host = explode(':', $_SERVER['HTTP_HOST'])[0];
        $parts = explode('.', $host);
        $count = count($parts);
        if ($count <= 2) {
            return $host;
        }
        return $parts[$count-2] . '.' . $parts[$count-1];
    }
    
    /**
     * 获取协议
     */
    public static function scheme()
    {
        if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
            return 'https://';
        }
        if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
            return 'https://';
        }
        if (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) {
            return 'https://';
        }
        return 'http://';
    }
    
    /**
     * 判断是否为HTTPS
     */
    public static function isHttps()
    {
        return self::scheme() === 'https://';
    }
}

// 使用示例
echo DomainHelper::fullUrl();     // https://www.example.com/page?id=1
echo DomainHelper::domain();       // https://www.example.com
echo DomainHelper::mainDomain();   // example.com
echo DomainHelper::isHttps() ? '是HTTPS' : '是HTTP';

总结

本文详细介绍了PHP获取当前域名的多种方法,从简单的$_SERVER变量获取,到自动识别HTTPS协议,再到提取主域名、二级域名等高级用法。在实际开发中,建议根据具体需求选择合适的方法,并封装成统一的工具函数便于复用。

对于在生产环境使用,建议:

  • 使用框架提供的方法(如Laravel的Request对象)
  • 封装统一的工具函数
  • 考虑反向代理场景的协议判断
  • 不要直接信任用户传入的域名信息

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部