web-dev-qa-db-fra.com

Comment valider un nom de domaine en PHP?

Est-ce possible sans utiliser l'expression régulière?

Par exemple, je veux vérifier qu'une chaîne est un domaine valide:

domain-name
abcd
example

Sont des domaines valides. Ce sont invalides bien sûr:

domaia@name
ab$%cd

Etc. Donc, fondamentalement, il devrait commencer par un caractère alphanumérique, puis il pourrait y avoir plus de caractères alnum plus un trait d'union. Et cela doit aussi se terminer par un personnage en alnum.

Si ce n'est pas possible, pourriez-vous me suggérer un modèle d'expression régulière pour le faire?

MODIFIER:

Pourquoi ça ne marche pas? Est-ce que j'utilise preg_match de manière incorrecte?

$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');
}
28
Richard Knop
<?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
}
?>

Cas de test:

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
125
velcrow

Avec cela, vous allez non seulement vérifier si le domaine a un format valide, mais aussi s'il est actif/a une adresse IP assignée.

$domain = "stackoverflow.com";

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

Notez que cette méthode nécessite que les entrées DNS soient actives. Par conséquent, si vous souhaitez qu'une chaîne de domaine soit validée sans être dans le DNS, utilisez la méthode d'expression régulière indiquée par velcrow ci-dessus.

De plus, cette fonction n'est pas destinée à valider une chaîne d'URL, utilisez FILTER_VALIDATE_URL pour cela. Nous n'utilisons pas FILTER_VALIDATE_URL pour un domaine car une chaîne de domaine n'est pas une URL valide.

54
RoboTamer

utilisez checkdnsrrhttp://php.net/manual/en/function.checkdnsrr.php

$domain = "stackoverflow.com";

checkdnsrr($domain , "A");

//returns true if has a dns A record, false otherwise
8
jacktrade

Je pense qu'une fois que vous avez isolé le nom de domaine, par exemple, en utilisant l'idée d'Erklan:

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

vous pouvez utiliser:

if (false === filter_var ($ myDomainName, FILTER_VALIDATE_URL)) {
 // le test a échoué 

}

Les fonctions de filtrage de PHP5 sont pour un tel but, je l'aurais pensé.

Il ne répond pas strictement à votre question car il n’utilise pas Regex, je me rends compte.

6
Cups

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)

Il n'est pas documenté ici: http://www.php.net/filter.filters.validate et une demande de bogue à cet effet se trouve ici: https://bugs.php.net/bug.php?id=72013

5
Rob

Voici une autre manière sans regex.

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

L'expression régulière est le moyen le plus efficace de vérifier une validation de domaine. Si vous ne voulez pas utiliser d'expression régulière (qui est une idiote, l'OMI est stupide), vous pouvez scinder chaque partie d'un domaine:

  • www./sous-domaine
  • nom de domaine
  • .extension

Vous devez ensuite vérifier chaque caractère dans une sorte de boucle pour vérifier qu'il correspond à un domaine valide.

Comme je l'ai dit, il est beaucoup plus efficace d'utiliser une expression régulière.

3
James Brooks

Votre expression régulière convient, mais vous n’utilisez pas preg_match right. Il retourne une int (0 ou 1), pas un booléen. Il suffit d'écrire if(!preg_match($regex, $string)) { ... }

2
Arthur Reutenauer

Si vous voulez vérifier si un nom de domaine ou une adresse IP particulière existe ou non, vous pouvez également utiliser checkdnsrr
Voici le doc http://php.net/manual/en/function.checkdnsrr.php

1
verdy

La bonne réponse est que vous ne ... laissez pas un outil testé par unité faire le travail à votre place:

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

lectures supplémentaires: https://www.w3schools.com/php/filter_validate_url.asp

1
Mike Q

Si vous ne voulez pas utiliser d'expressions régulières, vous pouvez essayer ceci:

$str = 'domain-name';

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

mais comme dit regexp sont le meilleur outil pour cela.

1
Matteo Riva

Un domaine valide est pour moi quelque chose que je peux enregistrer ou au moins quelque chose qui semble pouvoir être enregistré. C'est la raison pour laquelle j'aime séparer ceci des noms "localhost".

Et enfin, je me suis intéressé à la question principale si éviter Regex serait plus rapide et voici mon résultat:

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

Résultats comparés avec la fonction velcrow et 10000 itérations ( résultats complets contient de nombreuses variantes de code. Il était intéressant de trouver la plus rapide.):

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

$real_world ne contenait pas de noms de domaine extrêmement longs pour produire de meilleurs résultats. Et maintenant, je peux répondre à votre question: avec l'utilisation de ctype_alnum(), il serait possible de le réaliser sans regex, mais comme preg_match() était plus rapide, je préférerais cela.

Si vous n'aimez pas le fait que "local.Host" soit un nom de domaine valide, utilisez cette fonction à la place qui valide sur une liste tld publique. Peut-être que quelqu'un trouve le temps de combiner les deux.

1
mgutt

Je sais que c’est une vieille question, mais c’était la première réponse à une recherche sur Google. Cela semble donc pertinent. J'ai eu récemment le même problème. La solution dans mon cas consistait simplement à utiliser la liste des suffixes publics:

https://publicsuffix.org/learn/

Les bibliothèques suggérées, spécifiques au langage, devraient toutes permettre une validation facile non seulement du format de domaine, mais également de la validité du domaine de premier niveau.

0
jeffers102