你已经得到了解决方法,让我来补充一个更加技术性的答案:为什么会发生这种情况...
这种行为源自 ZEND_API int compare_function(..)
的独特实现方式。
当你调用 in_array(needle, haystack, strict)
时,如果 $strict=true 参数没有设置,则会使用 此函数 来 比较 needle
和 haystack 中的每个元素,直到找到匹配项为止。
在这里,你的 needle 是一个字符串,而 haystack 中的元素是整数。
让我们简单看一下 compare_function()
。
while(1) {
switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
case TYPE_PAIR(IS_LONG, IS_LONG):
ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
return SUCCESS;
[...more CASEs that don't apply on the first iteration of the while-loop...]
default:
[...some if-elseif cases that do not apply on the first iteration of the while-loop...]
} else {
zendi_convert_scalar_to_number(op1, op1_copy, result);
zendi_convert_scalar_to_number(op2, op2_copy, result);
converted = 1;
}
[...]
当这段代码第一次执行时,
op1~'test'
和
op2~0
。(其中 ~ 表示“大约是”,因为内部表示有点不同,但在这里并不重要。)
但没有 TYPE_PAIR(IS_STRING, IS_LONG) 的情况,所以它会命中默认分支。有一些 if 条件来处理对象,但是两个操作数都不是对象,所以它到达了将操作数转换的部分(仅一次)。
再次没有任何 if 条件适用,所以它进入最后一个 else 分支,将
两个 操作数都转换为数字。
'test'
被转换为
0
,而
0
保持为
0
。
然后 while 循环再次执行,现在是 TYPE_PAIR(IS_LONG,IS_LONG) - 第一个 case。现在
两个 操作数相等,因此 in_array() 返回 true。
...是的,我也觉得很混乱;-)
in_array('test', $people, true)
。 - bansi