如何使用整数等名称访问对象属性?

时间:2012-04-26 12:04:19

标签: php object properties

如何访问输出为的

的PHP对象属性
[highlighting] => stdClass Object
        (
            [448364] => stdClass Object
                (
                    [Data] => Array
                        (
                            [0] => Tax amount liability is ....... 

我想访问键[0]中的字符串值。我想做点什么:

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

但这两个数字/整数似乎有问题。

编辑:

我将在这里给出一些历史,从哪里获得myVar。我正在使用json_decode()之类的东西:

$myVar = json_decode(url)

7 个答案:

答案 0 :(得分:272)

已针对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 的“核”缺点,另外的缺点是,如果对象中有任何字符串,那么必须编码UTF-8(这是json_encode的要求)。

答案 1 :(得分:9)

只是想加入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 ......

答案 2 :(得分:1)

我从网上复制了这个功能。如果它按原样工作(“将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

答案 3 :(得分:1)

Jon的全面答案的最终替代方案:

只需使用json_decode(),第二个参数设置为 true

$array = json_decode($url, true);

然后返回一个关联数组而不是一个对象,因此在事后不需要转换。

这可能不适合每个应用程序,但它确实帮助我轻松引用了oroginal对象的属性。

在本教程中找到了解决方案 - http://nitschinger.at/Handling-JSON-like-a-boss-in-PHP/

此致

答案 4 :(得分:1)

  

对于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

答案 5 :(得分:0)

我担心你不能以数字开头命名对象。用字母重命名第一个“448364”。

第二个是一个数组,用括号访问这些数组:

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

代替

答案 6 :(得分:0)

如果对象以@开头,则为:

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']无效。