【问题标题】:Undefined offset while accessing array element which exists访问存在的数组元素时未定义的偏移量
【发布时间】:2012-06-20 20:44:41
【问题描述】:

我有一个数组和 PHP,当我将它打印出来时,我可以看到我需要访问的值,但是当我尝试通过它们的键访问它们时,我得到了一个 PHP 通知。我用print_r 打印了数组:

Array
(
    [207] => sdf
    [210] => sdf
)

当我尝试使用索引访问数组时,我收到未定义的偏移通知。这是我的代码:

print_r($output); 
echo $output[207];   // Undefined Offset
echo $output["207"]; // Undefined Offset

$output 数组是调用 array_diff_key 的结果,最初是通过 HTTP POST 请求作为 JSON 输入的。

array_keys 给了我以下信息:

Array
(
   [0] => 207
   [1] => 210
)

回应cmets:

var_dump(key($output)); 输出:

   string(3) "207"

var_dump(isset($output[key($output)])); 输出:

   bool(false)

【问题讨论】:

  • 试试var_dump(key($output)),告诉我们你得到了什么。
  • 需要更多信息。什么语境?这是在服务器端脚本中吗?
  • @deceze:这是输出string '207' (length=3)
  • @deceze:是的,我在代码中使用了很多数组。但是这个简单的事情让我发疯了。 :-)
  • @ascii-lime:没什么特别的。像往常一样 PHP :-)。是的,很混乱。

标签: php arrays indexing element undefined


【解决方案1】:

只要放error_reporting(0);在你的方法或文件的开头。它会解决你的问题。

【讨论】:

    【解决方案2】:

    castingarray 的对象具有有效整数的字符串键时,就会出现问题。

    如果你有这个对象:

    object(stdClass)#1 (2) {
      ["207"]=>
      string(3) "sdf"
      ["210"]=>
      string(3) "sdf"
    }
    

    然后你用

    $array = (array)$object
    

    你得到这个数组

    array(2) {
      ["207"]=>
      string(3) "sdf"
      ["210"]=>
      string(3) "sdf"
    }
    

    它的键只能通过循环访问,因为像$array["207"] 这样的直接访问将始终是converted$array[207],这不存在。

    因为你从json_decode() 得到一个像上面那样的对象,应用于一个字符串

    $json = '{"207":"sdf", "210":"sdf"}'
    

    最好的解决方案是首先避免使用数字键。这些可能更好地建模为对象数组的数字属性:

    $json = '[{"numAttr":207, "strAttr":"sdf"}, {"numAttr":210, "strAttr":"sdf"}]'
    

    这种数据结构比现在的有几个优点:

    1. 它更好地反映了原始数据,作为对象的集合 具有数字属性
    2. 它很容易与其他属性一起扩展
    3. 在不同系统间更便携 (如您所见,您当前的数据结构导致 PHP 出现问题,但如果您 应该碰巧使用您可能很容易遇到的另一种语言 类似的问题)。

    如果需要一个property → object map,可以很快得到,比如这样:

    function getNumAttr($obj) { return $obj->numAttr; } // for backward compatibility
    $arr = json_decode($json); // where $json = '[{"numAttr":...
    $map = array_combine(array_map('getNumAttr', $arr), $arr);
    

    另一种解决方案是按照 ascii-lime 的建议进行操作:强制 json_decode() 输出关联数组而不是对象,方法是将其第二个参数设置为 true

    $map = json_decode($json, true);
    

    对于您的输入数据,这会直接产生

    array(2) {
      [207]=>
      string(3) "sdf"
      [210]=>
      string(3) "sdf"
    }
    

    请注意,数组的键现在是整数而不是字符串。

    不过,我会考虑将 JSON 数据结构更改为更简洁的解决方案,尽管我知道这样做可能是不可能的。

    【讨论】:

    • 被点赞然后一段时间后又被取消投票很有趣。如果在我的回答中发现了错误,我很想知道它是什么
    【解决方案3】:

    试试

    var_dump($output);
    foreach ($output as $key => val) {
        var_dump($key);
        var_dump($val);
    }
    

    了解更多关于正在发生的事情。

    什么确切的行/语句向您发出警告?

    【讨论】:

      【解决方案4】:

      尝试使用我的方法:

      class ObjectToArray {
          public static function convert( $object ) {
              if( !is_object( $object ) && !is_array( $object ) ) {
                  return $object;
              }
      
              if( is_object( $object ) ) {
                 $object = get_object_vars( $object );
              }
      
              return array_map( 'ObjectToArray::convert', $object );
          }
      }
      
      $aNewArray = ObjectToArray::convert($oYourObject);
      

      【讨论】:

        【解决方案5】:

        我刚刚发现 this bug 在 PHP 中通过调用 unserialize 创建数组时有时会导致无法访问数组元素。

        创建一个包含(或从命令行运行)以下脚本的测试 PHP 文件:

        <?php 
        
        $a = unserialize('a:2:{s:2:"10";i:1;s:2:"01";i:2;}'); 
        
        print $a['10']."\n";
        
        $a['10'] = 3; 
        $a['01'] = 4; 
        
        print_r($a);
        
        foreach ($a as $k => $v) 
        { 
          print 'KEY: '; 
          var_dump($k); 
          print 'VAL: '; 
          var_dump($v); 
          print "\n"; 
        }
        

        如果您遇到错误,您的 PHP 版本中存在此错误,我建议升级到 PHP 5.3

        【讨论】:

        • 我使用 php 5.6 遇到了同样的问题
        【解决方案6】:

        请参阅PHP Manual 中有关将对象转换为数组的部分:

        键是成员变量名称,有几个值得注意的例外:整数属性不可访问;私有变量在变量名前面加上类名;受保护的变量在变量名前有一个“*”。

        在 PHP 中从对象转换为数组时,整数数组键在内部存储为字符串。当您在 PHP 中访问数组元素或正常使用数组时,包含有效整数的键将自动转换为整数。内部存储为字符串的整数是不可访问的键。

        注意区别:

        $x = (array)json_decode('{"207":"test"}');
        var_dump(key($x));  // string(3) "207"
        
        var_dump($x);
        // array(1) {
        //   ["207"]=>
        //   string(4) "test"
        // }
        
        
        $y['207'] = 'test';
        var_dump(key($y));  // int(207)
        
        var_dump($y);
        // array(1) {
        //   [207]=>
        //   string(4) "test"
        // }
        

        这两个数组上的print_r 提供相同的输出,但使用var_dump 您可以看到差异。

        这里有一些代码可以重现您的确切问题:

        $output = (array)json_decode('{"207":"sdf","210":"sdf"}');
        
        print_r($output);
        echo $output[207];
        echo $output["207"];
        

        简单的解决方法是将true 传递给json_decode 作为可选的assoc 参数,以指定您想要一个数组而不是对象:

        $output = json_decode('{"207":"sdf","210":"sdf"}', true);
        
        print_r($output);
        echo $output[207];
        echo $output["207"];
        

        【讨论】:

        • 原始数组是从 JSON POST 解码的。但是我遇到问题的数组是 array_diff_key 调用的结果。
        • @KevinRave 是的,因为调用的输入数组有同样的问题。尝试在您作为第一个参数传递给array_diff_key 的任何数组中访问$arr[207],您将看到完全相同的问题。您需要解决问题的根源,即在某些时候使用以下方式将对象转换为数组:$array = (array)$obj;
        • 我尝试更改原始数组。并尝试了其他一些事情。没有任何效果。我最终通过 foreach 循环获得了键/值。但这似乎是一个错误。 :-)
        • @KevinRave 你能确认你的原始阵列有同样的问题吗?
        • @KevinRave:$first = (array)json_decode('{"207":"sdf","210":"sdf"}',true); $output = array_diff($first, array());print_r($output);echo $output[207];echo $output["207"];array_diff 不是问题,解决方案仍然有效。尝试删除之前代码中的 true 你有你的错误。
        【解决方案7】:

        你是如何打印数组的?我建议print_r($arrayName);

        接下来,您可以打印单个元素,例如:echo $arrayName[0];

        【讨论】:

        • 如您所见,我使用了print_r。并且通过 [0] 访问它不是一种选择。
        猜你喜欢
        • 1970-01-01
        • 2020-05-17
        • 1970-01-01
        • 2012-08-25
        • 1970-01-01
        • 2018-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多