PHP';s型可变宽大

PHP';s型可变宽大,php,Php,最近对PHP的in_array()帮助页()的评论指出,由于PHP的“对变量类型的宽容”,出现了一些不寻常的结果,但没有解释为什么会出现这些结果。特别是,我不明白为什么会发生这些情况: // Example array $array = array( 'egg' => true, 'cheese' => false, 'hair' => 765, 'goblins' => null, 'ogres' => 'no ogres

最近对PHP的
in_array()
帮助页()的评论指出,由于PHP的“对变量类型的宽容”,出现了一些不寻常的结果,但没有解释为什么会出现这些结果。特别是,我不明白为什么会发生这些情况:

// Example array

$array = array(
    'egg' => true,
    'cheese' => false,
    'hair' => 765,
    'goblins' => null,
    'ogres' => 'no ogres allowed in this array'
);

// Loose checking (this is the default, i.e. 3rd argument is false), return values are in comments
in_array(763, $array); // true
in_array('hhh', $array); // true
或者为什么海报认为以下行为很奇怪

in_array('egg', $array); // true
in_array(array(), $array); // true
(当然“egg”确实出现在数组中,PHP不关心它是键还是值,并且有一个数组,PHP不关心它是否为空?)


有人能给出任何指针吗?

763==true,因为true等于任何非0、NULL或“”,数组也是这样,因为它是一个值(不是对象)

为了避免这个问题,您应该将第三个参数作为TRUE传递给STRICT,因此,is_rray将执行a===这是一个类型相等,因此

763!==真的


而且array()也不会真的

PHP将数组视为原始值是一个经常令人痛苦的问题,因为它们可能是非常复杂的数据结构,这没有任何意义。例如,如果将数组指定给某个对象,然后修改该数组,则不会修改原始数组,而是复制该数组

<?php

$arr = array(
    "key" => NULL
);



var_dump( array() == NULL ); //True :(
var_dump( in_array( array(), $arr ) ); //True, wtf? It's because apparently array() == NULL
var_dump( in_array( new stdClass, $arr ) ); //False, thank god

?>

“0”
根据任何可能的定义都是一个非空字符串,但它是一个伪值。

在内部,您可以想象基本的in_array()调用是这样工作的:

function in_array($needle, $haystack, $strict = FALSE) {
    foreach ($haystack as $key => $value) {
        if ($strict === FALSE) {
            if ($value == $needle) {
                return($key);
            }
        } else {
            if ($value === $needle) {
                return($key);
        }
    }
    return(FALSE);
}
请注意,它使用的是
==
比较运算符-此运算符允许进行类型转换。因此,如果您的数组包含一个简单的布尔值
TRUE
值,那么实际上,您在数组中搜索的所有内容都将被找到,并且除了PHP中的以下内容之外,几乎所有内容都可以被类型转换为TRUE:

'' == TRUE // false
0 == TRUE // false
FALSE == TRUE // false
array() == TRUE // false
'0' == TRUE // false
但是:

这就是为什么in_数组具有可选的第3个参数来强制进行严格比较。它只需在数组中执行
==
严格比较,而不是
=

也就是说

'a' === TRUE // FALSE

数组()!=是的;)你的意思可能是array()==false。我从内存中取出了它,但我早就完成了认证。谢谢你澄清这一点。在任何情况下,它都是有效的,因为数组中有一个true和一个false,所以每个In_数组调用都应该返回true,除了我不确定的对象的“maybe”之外。
In_数组
最重要的目的不是与任意类型的值进行比较,而是与字符串列表或所有整数进行比较。即使如此,它也只是使用Zends标准的弱类型规则此外,我们不应该在这里讨论php.net手动注释。只需提交一份bug报告。“PHP不在乎它是键还是值”——为什么你认为
in_array
可以在数组键上工作?文档摘要清楚地说“检查数组中是否存在值”(emphasis mine)。javascript和perl中的
“0”==false
。@MathieuDumoulin,在javascript中:
if(“0”){alert(“hello”);}
按预期传递:“0”是真实值,因为它是非空字符串。在PHP
if(“0”){echo“hello”;}
中,即使它是非空字符串,也不做任何事情。@gnud,这并不重要,因为在javascript中不这样做。如果使用
if(“0”)
if(x==true)
,则无需编写
if==true
,因为正如您所看到的,它会产生意外的结果。区别在于,在javascript中,“0”是一个真实的值,而在php中,“0”是一个虚假的值。与
true
相比,两者都被转换为
0
,这在两种语言中给出了相同的结果。因此,javascript对
if(“0”)
if(“0”==true)
的处理方式不同,而你抱怨PHPs类型怪异?@gnud,
if(某物)
在ecmascript规范中有很好的定义,没有什么意外
NaN、-0、+0、空字符串、false、null、未定义的
将不通过,而其他所有内容都将通过。在PHP中,您可以在我对MathieDumoulin的回复中看到,情况并非如此。
'a' == TRUE // true
1 == TRUE // true
'1' == TRUE // true
3.1415926 = TRUE // true
etc...
'a' === TRUE // FALSE