Reputation: 11148
I have an array. Here is it's var_dump:
array(1) {
["139"]=>
string(5) "my_data"
}
We see, that we have key 139, and it's string (var dumps of key: string(3) "139"). I want to get element from array, here's the code:
$bad_array = $this->get('some_data');
var_dump($bad_array);
var_dump($my_key);
var_dump(isset($bad_array[$my_key]));
var_dump($bad_array[$my_key]);
Here's the output:
array(1) {
["139"]=>
string(5) "my_data"
}
string(3) "139" // my key output
bool(false) // it's not isset
Notice: Undefined index: 139 in /my_file_path.php on line 89
NULL
WHY??? I have a string variable, all of keys are strings. How can it be?
Upvotes: 3
Views: 1237
Reputation: 12042
Short Answer
Array
type-casting from an Object
doesn't work with integer properties (as strings
i.e. "139").
Long answer
A bunch of testing code :
<pre>
<?php
$arr = array("139" => "some_data", "test" => "other_data");
$good = (object) $arr;
$good_arr = (array) $good;
$bad = json_decode(json_encode($arr));
$bad_arr = (array)($bad);
var_dump ($arr);
foreach ($arr as $k => $v)
var_dump (gettype ($k)); // 139 is integer
var_dump ($good);
foreach ($good as $k => $v)
var_dump (gettype ($k)); // 139 is integer
var_dump ($good_arr);
foreach ($good_arr as $k => $v)
var_dump (gettype ($k)); // 139 is integer
var_dump ($bad);
foreach ($bad as $k => $v)
var_dump (gettype ($k)); // 139 is string
var_dump ($bad_arr);
foreach ($bad_arr as $k => $v)
var_dump (gettype ($k)); // 139 is string
var_dump ($arr[139]); // string(9) "some_data"
var_dump ($arr["139"]); // string(9) "some_data"
var_dump ($arr["test"]); // string(10) "other_data"
var_dump ($good->{139}); // NULL
var_dump ($good->{"139"}); // NULL
var_dump ($good->{"test"}); // string(10) "other_data"
var_dump ($good_arr[139]); // string(9) "some_data"
var_dump ($good_arr["139"]); // string(9) "some_data"
var_dump ($good_arr["test"]); // string(10) "other_data"
var_dump ($bad->{139}); // string(9) "some_data"
var_dump ($bad->{"139"}); // string(9) "some_data"
var_dump ($bad->{"test"}); // string(10) "other_data"
var_dump ($bad_arr[139]); // NULL
var_dump ($bad_arr["139"]); // NULL
var_dump ($bad_arr["test"]); // string(10) "other_data"
?>
</pre>
bin2hex
is actually showing exactly the same value, and foreach
was working fine.
So how is that possible that it doesn't work when we're trying to access it directly ?
And how weird is it that the last is displaying fine ?
Well, actually, I got the answer to the second question from this part from the doc talking about array type casting As you can see there, when converting an object to array with type casting, this doesn't work for number properties, which are let inaccessible.
For the first question, I will assume that the type cast doesn't change how data are represented in memory, so that it can still iterate on it as if it was an object.
Next are just my assumptions of differences between both scenarios :
In the good scenario
PHP
is handling stuff all by himself. An array key of type string
representing an integer
is automatically converted to integer
.
Then, no problem when we convert it, it becomes a property (with integer
type) of the $good
object even though it isn't accessible (because it is trying to reach the "139"
property, not the 139
). (NULL
returned)
When we do the cast to array $good_arr
, the data structure hasn't changed, and we can still access it, because it reaches 139
and not "139"
.
In the bad scenario
Here the object is regenerated by json_decode
. This function doesn't generate bad objects (and tht's a good thing !), so all the properties will have type string
.
This is why we can access the property directly from the object here. It is a valid property (type string
) so we can access it.
But as told in the docs, when we cast it back to array
, the data structure hasn't changed, so we can't access it. Either we write $bad_arr[139]
or $bad_arr["139"]
it will try to access to the value with the key 139
(NULL
returned), when it should actually access "139"
.
Conclusion
This is a typical example of PHP
's magic. Converting string
s to int
automatically in arrays is what caused your problem.
So your solution of using the assoc
param of json_decode
seems to be the only one which will work here :
json_decode($json_arr, true);
Upvotes: 3
Reputation: 11148
I have an array, then I saves it to redis. After save I casts array to object through json_decode(json_encode($ar)) construction.
$redis->save($array);
$this->object = json_decode(json_encode($array));
...
Then I casts in to array again:
$ar = (array)$this->obj;
If I will do it, I can't access array properties. Solution:
$this->object = json_decode(json_encode($array), true); // get array
...
if (is_object($ar)) {
$ar = (array)$ar;
}
Strange things...
Upvotes: 2