Как проверить доменное имя в PHP? - PullRequest
29 голосов
/ 18 ноября 2009

Возможно ли это без использования регулярного выражения?

Например, я хочу проверить, является ли строка допустимым доменом:

domain-name
abcd
example

Действительные домены. Это недействительно, конечно:

domaia@name
ab$%cd

И так далее. Таким образом, в основном это должно начинаться с буквенно-цифрового символа, тогда может быть больше символов alnum плюс также дефис. И оно также должно заканчиваться символом alnum.

Если это невозможно, не могли бы вы предложить мне шаблон регулярного выражения для этого?

EDIT:

Почему это не работает? Я неправильно использую preg_match?

$domain = '@djkal';
$regexp = '/^[a-zA-Z0-9][a-zA-Z0-9\-\_]+[a-zA-Z0-9]$/';
if (false === preg_match($regexp, $domain)) {
    throw new Exception('Domain invalid');
}

Ответы [ 19 ]

127 голосов
/ 14 января 2011
<?php
function is_valid_domain_name($domain_name)
{
    return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name) //valid chars check
            && preg_match("/^.{1,253}$/", $domain_name) //overall length check
            && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name)   ); //length of each label
}
?>

Контрольные примеры:

is_valid_domain_name? [a]                       Y
is_valid_domain_name? [0]                       Y
is_valid_domain_name? [a.b]                     Y
is_valid_domain_name? [localhost]               Y
is_valid_domain_name? [google.com]              Y
is_valid_domain_name? [news.google.co.uk]       Y
is_valid_domain_name? [xn--fsqu00a.xn--0zwm56d] Y
is_valid_domain_name? [goo gle.com]             N
is_valid_domain_name? [google..com]             N
is_valid_domain_name? [google.com ]             N
is_valid_domain_name? [google-.com]             N
is_valid_domain_name? [.google.com]             N
is_valid_domain_name? [<script]                 N
is_valid_domain_name? [alert(]                  N
is_valid_domain_name? [.]                       N
is_valid_domain_name? [..]                      N
is_valid_domain_name? [ ]                       N
is_valid_domain_name? [-]                       N
is_valid_domain_name? []                        N
56 голосов
/ 19 ноября 2011

При этом вы будете не только проверять, имеет ли домен действительный формат, но также является ли он активным / ему назначен IP-адрес.

$domain = "stackoverflow.com";

if(filter_var(gethostbyname($domain), FILTER_VALIDATE_IP))
{
    return TRUE;
}

Обратите внимание, что этот метод требует, чтобы записи DNS были активными, поэтому, если вы хотите, чтобы строка домена была проверена, не находясь в DNS, используйте метод регулярного выражения, указанный в velcrow выше.

Также эта функция не предназначена для проверки строки URL, для этого используйте FILTER_VALIDATE_URL. Мы не используем FILTER_VALIDATE_URL для домена, поскольку строка домена не является допустимым URL-адресом.

9 голосов
/ 23 сентября 2010

Во-первых, вы должны уточнить, имеете ли вы в виду:

  1. метки отдельных доменных имен
  2. полных доменных имен (то есть несколько разделенных точками меток)
  3. имена хостов

Причина, по которой необходимо проводить различие, заключается в том, что метка может технически включать любые символы, включая символы NUL, @ и '.'. DNS поддерживает 8 бит, и вполне возможно иметь файл зоны, содержащий запись, читающую "an\0odd\.l@bel". Конечно, это не рекомендуется, не в последнюю очередь потому, что людям будет трудно отличить точку внутри ярлыка от этих разделяющих ярлыков, но это является законным.

Однако для URL требуется имя хоста в них, и они регулируются RFC 952 и 1123. Допустимые имена хоста являются подмножеством домен имен. В частности, разрешены только буквы, цифры и дефис. Кроме того, первый и последний символы не могут быть дефисами. RFC 952 не разрешил номер для первого символа, но RFC 1123 впоследствии смягчил это.

Таким образом:

  • a - действует
  • 0 - действует
  • a- - недействительно
  • a-b - действует
  • xn--dasdkhfsd - действителен (кодировка IDN в виде пункода)

Вне головы, я не думаю, что можно сделать недействительным пример a- с помощью одного простого регулярного выражения. Лучшее, что я могу придумать, чтобы проверить single host label:

if (preg_match('/^[a-z\d][a-z\d-]{0,62}$/i', $label) &&
   !preg_match('/-$/', $label))
{
    # label is legal within a hostname
}

Чтобы еще больше усложнить ситуацию, некоторые записи доменных имен (обычно SRV записей) используют метки с префиксом подчеркивания, например, _sip._udp.example.com. Это не имена хостов, но допустимые доменные имена.

9 голосов
/ 01 мая 2012

использование checkdnsrr http://php.net/manual/en/function.checkdnsrr.php

$domain = "stackoverflow.com";

checkdnsrr($domain , "A");

//returns true if has a dns A record, false otherwise
7 голосов
/ 15 февраля 2018

PHP 7

// Validate a domain name
var_dump(filter_var('mandrill._domainkey.mailchimp.com', FILTER_VALIDATE_DOMAIN));
# string(33) "mandrill._domainkey.mailchimp.com"

// Validate an hostname (here, the underscore is invalid)
var_dump(filter_var('mandrill._domainkey.mailchimp.com', FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
# bool(false)

Здесь не задокументировано: http://www.php.net/filter.filters.validate, и запрос об ошибке находится здесь: https://bugs.php.net/bug.php?id=72013

6 голосов
/ 18 ноября 2009

Я думаю, что как только вы изолировали доменное имя, скажем, используя идею Эрклана:

$myUrl = "http://www.domain.com/link.php";
$myParsedURL = parse_url($myUrl);
$myDomainName= $myParsedURL['host'];

вы можете использовать:

if( false === filter_var( $myDomainName, FILTER_VALIDATE_URL ) ) {
// failed test

}

PHP5s Функции фильтра предназначены именно для этой цели, я бы подумал.

Он не дает точного ответа на ваш вопрос, так как не использует Regex, я понимаю.

4 голосов
/ 18 ноября 2009

Вот еще один способ без регулярных выражений.

$myUrl = "http://www.domain.com/link.php";
$myParsedURL = parse_url($myUrl);
$myDomainName= $myParsedURL['host'];
$ipAddress = gethostbyname($myDomainName);
if($ipAddress == $myDomainName)
{
   echo "There is no url";
}
else
{
   echo "url found";
}
3 голосов
/ 18 ноября 2009

Регулярное выражение является наиболее эффективным способом проверки валидации домена. Если вы не можете использовать Регулярное выражение (что IMO глупо), то вы можете разделить каждую часть домена:

  • WWW. / поддомен
  • доменное имя
  • .extension

Затем вам нужно будет проверить каждый символ в каком-то цикле, чтобы убедиться, что он соответствует допустимому домену.

Как я уже сказал, гораздо эффективнее использовать регулярные выражения.

2 голосов
/ 18 ноября 2009

Ваше регулярное выражение в порядке, но вы не используете preg_match правильно. Возвращает int (0 или 1), а не логическое значение. Просто напишите if(!preg_match($regex, $string)) { ... }

1 голос
/ 22 марта 2018

Правильный ответ: вы не позволяете ... инструменту, протестированному на модуле, сделать работу за вас:

// return '' if host invalid --
private function setHostname($host = '')
{
    $ret = (!empty($host)) ? $host : '';
    if(filter_var('http://'.$ret.'/', FILTER_VALIDATE_URL) === false) {
        $ret = '';
    }
    return $ret;
}

дальнейшее чтение: https://www.w3schools.com/php/filter_validate_url.asp

...