【问题标题】:casting stdClass to array - keys not accessible将 stdClass 转换为数组 - 无法访问键
【发布时间】:2016-12-25 15:10:02
【问题描述】:

当我做这样的事情时,我正在运行 PHP7.0.9:

$s = json_decode('{"1": "xxx"}');//decode json to stdClass
$a = (array)$s;//cast to array
die(var_dump($a, $a['1'], $a[1], count($a)));

我得到这个结果:

array (size=1)
  '1' => string 'xxx' (length=3) //<-- key 1 exists
null // $a['1'] yields null
null // $a[1] doesn't work either
int 1 // count shows there is 1 element in the array

我期待这个结果:

array (size=1)
  '1' => string 'xxx' (length=3)
string 'xxx' (length=3) // $a['1'] should work
null
int 1

我的问题:为什么我不能访问$a['1'],即使数组的countvar_dump 都告诉我这个密钥存在?这是 PHP 中的错误,还是某种功能?

【问题讨论】:

  • 我在 PHP 5 中得到了相同的结果。
  • @Rizier123 但他访问的是数组,而不是对象。
  • 对象属性必须以A-Za-zunderscore 开头,并且不应以数字或仅以数字开头!您的代码强制执行的任何行为都是未知的。
  • @JustOnUnderMillions 这不是真的。您可以拥有其他对象属性,您只需使用更复杂的语法来访问它们。
  • 保存在保存区。取消保存区域$r=new stdClass(); $r-&gt;²³='A'; print $r-&gt;²³;

标签: php json php-7 stdclass


【解决方案1】:

引用PHP documentation

数组到对象

如果将对象转换为对象,则不会对其进行修改。如果将任何其他类型的值转换为对象,则会创建 stdClass 内置类的新实例。如果值为 NULL,则新实例将为空。数组转换为具有由键和相应值命名的属性的对象,但数字键除外,除非迭代否则不可访问。

对象到数组

当反过来转换时,类似的问题/怪癖会出现:(documentation)

如果将对象转换为数组,则结果是一个数组,其元素是对象的属性。键是成员变量名,有几个值得注意的例外:整数属性不可访问;私有变量在变量名前面加上类名;受保护的变量在变量名前有一个“*”。这些前置值在两边都有空字节。这可能会导致一些意外行为:

基本上,具有数字属性的对象可以转换为数组,并且您可以对其进行迭代,但是键是不可访问的(直接)。这是一个众所周知的怪癖。您可以通过使用json_decode($string, true); 立即转换为数组来绕过它,使用辅助循环来“重建”数组:

$reconstructed = [];
foreach ((array) $obj as $k => $v) {
    $reconstructed[$k] = $v;
}

尚不清楚这是错误还是功能。当我第一次遇到这种行为时,我称它为错误。鉴于它已记录在案并且是一个已知的怪癖,我现在说两者都不是。这不是一个真正的错误,因为它是已知的、理解的和记录在案的,但它几乎不是一个功能。这只是大多数语言都有的那些杂乱的怪癖之一。

你必须解决它,忍受它,避免它,并处理它。鉴于 PHP 邮件列表上有很多关于此的错误报告,并且它已添加到文档中,因此它可能不太可能很快得到修复。

【讨论】:

  • 这是关于从数组转换为对象。他走的是另一条路。
  • @Barmar:也添加了对对象到数组转换文档的引用
  • 这是我在 PHP 中见过的最奇怪的怪癖之一。我了解私有和受保护属性周围的空值的动机,但无法想象使整数属性无法访问的原因。
  • @Barmar:我知道,这在任何可能的意义上都是荒谬的。我记得查看 zend 引擎代码,了解它是如何实现的,以及为什么它的行为方式如此。我无法完全弄清楚发生了什么,但我从来没有真正深入了解这一切
  • 所有我能想到的是它没有出于某种原因将密钥放入哈希映射中。所以它只能在顺序扫描数组时找到那些元素。
猜你喜欢
  • 1970-01-01
  • 2016-11-12
  • 2016-12-25
  • 2020-03-20
  • 2012-08-07
  • 2011-11-08
  • 2013-11-21
  • 1970-01-01
  • 2016-07-09
相关资源
最近更新 更多