Regex are tricky, but here is what I came up with:
<?php
function is_valid_domain_name($domain_name,&$matches)
{
return (preg_match("/^(\*\.)?([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name,$matches) //valid chars check
&& preg_match("/^.{1,253}$/", $domain_name) //overall length check
&& preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name) ); //length of each label
}
I ran through the following test code:
<?php
$domains = Array('a',0,'a.b','localhost','google.com','*.example.com','news.google.co.uk','xn--fsqu00a.xn--0zwm56d','goo google.com','google..com','google.com ','google-.com','.google.com');
echo "/^(\*\.)?([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i";
foreach($domains as $domain)
{
echo $domain . ' - ';
echo is_valid_domain_name($domain,$matches) ? "VALID\n" : "NOT VALID\n";
print_r($matches);
}
Here was my output:
/^(\*\.)?([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/ia - VALID
Array
(
[0] => a
[1] =>
[2] => a
)
0 - VALID
Array
(
[0] => 0
[1] =>
[2] => 0
)
a.b - VALID
Array
(
[0] => a.b
[1] =>
[2] => a
[3] =>
[4] => .b
[5] => b
)
localhost - VALID
Array
(
[0] => localhost
[1] =>
[2] => localhost
[3] => t
)
google.com - VALID
Array
(
[0] => google.com
[1] =>
[2] => google
[3] => e
[4] => .com
[5] => com
[6] => m
)
*.example.com - VALID
Array
(
[0] => *.example.com
[1] => *.
[2] => example
[3] => e
[4] => .com
[5] => com
[6] => m
)
news.google.co.uk - VALID
Array
(
[0] => news.google.co.uk
[1] =>
[2] => news
[3] => s
[4] => .uk
[5] => uk
[6] => k
)
xn--fsqu00a.xn--0zwm56d - VALID
Array
(
[0] => xn--fsqu00a.xn--0zwm56d
[1] =>
[2] => xn--fsqu00a
[3] => a
[4] => .xn--0zwm56d
[5] => xn--0zwm56d
[6] => d
)
goo google.com - NOT VALID
Array
(
)
google..com - NOT VALID
Array
(
)
google.com - NOT VALID
Array
(
)
google-.com - NOT VALID
Array
(
)
.google.com - NOT VALID
Array
(
)
I included the optional $matches parameter to preg_match so I could see where the regex was matching what string.
Your final code will probably be:
<?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
}
UPDATE: Making TLDs NOT valid
<?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
}
DISCLAIMER: REGEX is super tricky so you use this at your own risk. :)