Laravel 验证 DNS 域名需自定义规则,推荐使用 RFC 1035 兼容正则或 PHP 7.4+ 的 FILTER_VALIDATE_DOMAIN;须处理空格、大小写、URL 前缀,并注意测试用例覆盖非法格式及本地域名。

验证请求体字段是否为合法 DNS 域名
直接用 dns 规则不行 —— Laravel 原生没有 dns 验证规则。你得靠 regex 或自定义规则,否则会误放 example..com、-test.com 这类非法值。
推荐用 RFC 1035 兼容的正则:开头结尾不能是点或连字符,每段长度 1–63 字符,只允许字母、数字和中划线,总长 ≤253 字符。
-
regex:/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/—— 覆盖常见二级/三级域名(如api.example.com),但不支持国际化域名(IDN) - 如果要校验纯主机名(不含 TLD),比如
my-server,改用:regex:/^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?$/ - 别用
url规则代替 —— 它接受http://foo.com,且对子域宽松,无法拦截..com这种明显错误
Laravel API 请求中对 domain 字段做必填+格式双重校验
API 场景下,domain 字段常出现在创建租户、绑定自定义域名等接口里。光写 'domain' => 'required|regex:...' 不够,得考虑空格、协议头、大小写归一化这些现实输入。
- 先用
Trim中间件或在验证前调用$request->merge(['domain' => trim($request->domain)]),避免前后空格绕过正则 - 加
lowercase规则(Laravel 10+)或手动转小写再验证,因为 DNS 域名不区分大小写,但example.COM会被正则误判 - 如果前端可能传带
https://或路径的字符串(比如用户粘贴了完整 URL),必须前置清理:parse_url($input, PHP_URL_HOST)提取 host,再校验 —— 否则正则直接炸
自定义 DNS 验证规则比正则更可靠
正则难覆盖所有边界情况(比如 Unicode 域名、超长标签、内部点号位置),且可读性差。Laravel 的 Validator::extend 是更稳的选择,尤其当你要复用或加日志。
在 AppServiceProvider::boot() 里注册:
Validator::extend('valid_dns', function ($attribute, $value, $parameters, $validator) {
if (!is_string($value) || !trim($value)) return false;
$host = idn_to_ascii(trim($value), 0, INTL_IDNA_VARIANT_UTS46) ?: trim($value);
return filter_var($host, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) === true;
});
-
idn_to_ascii处理中文域名(如例子.中国),需启用intl扩展 -
FILTER_VALIDATE_DOMAIN是 PHP 7.4+ 原生支持,比手写正则更贴近 RFC - 注意:该 filter 不校验长度上限(253 字符),若需严格合规,得额外加
string|between:1,253
测试时容易漏掉的 DNS 校验陷阱
本地开发常用 localhost 或 test.app 测试,但它们不是合法公网域名 —— FILTER_VALIDATE_DOMAIN 会返回 false,正则也可能不匹配。
- 测试用例必须包含:
example.com(通过)、sub.domain.co.uk(通过)、localhost(失败)、123.45.67.89(IP 地址,应失败)、foo..bar.com(双点,应失败) - 别依赖
phpunit默认的APP_URL环境变量来构造测试域名 —— 它可能含协议或路径,导致校验逻辑误触发 - 如果你的业务允许
localhost或内网域名(如service.internal),得显式白名单处理,而不是放宽正则
真正麻烦的是 IDN 和 DNSSEC 相关的边缘 case,日常业务基本遇不到;但只要没明确要求支持中文域名,就别开 idn_to_ascii,省得引入扩展依赖和编码问题。


















