PHP function to get the subdomain of a URL

只谈情不闲聊 提交于 2019-11-26 01:21:21
Michael Deal

Here's a one line solution:

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

Or using your example:

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

EDIT: Fixed "only variables should be passed by reference" by adding double parenthesis.


EDIT 2: Starting from PHP 5.4 you can simply do:

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

Uses the parse_url function.

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

$parsedUrl = parse_url($url);

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

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

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

You can do this by first getting the domain name (e.g. sub.example.com => example.co.uk) and then use strstr to get the subdomains.

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

Outputs:

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

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

As the only reliable source for domain suffixes are the domain registrars, you can't find the subdomain without their knowledge. There is a list with all domain suffixes at https://publicsuffix.org. This site also links to a PHP library: https://github.com/jeremykendall/php-domain-parser.

Please find an example below. I also added the sample for en.test.co.uk which is a domain with a 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;
$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, '.')); 

Simply...

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

Just read $match[1]

Working example

It works perfectly with this list of 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);
}

Simplest and fastest solution.

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

What I found the best and short solution is

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

For those who get 'Error: Strict Standards: Only variables should be passed by reference.' Use like this:

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

$domain = 'sub.dev.example.com';
$tmp = explode('.', $domain); // split into parts
$subdomain = current($tmp);
print($subdomain);     // prints "sub"

As seen in a previous question: How to get the first subdomain with PHP?

There isn't really a 100% dynamic solution - I've just been trying to figure it out as well and due to different domain extensions (DTL) this task would be really difficult without actually parsing all these extensions and checking them each time:

.com vs .co.uk vs org.uk

The most reliable option is to define a constant (or database entry etc.) that stores the actual domain name and remove it from the $_SERVER['SERVER_NAME'] using 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, '.');

}

Now if you're using this function under http://test.mymaindomain.co.uk it will give you test or if you have multiple sub-domain levels http://another.test.mymaindomain.co.uk you'll get another.test - unless of course you update the DOMAIN.

I hope this helps.

Simply

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

this is my solution, it works with the most common domains, you can fit the array of extensions as you need:

$SubDomain = explode('.', explode('|ext|', str_replace(array('.com', '.net', '.org'), '|ext|',$_SERVER['HTTP_HOST']))[0]);

Using regex, string functions, parse_url() or their combinations it's not real solution. Just test any of proposed solutions with domain test.en.example.co.uk, there will no any correct result.

Correct solution is use package that parses domain with Public Suffix List. I recomend TLDExtract, here is sample code:

$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'
// 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

I know I'm really late to the game, but here goes.

What I did was take the HTTP_HOST server variable ($_SERVER['HTTP_HOST']) and the number of letters in the domain (so for example.com it would be 11).

Then I used the substr function to get the subdomain. I did

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

I cut the substring off at 12 instead of 11 because substrings start on 1 for the second parameter. So now if you entered test.example.com, the value of $subdomain would be test.

This is better than using explode because if the subdomain has a . in it, this will not cut it off.

mohanad

if you are using drupal 7

this will help you:

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

From PHP 5.3 you can use strstr() with true parameter

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

Try this...

$domain = 'en.example.com';
$tmp = explode('.', $domain);
$subdomain = current($tmp);
echo($subdomain);     // echo "en"
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);
}

you can use this too

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

I'm doing something like this

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

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

$subdomain = $splitedByDot[0];

PHP 7.0: Using the explode function and create a list of all the results.

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

Example: sub.domain.com

echo $subdomain; 

Result: sub

echo $host;

Result: domain

We use this function to handle multiple subdomain and multiple tld also handle ip and 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;
    }

Suppose current url = sub.example.com


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

    if (count($host) >= 3){
       echo "Main domain is = ".$host[1].".".$host[0]." & subdomain is = ".$host[2];
       // Main domain is = example.com & subdomain is = sub
    } else {
       echo "Main domain is = ".$host[1].".".$host[0]." & subdomain not found";
       // "Main domain is = example.com & subdomain not found";
    }

If you only want what comes before the first period:

list($sub) = explode('.', 'en.example.com', 2);
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!