PHP Получение доменного имени из поддоменов - PullRequest
26 голосов
/ 29 июля 2009

Мне нужно написать функцию для анализа переменных, которые содержат доменные имена. Лучше всего объяснить это на примере, переменная может содержать любую из следующих вещей:

here.example.com
example.com
example.org
here.example.org

Но при прохождении через мою функцию все они должны возвращать либо example.com, либо example.co.uk, в основном имя корневого домена. Я уверен, что делал это раньше, но я искал в Google около 20 минут и ничего не могу найти. Любая помощь будет оценена.

РЕДАКТИРОВАТЬ: игнорировать .co.uk, предположим, что все домены, проходящие через эту функцию, имеют трехбуквенный TLD.

Ответы [ 22 ]

37 голосов
/ 29 июля 2009

Архив вопросов Stackoverflow:


print get_domain("http://somedomain.co.uk"); // outputs 'somedomain.co.uk'

function get_domain($url)
{
  $pieces = parse_url($url);
  $domain = isset($pieces['host']) ? $pieces['host'] : '';
  if (preg_match('/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $domain, $regs)) {
    return $regs['domain'];
  }
  return false;
}
7 голосов
/ 29 июля 2009

Я бы сделал что-то вроде следующего:

// hierarchical array of top level domains
$tlds = array(
    'com' => true,
    'uk' => array(
        'co' => true,
        // …
    ),
    // …
);
$domain = 'here.example.co.uk';
// split domain
$parts = explode('.', $domain);
$tmp = $tlds;
// travers the tree in reverse order, from right to left
foreach (array_reverse($parts) as $key => $part) {
    if (isset($tmp[$part])) {
        $tmp = $tmp[$part];
    } else {
        break;
    }
}
// build the result
var_dump(implode('.', array_slice($parts, - $key - 1)));
6 голосов
/ 02 августа 2012

Я использовал базу данных, которую имеет Mozilla.

Вот мой код:

fetch_mozilla_tlds.php содержит алгоритм кэширования. Эта строка важна:

$mozillaTlds = file('http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1');

Основной файл, используемый внутри приложения:

function isTopLevelDomain($domain)
{
    $domainParts = explode('.', $domain);
    if (count($domainParts) == 1) {
        return false;
    }

    $previousDomainParts = $domainParts;
    array_shift($previousDomainParts);

    $tld = implode('.', $previousDomainParts);

    return isDomainExtension($tld);
}

function isDomainExtension($domain)
{
    $tlds = getTLDs();

    /**
     * direct hit
     */
    if (in_array($domain, $tlds)) {
        return true;
    }

    if (in_array('!'. $domain, $tlds)) {
        return false;
    }

    $domainParts = explode('.', $domain);

    if (count($domainParts) == 1) {
        return false;
    }

    $previousDomainParts = $domainParts;

    array_shift($previousDomainParts);
    array_unshift($previousDomainParts, '*');

    $wildcardDomain = implode('.', $previousDomainParts);

    return in_array($wildcardDomain, $tlds);
}

function getTLDs()
{
    static $mozillaTlds = array();

    if (empty($mozillaTlds)) {
        require 'fetch_mozilla_tlds.php';
        /* @var $mozillaTlds array */
    }

    return $mozillaTlds;
}

UPDATE:
База данных эволюционировала и теперь доступна на собственном веб-сайте - http://publicsuffix.org/

5 голосов
/ 17 марта 2018

Если вы хотите быстрое простое решение, без внешних вызовов и проверки по заранее определенным массивам. Работает и для новых доменов, таких как www.domain.gallery, в отличие от самого популярного ответа.

function get_domain($host){
  $myhost = strtolower(trim($host));
  $count = substr_count($myhost, '.');
  if($count === 2){
    if(strlen(explode('.', $myhost)[1]) > 3) $myhost = explode('.', $myhost, 2)[1];
  } else if($count > 2){
    $myhost = get_domain(explode('.', $myhost, 2)[1]);
  }
  return $myhost;
}
  • domain.com -> domain.com
  • sub.domain.com -> domain.com
  • www.domain.com -> domain.com
  • www.sub.sub.domain.com -> domain.com
  • domain.co.uk -> domain.co.uk
  • sub.domain.co.uk -> domain.co.uk
  • www.domain.co.uk -> domain.co.uk
  • www.sub.sub.domain.co.uk -> domain.co.uk
  • domain.photography -> domain.photography
  • www.domain.photography -> domain.photography
  • www.sub.domain.photography -> domain.photography
5 голосов
/ 08 декабря 2010

Почти наверняка то, что вы ищете, это:

https://github.com/Synchro/regdom-php

Это библиотека PHP, которая использует (насколько это практически возможно) полный список различных TLD, собранных по адресу publicsuffix.org/list/, и упаковывает их в небольшую элегантную функцию.

Как только библиотека включена, это так же просто, как:

$registeredDomain = getRegisteredDomain( $domain );

2 голосов
/ 29 июля 2009
    $full_domain = $_SERVER['SERVER_NAME'];
$just_domain = preg_replace("/^(.*\.)?([^.]*\..*)$/", "$2", $_SERVER['HTTP_HOST']);
1 голос
/ 23 декабря 2014

Это короткий способ сделать это:

$host = $_SERVER['HTTP_HOST'];
preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
echo "domain name is: {$matches[0]}\n";
1 голос
/ 29 апреля 2012

Этот скрипт генерирует Perl-файл, содержащий одну функцию get_domain из ETLD-файла. Допустим, у вас есть имена хостов, такие как img1, img2, img3, ... в .photobucket.com. Для каждого из этих get_domain $ host вернул бы photobucket.com. Обратите внимание, что это не самая быстрая функция на земле, поэтому в моем главном анализаторе журналов, который использует это, я сохраняю хэш сопоставлений хоста с доменом и запускаю его только для хостов, которые еще не находятся в хэше.

#!/bin/bash

cat << 'EOT' > suffixes.pl
#!/bin/perl

sub get_domain {
  $_ = shift;
EOT

wget -O - http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1 \
  | iconv -c -f UTF-8 -t ASCII//TRANSLIT \
  | egrep -v '/|^$' \
  | sed -e 's/^\!//' -e "s/\"/'/g" \
  | awk '{ print length($0),$0 | "sort -rn"}' | cut -d" " -f2- \
  | while read SUFF; do
      STAR=`echo $SUFF | cut -b1`
      if [ "$STAR" = '*' ]; then
        SUFF=`echo $SUFF | cut -b3-`
        echo "  return \"\$1\.\$2\.$SUFF\" if /([a-zA-Z0-9\-]+)\.([a-zA-Z0-9\-]+)\.$SUFF\$/;"
      else
        echo "  return \"\$1\.$SUFF\" if /([a-zA-Z0-9\-]+)\.$SUFF\$/;"
      fi
    done >> suffixes.pl

cat << 'EOT' >> suffixes.pl
}

1;
EOT
1 голос
/ 30 сентября 2016

Это не надежно и должно действительно использоваться, только если вы знаете, что домен не будет чем-то непонятным, но его легче читать, чем большинство других опций:

$justDomain = $_SERVER['SERVER_NAME'];
switch(substr_count($justDomain, '.')) {
    case 1:
        // 2 parts. Must not be a subdomain. Do nothing.
        break;

    case 2:
        // 3 parts. Either a subdomain or a 2-part suffix
        // If the 2nd part is over 3 chars's, assume it to be the main domain part which means we have a subdomain.
        // This isn't foolproof, but should be ok for most domains.
        // Something like domainname.parliament.nz would cause problems, though. As would www.abc.com
        $parts = explode('.', $justDomain);
        if(strlen($parts[1]) > 3) {
            unset($parts[0]);
            $justDomain = implode('.', $parts);
        }
        break;

    default:
        // 4+ parts. Must be a subdomain.
        $parts = explode('.', $justDomain, 2);
        $justDomain = $parts[1];
        break;
}

// $justDomain should now exclude any subdomain part.
0 голосов
/ 03 сентября 2016

Существует два способа извлечь поддомен из хоста:

  1. Первый более точный метод - использовать базу данных tlds (например, public_suffix_list.dat ) и сопоставить домен с ней. Это немного тяжело в некоторых случаях. Есть несколько классов PHP для его использования, например php-domain-parser и TLDExtract .

  2. Второй способ не такой точный, как первый, но он очень быстрый и во многих случаях может дать правильный ответ, я написал для него следующую функцию:

    function get_domaininfo($url) {
        // regex can be replaced with parse_url
        preg_match("/^(https|http|ftp):\/\/(.*?)\//", "$url/" , $matches);
        $parts = explode(".", $matches[2]);
        $tld = array_pop($parts);
        $host = array_pop($parts);
        if ( strlen($tld) == 2 && strlen($host) <= 3 ) {
            $tld = "$host.$tld";
            $host = array_pop($parts);
        }
    
        return array(
            'protocol' => $matches[1],
            'subdomain' => implode(".", $parts),
            'domain' => "$host.$tld",
            'host'=>$host,'tld'=>$tld
        );
    }
    

    Пример:

    print_r(get_domaininfo('http://mysubdomain.domain.co.uk/index.php'));
    

    Возвращает:

    Array
    (
        [protocol] => https
        [subdomain] => mysubdomain
        [domain] => domain.co.uk
        [host] => domain
        [tld] => co.uk
    )
    
...