解决方案(简称):
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 documentation中也有描述。)
说明
如果不将参数strict设置为true,则搜索到的值与数组的每个值之间的比较是通过相等而不是通过标识来完成的。这意味着值的类型无关紧要,因此 PHP 在内部将值转换为相同的数据类型以便能够比较它们。
这意味着在第一个示例中,搜索到的值'Gary'在与true比较时被转换为布尔值,因此导致true与true比较,显然是@987654333 @。
第二个数组也是如此,其中0最终与null进行比较,得到true,尽管0显然与null不一样(这在当例如,您使用数字和/或函数结果,其中null 可以表示空值而不是0)。
第三个数组看起来很奇怪,因为我们检查数组中的值true,它只包含-1,但in_array()仍然返回true进行比较。在这种情况下,-1 被转换为布尔值true。所以问题在两个方向上都是一样的。
你可以在this Stack Overflow answer找到更多关于PHP比较问题的例子(因为这和==/===一样)。
不幸的是,调用in_array() 时strict 参数的默认值是……嗯,是的,false。 :-/ PHP 正在输入...
后果
如果没有将 strict 参数设置为 true,您真的不应该调用 in_array()。当您没有混合类型的数组并且您只检查具有相同类型的值时,in_array() 按预期工作。看这个例子:
$arrayWithStrings = ['Andreas', 'Philipp', 'Friedrich'];
var_dump(in_array('Gary', $arrayWithStrings)); // returns bool(false)
所以至少这可以按预期工作。但在我看来,总是用 strict true 调用in_array() 要容易得多。 (类似于“SQL 注入问题”...始终使用 PDO 和准备好的语句,这样您就安全了,即使它是一个没有可变参数的查询。那么您总是安全的。)
还是要小心
您绝对应该使用 strict true 调用 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 一起使用。 ;-)