为什么 in_array() return 出乎意料/奇怪的结果?
Why does in_array() return unexpected / strange results?
为什么 in_array()
有时表现得如此奇怪并且 returns 出现如此意想不到的结果?
让我们看几个例子:
$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)
嗯?这里发生了什么!?
(几年前我对这个问题感到疑惑,起初,奇怪的行为。我认为它可能对某些人有用,因此我输入了这个问题。)
解法(简称):
始终使用 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
,这显然是 true
.
第二个数组也是如此,其中0
最终与null
进行比较,得到true
,尽管0
显然与0
不相同null
(例如,当您处理数字和/或函数结果时,这可能特别棘手,其中 null
可以表示空值而不是 0
)。
第三个数组看起来很奇怪,因为我们检查数组中的值true
,它只包含-1
,但in_array()
仍然returns true
进行比较。在这种情况下,-1
被转换为布尔值 true
。所以问题在两个方向上都是一样的。
您可以在PHP中找到更多关于比较问题的示例(因为这与==
/ ===
相同)在this Stack Overflow answer.
不幸的是,调用 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 Injection Problem"...只要始终使用 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
即可使用。 ;-)
为什么 in_array()
有时表现得如此奇怪并且 returns 出现如此意想不到的结果?
让我们看几个例子:
$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)
嗯?这里发生了什么!?
(几年前我对这个问题感到疑惑,起初,奇怪的行为。我认为它可能对某些人有用,因此我输入了这个问题。)
解法(简称):
始终使用 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
,这显然是 true
.
第二个数组也是如此,其中0
最终与null
进行比较,得到true
,尽管0
显然与0
不相同null
(例如,当您处理数字和/或函数结果时,这可能特别棘手,其中 null
可以表示空值而不是 0
)。
第三个数组看起来很奇怪,因为我们检查数组中的值true
,它只包含-1
,但in_array()
仍然returns true
进行比较。在这种情况下,-1
被转换为布尔值 true
。所以问题在两个方向上都是一样的。
您可以在PHP中找到更多关于比较问题的示例(因为这与==
/ ===
相同)在this Stack Overflow answer.
不幸的是,调用 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 Injection Problem"...只要始终使用 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
即可使用。 ;-)