2013-03-28 186 views
2
$obj = (object)array('a', 'b', 'c'); 
$refl = new \ReflectionObject($obj); 
$props = $refl->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED);  

foreach($props as $prop) 
    print $prop->name; 

打印一些奇怪的名称,如linefileline(而不是1,2,3)。为什么?我意识到名称是无效的,因为它们是数字,但为什么我会得到这些随机字符串?奇怪行为

get_object_vars($obj)说明不了什么,而实际上print_r((array)$obj)正确打印值。


如果反射无法显示数字属性,有什么办法可以让它忽略它们吗?


它也发生在许多SPL interators(如ArrayObject S,SplFixedArray S,SplHeap S)。显然,这种行为只存在于某些PHP 5.3版本中。 PHP 5.4没有任何显示。


Related PHP bug和我的作为在溶液(property_exists忽略无效名称):

if(version_compare(PHP_VERSION, '5.4') < 0){ 
    $props = array_filter($props, function($prop) use($obj){ 
    return !$prop->isPublic() || property_exists($obj, $prop->name); 
    }); 
} 
+0

什么ArrayObjects? – sectus 2013-03-28 01:33:17

回答

1

It's a won't fix bug... or strange php behavior。所以,如果你不确定数字键的话,你就不能使用对象类型转换。使用这样的事情

$obj = new \stdClass(); 
foreach($array as $key=>$value) 
    $obj->{$key} = $value; 

您可以使用从陌生PHP行为的另一使坏。获取所有属性而不反射。

$obj = (object) array('a', 'b', 'c'); 
$obj->{0}='asd'; 
while (list($field, $value) = each($obj)) 
    { 
    var_dump($field, $value); 
    } 

此外,我认为这个问题只发生在stdClass对象。

+0

它也出现在任何Iterator对象上,比如ArrayObject,SplFixedArray等:( – 2013-03-28 02:35:30

+0

@OneTrickPony,你能打印例子吗?我的诡计呢? – sectus 2013-03-28 02:45:29

+0

它似乎与我的(数组)解决方案一样工作。经过多次搜索后,我发现它是5.3中的一个[bug](https://bugs.php.net/bug.php?id=49154) – 2013-03-28 11:50:08

1

铸造的阵列的一个对象数组键入的属性名称,以及将值转换为它们的值。

你的数组有数字键。你的对象有数字属性。哪些是无效的。

你真的想:

$obj = (object) array('a'=> null, 'b' => null, 'c'=> null);

+0

数字字段名称是合法的。 '$ obj2 = new \ stdClass(); $ obj2 - > {'0'} ='a';' – sectus 2013-03-28 00:55:01

+0

不在PHP中。这是一个语法错误:'$ obj-> 2 =“yey”;'“语法错误,意想不到T_LNUMBER,期待T_STRING或T_VARIABLE或‘{’或‘$’” – Sven 2013-03-28 00:56:35

+0

你的示例不使用整数值作为属性名称。它确实使用了一个带有数字的字符串。这是不同的。在数组内部,键总是整数,而不是字符串。因此,至少在用作属性名称时,数值非常成问题。 – Sven 2013-03-28 00:58:36