如何在 PHP 中验证域名?
不使用正则表达式可以吗?
例如,我想检查一个字符串是否是有效域:
domain-name
abcd
example
Are validdomains。这些当然是无效的:
domaia@name
ab$%cd
等等。所以基本上它应该以字母数字字符开头,然后可能有更多的数字字符加上连字符。并且它也必须以 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');
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(20)
测试用例:
Test cases:
这样,您不仅可以检查域的格式是否有效,还可以检查域是否处于活动状态/是否分配有 IP 地址。
请注意,此方法要求 DNS 条目处于活动状态,因此如果您需要在 DNS 中不存在的情况下验证域字符串,请使用上面 velcrow 给出的正则表达式方法。
此外,此函数并不打算使用 FILTER_VALIDATE_URL 来验证 URL 字符串。我们不会对域使用 FILTER_VALIDATE_URL,因为域字符串不是有效的 URL。
With this you will not only be checking if the domain has a valid format, but also if it is active / has an IP address assigned to it.
Note that this method requires the DNS entries to be active so if you require a domain string to be validated without being in the DNS use the regular expression method given by velcrow above.
Also this function is not intended to validate a URL string use FILTER_VALIDATE_URL for that. We do not use FILTER_VALIDATE_URL for a domain because a domain string is not a valid URL.
这里没有记录:http://www.php。 net/filter.filters.validate ,此错误请求位于: https://bugs.php.net/bug.php?id=72013
It is not documented here: http://www.php.net/filter.filters.validate and a bug request for this is located here: https://bugs.php.net/bug.php?id=72013
使用 checkdnsrr http://php.net/manual/en/ function.checkdnsrr.php
use checkdnsrr http://php.net/manual/en/function.checkdnsrr.php
首先,您应该澄清您的意思是否为:
需要区分的原因是标签在技术上可以包含任何字符,包括NUL、
@
和 '.
' 字符。 DNS 支持 8 位,并且完全有可能拥有一个包含“an\0odd\.l@bel
”条目的区域文件。当然,不推荐这样做,尤其是因为人们很难区分标签内的点和分隔标签,但这是合法的。但是,URL 中需要主机 名称,并且这些名称受 RFC 952 和 1123 的约束。有效的主机名称是主机名称的子集>域名。具体来说,仅允许使用字母、数字和连字符。此外,第一个和最后一个字符不能是连字符。 RFC 952 不允许第一个字符使用数字,但 RFC 1123 随后放宽了这一点。
因此:
a
- 有效0
- 有效a-
ab
- 有效xn--dasdkhfsd
- 有效(IDN 的 punycode 编码)strong > 我认为不可能用一个简单的正则表达式使
a-
示例无效。我能想到的检查单个主机标签的最佳方法是:为了使问题更加复杂,一些域名条目(通常是
SRV
记录)使用带有下划线前缀的标签,例如_sip._udp.example.com
。这些不是主机名,而是合法域名。Firstly, you should clarify whether you mean:
The reason the distinction is necessary is that a label can technically include any characters, including the NUL,
@
and '.
' characters. DNS is 8-bit capable and it's perfectly possible to have a zone file containing an entry reading "an\0odd\.l@bel
". It's not recommended of course, not least because people would have difficulty telling a dot inside a label from those separating labels, but it is legal.However, URLs require a host name in them, and those are governed by RFCs 952 and 1123. Valid host names are a subset of domain names. Specifically only letters, digits and hyphen are allowed. Furthermore the first and last characters cannot be a hyphen. RFC 952 didn't permit a number for the first character, but RFC 1123 subsequently relaxed that.
Hence:
a
- valid0
- valida-
- invalida-b
- validxn--dasdkhfsd
- valid (punycode encoding of an IDN)Off the top of my head I don't think it's possible to invalidate the
a-
example with a single simple regexp. The best I can come up with to check a single host label is:To further complicate matters, some domain name entries (typically
SRV
records) use labels prefixed with an underscore, e.g._sip._udp.example.com
. These are not host names, but are legal domain names.这是另一种没有正则表达式的方法。
Here is another way without regex.
我想一旦你隔离了域名,比如说,使用 Erklan 的想法:
你可以使用:
PHP5s 过滤器函数就是为了这样的目的,我想。
我意识到,它并没有严格回答您的问题,因为它不使用正则表达式。
I think once you have isolated the domain name, say, using Erklan's idea:
you could use :
PHP5s Filter functions are for just such a purpose I would have thought.
It does not strictly answer your question as it does not use Regex, I realise.
正则表达式是检查域验证的最有效方法。如果您坚决不使用正则表达式(在我看来这是愚蠢的),那么您可以拆分域的每个部分:
然后,您必须检查某种循环中的每个字符,以查看它是否与有效域匹配。
正如我所说,使用正则表达式要有效得多。
Regular expression is the most effective way of checking for a domain validation. If you're dead set on not using a Regular Expression (which IMO is stupid), then you could split each part of a domain:
You would then have to check each character in some sort of a loop to see that it matches a valid domain.
Like I said, it's much more effective to use a regular expression.
您的正则表达式很好,但您没有正确使用
preg_match
。它返回一个int
(0或1),而不是一个布尔值。只需编写if(!preg_match($regex, $string)) { ... }
Your regular expression is fine, but you're not using
preg_match
right. It returns anint
(0 or 1), not a boolean. Just writeif(!preg_match($regex, $string)) { ... }
如果你不想使用正则表达式,你可以尝试这个:
但正如所说,正则表达式是最好的工具。
If you don't want to use regular expressions, you can try this:
but as said regexp are the best tool for this.
如果您想检查某个域名或IP地址是否存在,也可以使用
checkdnsrr
这是文档 http://php.net/manual/en/function.checkdnsrr.php
If you want to check whether a particular domain name or ip address exists or not, you can also use
checkdnsrr
Here is the doc http://php.net/manual/en/function.checkdnsrr.php
对我来说,有效域名是我能够注册的域名,或者至少是看起来我可以注册的域名。这就是为什么我喜欢将其与“localhost”名称分开的原因。
最后,我对主要问题感兴趣,如果避免正则表达式会更快,这是我的结果:
与 velcrow 的函数<进行比较的基准结果< /a> 和 10000 次迭代(完整结果包含许多代码找到最快的变体很有趣。):
$real_world
不包含极长的域名以产生更好的结果。现在我可以回答你的问题:使用ctype_alnum()
可以在没有正则表达式的情况下实现它,但由于preg_match()
更快,我更喜欢。如果您不喜欢“local.host”是有效域名这一事实,请使用此函数,而不是对公共顶级域名 (TLD) 列表。也许有人有时间将两者结合起来。
A valid domain is for me something I'm able to register or at least something that looks like I could register it. This is the reason why I like to separate this from "localhost"-names.
And finally I was interested in the main question if avoiding Regex would be faster and this is my result:
Benchmark results compared with velcrow 's function and 10000 iterations (complete results contains many code variants. It was interesting to find the fastest.):
$real_world
did not contain extreme long domain names to produce better results. And now I can answer your question: With the usage ofctype_alnum()
it would be possible to realize it without regex, but aspreg_match()
was faster I would prefer that.If you don't like the fact that "local.host" is a valid domain name use this function instead that valids against a public tld list. Maybe someone finds the time to combine both.
正确的答案是您不......您让单元测试的工具为您完成工作:
进一步阅读:https://www.w3schools.com/php/filter_validate_url.asp
The correct answer is that you don't ... you let a unit tested tool do the work for you:
further reading :https://www.w3schools.com/php/filter_validate_url.asp
如果您可以运行 shell 命令,以下是确定域是否已注册的最佳方法。
如果域名未注册,则此函数返回 false,否则返回域名。
优点
缺点
If you can run shell commands, following is the best way to determine if a domain is registered.
This function returns false, if domain name isn't registered else returns domain name.
Pros
Cons
在阅读了添加功能的所有问题后,我决定需要更准确的东西。
这是我想出的对我有用的方法。
如果您需要专门验证主机名(它们必须以字母数字字符开头和结尾,并且仅包含字母数字和连字符),此功能应该足够了。
请注意,此函数适用于大多数(尚未测试所有语言)LTR 语言。它不适用于 RTL 语言。
After reading all the issues with the added functions I decided I need something more accurate.
Here's what I came up with that works for me.
If you need to specifically validate hostnames (they must start and end with an alphanumberic character and contain only alphanumerics and hyphens) this function should be enough.
Note that this function will work on most (haven't tested all languages) LTR languages. It will not work on RTL languages.
我知道这是一个老问题,但这是谷歌搜索的第一个答案,所以它看起来很相关。我最近也遇到了同样的问题。我的解决方案是仅使用公共后缀列表:
https://publicsuffix.org/learn/
列出的建议的特定于语言的库都应该不仅可以轻松验证域格式,还可以轻松验证顶级域的有效性。
I know that this is an old question, but it was the first answer on a Google search, so it seems relevant. I recently had this same problem. The solution in my case was to just use the Public Suffix List:
https://publicsuffix.org/learn/
The suggested language specific libraries listed should all allow for easy validation of not just domain format, but also top level domain validity.
检查php函数
checkdnsrr
Check the php function
checkdnsrr
这是 javascript 中的域名验证:
This is validation of domain name in javascript:
这很简单。某些 php egnine 在 split() 方面存在问题。
下面的代码将起作用。
This is simple. Some php egnine has a problem with split().
This code below will work.