针对 PHP 7.2 更新
PHP 7.2 引入了一个行为更改,用于在对象和数组转换中转换数字键,从而修复了这种特殊的不一致,并使以下所有示例的行为都按预期进行。
少了一件令人困惑的事情!
原始答案(适用于 7.2.0 之前的版本)
PHP有它黑暗的小巷,你真的不想发现自己在里面。名称为数字的对象属性就是其中之一...
他们从未告诉你什么
事实#1:您无法轻松访问名称不是合法变量名称的属性
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->123foo; // error
事实#2:您可以使用大括号语法访问此类属性
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!
事实#3:但如果属性名称都是数字,则不会!
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!
echo $o->{'123'}; // error!
活生生的例子。
事实#4:好吧,除非对象一开始就不是来自数组。
$a = array('123' => '123');
$o1 = (object)$a;
$o2 = new stdClass;
$o2->{'123'} = '123'; // setting property is OK
echo $o1->{'123'}; // error!
echo $o2->{'123'}; // works... WTF?
活生生的例子。
很直观,你不同意吗?
您可以做什么
选项#1:手动操作
最实用的方法是简单地将您感兴趣的对象转换回数组中,这将允许您访问属性:
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
$a = (array)$o;
echo $o->{'123'}; // error!
echo $a['123']; // OK!
不幸的是,这不能递归地工作。因此,在您的情况下,您需要执行以下操作:
$highlighting = (array)$myVar->highlighting;
$data = (array)$highlighting['448364']->Data;
$value = $data['0']; // at last!
选项#2:核选项
另一种方法是编写一个函数,以递归方式将对象转换为数组:
function recursive_cast_to_array($o) {
$a = (array)$o;
foreach ($a as &$value) {
if (is_object($value)) {
$value = recursive_cast_to_array($value);
}
}
return $a;
}
$arr = recursive_cast_to_array($myVar);
$value = $arr['highlighting']['448364']['Data']['0'];
但是,我不相信这是一个更好的选择,因为它会不必要地将你不感兴趣的所有属性以及你现在的属性都强制转换为数组。
选项#3:聪明地玩
上述选项的替代方法是使用内置的 JSON 函数:
$arr = json_decode(json_encode($myVar), true);
$value = $arr['highlighting']['448364']['Data']['0'];
JSON 函数有助于执行到数组的递归转换,而无需定义任何外部函数。无论这种外观多么理想,它都有选项#2的“nuke”缺点,另外还有一个缺点,即如果对象内有任何字符串,这些字符串必须以UTF-8编码(这是json_encode
的要求)。