简体   繁体   English

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

[英]Accessing nested property on stdClass Object with string representation of the node

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?如何使用字符串访问值“Travis”? 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`但它寻找一个名为 'parent->requestdata->inputs->firstname' 的属性,而不是位于 $obj->parent->requestdtaa->inputs->firstname` 的属性

I've tried various types of concatenation, use of var_export(), and others.我尝试了各种类型的连接、var_export() 的使用等。 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.但是变量 '$property' 可以保存一个深度为 16 级的值。 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;而且,我正在解析的数据可能有数百个我需要导入的属性,因此在每次迭代中循环并返回值,直到达到 16 X 100 个项目的级别似乎非常低效; 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 ?如何获得给定(stdClass)$obj(string)$property的值'Travis'

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.我最初的搜索并没有产生很多结果,但是,在考虑了更广泛的搜索词之后,我在 SO 上发现了其他解决类似问题的问题。 I've come up with three solutions.我想出了三个解决方案。 All will work, but not all will work for everyone.一切都会奏效,但并非所有人都适用。

Solution 1 - Looping解决方案 1 - 循环

Using an approach similar to the question referenced in my original question or the loop proposed by @miken32 will work.使用类似于我的原始问题中引用的问题的方法或@miken32 提出的循环将起作用。

Solution 2 - anonymous function解决方案 2 - 匿名函数

The string can be exploded into an array.字符串可以分解为数组。 The array can then be parsed using array_reduce() to produce the result.然后可以使用 array_reduce() 解析数组以产生结果。 In my case, the working code (with a check for incorrect/non-existent property names/spellings) was this (PHP 7+):就我而言,工作代码(检查不正确/不存在的属性名称/拼写)是这样的(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解决方案 3 - symfony 属性访问组件

In my case, it was easy to use composer to require this component.就我而言,使用 composer 来要求这个组件很容易。 It allows access to properties on arrays and objects using simple strings.它允许使用简单的字符串访问数组和对象的属性。 You canread about how to use it on the symfony website.您可以在 symfony 网站上阅读有关如何使用它的信息。 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.选择适合您的那一种。

You're right that you'll have to do a loop iteration for each nested object, but you don't need to loop through "hundreds of properties" for each of them, you just access the one you're looking for:你是对的,你必须对每个嵌套对象进行循环迭代,但你不需要为每个对象循环遍历“数百个属性”,你只需访问你正在寻找的一个:

$obj = (object)[
    'parent' => (object)[
        'requestdata' => (object)[
            'inputs' => (object)[
                'firstname' => 'Travis'
             ]
         ]
    ]
];
$property = "parent->requestdata->inputs->firstname";
$props = explode("->", $property);
while ($props && $obj !== null) {
    $prop = array_shift($props);
    $obj = $obj->$prop ?? null;
}
var_dump($obj);

Totally untested but seems like it should work and be fairly performant.完全未经测试,但似乎它应该可以工作并且具有相当的性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM