可以从magic__get()返回字段


can get_object_vars() return fields from magic __get()?

我正在运行一组数组和对象以进行进一步处理。如果它是一个对象,我使用get_object_vars($obj)来获取它的问题。但是,如果该对象使用magic getters/ssetters,它将返回一个空数组。这里有一个问题的小演示:

class Foo {
    protected
        $fields = array(
            'foo'=>1,
            'bar'=>2
        );
    function __get($key) {
        return $this->fields[$key];
    }
    function __isset($key) {
        return array_key_exists($key,$this->fields);
    }
}
$foo = new Foo();
var_dump(get_object_vars($foo));

我希望get_object_vars返回$fields键值对。有没有什么方法可以走,或者有什么方法可以在Foo中实现以使其工作?

谢谢你的提示。

这与魔术方法无关,但与get_object_vars()返回指定对象相对于作用域的可访问非静态属性数组有关。如果调用来自对象内部,但仅来自对象外部的公共调用,则它将返回所有属性。但是,您可以使用IteratorAggregate接口和ArrayIdeator类,并将其与迭代器_to_array()函数相结合,以获得类似的行为和一些额外的好处,如本例所示。

class Foo implements IteratorAggregate {
    protected
        $fields = array(
            'foo' => 1,
            'bar' => 2
        );
    function __get( $name ) {
        return array_key_exists( $name, $this->fields ) ? $this->fields[$name] : null;
    }
    public function __set( $name, $value )
    {
        $this->fields[$name] = $value;
    }
    function __isset( $name ) {
        return isset( $this->fields[$name] );
    }
    public function getIterator() {
        return new ArrayIterator( $this->fields );
    }
}
$foo = new Foo();
$foo->baz = 3;
foreach( $foo as $key => $value ) {
    echo "$key: $value ";   // OUTPUT: foo: 1 bar: 2 baz: 3
}
array_walk( ( iterator_to_array( $foo ) ), function( $value, $key ) {
    echo "$key: $value ";   // OUTPUT: foo: 1 bar: 2 baz: 3
});
print_r( iterator_to_array( $foo ) );   // OUTPUT: Array ( [foo] => 1 [bar] => 2 [baz] => 3 ) 

get_object_vars仅返回可见属性。当您从对象外部调用函数时,它对protected字段不可见,因此不会返回。

相反,您可以将对象强制转换为数组:

var_dump((array) $foo);

这会稍微改变一下钥匙。请查看此处了解详细信息。

另一种选择是在对象中创建一个从内部返回get_object_vars的方法,因为它可以查看所有内容。例如

class Foo {
    ...
    public function get_object_vars() {
        return get_object_vars($this);
    }
}
$foo = new Foo();
var_dump($foo->get_object_vars());

另一种选择显然是简单地将属性更改为public而不是protected