如何在php中访问名为变量(点表示法)的深层对象属性?

如何在php中访问名为变量(点表示法)的深层对象属性?,php,properties,Php,Properties,有许多问题与此类似,但这有点不同,因为它涉及深度对象属性访问,而不仅仅是一个深度级别 假设我有一个包含字符串foo.bar的变量。 我想通过使用$variable响应$user->foo->bar: 这是我迄今为止尝试过的,但没有成功(它说空): 做这件事没有简单的方法 幸运的是,很多人都想这样做,所以有一些库支持它,比如Symfony的PropertyAccessor: 使用变量属性表示法($o->$p)简化对象路径非常容易: 这可以很容易地转化为一个小的帮助函数。我将此作为对一个答案(

有许多问题与此类似,但这有点不同,因为它涉及深度对象属性访问,而不仅仅是一个深度级别

假设我有一个包含字符串
foo.bar
的变量。

我想通过使用
$variable
响应
$user->foo->bar

这是我迄今为止尝试过的,但没有成功(它说空):


做这件事没有简单的方法

幸运的是,很多人都想这样做,所以有一些库支持它,比如Symfony的PropertyAccessor:

使用变量属性表示法(
$o->$p
)简化对象路径非常容易:


这可以很容易地转化为一个小的帮助函数。

我将此作为对一个答案()的补充,该答案对数组也有同样的作用

通过
explode()
(或添加到函数)创建
$path
数组,然后使用引用

$path = explode('.', $variable);
吸气剂 当然,不推荐使用邪恶的
eval()

$value = str_replace('.', '->', $variable);
eval("echo \$user->$value;");

对@deceze post进行了一些改进

这允许处理需要遍历阵列的情况

$path = 'foo.bar.songs.0.title';
echo array_reduce(explode('.', $path), function ($o, $p) { return is_numeric($p) ? $o[$p] : $o->$p; }, $user);
编辑:

如果您有PHP7+,那么如果属性的名称输入错误或者不存在,那么下面的代码将安全地返回null

$path = 'foo.bar.songs.0FOOBAR.title';
echo array_reduce(explode('.', $path), function ($o, $p) { return is_numeric($p) ? ($o[$p] ?? null) : ($o->$p ?? null); }, $user);
您可以使用“使用编写器”:

composer require machitgarha/json
例如:

$userJson = new MAChitgarha\Component\JSON(new User());

$userJson->set("foo", new Foo());
$userJson->set("foo.bar", "Hello World");

$userJson->get("foo.bar"); // Hello World 

我编写了一个递归算法来查找所有的值​​财产的所有权

    public function findAttributeFromJson($json,$attributeFind,$assignAttribute)
{
    if(!is_array($json)) return $assignAttribute;

    $properties = array_keys($json);

    foreach ($properties as $value) {
        if($value === $attributeFind)
        {
            $assignAttribute[count($assignAttribute)] = $json[$value];
        }
        $assignAttribute = $this->findAttributeFromJson($json[$value],$attributeFind,$assignAttribute);
    }
    return $assignAttribute;
}
并使用它

        $arrResult = array();
        $arrResult = $this->findAttributeFromJson($arrFind,$properties,$arrResult );

仅供参考,
$user->{$value}
试图访问
$user
上名为“foo->bar”的属性(不,不是属性“foo”上的属性“bar”,而是名为“foo->bar”的属性)。因此
$user->{$value}
意味着
$user->{foo->bar}
是的。不管变量包含什么,
$o->$p
(有或没有
{}
)都意味着您正在访问
$o
上的一个直接属性,而不是嵌套链。为什么会被否决?“这是解决这个问题的一个干净的办法。”马夫说,因为这个办法很简单,而且不涉及使用整个系统framework@Vir它不是一个框架,只是一个库。该库解决了大量使用简单解决方案时会遇到的bug和问题。几乎Symfony的每一个组件都是独立工作的,并且肯定比您在这里找到的任何组件都工作得更好。@Erik对这些崩溃的保护仍然很简单。这里发布的只是针对目标用途的简单解决方案。还要注意的是,项目可能会使用不同的框架和其他东西——将它与Symfony混用只是为了简单的代码片段不是一个好办法。要证明使用整个第三方代码的合理性,这个问题并不复杂。如果“任何级别的结构都不存在”,那么这个代码应该崩溃,然后应该捕获并处理该异常(可能需要在那里添加抛出)。FWIW,您可以轻松地调整my
array\u reduce
来处理数组(
返回$a[$k]
)。您甚至可以动态地判断您是在处理数组还是对象,并动态地使用
$o->$p
$a[$k]
。太棒了!谢谢
$path = 'foo.bar.songs.0FOOBAR.title';
echo array_reduce(explode('.', $path), function ($o, $p) { return is_numeric($p) ? ($o[$p] ?? null) : ($o->$p ?? null); }, $user);
composer require machitgarha/json
$userJson = new MAChitgarha\Component\JSON(new User());

$userJson->set("foo", new Foo());
$userJson->set("foo.bar", "Hello World");

$userJson->get("foo.bar"); // Hello World 
    public function findAttributeFromJson($json,$attributeFind,$assignAttribute)
{
    if(!is_array($json)) return $assignAttribute;

    $properties = array_keys($json);

    foreach ($properties as $value) {
        if($value === $attributeFind)
        {
            $assignAttribute[count($assignAttribute)] = $json[$value];
        }
        $assignAttribute = $this->findAttributeFromJson($json[$value],$attributeFind,$assignAttribute);
    }
    return $assignAttribute;
}
        $arrResult = array();
        $arrResult = $this->findAttributeFromJson($arrFind,$properties,$arrResult );