Fungsi PHP untuk mendapatkan subdomain dari sebuah URL


107

Apakah ada fungsi dalam PHP untuk mendapatkan nama subdomain?

Pada contoh berikut, saya ingin mendapatkan bagian "en" dari URL:

en.example.com

6
Apakah Anda memiliki URL sebagai string yang disimpan dalam variabel atau dari mana asalnya URL ini? Apa konteksnya? Tolong jelaskan.
Felix Kling

Tidak bisakah Anda menggunakan regex yang melakukan sesuatu seperti (^|://)(.*)\.dan menangkapnya .*? Saya agak payah di php dan regex, tapi ini yang terlintas dalam pikiran.
corsiKa

Apa yang harus dimasukkan en.foo.bar.example.comatau en.example.co.uk?
Álvaro González

parse_url juga dapat membantu
Swapnil

Jawaban:


132

Berikut solusi satu baris:

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

Atau menggunakan contoh Anda:

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

EDIT: Tetap "hanya variabel yang harus diteruskan dengan referensi" dengan menambahkan tanda kurung ganda.


EDIT 2 : Mulai dari PHP 5.4 Anda cukup melakukan:

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

17
Hanya variabel yang harus diteruskan dengan referensi.
Tamás Pap

8
Apakah Anda tidak bisa melakukannya explode(...)[0]daripada menggunakan shift hari ini? Belum PHPing selama beberapa tahun ..
Tor Valamo

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

1
cukup yakin Anda bisa (meledak (...)) [0] meskipun, harus beroperasi pada array yang dikembalikan alih-alih fungsi paranthesis (sebelum 5,4)
Garet Claborn

3
Solusi ini tidak akan berfungsi jika seseorang mengetik www.en.example.comdan dengan demikian akan kembali wwwsebagai subdomain.
lolbas

65

Menggunakan fungsi parse_url .

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

$parsedUrl = parse_url($url);

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

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

Untuk beberapa 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 - Apakah ini menyelesaikan masalah beberapa subdomain, seperti usa.en.example.com? Hanya bertanya-tanya (jawaban saya sendiri tidak, btw).
Jared Farrish

@Jared, baru saja menambahkan solusi untuk mendeteksi beberapa subdomain.
Mike Lewis

1
@Mike - Apakah itu akan berfungsi dengan tx.usa.en.example.com? (atau science.news.bbc.co.uk )? (btw, itu bukan tautan yang berfungsi, hanya sebuah contoh, meskipun news.bbc.co.uk berfungsi)
Jared Farrish

4
Itu berfungsi untuk semua yang memiliki satu 'kata' TLD seperti net, com, biz dll. Namun ketika berurusan dengan co.uk, misalnya, tidak. Seperti yang terlihat di sini Ini sebenarnya masalah yang lebih sulit untuk dipecahkan.
Mike Lewis

2
ini juga gagal jika tidak ada subdomain sama sekali.
raveren

32

Anda dapat melakukan ini dengan terlebih dahulu mendapatkan nama domain (mis. Sub.example.com => example.co.uk) dan kemudian menggunakan strstr untuk mendapatkan subdomain.

$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;
}

Keluaran:

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

2
Ini tampaknya merupakan solusi terbaik karena juga memungkinkan domain tanpa subdomain, daripada melakukan tuning ulang nama domain karena subdomain menjadi bagian sebelum titik pertama. Sangat berguna untuk memeriksa keberadaan subdomain.
Karl MW

Saya perlu mendapatkan domain "base" (tanpa subdomain), dan saya membuat solusi sendiri dengan meledakkan host dan mendapatkan elemen terakhir dari array dengan forloop, tetapi saya harus memeriksa panjangnya (untuk mendeteksi apakah mereka adalah bagian dari domain seperti "co.uk"). Sebenarnya, solusi Anda jauh lebih sederhana daripada yang saya lakukan sebelumnya. Regex menyelamatkan nyawa, terima kasih!
Yoone

1
Luar biasa .. ini berfungsi sangat baik untuk semua jenis domain dan subdomain .. bagus.
jon

2
Meskipun solusi ini sangat rapi dan dapat berfungsi di hampir semua kasus, ketahuilah bahwa nama domain mungkin memiliki lebih dari 6 karakter, suka pvt.k12.ma.us, health.vnatau bahkan k12.ak.us. Selain itu, nama domain mungkin menggunakan himpunan karakter bahasa Cina atau Rusia sehingga bagian regex [a-z\.]{2,6}tidak akan cocok dengan mereka. Lihat di sini untuk mendapatkan contoh nama domain: 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

Karena satu-satunya sumber yang dapat diandalkan untuk sufiks domain adalah pendaftar domain, Anda tidak dapat menemukan subdomain tanpa sepengetahuan mereka. Ada daftar dengan semua sufiks domain di https://publicsuffix.org . Situs ini juga tertaut ke pustaka PHP: https://github.com/jeremykendall/php-domain-parser .

Temukan contoh di bawah ini. Saya juga menambahkan contoh untuk en.test.co.uk yang merupakan domain dengan multi sufiks (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

Solusi paling sederhana dan tercepat.

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

4

Secara sederhana...

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

Baru saja membaca $ match [1]

Contoh kerja

Ini berfungsi sempurna dengan daftar url ini

$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 - Saya tidak tahu apa yang tertulis dalam teks Rusia. Hanya mengambil beberapa kata santai dari ru.wikipedia.org ;)
Kamafeather

Bukankah itu bahasa Ukraina? .uaadalah kode negara untuk Ukraina.
nalply

Nggak. Informasi hanya bercampur. Tapi saya tidak yakin, saya tidak cukup baik untuk membedakannya;)
Kamafeather

3
Sehubungan dengan bahasa Rusia, google translate dari bahasa Rusia ke bahasa Inggris muncul kembali sebagai "nilai yang dipublikasikan" (jika ada yang penasaran seperti saya)
Jeremy Harris

@Kather ini terlihat seperti peluru. Adakah cara untuk mendapatkan $match[1]bagian itu? $match[0]sepertinya tidak perlu.
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
Ada cara yang lebih baik untuk secara otomatis mendeteksi host saat ini (seperti $_SERVER['HTTP_HOST']) kemudian mengandalkan tajuk perujuk yang dapat dipalsukan, dengan asumsi itulah gagasan umum di balik jawabannya.
Matius

Benar, saya menggunakan kode lama. Namun, contohnya masih berlaku. Itu bukanlah akar dari pertanyaannya.
Jared Farrish

Hanya untuk menambahkan komentar di atas, mengandalkan $ _SERVER ['HTTP_HOST'] mungkin tidak efisien, karena ada kemungkinan tidak disetel.
gmslzr

2

PHP 7.0: Menggunakan fungsi meledak dan membuat daftar semua hasil.

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

Contoh: sub.domain.com

echo $subdomain; 

Hasil: sub

echo $host;

Hasil: domain


Anda lupa TLD seperti .co.uk- cuplikan Anda tidak akan berfungsi dengan TLD ini
Adrian Preuss

1

Apa yang saya temukan adalah solusi terbaik dan singkat

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

Akan menyebabkan kesalahan Strict. Output dari ledakan tidak dapat dikirim langsung ke array_shift.
YAAK

1

Bagi mereka yang mendapatkan 'Kesalahan: Standar Ketat: Hanya variabel yang harus diteruskan dengan referensi.' Gunakan seperti ini:

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


Bukan itu pertanyaannya, tapi terima kasih atas masukannya.
FazoM


1

Sebenarnya tidak ada solusi dinamis 100% - Saya baru saja mencoba mengetahuinya juga dan karena ekstensi domain (DTL) yang berbeda, tugas ini akan sangat sulit tanpa benar-benar mem-parsing semua ekstensi ini dan memeriksanya setiap kali:

.com vs .co.uk vs org.uk

Opsi yang paling dapat diandalkan adalah dengan menentukan konstanta (atau entri database, dll.) Yang menyimpan nama domain sebenarnya dan menghapusnya dari $_SERVER['SERVER_NAME']penggunaansubstr()

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, '.');

}

Sekarang jika Anda menggunakan fungsi ini di bawahnya, http://test.mymaindomain.co.ukitu akan memberi Anda testatau jika Anda memiliki beberapa tingkat sub-domain http://another.test.mymaindomain.co.ukAnda akan mendapatkan another.test- kecuali tentu saja Anda memperbarui DOMAIN.

Saya harap ini membantu.


1

Secara sederhana

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


1

Menggunakan regex, fungsi string, parse_url () atau kombinasinya, ini bukan solusi nyata. Cukup uji salah satu solusi yang diusulkan dengan domain test.en.example.co.uk, tidak akan ada hasil yang benar.

Solusi yang tepat adalah menggunakan paket yang mem-parsing domain dengan Daftar Sufiks Publik . Saya merekomendasikan TLDExtract , berikut ini contoh kode:

$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

ini adalah solusi saya, ini berfungsi dengan domain yang paling umum, Anda dapat menyesuaikan berbagai ekstensi yang Anda butuhkan:

$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

Saya tahu saya sangat terlambat ke permainan, tapi ini dia.

Apa yang saya lakukan adalah mengambil variabel server HTTP_HOST ( $_SERVER['HTTP_HOST']) dan jumlah huruf dalam domain (jadi untuk example.comitu akan menjadi 11).

Kemudian saya menggunakan substrfungsi tersebut untuk mendapatkan subdomain. aku melakukannya

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

Saya memotong substring pada 12, bukan 11 karena substring dimulai pada 1 untuk parameter kedua. Jadi sekarang jika Anda memasukkan test.example.com, nilainya $subdomainadalah test.

Ini lebih baik daripada menggunakan explodekarena jika subdomain memiliki .di dalamnya, ini tidak akan memotongnya.


Posisi awal "0" tidak ada dalam jawaban Anda. $ subdomain = substr ($ _ SERVER ['HTTP_HOST'], 0, $ numberOfLettersInSubdomain);
Jamie

0

jika Anda menggunakan drupal 7

ini akan membantu Anda:

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

Dari PHP 5.3 Anda dapat menggunakan strstr () dengan parameter true

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

Ini hanya akan bekerja jika tidak ada wwwdi awal string. Pendekatan yang agak terlalu sepele.
FooBar

Ini menyederhanakan banyak hal untuk pengembang lain dalam tim, saya lebih suka menggunakan ini daripada beberapa exp reg lanjutan. Jika Anda ingin memangkas www, gunakan trim ($ s, 'www'); atau sesuaikan saja dengan logika bisnis Anda ...
tasmaniski

1
Demi kelengkapan, www adalah benar-benar subdomain. Ini biasanya dialiaskan ke nama domain itu sendiri karena alasan historis.
Levi Morrison

0

Coba ini...

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

Saya pikir akan lebih membantu bagi OP dan pengunjung selanjutnya, ketika Anda menambahkan beberapa penjelasan untuk Anda.
Reporter

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
baris # 7 harus$host = explode('.', isset($parsedUrl['path']) ? $parsedUrl['path'] : $parsedUrl['host']);
Kal

0

kamu bisa menggunakan ini juga

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

0

Saya melakukan sesuatu seperti ini

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

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

$subdomain = $splitedByDot[0];

0

Kami menggunakan fungsi ini untuk menangani banyak subdomain dan banyak tld juga menangani ip dan 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

Misalkan url saat ini = sub.example.com

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

    if (hitung ($ host)> = 3) {
       echo "Domain utama adalah =". $ host [1]. ".". $ host [0]. "& subdomain adalah =". $ host [2];
       // Domain utama adalah = example.com & subdomain is = sub
    } lain {
       echo "Domain utama adalah =". $ host [1]. ".". $ host [0]. "& subdomain tidak ditemukan";
       // "Domain utama adalah = example.com & subdomain tidak ditemukan";
    }


-3

Jika Anda hanya menginginkan apa yang datang sebelum periode pertama:

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

Bagaimana jika ada penangan protokol di awal, seperti http: //, https: //, ftp: //, dll ...? ;)
Jared Farrish

@ Jared, tidak ada protokol dalam string yang ingin dia parse ... Tetapi jika ada, saya akan menggunakan parse_url()untuk mengekstrak host.
Matius

Jadi kami telah menyediakan dua pendekatan yang akan sesuai dalam konteks yang berbeda.
Jared Farrish

Terutama, saya senang seseorang belum memposting jawaban regex (belum). Belum lagi baris terakhir jawaban saya juga mencapai hal yang sama dengan milik Anda.
Jared Farrish

Dan jika nama hostnya adalah en.example.co.uk?
Marc B
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.