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

I'm running through a set of arrays and objects for further processing. If it's an object i use get_object_vars($obj) to get its proberties. But if that object uses magic getters/setters, it returns an empty array. Here a little demo of the issue:

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));

I want that get_object_vars returns the $fields key-value pairs. Is there any way to go, or any method to implement in Foo to make it work?

thanks for any hint.

That is not related to magic methods, but with the fact that get_object_vars() returns an array of accessible non-static properties for the specified object relative to scope. It will return all properties if the call is from inside the objects, but, only public from outside the object. You can however, use the IteratorAggregate interface, and ArrayIterator class, and combine that with iterator_to_array() function to obtain similar behavior and some additional benefits, as in this example.

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 only returns visible properties. As you're calling the function from outside the object, it has no visibility of your protected field, so it won't be returned.

What you can do instead is cast the object to an array:

var_dump((array) $foo);

This will alter the key a bit. Have a look here for specifics.

Another option is to create a method in the object that returns get_object_vars from the inside, as it will have visibility of everything. e.g.

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

And yet another option is obviously to simply change your property to public instead of protected.