15

I have encountered something odd.

I have a php array, indexed with numerical keys. However it appears impossible to access any of the elements because php automatically treats numerical strings as integers, causing an illegal offset notice.

Under normal circumstances its imposable to create a php array with numerical string indexes, but it can happen with type casting.

To reproduce:

$object = new stdClass();
$object->{'1'} = 'one';

$array = (array) $object;

var_dump($array);
/* produces
array(1) {
  ["1"]=>
  string(3) "one"
}
*/

//none of the following will work
$key = '1';
echo $array[1], $array['1'], $array["1"], $array[(string)1], $array[$key];

Is this just an edge case bug? I only encountered the problem when attempting to improve my answer for another SO question

Live code example: http://codepad.viper-7.com/dFSlH1

11
  • 2
    Some info here php.net/manual/en/… Commented Nov 13, 2015 at 15:33
  • 1
    String keys containing valid integer values would be cast to integer keys automatically in “normal” array creation – but it seems casting from object to array doesn’t apply the same logic. It can be fixed however, by using $array = array_combine(array_keys($array), array_values($array)); after your line that creates the array from the object. codepad.viper-7.com/v5rGJa Commented Nov 13, 2015 at 15:34
  • 2
    to add to danjam's comment... with a few notable exceptions: integer properties are unaccessible; Commented Nov 13, 2015 at 15:34
  • 1
    @danjam Are, well spotted. So it is documented. Though i would still consider it a bug. Commented Nov 13, 2015 at 15:36
  • 1
    @Steve not a bug, it's a language "feature" :) Commented Nov 13, 2015 at 15:37

4 Answers 4

13

Unbelievable but this is normal behavior in php, it was considered as a bug (link) in the year 2008.

But they just pointed out to the manual for the cast with (array):

If an object is converted to an array, the result is an array whose elements are the object's properties. The keys are the member variable names, with a few notable exceptions: integer properties are unaccessible;

You can use get_object_vars() instead:

$object = new stdClass();
$object->{'1'} = 'one';

$array = get_object_vars( $object );

$key = '1';
echo $array[1]."<br>";
echo $array['1']."<br>";
echo $array["1"]."<br>";
echo $array[(string)1]."<br>";
echo $array[$key]."<br>";

Doesn't explain why this happens, but is a solution to avoid the cast problem.

Off topic but I thought maybe it is interesting. Found this in the manual.

To avoid these kind of problems, always use an integer OR a string as index, don't mix it up and don't use integers in a string.

Example of mixed array:

$array = array(
    1    => "a",
    "1"  => "b",//overrides 1
    1.5  => "c",//overrides "1"
    true => "d",//overrides 1.5
);

var_dump($array);
Sign up to request clarification or add additional context in comments.

Comments

5

You can use

$vars  = get_object_vars($object);
echo $vars[1];

1 Comment

oh great, you were faster than me :)
2

String keys containing valid integer values would be cast to integer keys automatically in “normal” array creation – but it seems casting from object to array doesn’t apply the same logic.

It can be fixed however, by using

$array = array_combine(array_keys($array), array_values($array));

after your line that creates the array from the object. http://codepad.viper-7.com/v5rGJa


Although, same as Dave already said in his comment, using get_object_vars looks like a “cleaner” solution to me as well.

Comments

1
foreach ($array as $key => $value){
    var_dump($key);
    var_dump($value);
}

shows

string(1) "1"
string(3) "one"

But echo $array['"1"']; gives

E_NOTICE :  type 8 -- Undefined index: "1" -- at line 8

That's strange!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.