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
Damiano
sumber
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];
Kesepakatan Michael
sumber
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
sumber
@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
Mazon
sumber
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:[email protected]/path?argument=value#anchor';
  $array=parse_url($url);
  $array['host']=explode('.', $array['host']);

  echo $array['host'][0]; // returns 'en'
?>
JMW
sumber
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;
Sascha Frinken
sumber
5

Solusi paling sederhana dan tercepat.

$sSubDomain = str_replace('.example.com','',$_SERVER['HTTP_HOST']);
Arjen
sumber
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);
}
Kamafeather
sumber
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, '.')); 
Jared Farrish
sumber
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

Jeacovy Gayle
sumber
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']));
Zulqurnain abbas
sumber
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);

Naseer
sumber
Bukan itu pertanyaannya, tapi terima kasih atas masukannya.
FazoM
1
$domain = 'sub.dev.example.com';
$tmp = explode('.', $domain); // split into parts
$subdomain = current($tmp);
print($subdomain);     // prints "sub"

Seperti yang terlihat pada pertanyaan sebelumnya: Bagaimana cara mendapatkan subdomain pertama dengan PHP?

Komunitas
sumber
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.

Sebastian Sulinski
sumber
1

Secara sederhana

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

Adam F
sumber
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'
Oleksandr Fediashov
sumber
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]);
Sergio Lopez Loya
sumber
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
Rahul Prasad
sumber
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.

Piccolo
sumber
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];
mohanad
sumber
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 />';
Brynner Ferreira
sumber
0

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

echo strstr($_SERVER["HTTP_HOST"], '.', true); //prints en
tasmaniski
sumber
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"
edCoder
sumber
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);
}
itsazzad
sumber
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));
XIMvad
sumber
0

Saya melakukan sesuatu seperti ini

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

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

$subdomain = $splitedByDot[0];
Sheik Althaf
sumber
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;
    }
Javad Adib
sumber
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";
    }

Khorshed Alam Shohel
sumber
-3

Jika Anda hanya menginginkan apa yang datang sebelum periode pertama:

list($sub) = explode('.', 'en.example.com', 2);
Matthew
sumber
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