【问题标题】:PHP: how to resolve a dynamic property of an object that is multiple levels deepPHP:如何解析多层次深度的对象的动态属性
【发布时间】:2014-12-02 13:19:58
【问题描述】:

我已经编写了一个辅助函数来“清理”回调变量以输入 MySQL。这是我写的函数:

public function string($object, $objectPath) {
    if (!empty($object->$objectPath) || $object->$objectPath !== '') {
        $value = $object->$objectPath;
    } else {
        return 'NULL';
    }
    if (!empty($value) || $value != '') {
        return "'".str_replace("'","''",$value)."'";
    } else {
        return 'NULL';
    }
}

现在,$object 始终是调用返回的对象,$objectPath 始终是指向给定值的字符串。这就是问题所在。这很有效:

$value = $this->db->string($object, 'foo');

但是,这不起作用:

$value = $this->db->string($object, 'foo->bar->foo1->bar1');

每当$objectPath 的深度超过“一层”时,我就会从(亚马逊的)客户端库中收到以下错误:

Fatal error:  Call to undefined method MarketplaceWebServiceOrders_Model_Order::getFoo->Bar() in /path/to/Model.php on line 63

错误所指的代码块是这样的:

public function __get($propertyName)
    {
       $getter = "get$propertyName"; 
       return $this->$getter(); // this is line 63
    }

$object 不是 XML,所以我不能使用 SimpleXMLElementXPath

我的代码有什么问题?我是在连接一个对象和一个字符串吗?如果是这样,我怎样才能做到这一点?我怎样才能让这个函数完成我想要做的事情?

顺便说一下,我使用的是 PHP 5.4.27。

【问题讨论】:

    标签: php mysql string object amazon-web-services


    【解决方案1】:

    PHP 不会像您尝试的那样自动将包含多个路径级别的字符串解析为对象的子对象。

    即使$obj 包含您期望的子层次结构,这不会起作用:

    $obj = ...;  
    $path = 'level1->level2->level3';
    echo $obj->$path;    // WRONG!
    

    您需要拆分路径并“遍历”对象以尝试解析最终属性。 这是基于您的示例:

    <?php
    $obj = new stdClass();
    $obj->name = 'Fred';
    $obj->job = new stdClass();
    $obj->job->position = 'Janitor';
    $obj->job->years = 4;
    print_r($obj);
    
    echo 'Years in current job: '.string($obj, 'job->years').PHP_EOL;
    
    
    function string($obj, $path_str)
    {
        $val = null;
    
        $path = preg_split('/->/', $path_str);
        $node = $obj;
        while (($prop = array_shift($path)) !== null) {
            if (!is_object($obj) || !property_exists($node, $prop)) {
                $val = null;
                break;
    
            }
            $val = $node->$prop;
            // TODO: Insert any logic here for cleaning up $val
    
            $node = $node->$prop;
        }
    
        return $val;
    }
    

    它正在运行:http://3v4l.org/9L4gc

    【讨论】:

    • 您好,抱歉,它不适合您。正如您从我提供的链接中看到的那样,它适用于标准对象。您可以尝试将!property_exists($node, $prop) 更改为isset($node-&gt;$prop)
    【解决方案2】:

    在@itsmejodie 的帮助下,我终于找到了一个可行的解决方案:

    public function string($node, $objectPath) {
        $value = NULL;
        $path = explode('->', $objectPath);
        while (($prop = array_shift($path)) !== NULL) {
            if (!$node->$prop) {
                break;
            }
            $value = $node->$prop;
            $node = $node->$prop;
        }
        if (is_string($value)) {
            return "'".str_replace("'","''",$value)."'";
        } else {
            return 'NULL';
        }
    }
    

    对我来说,关键是看到,正如@itsmejodie 所说,“PHP 不会自动将包含多个路径级别的字符串解析为对象的子级。”在像'foo-&gt;bar-&gt;foo1-&gt;bar2' 这样的字符串中,PHP 不会将-&gt; 转换为T_OBJECT_OPERATOR,因此将字符串附加到对象(例如$object-&gt;foo-&gt;bar-&gt;foo1-&gt;bar2)将不起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-06
      • 2013-12-17
      • 1970-01-01
      • 2023-03-23
      • 2015-04-25
      • 1970-01-01
      • 2021-11-23
      • 1970-01-01
      相关资源
      最近更新 更多