douyue5856 2019-04-21 19:44
浏览 94
已采纳

使用节点的字符串表示形式访问stdClass对象上的嵌套属性

Given a variable that holds this string:

$property = 'parent->requestdata->inputs->firstname';

And an object:

$obj->parent->requestdata->inputs->firstname = 'Travis';

How do I access the value 'Travis' using the string? I tried this:

$obj->{$property}

But it looks for a property called 'parent->requestdata->inputs->firstname' not the property located at $obj->parent->requestdtaa->inputs->firstname`

I've tried various types of concatenation, use of var_export(), and others. I can explode it into an array and then loop the array like in this question.

But the variable '$property' can hold a value that goes 16 levels deep. And, the data I'm parsing can have hundreds of properties I need to import, so looping through and returning the value at each iteration until I get to level 16 X 100 items seems really inefficient; especially given that I know the actual location of the property at the start.

How do I get the value 'Travis' given (stdClass)$obj and (string)$property?

  • 写回答

2条回答 默认 最新

  • dragon201401 2019-04-21 23:05
    关注

    My initial searches didn't yield many results, however, after thinking up a broader range of search terms I found other questions on SO that addressed similar problems. I've come up with three solutions. All will work, but not all will work for everyone.

    Solution 1 - Looping

    Using an approach similar to the question referenced in my original question or the loop proposed by @miken32 will work.

    Solution 2 - anonymous function

    The string can be exploded into an array. The array can then be parsed using array_reduce() to produce the result. In my case, the working code (with a check for incorrect/non-existent property names/spellings) was this (PHP 7+):

    //create object - this comes from and external API in my case, but I'll include it here 
    //so that others can copy and paste for testing purposes
    
    $obj = (object)[
        'parent' => (object)[
            'requestdata' => (object)[
                'inputs' => (object)[
                    'firstname' => 'Travis'
                 ]
             ]
        ]
    ];
    
    //string representing the property we want to get on the object
    
    $property = 'parent->requestdata->inputs->firstname';
    
    $name = array_reduce(explode('->', $property), function ($previous, $current) {
        return is_numeric($current) ? ($previous[$current] ?? null) : ($previous->$current ?? null); }, $obj);
    
    var_dump($name); //outputs Travis
    
    

    see this question for potentially relevant information and the code I based my answer on.

    Solution 3 - symfony property access component

    In my case, it was easy to use composer to require this component. It allows access to properties on arrays and objects using simple strings. You can read about how to use it on the symfony website. The main benefit for me over the other options was the included error checking.

    My code ended up looking like this:

    //create object - this comes from and external API in my case, but I'll include it here 
    //so that others can copy and paste for testing purposes
    //don't forget to include the component at the top of your class
    //'use Symfony\Component\PropertyAccess\PropertyAccess;'
    
    $obj = (object)[
        'parent' => (object)[
            'requestdata' => (object)[
                'inputs' => (object)[
                    'firstname' => 'Travis'
                 ]
             ]
        ]
    ];
    
    //string representing the property we want to get on the object
    //NOTE: syfony uses dot notation. I could not get standard '->' object notation to work.
    
    $property = 'parent.requestdata.inputs.firstname';
    
    //create symfony property access factory
    
    $propertyAccessor = PropertyAccess::createPropertyAccessor();
    
    //get the desired value
    
    $name = $propertyAccessor->getValue($obj, $property);
    
    var_dump($name); //outputs 'Travis'
    

    All three options will work. Choose the one that works for you.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 运筹学排序问题中的在线排序
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥30 求一段fortran代码用IVF编译运行的结果
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥30 python代码,帮调试,帮帮忙吧
  • ¥15 #MATLAB仿真#车辆换道路径规划