访问存在的数组元素时未定义的偏移量


Undefined offset while accessing array element which exists

我有一个数组和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
)

针对评论:

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

   string(3) "207"

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

   bool(false)

请参阅PHP手册中有关将对象转换为数组的这一部分:

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

在 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"];

简单的解决方法是为可选的 assoc 参数传入true to json_decode,以指定您想要数组而不是对象:

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

强制转换为array具有有效整数的字符串键的对象时出现问题。

如果您有此对象:

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"]这样的直接访问将始终转换为 $array[207] ,这不存在。

由于您从json_decode()应用于字符串中获取了类似上面的对象

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

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

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

与现有数据结构相比,此数据结构具有以下几个优点:

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

如果需要属性→对象映射,可以快速获取,例如,如下所示:

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 的建议进行操作:通过将第二个参数设置为 true 来强制json_decode()输出关联数组而不是对象:

$map = json_decode($json, true);

对于您的输入数据,这将直接生成

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

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

不过,我会考虑更改 JSON 数据结构是一个更干净的解决方案,尽管我知道这样做可能是不可能的。

我刚刚发现了这个错误,当通过调用反序列化创建数组时,它会导致数组元素有时在 PHP 中无法访问。

创建一个包含(或从命令行运行)以下脚本的测试 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

试试

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

以了解有关正在发生的事情的更多信息。

究竟是什么行/语句在向您发出警告?

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

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

尝试使用我的方法:

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

只需将 error_reporting(0); 放入 you 方法或文件开头。它将解决您的问题。