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

时间:2016-05-06 20:05:50

标签: php arrays comparison

为什么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 个答案:

答案 0 :(得分:16)

解决方案(简称):

始终使用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()的工作方式与您预期的一样。< / p>

(参数 strict 也在php.net documentation中描述。)

说明

如果没有将参数 strict 设置为true,则搜索的值与数组的每个值之间的比较是通过相等而不是通过标识完成的。这意味着值的类型无关紧要,因此PHP将值内部转换为相同的数据类型,以便能够比较它们。

这意味着在第一个示例中,搜索到的值'Gary'在与true进行比较时会转换为布尔值,因此会导致true的比较使用true,显然是true

同样适用于第二个数组,其中0最终与null进行比较,结果为true,即使0显然与{null不同1}}(例如,当您处理数字和/或函数结果时,这可能会特别棘手,其中null可以表示空值而不是0)。

第三个数组看起来很奇怪,因为我们检查数组中的值true,其中只包含-1,但in_array()仍会返回true比较。在这种情况下,-1将转换为布尔值true。所以两个方向的问题都是一样的。

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

不幸的是,调用in_array() strict 参数的默认值是......好吧,是的,false。 : - / PHP和它的打字......

后果

如果严格参数设置为in_array(),您绝不应该致电true。如果没有混合类型的数组,并且只检查具有相同类型的值,in_array()将按预期工作。见这个例子:

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

所以至少这可以按预期工作。但在我看来,总是使用严格 in_array()来调用true要容易得多。 (类似于&#34; SQL注入问题&#34; ...只要总是使用PDO和准备好的语句,这样你就可以安全,即使它是一个没有可变参数的查询。你永远都是那么安全。)

小心但

您绝对应该使用严格 in_array()致电true。但是有一个缺点,我想提一下(尽管很明显)。在调用in_array()时,您必须使用正确的类型:

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

但是当你知道比较数字时,你可以使用Type Casting:

$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即可使用。 ; - )