在PHP中动态访问对象的对象属性

时间:2018-01-02 19:48:40

标签: php object properties

鉴于我根据API I查询得到不同的对象结果,以下是我必须实现的35个例子中的两个:

stdClass Object
(
    [mid] => 7127.75
    [bid] => 7126.6
    [ask] => 7128.9
    [last_price] => 7128.8
    [low] => 7000.0
    [high] => 7492.1
    [volume] => 53255.4195502
    [timestamp] => 1510265647.9803913
)


stdClass Object
(
    [Success] => 1
    [Message] =>
    [Data] => stdClass Object
        (
            [AskPrice] => 7095
            [BidPrice] => 7070
            [Low] => 7001
            [High] => 7540
            [Volume] => 17.38943459
            [LastPrice] => 7090
            [Change] => -1.02
            [Open] => 7163
            [Close] => 7090
        )

    [Error] =>
)

我想构建映射变量数组以轻松访问对象。

$xmap["a"]["bid"] = "bid";
$xmap["b"]["bid"] = "Data->BidPrice";

假设$ content有第一个示例对象,这将起作用:

print $content->{$xmap["a"]["bid"]};  // the result is 7128.9

对于第二个示例对象,它不会:

print $content->{$xmap["b"]["bid"]};  // the result is PHP Notice:  Undefined property: stdClass::$Data->BidPrice in ...

可以这样做,还是我坚持使用if语句!

2 个答案:

答案 0 :(得分:0)

首先,将所有对象转换为assoc。数组使用json_encode / decode。您可以在stackoverflow中多次找到此代码

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

其次,我建议使用关键路径的点符号,加上一个微小的函数来查找多维数组中的值。 例如:

function fromArray($key, $arr) {
    $keys = explode('.', $key);
    foreach($keys as $k) { 
        if (!isset($arr[$k]))
            return array(); // return empty array
        $arr = $arr[$k];
    }
    return $arr; // can be a scalar value or array
}

$key = 'my.super.array.content';
$array = ['my' => [
            'super' => [
                'array' =>[
                    'content'=>4711
                    ]
                ]
            ]
        ];

var_dump($array, fromArray($key, $array));  
/*
array(1) {
  ["my"]=>
  array(1) {
    ["super"]=>
    array(1) {
      ["array"]=>
      array(1) {
        ["content"]=>
        int(4711)
      }
    }
  }
}
int(4711)
*/

我发现点符号在处理复杂结构时非常有用。

答案 1 :(得分:0)

您可以将对象转换为数组并构建一个需要维护的大型映射数组,然后将其展开并循环遍历它以访问其他数组;或者您可以尝试使用模式。我在想Adapter,但也许另一个更适合。这是以第二个对象为例,但只需添加所需数量:

class ContentAdapter {

    public function __get($name) {
        return $this->obj->{$xmap[$name]};
    }
}    

class ContentAdapter_API_B extends ContentAdapter {

    public $xmap = ['bid' => 'BidPrice', 'ask' => 'AskPrice'];

    public function __construct($obj) {
        $this->obj = $obj->data;
    }
}

现在无论对象如何都是一致的,因为每个对象都有一个适配器:

$content = new ContentAdapter_API_B($content);
echo $content->bid;

使用您的第一个对象,您也可以创建一个子项(ContentAdapter_API_A以防结构发生变化)或直接实例化:

$content = new ContentAdapter($content);
echo $content->bid;

或者显然只是按原样使用它:

echo $content->bid;

没有继承的另一种方法是使用getter:

class ContentAdapter_API_B {

    public function __construct($obj) {
        $this->obj = $obj->data;
    }

    public function getBid() { return $this->obj->BidPrice; }
}

只要方法一致,那么它将始终有效:

$content = new ContentAdapter_API_B($content);
echo $content->getBid;