从 $_SERVER['SERVER_NAME'] 中删除子域名

8

我需要编写一个脚本,它可以从$_SERVER['SERVER_NAME']中删除子域名,并将其用于setcookie函数的域选项中,以允许在所有可能的子域上访问cookie。

例如,假设我有:

function strip_out_subdomain($domain)
{
    //do something to remove subdomain
    return $only_my_domain;
}
$domain = strip_out_subdomain($_SERVER['SERVER_NAME']);
setcookie('mycookie', '123', time()+3600, '/', $domain);

这里的主要问题是我不知道我的域名模式。它可能是以下任何一种形式:
  • www.mydomain.com
  • subdomain.mydomain.com
  • subdo.mydo.co
  • subdo.subdo.mydomain.com
  • subdo.subdo.mydo.co.uk
  • 等等。
谢谢。
Stephanie

1
你需要手动定义模式。没有明确的规则(TLD可以由一个部分.com或两个.co.jp组成),有一个SO上的问题列出了大部分,但我现在找不到它。 - Pekka
2
这个问题昨天也出现了。http://stackoverflow.com/questions/5319296/php-url-parsing-disecting - 在评论的末尾有一个全面的列表(由Mozilla维护)。 - mario
@Mario:谢谢你的链接。我看到这个问题很常见,而且不容易解决。 - Stef
请参见https://dev59.com/w1DTa4cB1Zd3GeqPNOYB#3853473。 - Gumbo
可能是重复的问题:用于提取任意域名子域的 PHP 正则表达式 - outis
4个回答

4

这是一种正则表达式的方式,用于从完整域名中删除子域名部分。

.*? 运算符使通配符匹配变得非贪婪,以便它匹配第一个点号。

function strip_out_subdomain($domain)
{
    $only_my_domain = preg_replace("/^(.*?)\.(.*)$/","$2",$domain);
    return $only_my_domain;
}

3

在服务器配置文件(httpd.conf、.htaccess)中定义变量是否可能?这需要一些额外的初始管理工作,但至少可以在一个集中位置完成。

我已经成功在Apache中设置了一个变量。

SetEnv MY_DOMAIN mydomain.com

这可以在PHP中使用:

$_SERVER['MY_DOMAIN']

2
您可以使用 cURL 查询 Alexa 服务 并提取没有子域名的主机名:
function hostname($domain) {

$querystring = 'http://xml.alexa.com/data?cli=10&dat=nsa&ver=quirk-searchstatus&uid=19700101000000&userip=127.0.0.1&url='.urlencode($domain);
$ch = curl_init();
$user_agent = $_SERVER['HTTP_USER_AGENT'];
curl_setopt ($ch, CURLOPT_URL, $querystring);
curl_setopt ($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt ($ch, CURLOPT_HEADER, 1);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($ch, CURLOPT_TIMEOUT, 120);
$data= curl_exec($ch);
curl_close($ch);

preg_match('/\<POPULARITY URL="(.*?)" TEXT="(.*?)" SOURCE="(.*?)"\/\>/Ui',$data,$extract);
$hostname = str_replace('/', '', $extract[1]);

return($hostname);
}

1

我知道现在已经过了好几年,但为什么不这样做:

$dom='a.b.c.d.co.jp';
$sub=preg_replace("/.*?([^\.]+)(\.((co\.\w+)|\w+))$/i",'\1\2',$dom); //strip subdomains

这段代码会输出 d.co.jp

其中 .*?([^\.]+)(\.((co\.\w+)|\w+))$ 的意思是:

.*? 懒惰匹配(以便不获取主域名),匹配所有字符直到后面的内容

([^\.]+) 匹配不包含点号的一组字符(即主域名或次级域名)(+ 表示至少有一个该类字符),并将其返回到 \1

(\.((co\.\w+)|\w+)) 匹配顶级域名及其前面的点号,无论它是 .co.something 还是 .something,并通过 \2 返回;加号在此处也起到同样的作用

$ 将所有内容锚定到字符串末尾,因此我们可以从 TLD 向左遍历到子域名部分,无论它们有多少个

附言:我不确定是否还有其他的双段顶级域名,但它们也可以被添加。通过https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains快速浏览告诉我没有,但如果有的话,我猜它们并不多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接