URLのサブドメインを取得するPHP関数


107

PHPにサブドメインの名前を取得する関数はありますか?

次の例では、URLの「en」の部分を取得します。

en.example.com

6
変数に格納された文字列としてのURLはありますか、またはこのURLはどこから来ていますか?コンテキストとは何ですか?詳しく説明してください。
Felix Kling

あなたは何かをしたような正規表現を使用して(^|://)(.*)\.キャプチャできません.*か?私はどちらかと言えばphpとregexを吸うのですが、これは頭に浮かびます。
corsiKa 2011年

それは何をしてもらう必要がありますen.foo.bar.example.comen.example.co.uk
アルバロ・ゴンサレス

parse_urlも役立ちます
Swapnil 2014

回答:


132

これが1行のソリューションです。

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

またはあなたの例を使用して:

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

編集:二重括弧を追加することにより、「変数のみを参照で渡す必要がある」を修正しました。


編集2PHP 5.4から、あなたは簡単に行うことができます:

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

17
参照によって渡されるのは変数のみです。
タマシュのPap

8
explode(...)[0]最近シフトを使う代わりにあなただけでできるのではないですか?数年前からではないとなってPHPing ...
TorのValamo

エラー:Strict Standards: Only variables should be passed by reference.
Justin

1
(explode(...))[0]ができますが、関数の
括弧

3
このソリューションは、誰かが入力してサブドメインとしてwww.en.example.com戻る場合には機能しませんwww
lolbas 2017

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などの複数のサブドメインの問題を解決しますか?ただ疑問に思っています(私の答えはそうではありません)。
Jared Farrish

@Jared、複数のサブドメインを検出するソリューションを追加しました。
Mike Lewis

1
@マイク-tx.usa.en.example.comで動作しますか?(またはscience.news.bbc.co.uk)?(ところで、news.bbc.co.ukは機能しますが、リンクは機能していません。例にすぎません)
Jared

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」のようなドメインの一部でした)。実際、あなたの解決策は私がやっていたことよりもはるかに単純です。正規表現は命を救う、ありがとう!
Yoone 2013

1
すばらしい..これは、すべてのドメインタイプとサブドメインで非常にうまく機能します。
2013年

2
この解決策は非常に優れており、ほとんどすべての場合に機能する可能性がありますが、ドメイン名には、、またはのようpvt.k12.ma.usに6文字を超える文字が含まれる場合があることに注意しhealth.vnてくださいk12.ak.us。また、ドメイン名は中国語またはロシア語の文字セットを使用している可能性があるため、正規表現の部分[a-z\.]{2,6}はそれらに一致しません。ここでドメイン名の例を確認してください:publicsuffix.org/list
pomeh '28

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
PS-ロシア語のテキストで何が書かれているかはわかりません。ru.wikipedia.orgからいくつかのさりげない言葉をとりました ;)
カマフェザー14

ウクライナじゃないですか?.uaウクライナの国コードです。
nalply 2014

いいえ。ちょうど混合した情報。しかし、私には
わかり

3
ロシア語に関して、ロシア語から英語へのグーグル翻訳は「公開された値」として返されます(私がそうであるように誰かが興味を持っていた場合)
Jeremy Harris

@Kamafeatherこれは防弾のようです。$match[1]パーツを入手する方法はありますか?$match[0]必要ないようです。
アンドレス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'])を自動検出して、なりすまし可能なリファラーヘッダーに依存するより良い方法があります。
マシュー

そうです、私は古いコードを使用していました。ただし、この例はまだ有効です。それは問題の根本ではありません。
Jared Farrish

上記のコメントを合計すると、$ _ SERVER ['HTTP_HOST']に依存することは、設定されていない可能性があるため、効率的でない場合があります。
gmslzr 2017

2

PHP 7.0:関数explodeを使用して、すべての結果のリストを作成します。

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

例:sub.domain.com

echo $subdomain; 

結果:サブ

echo $host;

結果:ドメイン


TLDのようなものを忘れた.co.uk-スニペットはこれらのTLDでは機能しません
Adrian Preuss


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でテストするだけで、正しい結果は得られません。

正しい解決策は、パブリックサフィックスリストを使用してドメインを解析するパッケージを使用することです。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);

2番目のパラメーターの部分文字列は1で始まるため、11ではなく12で部分文字列を切り捨てます。したがって、test.example.comと入力すると、の値はに$subdomainなりますtest

これは使用するよりも優れてexplodeいます。サブドメインにa .がある場合、これはそれを切り取らないためです。


開始位置「0」が回答にありませんでした。$ subdomain = substr($ _ SERVER ['HTTP_HOST']、0、$ numberOfLettersInSubdomain);
ジェイミー

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 14

これは、チームの他の開発者にとって物事を簡素化します。私は、いくつかの高度な正規表現よりもこれを使用したいと思います。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']);
Kal

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とローカルホストを処理します

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です
    } そうしないと {
       echo "メインドメインは="。$ host [1]。 "。"。$ host [0]。 "&サブドメインが見つかりません";
       // "メインドメインは= example.com&サブドメインが見つかりません";
    }


-3

最初の期間の前に来るものだけが必要な場合:

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

http://、https://、ftp://などのプロトコルハンドラが最初にある場合はどうなりますか?;)
Jared Farrish

@Jared、彼が解析しようとしている文字列にはプロトコルがありません...しかし、もしあればparse_url()、ホストの抽出に使用します。
マシュー

したがって、異なる状況で適切な2つのアプローチを提供しました。
Jared Farrish

主に、誰かが正規表現の回答を(まだ)投稿しなかったことをうれしく思います。私の回答の最後の行は言うまでもなく、あなたがするのと同じことを達成します。
Jared Farrish 2011年

ホスト名がen.example.co.ukの場合
マークB
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.