Returning Arrays from __get

Sometimes you have a class that has magic properties, ie. it implements property access overload methods. And you might have had the problem that one of these magic properties holds an array. And you just can’t seem to update that array what-so-ever.

PHP.net tells you the reason and one way around that. Basically, you need to be aware of the fact that whenever you access a magic property, it isn’t really a property. It really is a value passed to or returned from a method. And since in PHP all values (except objects) are passed and returned by copy and not by reference, what you really have is not the array itself, but a copy of that array.

But in that sentence is also one solution to the problem, you need to return an object. That object should look and act like an array, and PHP has just the thing for us: ArrayObject.

Here’s an example:


<?php
class Overload {
    private $dynamicProperties = array();
    public function __get( $property ) {
        if ( is_array( $this->dynamicProperties[ $property ] ) )
            // initialize a new ArrayObject with a *reference* to the array!
            return new ArrayObject( &$this->dynamicProperties[ $property ] );
        return $this->dynamicProperties[ $property ];
    }
    public function __set( $property, $value ) {
        $this->dynamicProperties[ $property ] = $value;
    }
    public function dump() {
        var_dump( $this->dynamicProperties );
    }
}

/*
Lets test this class
*/
$o = new Overload;

/* equivalent to:
$var = array();
$o->__set( "items", $var );
*/
$o->items = array();

/* equivalent to:
$items = $o->__get( "items" );
$items[] = "item one";
*/
$o->items[] = "item one";

/* equivalent to:
$items = $o->__get( "items" );
$items[] = "item two";
*/
$o->items[] = "item two";

/* equivalent to:
$items = $o->__get( "items" );
$items[] = "item three";
*/
$o->items[] = "item three";

$o->dump();

And this is the output, note how the internal array was updated:

array(1) {
  ["items"]=>
  array(3) {
    [0]=>
    string(8) "item one"
    [1]=>
    string(8) "item two"
    [2]=>
    string(10) "item three"
  }
}

So there you have it, a dynamic property that is an array. The important bit in this example is how an ArrayObject initialized with a reference to the array is returned by the __get() method. Beware though, this solution still can cause some problems since is_array(ArrayObject) === false.

And once again fixed another problem with PHP that shouldn’t have existed in the first place. What a mess that language is.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: