如何在PHP中验证域名?

Ric*_*nop 31 php regex domain-name

是否可以不使用正则表达式?

例如,我想检查一个字符串是否是一个有效的域:

domain-name
abcd
example
Run Code Online (Sandbox Code Playgroud)

是有效的域名.这些当然是无效的:

domaia@name
ab$%cd
Run Code Online (Sandbox Code Playgroud)

等等.所以基本上它应该以字母数字字符开头,然后可能会有更多的alnum字符加上连字符.它也必须以alnum角色结束.

如果不可能,你能建议我采用正则表达式吗?

编辑:

为什么这不起作用?我错误地使用了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');
}
Run Code Online (Sandbox Code Playgroud)

vel*_*row 130

<?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
}
?>
Run Code Online (Sandbox Code Playgroud)

测试用例:

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
Run Code Online (Sandbox Code Playgroud)

  • 别忘了检查(计数($件)> 1) (4认同)
  • 根据经验,您应该使用单引号在 php 中编写正则表达式,这样它就不会处理其中的任何特殊字符 (2认同)

Rob*_*mer 57

通过这种方式,您不仅可以检查域是否具有有效格式,还可以检查域是否处于活动状态/是否为其分配了IP地址.

$domain = "stackoverflow.com";

if(filter_var(gethostbyname($domain), FILTER_VALIDATE_IP))
{
    return TRUE;
}
Run Code Online (Sandbox Code Playgroud)

请注意,此方法要求DNS条目处于活动状态,因此如果您需要在不使用DNS的情况下验证域字符串,请使用上面的velcrow给出的正则表达式方法.

此函数也不用于验证URL字符串使用FILTER_VALIDATE_URL.我们不对域使用FILTER_VALIDATE_URL,因为域字符串不是有效的URL.

  • gethostbyname执行阻塞dns查找,因此不要运行它来循环遍历大型数据集,您将有可怕的运行时. (5认同)
  • 对于尚未在DNS中实际存在的有效域或主机名,这将失败.-1. (4认同)

Rob*_*Rob 14

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)
Run Code Online (Sandbox Code Playgroud)

这里没有记录:http://www.php.net/filter.filters.validate对此的错误请求位于:https://bugs.php.net/bug.php?id=72013


Aln*_*tak 9

首先,你应该澄清你的意思是:

  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的punycode编码)

我不认为a-用一个简单的正则表达式使这个例子无效是不可能的.我可以提出检查单个 主机标签的最佳方法是:

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

更复杂的是,一些域名条目(通常是SRV记录)使用带有下划线的标签,例如_sip._udp.example.com.这些不是主机名,但是是合法域名.


jac*_*ade 9

使用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
Run Code Online (Sandbox Code Playgroud)

  • 如果要检查具有有效结构但尚未注册的域,则不是很有用. (3认同)
  • 所以您基本上是建议首先注册您要在本地检查的每个域?这是没有意义的,您也可以在本地注册无效域,这超出了 @richard-knop 在这里试图实现的目的。 (2认同)

Cup*_*ups 6

我想,一旦你使用Erklan的想法隔离了域名:

$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过滤功能只是出于我想象的目的.

我意识到,它没有严格回答你的问题,因为它没有使用正则表达式.


Erk*_*BAN 5

这是没有正则表达式的另一种方式。

$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";
}
Run Code Online (Sandbox Code Playgroud)


Jam*_*oks 3

正则表达式是检查域验证的最有效方法。如果您坚决不使用正则表达式(在我看来这是愚蠢的),那么您可以拆分域的每个部分:

  • 万维网。/ 子域
  • 域名
  • 。扩大

然后,您必须检查某种循环中的每个字符,以查看它是否与有效域匹配。

正如我所说,使用正则表达式要有效得多。