根本原因是in_array()默认使用松散比较(==),会触发隐式类型转换;例如'0123'和'123'均转为数字123而相等,或0与任意非空字符串比较时后者转为0导致误判。

PHP 的 in_array() 匹配错,根本原因不是函数坏了,而是它默认用松散比较(==),会自动做类型转换——你没拦住它。
为什么字符串 '0123' 会匹配到数组里的 '123'
因为 PHP 在非严格模式下,会把带前导零的字符串(如 '0123')当作数字解析,再跟数组中字符串 '123' 做数值比较:'0123' == 123 → true,而 '123' == 123 也是 true,于是连起来就“误判”了。
- 这种行为在处理 ID、序列号、订单号等必须保留前导零的字段时极其危险
- 哪怕数组全是字符串,只要
$needle是数字或含数字字符,就可能触发隐式转换 - PHP 8.0+ 虽然收紧了部分转换规则,但
'0123'和'123'在松散比较下仍可能被当成相等
为什么 in_array(0, ['a', 'b']) 竟然返回 true
这是最反直觉的坑:当 $needle 是整数 0,而数组里有任意非空字符串(如 'a'),松散比较下 0 == 'a' 会先将 'a' 转成整数 —— 结果是 0,所以判定为 true。
- 同理,
in_array(0, ['', false, null])全部返回true - 甚至
in_array('hello', [0, false, null])也可能返回true('hello'转布尔为true,而true == 0在某些上下文中成立) - 这不是 bug,是 PHP 弱类型比较逻辑的必然结果
strict 参数不加,等于主动交出控制权
第三个参数 $strict 不传或传 false,in_array() 就按 == 比;传 true 才走 === 全等判断 —— 类型和值都必须一致。
- 正确写法永远是:
in_array($value, $array, true) - 尤其当
$array来自配置、数据库或用户输入时,你根本无法保证里面混着什么类型 - 漏掉
true,等于把“是否相等”的解释权交给 PHP 的类型转换引擎,而不是你自己
大小写和 HTML 干扰会让问题更隐蔽
in_array() 对字符串默认区分大小写,且不做任何清洗。如果白名单是 ['Gmail.com'],而输入是 'gmail.com' 或 '<span>gmail.com</span>',即使启用了严格模式也会失败。
- 域名匹配场景常见错误:直接用
substr(strrchr($email, '@'), 1)提取,没过strip_tags()和trim() - 没统一转小写:
strtolower($domain)缺失会导致'GMAIL.COM'查不到 - 换行符混乱(
\r\nvs\n)导致 explode 后数组含空元素,in_array('', $list, true)可能意外命中
真正容易被忽略的点是:你写 in_array($x, $y) 的那一刻,就已经在依赖 PHP 的类型转换规则了——而这个规则,在不同 PHP 版本间还有细微差异。不加 true,就别怪它“匹配错”,它只是按规则执行了而已。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











