2011-03-13 72 views
86

PHP中是否有函數來獲取子域名?PHP函數獲取URL的子域名

在下面的例子中,我想獲得的URL的「連接」部分:

en.example.com 
+5

你有存儲在字符串的URL一個變量或這個URL來自哪裏?什麼是上下文?請詳細說明。 – 2011-03-13 22:39:06

+0

難道你不能使用像'(^ |://(。*)\ .'這樣的正則表達式並捕獲'。*'?我非常喜歡PHP和正則表達式,但是想到這一點。 – corsiKa 2011-03-13 22:50:24

+0

@glowcoder - booo。 – 2011-03-13 22:51:26

回答

-2

如果你只是想在第一時間段之前會發生什麼:

list($sub) = explode('.', 'en.example.com', 2); 
+0

如果在開始時有一個協議處理程序,如http://,https://,ftp://等...怎麼辦? ;) – 2011-03-13 22:44:51

+0

@Jared,他希望解析的字符串中沒有協議......但是如果有的話,我會使用'parse_url()'來提取主機。 – Matthew 2011-03-13 22:47:33

+0

所以我們提供了兩種適用於不同環境的方法。 – 2011-03-13 22:49:30

2
$REFERRER = $_SERVER['HTTP_REFERER']; // Or other method to get a URL for decomposition 

$domain = substr($REFERRER, strpos($REFERRER, '://')+3); 
$domain = substr($domain, 0, strpos($domain, '/')); 
// This line will return 'en' of 'en.example.com' 
$subdomain = substr($domain, 0, strpos($domain, '.')); 
+1

有更好的方法來自動檢測當前的主機(比如'$ _SERVER ['HTTP_HOST']'),然後依靠一個可欺騙的引用標頭,假設這就是答案背後的一般想法。 – Matthew 2011-03-13 22:42:47

+0

對,我正在使用一段舊代碼。但是,這個例子依然存在。這不是問題的根源。 – 2011-03-13 22:43:45

+0

只需在上面添加這些註釋,依靠$ _SERVER ['HTTP_HOST']可能效率不高,因爲它有可能不會被設置。 – gmslzr 2017-09-20 14:47:11

10

http://php.net/parse_url

<?php 
    $url = 'http://user:[email protected]/path?argument=value#anchor'; 
    $array=parse_url($url); 
    $array['host']=explode('.', $array['host']); 

    echo $array['host'][0]; // returns 'en' 
?> 
+0

對於像這樣的網址不好:en.site.com,沒有'http://' – 2015-12-13 01:16:43

48

使用parse_url功能。

$url = 'http://en.example.com'; 

$parsedUrl = parse_url($url); 

$host = explode('.', $parsedUrl['host']); 

$subdomain = $host[0]; 
echo $subdomain; 

爲多個子域

$url = 'http://usa.en.example.com'; 

$parsedUrl = parse_url($url); 

$host = explode('.', $parsedUrl['host']); 

$subdomains = array_slice($host, 0, count($host) - 2); 
print_r($subdomains); 
+0

@Mike Lewis - 這是否解決了多個子域的問題,例如usa.en.example.com?只是想知道(我自己的答案不,順便說一句)。 – 2011-03-13 22:53:42

+0

hehehe ...同樣的解決方案:) – JMW 2011-03-13 22:54:25

+0

@Jared,剛剛添加了一個解決方案來檢測多個子域。 – 2011-03-13 22:59:23

101

這裏有一個在線解決方案:

array_shift((explode('.', $_SERVER['HTTP_HOST']))); 

或使用例如:

array_shift((explode('.', 'en.example.com'))); 

編輯:修正「只應通過引用傳遞」通過添加雙括號。


編輯2:從PHP 5.4開始,你可以簡單地做:

explode('.', 'en.example.com')[0]; 
+14

只有變量應該通過引用傳遞。 – 2012-09-19 07:09:16

+8

難道你不能僅僅使用'爆炸(...)[0]'而不是現在使用shift?幾年來一直沒有PHP .. – 2012-11-09 15:23:54

+0

錯誤:'嚴格的標準:只有變量應該通過引用傳遞。' – Justin 2012-12-09 05:45:37

27

可以通過先獲得域名(例如sub.example.com => example.co做到這一點。英國),然後使用strstr來獲取子域名。

$testArray = array(
    'sub1.sub2.example.co.uk', 
    'sub1.example.com', 
    'example.com', 
    'sub1.sub2.sub3.example.co.uk', 
    'sub1.sub2.sub3.example.com', 
    'sub1.sub2.example.com' 
); 

foreach($testArray as $k => $v) 
{ 
    echo $k." => ".extract_subdomains($v)."\n"; 
} 

function extract_domain($domain) 
{ 
    if(preg_match("/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i", $domain, $matches)) 
    { 
     return $matches['domain']; 
    } else { 
     return $domain; 
    } 
} 

function extract_subdomains($domain) 
{ 
    $subdomains = $domain; 
    $domain = extract_domain($subdomains); 

    $subdomains = rtrim(strstr($subdomains, $domain, true), '.'); 

    return $subdomains; 
} 

輸出:

0 => sub1.sub2 
1 => sub1 
2 => 
3 => sub1.sub2.sub3 
4 => sub1.sub2.sub3 
5 => sub1.sub2 
+2

這似乎是最好的解決方案,因爲它也允許沒有子域名的域名,而不是重新將域名作爲子域名作爲第一個名稱之前的部分。檢查子域的存在非常有用。 – 2013-07-25 23:51:31

+0

我需要獲得「基本」域(沒有子域),並且我通過爆炸主機並通過'for'循環獲取數組的最後一個元素來製作自己的解決方案,但是我必須檢查它們的長度(以檢測它們是否是像「co.uk」這樣的域的一部分)。實際上,你的解決方案比我所做的要簡單得多。正則表達式拯救生命,謝謝! – Yoone 2013-09-30 08:26:01

+1

真棒..這適用於所有域類型和子域..好。 – jon 2013-10-30 09:58:49

1

我找到了最好的和短期的解決方案是

array_shift(explode(".",$_SERVER['HTTP_HOST'])); 
+0

會造成嚴重錯誤。爆炸的輸出不能直接傳遞給array_shift。 – YAAK 2013-01-30 18:45:48

2

簡單和最快的解決方案。

$sSubDomain = str_replace('.example.com','',$_SERVER['HTTP_HOST']); 
0
// For www.abc.en.example.com 
$host_Array = explode(".",$_SERVER['HTTP_HOST']); // Get HOST as array www, abc, en, example, com 
array_pop($host_Array); array_pop($host_Array); // Remove com and exmaple 
array_shift($host_Array);       // Remove www (Optional) 
echo implode($host_Array, ".");     // Combine array abc.en 
0

我知道我真的太遲了,但在這裏不用。

我所做的是採取HTTP_HOST服務器變量($_SERVER['HTTP_HOST'])和域中的字母數(因此對於example.com它將是11)。

然後我用substr函數來獲取子域。我做了

$numberOfLettersInSubdomain = strlen($_SERVER['HTTP_HOST'])-12 
$subdomain = substr($_SERVER['HTTP_HOST'], $numberOfLettersInSubdomain); 

我把子串從12減掉而不是11,因爲子串從1開始爲第二個參數。所以現在如果你輸入了test.example。com,$subdomain的值將是test

這比使用explode好,因爲如果子域中有一個.,這不會將其切斷。

+0

答案中缺少開始位置「0」。 $ subdomain = substr($ _ SERVER ['HTTP_HOST'],0,$ numberOfLettersInSubdomain); – Jamie 2013-05-19 18:48:11

0

如果您正在使用Drupal 7的

這將幫助你:

global $base_path; 
global $base_root; 
$fulldomain = parse_url($base_root);  
$splitdomain = explode(".", $fulldomain['host']); 
$subdomain = $splitdomain[0]; 
1

對於那些誰得到「錯誤:嚴格的標準:只有變量應該按引用傳遞。」 使用這樣的:

$env = (explode(".",$_SERVER['HTTP_HOST'])); $env = array_shift($env);

+0

這不是問題,但感謝您的意見。 – FazoM 2013-10-26 07:10:00

0
$host = $_SERVER['HTTP_HOST']; 
preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches); 
$domain = $matches[0]; 
$url = explode($domain, $host); 
$subdomain = str_replace('.', '', $url[0]); 

echo 'subdomain: '.$subdomain.'<br />'; 
echo 'domain: '.$domain.'<br />'; 
0

從PHP 5.3,你可以使用的strstr()真正參數

echo strstr($_SERVER["HTTP_HOST"], '.', true); //prints en 
+0

只有在字符串開始處沒有「www」時才能使用。有點太平凡的做法。 – FooBar 2014-07-27 17:09:17

+0

這爲團隊中的其他開發人員簡化了一些事情,我寧願使用這個比一些高級的reg exp。如果你想修剪www使用trim($ s,'www');或者只是將其調整到您的業務邏輯... – tasmaniski 2014-08-21 10:03:33

+1

爲了完整起見,'www' * *實際上是一個子域。由於歷史原因,它通常只是域名本身的別名。 – 2014-08-26 19:23:14

0
function get_subdomain($url=""){ 
    if($url==""){ 
     $url = $_SERVER['HTTP_HOST']; 
    } 
    $parsedUrl = parse_url($url); 
    $host = explode('.', $parsedUrl['path']); 
    $subdomains = array_slice($host, 0, count($host) - 2); 
    return implode(".", $subdomains); 
} 
+1

line#7應該是'$ host = explode('。',isset($ parsedUrl ['path'])?$ parsedUrl ['path']:$ parsedUrl ['host']);' – Kal 2015-09-09 07:59:50

0

嘗試......

$domain = 'en.example.com'; 
$tmp = explode('.', $domain); 
$subdomain = current($tmp); 
echo($subdomain);  // echo "en" 
+0

我認爲它會對於OP和更多的訪問者來說,當你爲你的意圖添加一些解釋時會更有幫助。 – reporter 2014-08-27 10:58:17

3

簡單...

preg_match('/(?:http[s]*\:\/\/)*(.*?)\.(?=[^\/]*\..{2,5})/i', $url, $match); 

剛看完$匹配[1]

工作實例

它與該URL列表完美的作品

$url = array(
    'http://www.domain.com', // www 
    'http://domain.com', // --nothing-- 
    'https://domain.com', // --nothing-- 
    'www.domain.com', // www 
    'domain.com', // --nothing-- 
    'www.domain.com/some/path', // www 
    'http://sub.domain.com/domain.com', // sub 
    'опубликованному.значения.ua', // опубликованному ;) 
    'значения.ua', // --nothing-- 
    'http://sub-domain.domain.net/domain.net', // sub-domain 
    'sub-domain.third-Level_DomaIN.domain.uk.co/domain.net' // sub-domain 
); 

foreach ($url as $u) { 
    preg_match('/(?:http[s]*\:\/\/)*(.*?)\.(?=[^\/]*\..{2,5})/i', $u, $match); 
    var_dump($match); 
} 
+2

PS - 我不知道它在俄文中寫的是什麼。只是從* ru.wikipedia.org *;) – Kamafeather 2014-08-28 09:58:13

+0

一些休閒的話是不是烏克蘭? '.ua'是烏克蘭的國家代碼。 – nalply 2014-08-28 13:38:15

+0

沒有。只是混合的信息。但我不確定,我不夠好區分它們) – Kamafeather 2014-08-28 14:43:03

6

域名後綴的唯一可靠來源是域名註冊商,如果不知情,您將無法找到子域名。 在https://publicsuffix.org有一個包含所有域後綴的列表。本網站還鏈接到一個PHP庫:https://github.com/jeremykendall/php-domain-parser

請在下面找到一個例子。我還爲en.test.co.uk添加了一個帶有多後綴(co.uk)的域的示例。

<?php 

require_once 'vendor/autoload.php'; 

$pslManager = new Pdp\PublicSuffixListManager(); 
$parser = new Pdp\Parser($pslManager->getList()); 
$host = 'http://en.example.com'; 
$url = $parser->parseUrl($host); 

echo $url->host->subdomain; 


$host = 'http://en.test.co.uk'; 
$url = $parser->parseUrl($host); 

echo $url->host->subdomain; 
1
$domain = 'sub.dev.example.com'; 
$tmp = explode('.', $domain); // split into parts 
$subdomain = current($tmp); 
print($subdomain);  // prints "sub" 

在之前的問題看出: How to get the first subdomain with PHP?

1

是不是真的有一個100%的動態的解決方案 - 我剛剛一直在試圖弄明白,以及和由於不同域擴展(DTL)這個任務將是非常困難的,而無需實際解析這些擴展和每次檢查他們:

.com vs .co.uk vs org.uk

最可靠的選擇是定義一個常量(或數據庫條目等)),存儲實際的域名,並使用substr()

defined("DOMAIN") 
    || define("DOMAIN", 'mymaindomain.co.uk'); 



function getSubDomain() { 

    if (empty($_SERVER['SERVER_NAME'])) { 

     return null; 

    } 

    $subDomain = substr($_SERVER['SERVER_NAME'], 0, -(strlen(DOMAIN))); 

    if (empty($subDomain)) { 

     return null; 

    } 

    return rtrim($subDomain, '.'); 

} 

現在從$_SERVER['SERVER_NAME']刪除它,如果你正在使用http://test.mymaindomain.co.uk在此功能下,它會給你test或者如果你有多個子域名級別http://another.test.mymaindomain.co.uk你會得到another.test - 除非你更新DOMAIN

我希望這會有所幫助。

1

只需

reset(explode(".", $_SERVER['HTTP_HOST']))

1

這是我的解決方案,它的工作原理與最常見的域名,您可以根據您的需要適應擴展的陣列:

$子域=爆炸(「」 ,explode('| ext |',str_replace(array('。com','.net','.org'),'| ext |',$ _ SERVER ['HTTP_HOST']))[0]);

0

使用正則表達式,字符串函數,parse_url()或它們的組合它不是真正的解決方案。只要測試域名爲test.en.example.co.uk的任何建議解決方案,就不會有任何正確的結果。

正確的解決方案是使用包解析域Public Suffix List。我建議TLDExtract,這裏是示例代碼:

$extract = new LayerShifter\TLDExtract\Extract(); 

$result = $extract->parse('test.en.example.co.uk'); 
$result->getSubdomain(); // will return (string) 'test.en' 
$result->getSubdomains(); // will return (array) ['test', 'en'] 
$result->getHostname(); // will return (string) 'example' 
$result->getSuffix(); // will return (string) 'co.uk' 
0

你可以使用這個太

echo substr($_SERVER['HTTP_HOST'], 0, strrpos($_SERVER['HTTP_HOST'], '.', -5)); 
0

我在做這樣的事情

$url = https://en.example.com 

$splitedBySlash = explode('/', $url); 
$splitedByDot = explode('.', $splitedBySlash[2]); 

$subdomain = $splitedByDot[0]; 
0

PHP 7.0:使用爆炸功能,創建所有結果的列表。

list($subdomain,$host) = explode('.', $_SERVER["SERVER_NAME"]); 

例子:sub.domain.com

echo $subdomain; 

結果:子

echo $host; 

結果:域