PHP Arrays
Accessing an Object Using Array Syntax
Problem
You have an object, but you want to be able to read and write data to it as an array. This allows you to combine the benefits from an object-oriented design with the familiar interface of an array.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";
}
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. Because 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";
}
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.
No comments:
Post a Comment