Php (bool)true-var不会在数组赋值时转换为数组,但(bool)false会转换为数组。为什么?
使用PHP。。。举个例子。这会产生一个警告(正如预期的那样),并且Php (bool)true-var不会在数组赋值时转换为数组,但(bool)false会转换为数组。为什么?,php,arrays,Php,Arrays,使用PHP。。。举个例子。这会产生一个警告(正如预期的那样),并且$myVar保持为bool(true) 但下一个示例“有效”,将“$myVar转换为一个包含单个元素“Hello”的数组 $myVar = false; $myVar[] = 'Hello'; // Converted into an array 结果: array(1) { [0]=> string(5) "Hello" } 然而bool(真)和bool(假)都是标量。那么为什么会有区别呢?PHP中的什么规则
$myVar
保持为bool(true)
但下一个示例“有效”,将“$myVar
转换为一个包含单个元素“Hello”的数组
$myVar = false;
$myVar[] = 'Hello'; // Converted into an array
结果:
array(1) {
[0]=>
string(5) "Hello"
}
然而bool(真)和bool(假)都是标量。那么为什么会有区别呢?PHP中的什么规则控制这种行为?还是“就是这样”
我最初认为这可能与类型转换规则有关,但bool(true)和bool(false)在这方面表现相同
谢谢。PHP不是强类型语言。将数组分配给包含
false
值的变量,不需要布尔false
值
在PHP封面下,它必须将$myVar
视为具有一个计算结果为空的值,因此允许数组赋值
同样,如果您将PHP视为一种动态脚本语言,这并不完全出乎意料。如果您想知道为什么会这样,请签出PHP,编译它,并使用gdb进行逐步调试。。。除非有人足够优秀,能够找到对此负责的代码。 然后看看代码周围的注释(如果有)。 正如下面的评论中提到的,另一种查找方法是搜索代码以查找错误消息。让我们这样做
[greg@liche php-src-5.3]$ grep -rn --exclude-dir=".svn" "Cannot use a scalar value as an array" .
./tests/lang/bug29893.phpt:10:Warning: Cannot use a scalar value as an array in %sbug29893.php on line %d
./tests/lang/engine_assignExecutionOrder_002.phpt:12:// Warning: Cannot use a scalar value as an array in %s on line %d
./tests/lang/engine_assignExecutionOrder_002.phpt:94:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/zend_execute.c:1015: zend_error(E_WARNING, "Cannot use a scalar value as an array");
./Zend/tests/indexing_001.phpt:51:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:54:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:57:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:77:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:96:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:99:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:102:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:119:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:137:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:140:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:143:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:160:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:179:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:182:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:185:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:202:Warning: Cannot use a scalar value as an array in %s on line %d
看起来它在zend_execute.c中,下面是我发现的:
case IS_BOOL:
1223 if (type != BP_VAR_UNSET && Z_LVAL_P(container)==0) {
1224 goto convert_to_array;
1225 }
1226 /* break missing intentionally */
1227
1228 default:
1229 if (type == BP_VAR_UNSET) {
1230 zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
1231 AI_SET_PTR(result, &EG(uninitialized_zval));
1232 PZVAL_LOCK(&EG(uninitialized_zval));
1233 } else {
1234 zend_error(E_WARNING, "Cannot use a scalar value as an array");
1235 result->var.ptr_ptr = &EG(error_zval_ptr);
1236 PZVAL_LOCK(EG(error_zval_ptr));
1237 }
1238 break;
我认为ZLVAL\u p(container)=0条件是造成这种差异的原因。。。lval表示左值,即正在分配的值。。。我认为它的计算结果为0。所以,尽管我不知道PHP为什么会这样做,但我看了一些Zend代码,至少可以告诉您在哪里可以找到PHP是如何做到这一点的 所以,重要的代码在 那么,让我们来介绍一下上述情况: 如果它
是_ARRAY
-一切都很明显
如果它是\u对象
抛出错误,除非它有数组访问
如果是\u STRING
抛出错误,除非字符串长度为零
如果为空
则创建一个新数组
如果它为布尔值,则抛出一个错误,除非它为false
否则,抛出一个错误
因此,这证实了您和我的测试:
如果对象、非空字符串、true
和其他标量(即long和double)出现错误。
如果是数组、空字符串、null
和false
,则无错误。因此,基本上它对大多数(但不是所有)“falsy”值进行自动强制转换。虽然PHP是松散类型,但类型仍然具有一定的重要性,因此===或!==比如说
如果Nikic被重置为零,它会出错的原因是它现在实际上是一个整数,而不是布尔值
为了演示,您可以执行以下操作,并通过强制转换获得相同的错误
$a = (int) false;
$a[] = 'goat'; #throws warning, thinks it's a 0
$a = (bool) 0;
$a[] = 'goat'; #works, thinks it's a false
然而,我知道这只是一个迂腐的例子!(bool)true的计算结果仍然是1。你到底为什么要做这样的事?:]这是一个非常简单的例子。函数在允许的错误状态下返回数组或(bool)false。然后使用$myVar[$key]
将元素添加到此数组中。在(bool)false的情况下,将创建一个新数组-非常好。然后有一天,函数做了一些奇怪的事情,返回int(1),脚本失败了。这让我想知道为什么这个脚本一开始就用(bool)false!这不可能是全部真相。正如我在回答中所说,0
即使empty
也会抛出一个错误。虽然PHP不是强类型的,但它是一个布尔假值(==false)。是的,正如nikic所说,当var计算为空时也不一定如此。@nikic,这肯定不是全部正确的。但很明显,它没有像w3d所提到的那样进行严格的平等性检查。如果你发现了全部真相,那么你就回答了自己的问题;)我已经在查看Zend代码,但找不到导致这种奇怪现象的文件。找到第612行convert\u scalar\u to \u array
。这可能是函数,但它对我也没有帮助。至少它没有向我解释任何事情。如果你对一个数组输入(bool)true或(bool)false,你会得到基本相同的结果。。。元素值为(bool)true或(bool)false的单个元素数组。我们不知道是否有强制转换的尝试。我们正在查找的代码使用了运算符“[”。在checkouted本地副本中搜索错误消息将是一个很好的方法。@gregwire yes true。事实上,该值已被覆盖/替换(或“转换”),根本没有强制转换。是的,感谢您的分解。因此,您的初始响应似乎是,“我认为这是因为一个是true
,另一个是false
:D这就是PHP!“,基本上在按钮上!:)其实一点也不奇怪。将空数组转换为bool
会产生false
,而将非空数组转换为bool
则会产生true
。这是一个愚蠢的语法糖,可以让你通过一个简单的if($array)来测试数组是否为空。”
。向后看,false
应该在逻辑上转换为空数组。但是,没有明智的方法将true
转换为填充数组,因此会抛出错误。@meagar:当然可以将true转换为填充数组:php>var_dump((数组)true);数组(1){[0]=>bool(true)}@w3d:随着时间的推移,我完全忘记了这一点。但现在再看一遍,我认为这种行为是有意义的。PHP的一个特性是数组不需要显式初始化,也就是说,您可以编写$array[]='x'
即使尚未定义$array
。上述行为与此相匹配,允许推送到null
值(
$a = (int) false;
$a[] = 'goat'; #throws warning, thinks it's a 0
$a = (bool) 0;
$a[] = 'goat'; #works, thinks it's a false