(bool) true var does not convert to an array when assigning the array, but (bool) false does. What for?

Using PHP ... example. This raises a warning - as expected - and $myVar stays as bool (true).

 $myVar = true; $myVar[] = 'Hello'; // Warning: Cannot use a scalar value as an array 

But this next example "works", $myVar converted to an array with one "Hello" element.

 $myVar = false; $myVar[] = 'Hello'; // Converted into an array 

Results in:

 array(1) { [0]=> string(5) "Hello" } 

However, both bool (true) and bool (false) are scalar. So why the difference? What rule in PHP controls this behavior? Or is it "as it is" ?!

Initially, I thought this might be due to type selection rules, but both bool (true) and bool (false) behave the same in this regard.

Thanks.

+4
source share
4 answers

So, although I don't know why PHP does this, I looked at the Zend code and at least tell you where you can find out exactly how PHP does it.

So, the important code in zend_fetch_dimension_address .

So, consider the above cases:

If this is IS_ARRAY - everything is obvious.

If it IS_OBJECT throws an error, if it does not have ArrayAccess .

If it IS_STRING will give an error if the length of the lines is not equal to zero.

If it is IS_NULL creates a new array.

If it IS_BOOL throws an error, if it is not false.

Otherwise, print an error.

So this confirms your and my tests:

Error if the object, non-empty string, true and other scalars, i.e. long and double. There is no error if the array, empty string, null and false . Thus, basically it does an automatic cast of most (but not all) false values.

+7
source

PHP is not a strongly typed language. You assign an array to a variable that contains false , not boolean false .

In PHP shells, it should see $myVar as having a value that evaluates to empty and therefore allows you to assign an array.

Again, if you look at PHP as a dynamic scripting language, this is not so unexpected.

+1
source

If you want to know why this is so, then the PHP control here I think is to compile it and take some step beyond -step debugging with gdb ... if someone is good enough to find the piece of code responsible for this. Then look at the comments (if any) around the code responsible for this. As mentioned in the comments below, another way to find out if there will be a code search for the error message. Let me do it!

  [ 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 

looks like in zend_execute.c, here is what I found:

  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; 

I think the condition ZLVAL_P(container)==0 is responsible for this difference ... lval means the left value, the value that is assigned ... and I think it evaluates to 0.

+1
source

While PHP is free to type, types still have some meaning, so === or! == for example.

The reason Nikic gets the error if it is reset is zero, it is actually now an integer, not a logical one.

To demonstrate, you can do the following and get the same error when casting.

 $a = (int) false; $a[] = 'goat'; #throws warning, thinks it a 0 $a = (bool) 0; $a[] = 'goat'; #works, thinks it a false 

I know this is just a pedantic example! (bool) true still evaluates to 1.

0
source

Source: https://habr.com/ru/post/1315453/


All Articles