为什么in_array()返回意外/奇怪的结果?

7

为什么in_array()有时表现得很奇怪,并返回意外的结果?

让我们看几个例子:

$arrayWithTrue = ['Andreas', 'Philipp', true];
$arrayWithNull = [1, 2, 3, null];
$arrayWithMinusOne = [-1];

var_dump(in_array('Gary', $arrayWithTrue)); // returns bool(true)
var_dump(in_array(0, $arrayWithNull)); // returns bool(true)
var_dump(in_array(true, $arrayWithMinusOne)); // returns bool(true)

哎?这里发生了什么!?

(几年前,我对这种一开始看起来很奇怪的行为感到困惑。但我认为这可能对某些人有用,因此我提出了这个问题。)

1个回答

19

解决方案(简要):

始终将in_array()与第三个参数strict true一起使用:

$arrayWithTrue = ['Andreas', 'Philipp', true];
$arrayWithNull = [1, 2, 3, null];
$arrayWithMinusOne = [-1];

var_dump(in_array('Gary', $arrayWithTrue, true)); // returns bool(false)
var_dump(in_array(0, $arrayWithNull, true)); // returns bool(false)
var_dump(in_array(true, [-1], true)); // returns bool(false)

如果您在使用in_array()函数时,将第三个参数设置为true,则搜索值和数组之间的比较是严格进行的。这意味着in_array()的工作方式与您期望的相同。

(关于strict参数也在php.net文档中有描述。)

如果没有将strict参数设置为true,则搜索值和数组中的每个值之间的比较是通过等式而不是恒等式进行的。这意味着值的类型不重要,因此PHP会将这些值内部转换为相同的数据类型,以便进行比较。

这意味着,在第一个示例中,当搜索值'Gary'true进行比较时,它会被转换为布尔值,因此结果是truetrue进行比较,显然结果是true

对于第二个数组,0最终与null进行比较,结果是true,即使0明显不等于null(尤其是在处理数字和/或函数结果时可能会出现问题,其中null可以表示为空值而不是0)。

第三个数组看起来非常奇怪,因为我们在数组中检查值true,该数组仅包含-1,但in_array()仍然返回true用于比较。在这种情况下,-1被转换为布尔值true。因此问题在两个方向上都相同。

您可以在这个Stack Overflow答案中找到更多有关PHP比较问题(因为这与==/===相同)的示例。

很遗憾,在调用in_array()时,默认值为... 是的,false。:-/ PHP及其类型系统...

后果是,您真的永远不应该在没有将strict参数设置为true的情况下调用in_array()函数。当您没有混合类型的数组并且只检查具有相同类型的值时,in_array()就如预期工作。请参考以下示例:

$arrayWithStrings = ['Andreas', 'Philipp', 'Friedrich'];
var_dump(in_array('Gary', $arrayWithStrings)); // returns bool(false)

所以至少这个功能是按照预期工作的。但在我看来,只需始终使用true strict 调用 in_array() 更容易。 (类似于“SQL注入问题”...始终使用PDO和准备好的语句,以便您安全,即使它是一个没有变量参数的查询。那时您总是安全的。)

不过要小心

您肯定应该使用true strict调用in_array()。但是也有一个缺点,我想提一下(即使这是显而易见的)。然后您在调用in_array() 时必须确保使用正确的类型:

$arrayWithNumbers = [1, 2, 3];
var_dump(in_array('1', $arrayWithNumbers, true)); // returns bool(false)

但是当你知道要比较数字时,你可以使用类型转换:

$arrayWithNumbers = [1, 2, 3];
var_dump(in_array((int)'1', $arrayWithNumbers, true)); // returns bool(true)

奖金

// Comparing false with an empty array
var_dump(in_array(false, [[]])); // returns bool(true)

嗯,是的...只需将 strict 设置为true即可。 ;-)


这个奖金让我开心极了 "var_dump(in_array(false, [[]]))" - 干得好 - John Tribe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接