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

And*_*eas 7 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)
Run Code Online (Sandbox Code Playgroud)

咦?这里发生了什么事!?

(几年前,我开始对这种奇怪的行为感到疑惑.我认为这可能对某些人有用,因此我输入了这个问题.)

And*_*eas 16

解决方案(简而言之):

使用in_array()第三个参数始终严格 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)
Run Code Online (Sandbox Code Playgroud)

因此,当您使用in_array()with true作为第三个参数时,搜索值和数组之间的比较是严格完成的,这意味着in_array()您可能会期望它.

(参数strict也在php.net文档中描述.)

说明

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

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

第二个数组0也是如此,最后在那里进行比较null,结果true,尽管0显然不一样null(当你处理数字和/或函数结果时,这可能特别棘手,例如,在哪里null可以表示一个空值而不是0).

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

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

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

后果

如果in_array()没有设置严格的参数,你应该永远不会打电话true.如果没有混合类型的数组,并且只检查具有相同类型的值,in_array()则按预期工作.看这个例子:

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

所以至少这可以按预期工作.但在我看来,总是in_array()严格 来电话要容易得多true.(与"SQL注入问题"类似...只是总是使用PDO和预处理语句,所以你是安全的,即使它是一个没有可变参数的查询.你总是安全的.)

但要小心

你一定要打电话in_array()严格 true.但是有一个缺点,我想提一下(尽管很明显).在调用时你必须使用正确的类型in_array():

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

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

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

奖金

// Comparing false with an empty array
var_dump(in_array(false, [[]])); // returns bool(true)
Run Code Online (Sandbox Code Playgroud)

嗯,是的......只要严格使用就可以了true.;-)