Подтвердить что ты не робот

Как проверить доменное имя в PHP?

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

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

domain-name
abcd
example

Являются допустимыми доменами. Конечно, они недействительны:

[email protected]
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');
}
4b9b3361

Ответ 1

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

Ответ 2

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

$domain = "stackoverflow.com";

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

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

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

Ответ 4

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

  • индивидуальные метки имен доменов
  • целые имена доменов (т.е. многоточечные метки)
  • имена хостов

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

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

Следовательно:

  • a - действительный
  • 0 - действительный
  • a- - недействительный
  • a-b - действительный
  • xn--dasdkhfsd - действительный (punycode encoding of IDN)

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

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

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

Ответ 5

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

$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 Filter для такой цели я бы подумал.

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

  • WWW./sub-domain
  • доменное имя
  • .extension

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

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

Ответ 9

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

Ответ 10

Если вы не хотите использовать регулярные выражения, вы можете попробовать следующее:

$str = 'domain-name';

if (ctype_alnum(str_replace('-', '', $str)) && $str[0] != '-' && $str[strlen($str) - 1] != '-') {
    echo "Valid domain\n";
} else {
    echo "Invalid domain\n";
}

но поскольку указанное regexp - лучший инструмент для этого.

Ответ 11

Если вы хотите проверить, существует ли конкретное доменное имя или IP-адрес, вы также можете использовать checkdnsrr
Вот документ http://php.net/manual/en/function.checkdnsrr.php

Ответ 12

Допустимый домен - это то, что я могу зарегистрировать или, по крайней мере, что-то похожее на то, что я могу его зарегистрировать. Именно по этой причине мне нравится отделять это от "localhost" -names.

И, наконец, меня заинтересовал главный вопрос, если бы избежать Regex было бы быстрее, и это мой результат:

<?php
function filter_hostname($name, $domain_only=false) {
    // entire hostname has a maximum of 253 ASCII characters
    if (!($len = strlen($name)) || $len > 253
    // .example.org and localhost- are not allowed
    || $name[0] == '.' || $name[0] == '-' || $name[ $len - 1 ] == '.' || $name[ $len - 1 ] == '-'
    // a.de is the shortest possible domain name and needs one dot
    || ($domain_only && ($len < 4 || strpos($name, '.') === false))
    // several combinations are not allowed
    || strpos($name, '..') !== false
    || strpos($name, '.-') !== false
    || strpos($name, '-.') !== false
    // only letters, numbers, dot and hypen are allowed
/*
    // a little bit slower
    || !ctype_alnum(str_replace(array('-', '.'), '', $name))
*/
    || preg_match('/[^a-z\d.-]/i', $name)
    ) {
        return false;
    }
    // each label may contain up to 63 characters
    $offset = 0;
    while (($pos = strpos($name, '.', $offset)) !== false) {
        if ($pos - $offset > 63) {
            return false;
        }
        $offset = $pos + 1;
    }
    return $name;
}
?>

Результаты тестов по сравнению с функцией липучки и 10000 итераций (полные результаты содержит много вариантов кода. Было интересно найти самый быстрый.):

filter_hostname($domain);// $domains: 0.43556308746338 $real_world: 0.33749794960022
is_valid_domain_name($domain);// $domains: 0.81832790374756 $real_world: 0.32248711585999

$real_world не содержал крайних длинных доменных имен для получения лучших результатов. И теперь я могу ответить на ваш вопрос: с использованием ctype_alnum() было бы возможно реализовать его без регулярного выражения, но поскольку preg_match() был быстрее, я бы предпочел это.

Если вам не нравится тот факт, что "local.host" является действительным доменным именем, используйте эту функцию вместо этого, чтобы валиды против публичного списка tld. Может быть, кто-то найдет время, чтобы объединить оба.

Ответ 13

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

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

Ответ 14

Я знаю, что это старый вопрос, но это был первый ответ на поиск Google, поэтому он кажется актуальным. У меня недавно была такая же проблема. Решение в моем случае состояло в том, чтобы просто использовать публичный список суффикса:

https://publicsuffix.org/learn/

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

Ответ 15

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

Эта функция возвращает false, если доменное имя не зарегистрировано, иначе возвращает доменное имя.

function get_domain_name($domain) { 
    //Step 1 - Return false if any shell sensitive chars or space/tab were found
    if(escapeshellcmd($domain)!=$domain || count(explode(".", $domain))<2 || preg_match("/[\s\t]/", $domain)) {
            return false;
    }

    //Step 2 - Get the root domain in-case of subdomain
    $domain = (count(explode(".", $domain))>2 ? strtolower(explode(".", $domain)[count(explode(".", $domain))-2].".".explode(".", $domain)[count(explode(".", $domain))-1]) : strtolower($domain));

    //Step 3 - Run shell command 'dig' to get SOA servers for the domain extension
    $ns = shell_exec(escapeshellcmd("dig +short SOA ".escapeshellarg(explode(".", $domain)[count(explode(".", $domain))-1]))); 

    //Step 4 - Return false if invalid extension (returns NULL), or take the first server address out of output
    if($ns===NULL) {
            return false;
    }
    $ns = (((preg_split('/\s+/', $ns)[0])[strlen(preg_split('/\s+/', $ns)[0])-1]==".") ? substr(preg_split('/\s+/', $ns)[0], 0, strlen(preg_split('/\s+/', $ns)[0])-1) : preg_split('/\s+/', $ns)[0]);

    //Step 5 - Run another dig using the obtained address for our domain, and return false if returned NULL else return the domain name. This assumes an authoritative NS is assigned when a domain is registered, can be improved to filter more accurately.
    $ans = shell_exec(escapeshellcmd("dig +noall +authority ".escapeshellarg("@".$ns)." ".escapeshellarg($domain))); 
    return (($ans===NULL) ? false : ((strpos($ans, $ns)>-1) ? false : $domain));
}

Pros

  1. Работает на любом домене, в то время как функции php dns могут не работать на некоторых доменах. (мой домен .pro не удалось на PHP PHP)
  2. Работает на свежих доменах без каких-либо записей DNS (например, A)
  3. Unicode дружественный

Cons

  1. Использование исполнения оболочки, возможно

Ответ 16

<?php

if(is_valid_domain('https://www.google.com')==1){
  echo 'Valid';
}else{
   echo 'InValid';
}

 function is_valid_domain($url){

    $validation = FALSE;
    /*Parse URL*/    
    $urlparts = parse_url(filter_var($url, FILTER_SANITIZE_URL));

    /*Check host exist else path assign to host*/    
    if(!isset($urlparts['host'])){
        $urlparts['host'] = $urlparts['path'];
    }

    if($urlparts['host']!=''){
        /*Add scheme if not found*/        if (!isset($urlparts['scheme'])){
        $urlparts['scheme'] = 'http';
        }

        /*Validation*/        
    if(checkdnsrr($urlparts['host'], 'A') && in_array($urlparts['scheme'],array('http','https')) && ip2long($urlparts['host']) === FALSE){ 
        $urlparts['host'] = preg_replace('/^www\./', '', $urlparts['host']);
        $url = $urlparts['scheme'].'://'.$urlparts['host']. "/";            

            if (filter_var($url, FILTER_VALIDATE_URL) !== false && @get_headers($url)) {
                $validation = TRUE;
            }
        }
    }

    return $validation;

}
?>

Ответ 17

Проверьте функцию php checkdnsrr

function validate_email($email){

   $exp = "^[a-z\'0-9]+([._-][a-z\'0-9]+)*@([a-z0-9]+([._-][a-z0-9]+))+$";

   if(eregi($exp,$email)){

      if(checkdnsrr(array_pop(explode("@",$email)),"MX")){
        return true;
      }else{
        return false;
      }

   }else{

      return false;

   }   
}

Ответ 18

Это подтверждение имени домена в javascript:

<script>
function frmValidate() {
 var val=document.frmDomin.name.value;
 if (/^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9](?:\.[a-zA-Z]{2,})+$/.test(val)){
      alert("Valid Domain Name");
      return true;
 } else {
      alert("Enter Valid Domain Name");
      val.name.focus();
      return false;
 }
}
</script>

Ответ 19

Это просто. У некоторых php egnine есть проблема с split(). Этот код ниже будет работать.

<?php
$email = "[email protected]"; 
$domain = strtok($email, "@");
$domain = strtok("@");
if (@getmxrr($domain,$mxrecords)) 
   echo "This ". $domain." EXIST!"; 
else 
   echo "This ". $domain." does not exist!"; 
?>