应始终对邮箱先trim()再用filter_var()严格比较:filter_var(trim($email), filter_validate_email) !== false,因该函数不自动去空格、返回字符串而非布尔值、且php 7.1+起弱比较易导致"0@example.com"等合法邮箱被误判或绕过校验。

filter_var($email, FILTER_VALIDATE_EMAIL) 在 PHP 7.4 的行为没变,但你得注意 trim
PHP 7.4 并未修改 FILTER_VALIDATE_EMAIL 的逻辑,它依然严格遵循 RFC 5322 简化版,支持 "a@b.c"、user+tag@example.com、"test@localhost" 这类合法格式。但常见误判不是来自版本差异,而是输入没清理:filter_var(" user@example.com ", FILTER_VALIDATE_EMAIL) 直接返回 false——空格不自动去除。必须先 trim(),再判断是否 !== false。
PHP 7.1 的 preg_match 正则写法容易漏掉关键锚点和字符集
很多项目在 PHP 7.1 时代沿用的正则如 /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/i,表面看没问题,实际有三个硬伤:
- 没处理 Unicode 域名(如
用户@例子.测试),而 PHP 7.1 的 PCRE 默认不启用u修饰符,导致匹配失败 - 本地部分(@前)用
[a-z0-9._%+-]排除了中文、emoji 等合法字符,但更严重的是:它允许..连续点号(如ab..cd@example.com),而 RFC 明确禁止 - 顶级域部分写成
[a-z]{2,}会拒绝.museum或.travel这类长 TLD,且无法匹配.co.uk这样的多级后缀
别混用 filter_var 和正则做同一层校验
有人在 PHP 7.4 里先跑 filter_var,再用正则二次“加强”,结果反而引入漏洞:
-
filter_var允许test@192.168.1.1,但你的正则如果写成/@[\w.-]+\.\w+$/可能意外放过 IP 字符串,造成逻辑不一致 - 若正则加了
u修饰符而filter_var没开 Unicode 支持(它本身不处理 Unicode 域名解析),两者对同一字符串的判定可能相反 - 性能上,
filter_var是 C 实现,比preg_match快 2–3 倍;重复校验纯属浪费 CPU
真正该关注的兼容性断层不在 7.1→7.4,而在 filter_var 的返回值类型
这个坑跨所有 PHP 版本,但 PHP 7.1 开始类型警告更敏感:
-
filter_var("0@example.com", FILTER_VALIDATE_EMAIL)返回字符串"0@example.com",不是true - 写成
if (filter_var($email, FILTER_VALIDATE_EMAIL))在弱比较下看似可行,但遇到$email = "0"(非法邮箱)时,filter_var("0", FILTER_VALIDATE_EMAIL)返回false,而"0@example.com"被当成 truthy —— 类型混淆直接绕过校验 - PHP 7.1+ 推荐始终用严格比较:
filter_var(trim($email), FILTER_VALIDATE_EMAIL) !== false
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











