在日常的 PHP 编程中,array_diff() 是一个非常实用的函数,它可以用来找出两个数组之间的差异。但很多开发者在使用这个函数时可能会遇到一种奇怪的情况:
这到底是怎么回事呢?让我们一起来探究其中的原因。
来看下面这段代码:
$a = [true, false];
$b = [0];
$result = array_diff($a, $b);
print_r($result);
你可能会直觉地认为 true 和 false 都不在数组 $b 中,所以 $result 应该是 [true, false],但实际上你会得到如下输出:
Array
(
[0] => 1
)
是不是有点懵?为什么 false 被过滤掉了?而且 true 还变成了整数 1?我们接下来逐步拆解这个问题。
首先要理解 array_diff() 的底层行为。根据 PHP 官方文档 的说明:
array_diff() 使用“非严格比较”(==)来检查值是否相等。
也就是说,array_diff() 并不是使用全等 === 来比较值,而是用双等号 ==。
这就意味着以下值会被认为是“相等”的:
false == 0; // true
true == 1; // true
true == "1"; // true
false == ""; // true
在我们的示例中,false 被 0 判定为相等,因此被 array_diff() 排除在结果之外。
另一个细节是,array_diff() 返回的数组是数值数组,PHP 会在某些情况下对布尔值进行隐式转换。例如:
var_dump(true); // 输出 bool(true)
echo true; // 输出 1
在 print_r() 中输出时,布尔值 true 会被转换为 1。这就是为什么你会看到结果中出现了 1,而不是 true。
如果你需要比较的数据类型比较严格(比如你真的需要区分 true 和 1),可以使用 array_udiff() 并配合一个自定义的比较函数:
$a = [true, false];
$b = [0];
$result = array_udiff($a, $b, function($x, $y) {
return ($x === $y) ? 0 : 1;
});
print_r($result);
输出:
Array
(
[0] => 1
[1] =>
)
注意,这次 false(对应值为空)也被保留了,因为我们使用了全等比较 ===。
如果你需要更清晰地区分这些值并保留布尔类型的表现形式,可以结合 var_export() 来输出结果:
var_export($result);
array_diff() 的默认行为虽然在很多场景下表现得非常高效,但在处理布尔值、数字与字符串混合的数组时,就容易产生让人疑惑的结果。这也是 PHP 中类型弱化带来的一个典型陷阱。
在开发中,如果你对数据类型有严格要求,避免使用默认的 array_diff(),转而使用 array_udiff() 并提供自己的比较函数,是一个更安全可靠的做法。