如何在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,您可以轻松地调整myarray\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 );