【问题标题】:Accessing the properties of an object of an object dynamically in PHP在 PHP 中动态访问对象的对象的属性
【发布时间】:2018-06-12 12:18:03
【问题描述】:

鉴于我根据查询的 API 获得不同的对象结果,这里是我必须实现的 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个不同的API吗?如果是这样创建一个接口

标签: php object properties


【解决方案1】:

首先,将所有对象转换为 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)
*/

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

【讨论】:

    【解决方案2】:

    您可以将您的对象转换为数组并构建一个需要维护的大型映射数组,然后将其分解并循环访问其他数组;或者您可以尝试使用模式。我在想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;
    

    【讨论】:

      猜你喜欢
      • 2011-08-10
      • 2017-07-05
      • 2014-10-10
      • 2011-03-09
      • 2013-07-21
      • 1970-01-01
      • 2023-03-23
      • 2019-09-01
      • 1970-01-01
      相关资源
      最近更新 更多