数组中未定义的索引,但它就在那里

时间:2014-01-23 09:52:46

标签: php arrays

我有一个数组。这是var_dump:

array(1) {
  ["139"]=>
  string(5) "my_data"
}

我们看到,我们有密钥139,它是字符串(密钥的var转储: string(3)“139”)。 我想从数组中获取元素,这里是代码:

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

这是输出:

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 ???我有一个字符串变量,所有键都是字符串。怎么会这样?

2 个答案:

答案 0 :(得分:3)

简答

来自Array doesn't work with integer properties (as strings i.e. "139")

Object输入法。

答案很长

一堆测试代码:

<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实际上显示的值完全相同,foreach工作正常。

那么当我们试图直接访问它时,它怎么可能不起作用呢? 最后一个显示正常的是多么奇怪?

嗯,实际上,我从第part from the doc talking about array type casting个问题得到了答案。 正如你在那里看到的那样,当使用类型转换将对象转换为数组时,这对数字属性不起作用,这些属性是不可访问的。

对于第一个问题,我将假设类型转换不会改变数据在内存中的表示方式,因此它仍然可以像对象一样迭代它。

接下来只是我对两种情景之间差异的假设:

在好的情景中

PHP正在处理所有事情。表示string的{​​{1}}类型的数组键会自动转换为integer 然后,当我们转换它时没有问题,它成为integer对象的属性(具有integer类型),即使它不可访问(因为它试图到达$good属性,而不是"139")。 (139返回)
当我们对数组NULL执行转换时,数据结构没有更改,我们仍然可以访问它,因为它到达$good_arr而不是139

在糟糕的情况下

此处对象由"139"重新生成。这个函数不会生成坏对象(这是件好事!),所以所有属性都有json_decode类型。
这就是为什么我们可以直接从这里的对象访问该属性。它是一个有效的属性(类型string),因此我们可以访问它 但正如文档中所述,当我们将其强制转换回string时,数据结构没有改变,因此我们无法访问它。我们写array$bad_arr[139]时会尝试使用密钥$bad_arr["139"]139返回)来访问该值,而它应该实际访问NULL

<强>结论

这是"139"神奇的典型例子。 PHP转换为string是造成问题的原因。

因此,使用int的{​​{1}}参数的解决方案似乎是唯一可以在此处运行的解决方案:

assoc

答案 1 :(得分:2)

我有一个数组,然后我将它保存到redis。保存后,我通过json_decode(json_encode($ ar))构造将数组转换为对象。

$redis->save($array);
$this->object = json_decode(json_encode($array));
...

然后我再次投入数组:

$ar = (array)$this->obj;

如果我这样做,我就无法访问数组属性。 的解决方案

$this->object = json_decode(json_encode($array), true); // get array
...
if (is_object($ar)) {
    $ar = (array)$ar;
}

奇怪的事情......