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

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

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

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:password@sub.hostname.tld/path?argument=value#anchor';
  $array=parse_url($url);
  $array['host']=explode('.', $array['host']);

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

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;

5

Einfachste und schnellste Lösung.

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

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

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

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


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

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


Das war nicht die Frage, aber danke für Ihre Eingabe.
FazoM


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.



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'

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

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

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.


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

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

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

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

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"

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

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

0

Ich mache so etwas

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

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

$subdomain = $splitedByDot[0];

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

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


-3

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

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

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.