php 如何访问名称为整型或无效属性名的对象属性?

pbossiut  于 2023-04-19  发布在  PHP
关注(0)|答案(7)|浏览(93)

我使用json_decode(),类似于:

$myVar = json_decode($data)

这会给我这样的输出:

[highlighting] => stdClass Object
        (
            [448364] => stdClass Object
                (
                    [Data] => Array
                        (
                            [0] => Tax amount liability is .......

我想访问key [0]中的字符串值。当我尝试执行以下操作时:

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

我得到这个错误:
解析错误:语法错误,意外的T_DNUMBER
这两个数字/整数似乎是问题所在。

okxuctiv

okxuctiv1#

PHP 7.2更新

PHP 7.2引入了对converting numeric keys in object and array casts的行为更改,修复了这种特殊的不一致性,并使以下所有示例都能按预期运行。
又少了一件让人困惑的事!

原始答案(适用于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!

Live example

**事实#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?

Live example
很直观,你不觉得吗?

你能做什么

选项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的要求)。

dkqlctbz

dkqlctbz2#

我只是想在Jon雄辩的解释中添加失败的原因。这都是因为当创建数组时,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...

ovfsdjhp

ovfsdjhp3#

  • 适用于PHP 7*

访问以数字作为属性名称的对象属性。
在将数组强制转换为对象后,通常需要使用该函数。

$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
ygya80vv

ygya80vv4#

最后一个替代乔恩的全面答案:
只需使用 json_decode(),第二个参数设置为true

$array = json_decode($url, true);

这将返回一个关联数组而不是一个对象,因此不需要在事后进行转换。
这可能并不适用于每个应用程序,但它确实帮助我轻松地引用了原始对象的属性。
在教程 Handling JSON like a boss in PHP 中找到了解决方案。

kcwpcxri

kcwpcxri5#

如果一个对象以@开头,如下所示:

SimpleXMLElement Object (
    [@attributes] => Array (
        [href] => qwertyuiop.html
        [id] => html21
        [media-type] => application/xhtml+xml
    )
)

您必须用途:

print_r($parent_object->attributes());

因为$parent_object->{'@attributes'}$parent_object['@attributes']不起作用。

pobjuy32

pobjuy326#

我从网上复制了这个函数。如果它像它说的那样工作(“将stdClass对象转换为多维数组的函数”),请尝试以下操作:

<?php

    function objectToArray($d) {
        if (is_object($d)) {
            // Gets the properties of the given object
            // with get_object_vars function
            $d = get_object_vars($d);
        }

        if (is_array($d)) {
            /*
            * Return array converted to object
            * Using __FUNCTION__ (Magic constant)
            * for recursive call
            */
            return array_map(__FUNCTION__, $d);
        }
        else {
            // Return array
            return $d;
        }
    }

?>
  • 首先将数组传递给objectToArray函数
  • 然后取返回值
  • echo [highlighting][448364][Data][0]

来源:PHP stdClass to Array and Array to stdClass

q3aa0525

q3aa05257#

恐怕你不允许以数字开头命名对象。请将第一个以字母开头的对象重命名为“448364”。
第二个是一个数组,它们可以通过括号访问,如下所示:

print myVar->highlighting->test_448364->Data[0]

反而

相关问题