get_object_vars()可以从magic __get()返回字段吗?

时间:2014-10-24 15:22:45

标签: php oop getter

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

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中实施任何方法才能使其有效?

感谢任何提示。

2 个答案:

答案 0 :(得分:2)

这与魔术方法无关,但事实上get_object_vars()返回指定对象相对于范围的可访问非静态属性数组。如果调用来自对象内部,它将返回所有属性,但是,仅从对象外部公开。但是,您可以使用IteratorAggregate接口和ArrayIterator类,并将其与iterator_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 ) 

答案 1 :(得分:1)

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

您可以做的是将对象强制转换为数组:

var_dump((array) $foo);

这会改变关键点。查看具体内容here

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

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

另一个选择显然只是将您的属性更改为public而不是protected