Why does treating integers as arrays ($int[$index]

2019-02-13 07:39发布

问题:

This question already has an answer here:

  • How does the “Array dereferencing” work on a scalar value of type boolean/integer/float/string as of PHP version 7.2.0? 1 answer

This is just a simple question out of curiosity. I spent the whole day debugging my PHP code, and found the problem was due to treating an integer as an array:

$x = $int[$index]; // this returns null, but no error at all

The integer was actually meant to be an array, but the function that was meant to pass the array messed up and passed the first value in the array instead. Is there any reason why an error isn't shown? Accessing an undefined index on an array creates an error, however trying to access a non-existent index on an integer doesn't?

回答1:

I originally thought; it typecasts $int to a string because [] is another way of accessing string positions. Seems plausible that that wouldn't generate an error:

$string 'Hello';
echo $string[0]; // H

However, that's not the case:

$int = 1;
echo $int[0];

Outputs nothing and var_dump($int[0]) returns NULL.

Interestingly, the same behavior is exhibited for bool and float and the operation used is FETCH_DIM_R which is Fetch the value of the element at "index" in "array-value" to store it in "result".

From the manual Arrays:

Note: Array dereferencing a scalar value which is not a string silently yields NULL, i.e. without issuing an error message.

Similar to this phenomenon, where no error is generated. Bugs #68110 and #54556:

$array['a'] = null;
echo $array['a']['non-existent'];

Not surprising that assigning doesn't work:

$int = 1;
$int[0] = 2;

Warning: Cannot use a scalar value as an array

So PHP is actually attempting to access the int, bool, float as an array but not generating an error. This is from at least version 4.3.0 to 7.2.2.



回答2:

Contrary to my original theory that you're invoking undefined behavior, this behavior actually is defined in the Array documentation.

Note:
Array dereferencing a scalar value which is not a string silently yields NULL, i.e. without issuing an error message.

In that case, it seems like there's no type juggling happening at all, so these references to documentation regarding conversion to array aren't useful in understanding this.


Explicit conversion to array is defined.

For any of the types integer, float, string, boolean and resource, converting a value to an array results in an array with a single element with index zero and the value of the scalar which was converted. In other words, (array)$scalarValue is exactly the same as array($scalarValue).

Automatic conversion to array is undefined according to the type juggling documenation.

Note:
The behaviour of an automatic conversion to array is currently undefined.

At first I thought this was what was happening in this case, but since salathe pointed out that this behavior is documented elsewhere, I'm not sure what "automatic conversion to array" is.

As to why this gives you a null value without throwing an error, warning, or notice, that's just how the PHP interpreter was implemented, and as far as why that is the case, it's not really answerable here. You'd have to ask the developers, and they might be able to tell you.



回答3:

this is "type juggling", a "feature" of PHP.

you can read more in the official doc

EDIT According to documentation, "The behaviour of an automatic conversion to array is currently undefined."

I run a quick test, just for curiosity:

<?php
$int = 1;
$index = 0; 
$x = $int[$index]; 
echo gettype($int[$index]) . PHP_EOL; 
var_dump($x);

and the output shows that gettype() returns NULL, so I guess that, in this case, is converted to NULL