URL의 하위 도메인을 가져 오는 PHP 함수


107

PHP에 하위 도메인의 이름을 가져 오는 함수가 있습니까?

다음 예에서 URL의 "en"부분을 가져오고 싶습니다.

en.example.com

6
변수에 저장된 문자열로 URL이 있습니까? 아니면이 URL의 출처는 어디입니까? 컨텍스트는 무엇입니까? 자세히 설명 해주세요.
Felix Kling 2011 년

뭔가를 (^|://)(.*)\.하고 캡처 하는 정규식을 사용할 수 .*없습니까? 나는 오히려 PHP와 정규식을 모두 빤다. 그러나 이것은 마음에 든다.
corsiKa 2011 년

en.foo.bar.example.com또는 무엇에 들어가야 en.example.co.uk합니까?
Álvaro González

parse_url도 도움이 될 수 있습니다
Swapnil 2014 년

답변:


132

다음은 한 줄 솔루션입니다.

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

또는 귀하의 예를 사용하여 :

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

편집 : 이중 괄호를 추가하여 "변수 만 참조로 전달해야 함"을 수정했습니다.


편집 2 : PHP 5.4 부터 간단하게 할 수 있습니다.

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

17
변수 만 참조로 전달해야합니다.
Tamás Pap

8
explode(...)[0]요즘은 시프트 대신 그냥 할 수 있지 않나요? 몇 년 동안 PHP를 사용하지 않았습니다.
Tor Valamo

오류 :Strict Standards: Only variables should be passed by reference.
Justin

1
(explode (...)) [0]하지만 함수
paranthesis

3
이 솔루션은 누군가 입력하는 경우 작동하지 않으므로 하위 도메인으로 www.en.example.com반환 www됩니다.
lolbas

65

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);

@Mike Lewis-usa.en.example.com과 같은 여러 하위 도메인의 문제가 해결됩니까? 그냥 궁금합니다 (내 대답은 그렇지 않습니다, btw).
Jared Farrish 2011 년

@Jared, 방금 여러 하위 도메인을 감지하는 솔루션을 추가했습니다.
Mike Lewis

1
@Mike-tx.usa.en.example.com에서 작동합니까? (또는 science.news.bbc.co.uk )? (btw, 작동하는 링크가 아닙니다. news.bbc.co.uk는 작동하지만 예제
일뿐입니다.

4
이는 net, com, biz 등과 같은 단일 '단어'TLD를 가진 모든 것에 적용됩니다.하지만 예를 들어 co.uk를 다룰 때는 그렇지 않습니다. 여기에서 볼 수 있듯이 이것은 실제로 해결하기 더 어려운 문제입니다.
Mike Lewis

2
하위 도메인이 전혀없는 경우에도 실패합니다.
raveren

32

먼저 도메인 이름 (예 : sub.example.com => example.co.uk)을 얻은 다음 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
하위 도메인이 첫 번째 점 앞의 일부인 도메인 이름을 되 돌리는 대신 하위 도메인이없는 도메인도 허용하므로 최상의 솔루션으로 보입니다. 하위 도메인의 존재를 확인하는 데 매우 유용합니다.
Karl MW

"기본"도메인 (하위 도메인없이)을 가져와야했고 호스트를 폭발시키고 for루프 가있는 배열의 마지막 요소를 가져 와서 나만의 솔루션을 만들고 있었지만 길이를 확인해야했습니다. "co.uk"와 같은 도메인의 일부 임). 사실, 당신의 해결책은 제가했던 것보다 훨씬 더 간단합니다. Regex는 생명을 구합니다, 감사합니다!
Yoone

1
굉장합니다 .. 이것은 모든 도메인 유형과 하위 도메인에서 잘 작동합니다.
jon

2
이 솔루션은 매우 깔끔하고 거의 모든 경우 에서 작동 할 수 있지만 도메인 이름에는 pvt.k12.ma.us, health.vn또는 k12.ak.us. 또한 도메인 이름은 중국어 또는 러시아어 문자 집합을 사용할 수 있으므로 정규식 부분 [a-z\.]{2,6}이 일치하지 않습니다. 예를 들어, 도메인 이름이 여기에 체크 아웃 : publicsuffix.org/list
pomeh

12

http://php.net/parse_url

<?php
  $url = 'http://user:password@sub.hostname.tld/path?argument=value#anchor';
  $array=parse_url($url);
  $array['host']=explode('.', $array['host']);

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

7

도메인 접미사의 신뢰할 수있는 유일한 소스는 도메인 등록 기관이므로 해당 지식 없이는 하위 도메인을 찾을 수 없습니다. https://publicsuffix.org에 모든 도메인 접미사가있는 목록이 있습니다 . 이 사이트는 또한 PHP 라이브러리 ( https://github.com/jeremykendall/php-domain-parser)로 연결됩니다 .

아래에서 예를 찾으십시오. 또한 다중 접미사 (co.uk)가있는 도메인 인 en.test.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;

5

가장 간단하고 빠른 솔루션.

$sSubDomain = str_replace('.example.com','',$_SERVER['HTTP_HOST']);

4

간단히...

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

$ 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
추신-나는 그것이 러시아어 텍스트로 쓰여진 것에 대해 전혀 모른다. 다만 일부 캐주얼 단어했다 ru.wikipedia.org를 )
Kamafeather

우크라이나어 아닌가요? .ua우크라이나의 국가 코드입니다.
nalply

아니. 혼합 된 정보입니다. 하지만 잘 모르겠습니다. 나는 그들을 구별하기에 충분하지 않습니다.)
Kamafeather 2014-08-28

3
러시아어와 관련하여, 러시아어에서 영어로의 Google 번역이 "게시 된 값"으로 돌아옵니다 (나처럼 궁금한 사람이있는 경우)
Jeremy Harris

@Kamafeather 이것은 방탄처럼 보입니다. $match[1]부품을 얻을 수있는 방법은 없나요? $match[0]불필요 해 보입니다.
Andres SK

3
$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

맞습니다, 저는 오래된 코드를 사용하고있었습니다. 그러나 그 예는 여전히 유효합니다. 그것은 질문의 근원이 아닙니다.
Jared Farrish 2011 년

위의 설명을 추가하기 위해 $ _SERVER [ 'HTTP_HOST']에 의존하는 것은 설정되지 않을 가능성이 있기 때문에 효과적이지 않을 수 있습니다.
gmslzr

2

PHP 7.0 : 분해 기능 사용 및 모든 결과 목록 생성.

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

예 : sub.domain.com

echo $subdomain; 

결과 : 하위

echo $host;

결과 : 도메인


당신은 TLD의 같은 잊지 .co.uk- 당신의 조각을 것이다 이러한 TLD를하지 작업
아드리안 Preuss의

1

내가 가장 좋고 짧은 해결책을 찾은 것은

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

엄격한 오류가 발생합니다. explode의 출력은 array_shift로 직접 전달할 수 없습니다.
YAAK

1

'오류 : 엄격한 표준 : 변수 만 참조로 전달해야합니다.' 다음과 같이 사용하십시오.

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


그것은 질문이 아니었지만 귀하의 의견에 감사드립니다.
FazoM 2013 년


1

실제로 100 % 동적 솔루션은 없습니다. 그냥 알아 내려고 노력해 왔으며 다른 도메인 확장 (DTL)으로 인해이 작업은 실제로 이러한 모든 확장을 구문 분석하고 매번 확인하지 않으면 정말 어려울 것입니다.

.com vs .co.uk vs org.uk

가장 신뢰할 수있는 옵션은 실제 도메인 이름을 저장하는 상수 (또는 데이터베이스 항목 등)를 정의하고 $_SERVER['SERVER_NAME']사용 에서 제거하는 것입니다.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, '.');

}

이제이 기능을 사용 http://test.mymaindomain.co.uk하는 경우에는 제공 test되거나 여러 하위 도메인 수준 http://another.test.mymaindomain.co.uk이있는 another.test경우 얻을 수 있습니다 DOMAIN. 물론 .

이게 도움이 되길 바란다.



1

정규식, 문자열 함수, parse_url () 또는 그 조합을 사용하는 것은 실제 솔루션이 아닙니다. domain으로 제안 된 솔루션을 테스트하기 만하면 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'

1

이것은 내 솔루션이며 가장 일반적인 도메인에서 작동하며 필요에 따라 확장 배열을 맞출 수 있습니다.

$SubDomain = explode('.', explode('|ext|', str_replace(array('.com', '.net', '.org'), '|ext|',$_SERVER['HTTP_HOST']))[0]);

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.com11 개) 를 가져 오는 것입니다.

그런 다음 substr함수를 사용 하여 하위 도메인을 얻었습니다. 나는했다

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

두 번째 매개 변수에 대해 부분 문자열이 1에서 시작하기 때문에 부분 문자열을 11 대신 12에서 잘라 냈습니다. 이제 test.example.com을 입력하면의 값은 $subdomain입니다 test.

explode하위 도메인에가 있으면 .잘리지 않기 때문에 사용하는 것보다 낫습니다 .


답변에서 시작 위치 "0"이 누락되었습니다. $ subdomain = substr ($ _ SERVER [ 'HTTP_HOST'], 0, $ numberOfLettersInSubdomain);
Jamie

0

drupal 7을 사용하는 경우

이것은 당신을 도울 것입니다 :

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

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부터는 true 매개 변수 와 함께 strstr () 을 사용할 수 있습니다.

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

이것은 www문자열 시작에 없는 경우에만 작동합니다 . 너무 사소한 접근 방식입니다.
FooBar

이것은 팀의 다른 개발자를 위해 일을 단순화합니다. 고급 정규식보다는 이것을 사용하고 싶습니다. www를 다듬 으려면 trim ($ s, 'www'); 아니면 그냥 ... 당신의 비즈니스 로직에 조정
tasmaniski

1
완전성을 위해, www 이다 실제로 하위 도메인. 역사적 이유로 일반적으로 도메인 이름 자체로 별칭이 지정됩니다.
Levi Morrison

0

이 시도...

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

나는 당신의 의도에 대한 설명을 추가하면 OP와 더 많은 방문객에게 더 도움이 될 것이라고 생각합니다.
기자

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
라인 # 7 있어야합니다$host = explode('.', isset($parsedUrl['path']) ? $parsedUrl['path'] : $parsedUrl['host']);

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

이 함수를 사용하여 여러 하위 도메인 을 처리 하고 여러 tld 도 ip 및 localhost를 처리합니다.

function analyse_host($_host)
    {
        $my_host   = explode('.', $_host);
        $my_result = ['subdomain' => null, 'root' => null, 'tld' => null];

        // if host is ip, only set as root
        if(filter_var($_host, FILTER_VALIDATE_IP))
        {
            // something like 127.0.0.5
            $my_result['root'] = $_host;
        }
        elseif(count($my_host) === 1)
        {
            // something like localhost
            $my_result['root'] = $_host;
        }
        elseif(count($my_host) === 2)
        {
            // like jibres.com
            $my_result['root'] = $my_host[0];
            $my_result['tld']  = $my_host[1];
        }
        elseif(count($my_host) >= 3)
        {
            // some conditons like
            // ermile.ac.ir
            // ermile.jibres.com
            // ermile.jibres.ac.ir
            // a.ermile.jibres.ac.ir

            // get last one as tld
            $my_result['tld']  = end($my_host);
            array_pop($my_host);

            // check last one after remove is probably tld or not
            $known_tld    = ['com', 'org', 'net', 'gov', 'co', 'ac', 'id', 'sch', 'biz'];
            $probably_tld = end($my_host);
            if(in_array($probably_tld, $known_tld))
            {
                $my_result['tld'] = $probably_tld. '.'. $my_result['tld'];
                array_pop($my_host);
            }

            $my_result['root'] = end($my_host);
            array_pop($my_host);

            // all remain is subdomain
            if(count($my_host) > 0)
            {
                $my_result['subdomain'] = implode('.', $my_host);
            }
        }

        return $my_result;
    }

0

현재 URL = sub.example.com 이라고 가정합니다.

    $ host = array_reverse (explode ( '.', $ _SERVER [ 'SERVER_NAME']));

    if (count ($ host)> = 3) {
       echo "주 도메인 =". $ host [1]. ".". $ host [0]. "& 하위 도메인 =". $ host [2];
       // 기본 도메인은 = example.com이고 하위 도메인은 = sub입니다.
    } else {
       echo "주 도메인 =". $ host [1]. ".". $ host [0]. "& 하위 도메인을 찾을 수 없음";
       // "기본 도메인 = example.com 및 하위 도메인을 찾을 수 없음";
    }


-3

첫 번째 기간 이전에 오는 것만 원하는 경우 :

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

처음에 http : //, https : //, ftp : // 등과 같은 프로토콜 처리기가 있으면 어떻게됩니까? ;)
Jared Farrish 2011 년

@Jared, 그가 파싱하려는 문자열에 프로토콜이 없습니다 ...하지만 만약 있다면 parse_url()호스트를 추출하는 데 사용합니다.
Matthew

그래서 우리는 서로 다른 상황에 적합한 두 가지 접근 방식을 제공했습니다.
Jared Farrish 2011 년

주로 누군가 정규식 답변을 게시하지 않은 것이 다행입니다 (아직). 내 대답의 마지막 줄은 말할 것도없이 당신과 같은 일을 수행합니다.
Jared Farrish 2011 년

그리고 호스트 이름이 en.example.co.uk이면?
Marc B
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.