Recipe 4.24. Making an Object Act like an Array


4.24.1. Problem

You have an object, but you want to be able to treat it as an array. This allows you to combine the benefits from an object-oriented design with the familiar interface of an array.

4.24.2. Solution

Implement SPL's ArrayAccess interface:

class FakeArray implements ArrayAccess {     private $elements;     public function __construct() {         $this->elements = array();     }     public function offsetExists($offset) {         return isset($this->elements[$offset]);     }     public function offsetGet($offset) {         return $this->elements[$offset];     }     public function offsetSet($offset, $value) {         return $this->elements[$offset] = $value;     }     public function offsetUnset($offset) {         unset($this->elements[$offset]);     } } $array = new FakeArray; // What's Opera, Doc? $array['animal'] = 'wabbit'; // Be very quiet I'm hunting wabbits if (isset($array['animal']) &&     // Wabbit tracks!!!     $array['animal'] == 'wabbit') {     // Kill the wabbit, kill the wabbit, kill the wabbit     unset($array['animal']);     // Yo ho to oh! Yo ho to oh! Yo ho... } // What have I done?? I've killed the wabbit.... // Poor little bunny, poor little wabbit... if (!isset($array['animal'])) {     print "Well, what did you expect in an opera? A happy ending?\n"; } Well, what did you expect in an opera? A happy ending?

4.24.3. Discussion

The ArrayAccess interface allows you to manipulate data in an object using the same set of conventions you use for arrays. This allows you to leverage the benefits of an object-oriented design, such as using a class hierarchy or implementing additional methods on the object, but still allow people to interact with the object using a familiar interface. Alternatively, it allows you create an "array" that stores its data in an external location, such as shared memory or a database.

An implementation of ArrayAccess requires four methods: offsetExists( ), which indicates whether an element is defined; offsetGet( ), which returns an element's value; offsetSet( ) , which sets an element to a new value; and offsetUnset( ), which removes an element and its value.

This example stores the data locally in an object property:

class FakeArray implements ArrayAccess {     private $elements;     public function __construct() {         $this->elements = array();     }     public function offsetExists($offset) {         return isset($this->elements[$offset]);     }     public function offsetGet($offset) {         return $this->elements[$offset];     }     public function offsetSet($offset, $value) {         return $this->elements[$offset] = $value;     }     public function offsetUnset($offset) {         unset($this->elements[$offset]);     } }

The object constructor initializes the $elements property to a new array. This provides you with a place to store the keys and values of your array. That property is defined as private, so people can only access the data through one of the accessor methods defined as part of the interface.

The next four methods implement everything you need to manipulate an array. Since offsetExists( ) checks if an array element is set, the method returns the value of isset($this->elements[$offset]).

The offsetGet( ) and offsetSet( ) methods interact with the $elements property as you would normally use those features with an array.

Last, the offsetUnset( ) method simply calls unset( ) on the element. Unlike the other three methods, it does not return the value from its operation. That's because unset( ) is a statement, not a function, and doesn't return a value.

Now you can instantiate an instance of FakeArray and manipulate it like an array:

$array = new FakeArray; // What's Opera, Doc? $array['animal'] = 'wabbit'; // Be very quiet I'm hunting wabbits if (isset($array['animal']) &&     // Wabbit tracks!!!     $array['animal'] == 'wabbit') {     // Kill the wabbit, kill the wabbit, kill the wabbit     unset($array['animal']);     // Yo ho to oh! Yo ho to oh! Yo ho... } // What have I done?? I've killed the wabbit.... // Poor little bunny, poor little wabbit... if (!isset($array['animal'])) {     print "Well, what did you expect in an opera? A happy ending?\n"; } Well, what did you expect in an opera? A happy ending?

Each operation calls one of your methods: assigning a value to $array['animal'] triggers offsetSet( ), checking isset($array['animal']) invokes offsetExists( ), offsetGet( ) comes into play when you do the comparison $array['animal'] == 'wabbit', and offsetUnset( ) is called for unset($array['animal']).

As you can see, after all this, the wabbit is "dead."

4.24.4. See Also

More on objects in Chapter 7; the ArrayAccess reference page at http://www.php.net/~helly/php/ext/spl/interfaceArrayAccess.html; and the Wikipedia entry on "What's Opera, Doc?" at http://en.wikipedia.org/wiki/What%27s_Opera%2C_Doc .




PHP Cookbook, 2nd Edition
PHP Cookbook: Solutions and Examples for PHP Programmers
ISBN: 0596101015
EAN: 2147483647
Year: 2006
Pages: 445

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net