使用PHP ......一个例子。这会产生警告 - 如预期的那样 - 并且$myVar
保持为bool(true)。
$myVar = true;
$myVar[] = 'Hello'; // Warning: Cannot use a scalar value as an array
但是下一个例子'工作',$myVar
被转换为一个单元素'Hello'的数组。
$myVar = false;
$myVar[] = 'Hello'; // Converted into an array
结果:
array(1) {
[0]=>
string(5) "Hello"
}
然而bool(true)和bool(false)都是标量。为什么差异呢? PHP中的什么规则控制着这种行为?或者它是'它的方式'?!
我最初认为它可能与类型转换规则有关,但bool(true)和bool(false)在这方面表现相同。
感谢。
答案 0 :(得分:7)
所以,即使我不知道为什么 PHP这样做,我看了一些Zend代码,至少可以告诉你在哪里可以找到PHP的确切方式。
因此,重要的代码在zend_fetch_dimension_address
。
所以,让我们来讨论上述情况:
如果IS_ARRAY
- 一切都很明显。
如果它IS_OBJECT
抛出错误,除非它有ArrayAccess
。
如果IS_STRING
抛出错误,除非字符串长度为零。
如果IS_NULL
创建新阵列。
如果IS_BOOL
抛出错误,除非错误。
否则,抛出错误。
所以,这证实了你和我的测试:
如果是对象,非空字符串,true
和其他标量,即long和double,则会出错。
数组,空字符串null
和false
没有错误。所以基本上它会对大多数(但不是全部)“虚假”值进行自动投射。
答案 1 :(得分:1)
PHP不是强类型语言。您将数组分配给包含false
值的变量,而不是布尔 false
值。
在PHP封面下,它必须将$myVar
视为具有值为空的值,因此允许数组赋值。
同样,如果你将PHP看作一种动态脚本语言,那就不是那么出乎意料了。
答案 2 :(得分:1)
如果您想知道为什么会这样,那么请检查php from here I think,编译它并使用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_P(container)==0
条件是造成这种差异的原因... lval表示左值,正在分配的值...我认为它的计算结果为0.
答案 3 :(得分:0)
虽然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。