Index indefinite in table, but it is there

微信扫一扫,分享到朋友圈

Index indefinite in table, but it is there

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?

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 :

 "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"
?>

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);

微信扫一扫,分享到朋友圈

Index indefinite in table, but it is there

Deferred resolution still in capture test

上一篇

比特米(BitRice)基于区块链的分布式共享存储生态数字资产

下一篇

你也可能喜欢

Index indefinite in table, but it is there

长按储存图像,分享给朋友