Как проверить доменное имя в 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 ]

1 голос
/ 04 марта 2015

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

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

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

Результаты тестов по сравнению с функцией velcrow и 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» является допустимым доменным именем, используйте эту функцию , которая действует в общедоступном списке рассылки. Может быть, кто-то найдет время объединить оба.

1 голос
/ 17 октября 2012

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

1 голос
/ 18 ноября 2009

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

$str = 'domain-name';

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

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

0 голосов
/ 17 мая 2019
<?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;

}
?>
0 голосов
/ 13 мая 2019

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

Эта функция возвращает 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));
}

За

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

Против

  1. Использование исполнения оболочки, вероятно
0 голосов
/ 12 декабря 2017

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

https://publicsuffix.org/learn/

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

0 голосов
/ 05 января 2015

Это проверка доменного имени в 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>
0 голосов
/ 28 июня 2013

Проверьте функцию 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;

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

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

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

...