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;

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

get_object_vars($obj)什么都不显示,print_r((array)$obj)实际上正确打印了值。


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


它也发生在许多 SPL 交互器(如ArrayObjects、SplFixedArrays、SplHeaps)上。显然这种行为只存在于某些 PHP 5.3 版本中。PHP 5.4 什么也没显示。


相关的 PHP 错误和我对解决方案的看法(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);
  });
}
4

2 回答 2

1

将数组转换为对象会将数组键转换为属性名称,并将值转换为它们的值。

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

你真的想要:

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

于 2013-03-28T00:45:49.400 回答
1

这是一个无法修复的错误......或奇怪的 php 行为。因此,如果您不确定其中的数字键,则不能使用对象类型转换。使用这样的东西

$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 对象上。

于 2013-03-28T01:24:09.283 回答