PHP HTTP_HOST извлечение поддомена, учитывая, что поддомен должен быть подстановочным знаком и содержать более одного '.'

Я пытаюсь извлечь поддомен из значения HTTP_HOST. Однако я столкнулся с проблемой, когда, если в поддомене есть более одной точки, он не может соответствовать должным образом. Учитывая, что это сценарий для запуска в нескольких разных доменах, и он может иметь неограниченное количество точек, а tld может состоять из 1 или 2 частей (и любой длины) - существует ли практический способ правильного сопоставления субдомена, домена и тдл во всех ситуациях?

Так, например, возьмите следующие значения HTTP_HOST и то, что требуется сопоставить.

  • www.buggedcom.co.uk
    • Поддомен: www
    • Домен: buggedcom.co.uk
    • TLD: co.uk
  • www.buggedcom.com
    • Поддомен: www
    • Домен: buggedcom.com
    • TLD: com
  • test.buggedcom.co.uk
    • Субдомен: тест
    • Домен: buggedcom.co.uk
    • TLD: co.uk
  • test.buggedcom.com
    • Субдомен: тест
    • Домен: buggedcom.com
    • TLD: com
  • multi.sub.test.buggedcom.co.uk
    • Субдомен: multi.sub.test
    • Домен: buggedcom.co.uk
    • TLD: co.uk
  • multi.sub.test.buggedcom.com
    • Субдомен: multi.sub.test
    • Домен: buggedcom.com
    • TLD: com

Я предполагаю, что единственный способ сделать это - загрузить список tlds, что позволяет, возможно, не очень-то и делать, так как это в начале скрипта и действительно требует такой тяжелой работы.

Ниже приведен текущий код.

define('HOST', isset($_SERVER['HTTP_HOST']) === true ? $_SERVER['HTTP_HOST'] : (isset($_SERVER['SERVER_ADDR']) === true ? $_SERVER['SERVER_ADDR'] : $_SERVER['SERVER_NAME']));
$domain_parts = explode('.', HOST); 
$domain_parts_count = count($domain_parts);
if($domain_parts_count > 1)
{   
    $sub_parts = array_splice($domain_parts, 0, $domain_parts_count-3);
    define('SUBDOMAIN', implode('.', $sub_parts));
    unset($sub_parts);
}
else
{
    define('SUBDOMAIN', '');
}
define('DOMAIN', implode('.', $domain_parts));
var_dump($domain_parts, SUBDOMAIN, DOMAIN);exit;

Просто подумал, может ли mod_rewrite добавить поддомен как параметр get?

4 ответа

Решение

Прежде всего я бы взорвался (и использовал бы первый индекс в массиве) на слэше, просто чтобы быть уверенным, что строка заканчивается TLD.

Тогда я бы вырезал его с помощью preg_replace. Этот rexexp соответствует домену +tld независимо от типа tld. Однако остерегайтесь, это может привести к проблемам с 2- и 3-буквенными доменами. Но это должно дать толчок в правильном направлении....

[a-zA-Z0-9]+\.(([a-zA-Z]{2,6})|([a-zA-Z]{2,3}\.[a-zA-Z]{2,3}))$

Изменить: как указано:.museum также возможно, поэтому отредактировал первый шаблон в части TLD....

И, конечно, TLD, как.UK может вести себя иначе, чем co.uk тьфу.. это не так просто...

Я думаю, что решение этой проблемы лучше обрабатывается теми, кто пытается сделать то же самое... в комментариях к документации PHP для функции parse_url есть куча лучших функций разбора URL, которые могут работать лучше: http://www.php.net/manual/en/function.parse-url.php

Не быть придирчивым, но с технической точки зрения .co.uk это домен второго уровня.

.uk является "Домен верхнего уровня кода страны" в этом случае, и .co предназначен для "коммерческого использования", определенного Соединенным Королевством.

Это может не ответить на ваш вопрос, хотя.

В Википедии есть довольно полный список доменов верхнего уровня, так как вы можете видеть, что они содержат только 1 "точку", за которой следует 1 "строка".

С помощью preg_match вы можете извлечь части поддоменов и tld за один раз, например:

function get_domain_parts($domain) {
    $parts = array();
    $pattern = "/(.*)\.buggedcom\.(.*)/";
    if (preg_match($pattern, $domain, $parts) == 1) {
        return array($parts[1], $parts[2]);
    } else {
        return FALSE;
    }
}

$result = get_domain_parts("multi.sub.test.buggedcom.co.uk");
if ($result) {
    echo($result[0] . " and " . $result[1]); // multi.sub.test and co.uk   
}
Другие вопросы по тегам