如何访问具有整数或无效属性名称的对象属性?

15 浏览
0 Comments

如何访问具有整数或无效属性名称的对象属性?

我正在使用json_decode(),类似于:\n

$myVar = json_decode($data)

\n这会给我输出如下:\n

[highlighting] => stdClass Object
        (
            [448364] => stdClass Object
                (
                    [Data] => Array
                        (
                            [0] => 税额责任是.......

\n我想访问键[0]中的字符串值。当我尝试像这样做时:\n

print $myVar->highlighting->448364->Data->0;

\n我得到了这个错误:\n

\n解析错误:语法错误,意外的T_DNUMBER\n

\n那两个数字似乎是问题所在。

0
0 Comments

在PHP 7中,如果对象属性的名称是数字,访问该属性会出现问题。这通常发生在将数组转换为对象后。

解决这个问题的方法是使用花括号语法来访问属性。例如,可以使用$o->{1}来访问属性值。下面是一个示例代码:

$arr = [2,3,7];
$o = (object) $arr;
$t = "1";
$t2 = 1;
$t3 = (1);
echo $o->{1};     // 3
echo $o->{'1'};   // 3
echo $o->$t;      // 3
echo $o->$t2;     // 3
echo $o->$t3;     // 3
echo $o->1;       // Error
echo $o->(1);     // Error

通过使用花括号语法,可以成功访问属性值。但是,如果直接使用$o->1或$o->(1)来访问属性,将会出现错误。因此,为了避免出现错误,应该始终使用花括号语法来访问属性。

0
0 Comments

PHP在创建数组时,会将键转换为整数,如果可能的话,这会导致将数组转换为对象后查找问题,因为数字键被保留下来。这是有问题的,因为所有的属性访问选项都期望或转换为字符串。可以通过以下方式确认这一点:

$arr = array('123' => 'abc');

$obj = (object) $arr;

$obj->{'123'} = 'abc';

print_r($obj);

输出结果为:

stdClass Object (

[123] => 'abc',

[123] => 'abc'

)

因此,对象有两个属性键,一个是数字键(无法访问),一个是基于字符串的键。这就是为什么Jon的解决方案(Fact 4)有效的原因,因为使用花括号设置属性意味着您始终定义一个基于字符串的键,而不是数字。

借鉴Jon的解决方案,但是将其扭转过来,可以通过以下方式生成一个始终具有基于字符串的键的对象:

$obj = json_decode(json_encode($arr));

从现在开始,您可以使用以下任一方式访问,因为以这种方式访问总是将花括号内的值转换为字符串:

$obj->{123};

$obj->{'123'};

这就是PHP的不合理之处...

解决方法就是使用json_encode和json_decode进行对象和数组之间的转换,以避免出现无法访问属性的问题。

0
0 Comments

PHP 7.2引入了一个行为变化,用于转换对象和数组转换中的数字键,修复了这个特定的不一致性,并使所有以下示例都能按预期运行。一个让人困惑的事情少了!

PHP中的对象属性名称为数字是其中之一...以下是问题的原因和解决方法。

事实1:您无法轻松访问名称不是合法变量名称的属性

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->123foo; // 错误

事实2:您可以使用花括号语法访问此类属性

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // 正确!

事实3:但是,如果属性名称全是数字,就不可以使用花括号语法访问

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // 正确!
echo $o->{'123'}; // 错误!

事实4:好吧,除非对象一开始就不是来自数组。

$a = array('123' => '123');
$o1 = (object)$a;
$o2 = new stdClass;
$o2->{'123'} = '123'; // 设置属性是可以的
echo $o1->{'123'}; // 错误!
echo $o2->{'123'}; // 可以... 什么鬼?

以上是原始回答,适用于早于7.2.0版本的PHP。

解决方法:

选择1:手动操作

最实用的方法是将您感兴趣的对象重新转换为数组,以便访问属性:

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
$a = (array)$o;
echo $o->{'123'}; // 错误!
echo $a['123']; // 正确!

不幸的是,这不会递归地工作。因此,在您的情况下,您需要执行类似以下的操作:

$highlighting = (array)$myVar->highlighting;
$data = (array)$highlighting['448364']->Data;
$value = $data['0']; // 最终获得结果!

选择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的“核弹”缺点,并且还有一个缺点,即如果对象中有任何字符串,那些字符串必须以UTF-8编码(这是 `json_encode` 的要求)。

选项3的另一种替代方法是不需要UTF-8的$o = unserialize('O:8:"StdClass"' . substr(serialize($a),1));

总之,尽管这种行为在某些情况下可能有些可疑,但它在某些情况下完全有意义。无论如何,在手册中有记录,工作方式如此,我们个人的意见并不重要。

关于选项3是否存在另一种访问这些数字的方法,手册中指出:“除非迭代”,否则无法访问具有数字键的属性。

0