29

I have a PHP array that has numeric keys as a string type.

But when I try and access them PHP is giving me an undefined index error.

$a = (array)json_decode('{"1":1,"2":2}');
var_dump($a);
var_dump(isset($a[1]));
var_dump(isset($a["1"]));
var_dump($a[1]);
var_dump($a["1"]);

Output:

array (size=2)
    '1' => int 1
    '2' => int 2

boolean false

boolean false

ERROR: E_NOTICE: Undefined offset: 1

null

ERROR: E_NOTICE: Undefined offset: 1

null

How do I access these values?

Demo: http://codepad.viper-7.com/8O03IM

Petah
  • 45,477
  • 28
  • 157
  • 213
  • 1
    give the reputation +100 before it's expired. – Josua Marcel C Sep 10 '12 at 14:47
  • 8
    @JosuaMarcelChrisano: There are 6 whole days before the bounty expires. The bounty was just started yesterday. Give him a break. Also there's no need for you to remind him again 6 days later - the system will do so. – BoltClock Sep 10 '12 at 21:08

6 Answers6

32

So, I haven't seen any other answers touch upon this, but @xdazz came close.

Let's start our environment, $obj equals the object notation of a decoded string:

php > $obj = json_decode('{"1":1,"2":2}');

php > print_r($obj);
stdClass Object
(
    [1] => 1
    [2] => 2
)

php > var_dump( $obj );
object(stdClass)#1 (2) {
  ["1"]=>
  int(1)
  ["2"]=>
  int(2)
}

If you want to access the strings, we know the following will fail:

php > echo $obj->1;

Parse error: parse error, expecting `T_STRING' or `T_VARIABLE' or `'{'' or `'$'' in php shell code on line 1

Accessing the object variables

You can access it like so:

php > echo $obj->{1};
1

Which is the same as saying:

php > echo $obj->{'1'};
1

Accessing the array variables

The issue with arrays is that the following return blank, which is the issue with typecasting.

php > echo $obj[1];
php >

If you typecast it back, the object is once again accessible:

php > $obj = (object) $obj;
php > echo $obj->{1};
1

Here is a function which will automate the above for you:

function array_key($array, $key){
    $obj = (object) $array;
    return $obj->{$key};
}

Example usage:

php > $obj = (array) $obj;
php > echo array_key($obj, 1);
1

php > echo array_key($obj, 2);
2
Mike Mackintosh
  • 13,917
  • 6
  • 60
  • 87
26

If you want array, set the second parameter of json_decode to true.

$a = json_decode('{"1":1,"2":2}', true);

Edit: when you cast a std object to array, numeric string key doesn't cast to number. Here is an example.

$obj = new stdClass;
$obj->{'1'} = 1;
$arr = (array) $obj;
var_dump($arr);
var_dump(isset($arr[1]));
xdazz
  • 158,678
  • 38
  • 247
  • 274
  • Thanks, this works for my problem. Bonus points if you can find a way to access an array with those type of keys though. – Petah Jul 17 '12 at 03:23
  • 4
    @Petah This is the problem of php, but you could still get the key and value through `foreach`. – xdazz Jul 17 '12 at 03:36
15

Apparently, this is a known issue, and there are no plans to fix it; see Doc Bug #45959 Object to array conversion leads to weird behaviour:

Fixing that implies a perfomance decrease, hence the better seems be keep it as an known issue, but documented.

This wonkiness is (then) noted in the documentation for the array type (emphasis mine):

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.... This can result in some unexpected behaviour....

hakre
  • 193,403
  • 52
  • 435
  • 836
  • 1
    Nice answer! I have to say that casting to an array is broken enough to declare a new rule: never ever cast anything to an array in PHP. – Mikko Rantalainen Sep 10 '12 at 07:17
1

Yes. I do agree, PHP has issue with typecasting from object to array but foreach is handling intelligently the object or associative array.

$a = json_decode('{"1":1,"2":2}'); //need not typecast but doesnt break even if u typecast

foreach ($a as $k=>$v){
    echo $v;
}
Angelin Nadar
  • 8,944
  • 10
  • 43
  • 53
1

I met the same problem recently.

$obj = new stdClass();
$obj->{'0'} = "test";

$array = (array)$obj;
foreach ($array as $key => $value) {
   $array[$key] = strtoupper($value);
}
var_dump($array);

This code outputs :

array(2) {
  ["0"]=>
  string(4) "test"
  [0]=>
  string(4) "TEST"
}

Found that when debugging a method to convert recursivly objects to array, I've been mad.

Alain Tiemblo
  • 36,099
  • 17
  • 121
  • 153
1

I had the same problem (but with array_intersect_key).

Here is my solution:

$array = array_combine(array_keys($array), $array);
user2765479
  • 345
  • 2
  • 2