动态访问嵌套对象
Posted
技术标签:
【中文标题】动态访问嵌套对象【英文标题】:Dynamically access nested object 【发布时间】:2011-10-25 14:52:12 【问题描述】:我正在构建一个地理编码类,它可以利用多种网络服务进行地理编码(即 Google、Yahoo、Bing 等)。我正在尝试以一种可以轻松配置新 Web 服务的方式来实现它。大多数 Web 服务返回 XML/JSON.. 对于 php,我选择 XML 作为我的主要关注点。所有代码都已经到位,但现在 Google 例如返回以下 XML(转换为 simple_xml_element)
SimpleXMLElement Object
(
[status] => OK
[result] => Array
(
[0] => SimpleXMLElement Object
(
[type] => postal_code
[formatted_address] => 1010 Lausanne, Switzerland
[address_component] => Array
(
[0] => SimpleXMLElement Object
(
[long_name] => 1010
[short_name] => 1010
[type] => postal_code
)
[1] => SimpleXMLElement Object
(
[long_name] => Lausanne
[short_name] => Lausanne
[type] => Array
(
[0] => locality
[1] => political
)
)
[2] => SimpleXMLElement Object
(
[long_name] => Vaud
[short_name] => VD
[type] => Array
(
[0] => administrative_area_level_1
[1] => political
)
)
[3] => SimpleXMLElement Object
(
[long_name] => Switzerland
[short_name] => CH
[type] => Array
(
[0] => country
[1] => political
)
)
)
[geometry] => SimpleXMLElement Object
(
[location] => SimpleXMLElement Object
(
[lat] => 46.5376186
[lng] => 6.6539665
)
[location_type] => APPROXIMATE
[viewport] => SimpleXMLElement Object
(
[southwest] => SimpleXMLElement Object
(
[lat] => 46.5253574
[lng] => 6.6384420
)
[northeast] => SimpleXMLElement Object
(
[lat] => 46.5467887
[lng] => 6.6745222
)
)
[bounds] => SimpleXMLElement Object
(
[southwest] => SimpleXMLElement Object
(
[lat] => 46.5253574
[lng] => 6.6384420
)
[northeast] => SimpleXMLElement Object
(
[lat] => 46.5467887
[lng] => 6.6745222
)
)
)
)
)
我需要的信息在 [location] 标签中,所以我尝试将路径存储在 var 中:
$lat_path = 'result[0]->geometry->location->lat;
然后尝试以这种方式访问该值:
(suppose $xml is the object)
$xml->$lat_path;
但这不起作用。有什么方法可以动态或基于变量访问信息。我不想用 Google 特定的代码破坏我的地理编码方法。
谢谢!
【问题讨论】:
使用 SimpleXMLElement::xpath 代替 php 反对表示法。 (如果你能展示一些xml,我会尝试提供一个示例实现) 你可以为此编写方法然后忘记.. 我也尝试过使用 Xpath,但它不起作用:( print_r($xml->Xpath('geometry/location')); 给了我一个空数组。 【参考方案1】:当你这样做时
$xml->$lat_path;
PHP 将使用$lat_path
中的任何内容作为变量名。它不会进入对象图或完全服从T_OBJECT_OPERATOR
。它只会寻找一个属性
'result[0]->geometry->location->lat;'
在$xml
。尝试运行此代码作为示例:
$obj = new StdClass;
$obj->'result[0]->geometry->location->lat;' = 1;
print_r($obj);
会输出
stdClass Object
(
[result[0]->geometry->location->lat;] => 1
)
如您所见,它是一个单一属性,而不是嵌套对象图。
像 cmets 中建议的那样,要么使用 XPath,要么直接转到所需的值:
$xml->result[0]->geometry->location->lat;
【讨论】:
【参考方案2】:如果您无法使用 xPath 并且需要动态访问对象,您可以使用以下方法:
$oObj = new StdClass;
$oObj->Root->Parent->ID = 1;
$oObj->Root->Parent->Child->ID = 2;
$sSeachInTree = 'Root\\Parent\\Child\\ID';
$aElements = explode("\\",$sSeachInTree);
foreach($aElements as $sElement)
if (isset($oObj->$sElement))
if (end($aElements) == $sElement)
echo "Found: " . $sElement . " = " . $oObj->$sElement;
$oObj = $oObj->$sElement;
【讨论】:
【参考方案3】:我今天遇到了这个问题。这是我的解决方案。
<?php
/**
* Traverse an object by splitting the path in the argument
* Only returns values that are in nested objects not arrays
*/
function get_property_from_nested_objects(object $object, string $path, $default_fallback = null)
if (strpos($path, '->') !== false)
$path_properties = explode('->', $path);
else
return isset($object->$path) ? $object->$path : $default_fallback;
$nested_objects = [];
foreach ($path_properties as $nested_obj_index => $object_key)
if (isset($object->$object_key) && is_object($object->$object_key))
$nested_objects[$nested_obj_index] = $object->$object_key;
continue;
elseif (isset($nested_objects[$nested_obj_index - 1]->$object_key) && is_object($nested_objects[$nested_obj_index - 1]->$object_key))
$nested_objects[$nested_obj_index] = $nested_objects[$nested_obj_index - 1]->$object_key;
continue;
elseif (isset($nested_objects[$nested_obj_index - 1]->$object_key) && !is_object($nested_objects[$nested_obj_index - 1]->$object_key))
return $nested_objects[$nested_obj_index - 1]->$object_key;
else
return $default_fallback;
echo get_property_from_nested_objects((object)[
'obj1' => (object) [
'prop' => 'works'
]
], 'obj1->prop');
// output: 'works'
【讨论】:
以上是关于动态访问嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章
在 flash actionscript 2 中动态访问嵌套的影片剪辑
使用 Linq.Expression 访问具有动态 lambda 的嵌套属性