PHP-Funktion zum Abrufen der Subdomain einer URL

106

Gibt es in PHP eine Funktion, um den Namen der Subdomain abzurufen?

Im folgenden Beispiel möchte ich den "en" -Teil der URL erhalten:

en.example.com
Damiano
quelle
6
Haben Sie eine URL als Zeichenfolge in einer Variablen gespeichert oder woher kommt diese URL? Was ist der Kontext? Bitte erläutern Sie.
Felix Kling
Könnten Sie nicht einen regulären Ausdruck verwenden, der so etwas wie das macht (^|://)(.*)\.und das erfasst .*? Ich lutsche lieber sowohl an PHP als auch an Regex, aber das fällt mir ein.
CorsiKa
Was soll es rein en.foo.bar.example.comoder en.example.co.uk?
Álvaro González
parse_url kann auch helfen
Swapnil

Antworten:

132

Hier ist eine einzeilige Lösung:

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

Oder verwenden Sie Ihr Beispiel:

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

BEARBEITEN: "Nur Variablen sollten als Referenz übergeben werden" durch Hinzufügen einer doppelten Klammer behoben.


EDIT 2 : Ab PHP 5.4 können Sie einfach:

explode('.', 'en.example.com')[0];
Michael Deal
quelle
17
Nur Variablen sollten als Referenz übergeben werden.
Tamás Pap
8
Können Sie explode(...)[0]heutzutage nicht einfach statt Schicht arbeiten? Seit einigen Jahren nicht mehr PHPing ..
Tor Valamo
Fehler:Strict Standards: Only variables should be passed by reference.
Justin
1
ziemlich sicher, dass Sie (explodieren (...)) [0] können, sollten auf dem Rückgabearray anstelle der Funktionsparanthesis (vor 5.4) arbeiten
Garet Claborn
3
Diese Lösung funktioniert nicht, wenn jemand etwas eingibt, www.en.example.comund wird daher wwwals Subdomain zurückgegeben.
Lolbas
65

Verwendet die Funktion parse_url .

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

$parsedUrl = parse_url($url);

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

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

Für mehrere Subdomains

$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
quelle
@Mike Lewis - Löst dies das Problem mehrerer Subdomains wie usa.en.example.com? Ich frage mich nur (meine eigene Antwort übrigens nicht).
Jared Farrish
@Jared, habe gerade eine Lösung hinzugefügt, um mehrere Subdomains zu erkennen.
Mike Lewis
1
@Mike - Funktioniert das mit tx.usa.en.example.com? (oder science.news.bbc.co.uk )? (Übrigens, das ist kein funktionierender Link, nur ein Beispiel, obwohl news.bbc.co.uk funktioniert)
Jared Farrish
4
Das funktioniert für alles, was eine einzige 'Wort'-TLD hat, wie net, com, biz usw. Wenn es sich jedoch zum Beispiel um co.uk handelt, ist dies nicht der Fall. Wie hier zu sehen ist dies tatsächlich ein schwieriger zu lösendes Problem.
Mike Lewis
2
Dies schlägt auch fehl, wenn überhaupt keine Subdomain vorhanden ist.
Raveren
32

Sie können dies tun, indem Sie zuerst den Domainnamen abrufen (z. B. sub.example.com => example.co.uk) und dann strstr verwenden, um die Subdomains abzurufen.

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

Ausgänge:

0 => sub1.sub2
1 => sub1
2 =>
3 => sub1.sub2.sub3
4 => sub1.sub2.sub3
5 => sub1.sub2
Mazon
quelle
2
Dies scheint die beste Lösung zu sein, da es auch Domänen ohne Subdomain ermöglicht, anstatt den Domainnamen als Subdomain neu auszurichten, die der Teil vor dem ersten Punkt ist. Sehr nützlich, um die Existenz einer Subdomain zu überprüfen.
Karl MW
Ich musste die "Basis" -Domäne (ohne die Subdomäne) abrufen, und ich machte meine eigene Lösung, indem ich den Host explodierte und die letzten Elemente des Arrays mit einer forSchleife abrief, aber ich musste ihre Länge überprüfen (um festzustellen, ob sie vorhanden waren waren ein Teil der Domain wie die "co.uk"). Eigentlich ist Ihre Lösung viel einfacher als das, was ich getan habe. Regex rettet Leben, danke!
Yoone
1
Genial .. das funktioniert so gut für alle Domain-Typen und Subdomains .. schön.
Jon
2
während dieser Lösung sehr ordentlich ist und in Arbeit kann fast alle Fälle beachten Sie, dass Domänen - Namen mehr als 6 Zeichen haben könnten, wie pvt.k12.ma.us, health.vnoder sogar k12.ak.us. Außerdem können Domänennamen einen chinesischen oder russischen Zeichensatz verwenden, sodass der Regex-Teil [a-z\.]{2,6}nicht mit ihnen übereinstimmt. Schauen Sie hier, um Beispieldomainnamen zu haben: 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
quelle
7

Da die einzige zuverlässige Quelle für Domain-Suffixe die Domain-Registrare sind, können Sie die Subdomain ohne deren Wissen nicht finden. Unter https://publicsuffix.org finden Sie eine Liste mit allen Domain-Suffixen . Diese Site enthält auch Links zu einer PHP-Bibliothek: https://github.com/jeremykendall/php-domain-parser .

Ein Beispiel finden Sie unten. Ich habe auch das Beispiel für en.test.co.uk hinzugefügt, eine Domain mit einem Multi-Suffix (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
quelle
5

Einfachste und schnellste Lösung.

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

Einfach...

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

Lies einfach $ match [1]

Arbeitsbeispiel

Es funktioniert perfekt mit dieser Liste von URLs

$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
quelle
2
PS: Ich habe keine Ahnung, was im russischen Text steht. Habe gerade ein paar beiläufige Worte von ru.wikipedia.org genommen ;)
Kamafeather
Ist es nicht ukrainisch? .uaist die Landesvorwahl für die Ukraine.
Nalply
Nee. Nur gemischte Informationen. Aber ich bin nicht sicher, ich bin nicht gut genug, um sie zu unterscheiden;)
Kamafeather
3
In Bezug auf das Russische kommt eine Google-Übersetzung vom Russischen ins Englische als "veröffentlichte Werte" zurück (falls jemand so neugierig war wie ich)
Jeremy Harris
@ Kamafeather das sieht kugelsicher aus. Gibt es eine Möglichkeit, nur das $match[1]Teil zu bekommen ? $match[0]scheint unnötig.
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
quelle
1
Es gibt bessere Möglichkeiten, den aktuellen Host (wie $_SERVER['HTTP_HOST']) automatisch zu erkennen, als sich auf einen fälschbaren Referrer-Header zu verlassen, vorausgesetzt, dies ist die allgemeine Idee hinter der Antwort.
Matthew
Richtig, ich habe einen alten Code verwendet. Das Beispiel steht jedoch noch. Das ist nicht die Wurzel der Frage.
Jared Farrish
Um diese obigen Kommentare zusammenzufassen, ist es möglicherweise nicht effizient, sich auf $ _SERVER ['HTTP_HOST'] zu verlassen, da die Möglichkeit besteht, dass es nicht festgelegt wird.
gmslzr
2

PHP 7.0: Verwenden Sie die Explosionsfunktion und erstellen Sie eine Liste aller Ergebnisse.

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

Beispiel: sub.domain.com

echo $subdomain; 

Ergebnis: sub

echo $host;

Ergebnis: Domain

Jeacovy Gayle
quelle
Sie vergessen .co.ukTLDs wie - Ihr Snippet wird mit diesen TLDs nicht funktionieren
Adrian Preuss
1

Was ich als beste und kurze Lösung gefunden habe, ist

array_shift(explode(".",$_SERVER['HTTP_HOST']));
Zulqurnain abbas
quelle
Verursacht einen strengen Fehler. Die Ausgabe von explode kann nicht direkt an array_shift übergeben werden.
YAAK
1

Für diejenigen, die "Fehler: Strenge Standards: Nur Variablen sollten als Referenz übergeben werden" erhalten. Verwenden Sie wie folgt:

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

Naseer
quelle
Das war nicht die Frage, aber danke für Ihre Eingabe.
FazoM
1
$domain = 'sub.dev.example.com';
$tmp = explode('.', $domain); // split into parts
$subdomain = current($tmp);
print($subdomain);     // prints "sub"

Wie in einer vorherigen Frage zu sehen: Wie bekomme ich die erste Subdomain mit PHP?

Gemeinschaft
quelle
1

Es gibt keine wirklich 100% dynamische Lösung - ich habe nur versucht, es auch herauszufinden, und aufgrund verschiedener Domain-Endungen (DTL) wäre diese Aufgabe wirklich schwierig, ohne alle diese Erweiterungen zu analysieren und jedes Mal zu überprüfen:

.com vs .co.uk vs org.uk

Die zuverlässigste Option besteht darin, eine Konstante (oder einen Datenbankeintrag usw.) zu definieren, in der der tatsächliche Domänenname gespeichert und aus der $_SERVER['SERVER_NAME']Verwendung entfernt wirdsubstr()

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

}

Wenn Sie diese Funktion verwenden http://test.mymaindomain.co.uk, erhalten Sie diese testoder wenn Sie mehrere Subdomain-Ebenen http://another.test.mymaindomain.co.ukhaben another.test- es sei denn, Sie aktualisieren die DOMAIN.

Ich hoffe das hilft.

Sebastian Sulinski
quelle
1

Einfach

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

Adam F.
quelle
1

Mit Regex, String-Funktionen, parse_url () oder deren Kombinationen ist dies keine echte Lösung. Testen Sie einfach eine der vorgeschlagenen Lösungen mit Domain test.en.example.co.uk, es wird kein korrektes Ergebnis angezeigt.

Die richtige Lösung ist die Verwendung eines Pakets, das die Domäne mit der öffentlichen Suffixliste analysiert . Ich empfehle TLDExtract , hier ist Beispielcode:

$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
quelle
1

Dies ist meine Lösung. Sie funktioniert mit den gängigsten Domänen. Sie können das Array der Erweiterungen nach Bedarf anpassen:

$SubDomain = explode('.', explode('|ext|', str_replace(array('.com', '.net', '.org'), '|ext|',$_SERVER['HTTP_HOST']))[0]);
Sergio Lopez Loya
quelle
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
quelle
0

Ich weiß, dass ich sehr spät zum Spiel komme, aber jetzt geht es los.

Ich habe die Servervariable HTTP_HOST ( $_SERVER['HTTP_HOST']) und die Anzahl der Buchstaben in der Domäne genommen (also example.com11).

Dann habe ich die substrFunktion verwendet, um die Subdomain zu erhalten. Ich tat

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

Ich schneide die Teilzeichenfolge bei 12 statt bei 11 ab, da die Teilzeichenfolge für den zweiten Parameter bei 1 beginnt. So , jetzt , wenn Sie test.example.com eingegeben, den Wert $subdomainwäre test.

Dies ist besser als die Verwendung, explodeda die Subdomain, wenn .sie eine enthält, diese nicht abschneidet.

Piccolo
quelle
Die Startposition "0" fehlte in Ihrer Antwort. $ subdomain = substr ($ _ SERVER ['HTTP_HOST'], 0, $ numberOfLettersInSubdomain);
Jamie
0

Wenn Sie Drupal 7 verwenden

das wird dir helfen:

global $base_path;
global $base_root;  
$fulldomain = parse_url($base_root);    
$splitdomain = explode(".", $fulldomain['host']);
$subdomain = $splitdomain[0];
Mohanad
quelle
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
quelle
0

Ab PHP 5.3 können Sie strstr () mit true- Parameter verwenden

echo strstr($_SERVER["HTTP_HOST"], '.', true); //prints en
Tasmaniski
quelle
Dies funktioniert nur, wenn wwwbeim Start der Zeichenfolge keine vorhanden ist . Ein bisschen zu trivialer Ansatz.
FooBar
Dies vereinfacht die Dinge für andere Entwickler im Team. Ich würde dies lieber verwenden als einige erweiterte Reg-Exp. Wenn Sie www trimmen möchten, verwenden Sie trim ($ s, 'www'). oder passen Sie es einfach an Ihre Geschäftslogik an ...
Tasmaniski
1
Der Vollständigkeit halber www ist eigentlich eine Subdomain. Es ist nur aus historischen Gründen häufig auf den Domainnamen selbst ausgerichtet.
Levi Morrison
0

Versuche dies...

$domain = 'en.example.com';
$tmp = explode('.', $domain);
$subdomain = current($tmp);
echo($subdomain);     // echo "en"
edCoder
quelle
Ich denke, es wäre hilfreicher für das OP und weitere Besucher, wenn Sie Ihrer Intensität eine Erklärung hinzufügen.
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
quelle
1
Zeile # 7 sollte sein$host = explode('.', isset($parsedUrl['path']) ? $parsedUrl['path'] : $parsedUrl['host']);
Kal
0

Sie können dies auch verwenden

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

Ich mache so etwas

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

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

$subdomain = $splitedByDot[0];
Scheich Althaf
quelle
0

Wir verwenden diese Funktion, um mehrere Subdomains zu verarbeiten, und mehrere tld verarbeiten auch IP und 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
quelle
0

Angenommen, die aktuelle URL = sub.example.com

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

    if (count ($ host)> = 3) {
       echo "Hauptdomäne ist =". $ host [1]. ".". $ host [0]. "& Unterdomäne ist =". $ host [2];
       // Hauptdomain ist = example.com & Subdomain ist = sub
    } else {
       echo "Hauptdomäne ist =". $ host [1]. ".". $ host [0]. "& Subdomain nicht gefunden";
       // "Hauptdomain ist = example.com & Subdomain nicht gefunden";
    }}

Khorshed Alam Shohel
quelle
-3

Wenn Sie nur wollen, was vor der ersten Periode kommt:

list($sub) = explode('.', 'en.example.com', 2);
Matthew
quelle
Was ist, wenn am Anfang ein Protokollhandler vorhanden ist, z. B. http: //, https: //, ftp: // usw.? ;)
Jared Farrish
@Jared, es gibt kein Protokoll in der Zeichenfolge, die er analysieren möchte ... Aber wenn ja, würde ich parse_url()den Host extrahieren.
Matthew
Daher haben wir zwei Ansätze bereitgestellt, die in unterschiedlichen Kontexten angemessen sind.
Jared Farrish
Hauptsächlich bin ich nur froh, dass jemand (noch) keine Regex-Antwort gepostet hat. Ganz zu schweigen davon, dass die letzte Zeile meiner Antwort dasselbe bewirkt wie Ihre.
Jared Farrish
Und wenn der Hostname en.example.co.uk ist?
Marc B