在PHP开发里,数组是最常用的数据结构,与之配套的数十个数组函数极大提升了处理效率。然而不少人在调用这些函数时,只记住了“它能干什么”,却忽略了“它在什么条件下会悄悄改变行为”。这种错误用法不会立刻抛出异常,而是在特定数据下输出错误结果,排查起来非常耗时。

一、in_array的松散比较陷阱
in_array函数原型为in_array($needle, $haystack, $strict = false),第三个参数默认为false,代表使用松散比较(==)。这意味着类型不同但值“相等”的元素也会被判定为存在。在权限校验、状态判断等场景中,这种特性可能导致严重逻辑漏洞。
例如,当用户角色ID从数据库读出为字符串'0e123',而白名单里存的是整数0,松散比较下'0e123' == 0结果为true,函数返回true,本不该通过的角色被误放行。要避免此类问题,必须显式传入第三个参数true开启严格比较,或者提前统一数据类型。
<?php
$whitelist = [0, 1, 2];
$userRole = '0e123'; // 来自数据库或表单
// 错误用法:松散比较
if (in_array($userRole, $whitelist)) {
echo '放行(实际不应放行)';
}
// 正确用法:严格比较
if (in_array($userRole, $whitelist, true)) {
echo '放行';
} else {
echo '拒绝';
}
?>
二、array_merge对非数组参数的处理差异
array_merge用于将多个数组合并,但当某个参数为null或非数组时,不同PHP版本表现不同。在PHP 7.4之前,传入null会触发警告并返回null;PHP 8.0之后则把null当作空数组静默处理。若代码依赖旧版报错来发现配置缺失,升级后错误配置会被无声覆盖。
更隐蔽的问题是,当使用展开运算符...配合可能为null的变量时,若变量为null会直接报错,而先转成数组再合并则安全。推荐在合并前用is_array判断或强制类型转换,保证函数入参始终为数组。
<?php $base = ['host' => 'localhost']; $override = null; // 可能从配置文件未读到 // 危险:null在PHP8下变空数组,配置被吞 $config = array_merge($base, $override); // 安全:确保为数组 $override = is_array($override) ? $override : []; $config = array_merge($base, $override); ?>
三、array_unique的索引与顺序错觉
array_unique可以去除重复值,并保留第一个出现元素的“逻辑顺序”,但它不会重建索引。去重后数组的键仍是原键名,导致键不连续。如果开发者用for循环从0到count-1遍历,就会因索引缺失而漏处理或越界访问。
此外,array_unique基于内部排序去重,对混合类型(如整数和字符串数字)的比较同样受松散规则影响。正确做法是去重后用array_values重置索引,或改用foreach遍历,避免依赖连续数字键。
<?php
$list = [10 => 'a', 20 => 'b', 30 => 'a'];
$unique = array_unique($list); // 键为 10, 20
// 错误:假设键连续
for ($i = 0; $i < count($unique); $i++) {
echo $unique[$i]; // 报错:Undefined offset
}
// 正确:重置索引后遍历
$unique = array_values(array_unique($list));
foreach ($unique as $item) {
echo $item;
}
?>
四、总结与规避建议
上述三个案例反映了同一类问题:数组函数的“友好默认行为”在边界数据下变成隐患。写代码时应养成查阅官方文档参数说明的习惯,对涉及比较、类型转换、索引结构的函数保持警惕。
建议在团队代码规范中强制in_array使用严格模式,合并数组前做类型约束,去重后显式重置索引。配合静态分析工具扫描危险调用,能大幅降低此类隐蔽bug流入生产环境的概率。