29

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

7 回答 7

25

请参阅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"];

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

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

print_r($output);
echo $output[207];
echo $output["207"];
于 2012-06-18T21:52:31.403 回答
22

转换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"
}

它具有只能通过循环访问它们的键,因为直接访问 like$array["207"]将始终转换$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 数据结构更改为更简洁的解决方案,尽管我知道这样做可能是不可能的。

于 2012-07-05T23:21:09.887 回答
1

我刚刚发现了这个错误,当通过调用unserialize创建数组时,有时在 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

于 2012-06-18T20:15:28.377 回答
1

尝试

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

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

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

于 2012-06-18T20:52:22.397 回答
0

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

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

于 2012-06-18T20:16:20.907 回答
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);
于 2012-07-06T12:20:07.337 回答
-2

Just put error_reporting(0); in you method or at start of file. It will solved your issue.

于 2017-01-26T05:21:51.500 回答