ArrayAccess vs ArrayObject
In very simple terms, ArrayAccess is an interface, which you can implement in your own objects; ArrayObject, on the other hand, is a class, which you can either use or extend.
ArrayAccess
ArrayAccess is an interface built in to PHP which lets you dictate how PHP behaves when an object has array syntax (square brackets) attached to it. Interfaces are collections of function prototypes that we can use as templates for our own code. If you read the manual page for ArrayAccess, it shows four functions:
ArrayAccess {
/* Methods */
abstract public boolean offsetExists ( mixed $offset )
abstract public mixed offsetGet ( mixed $offset )
abstract public void offsetSet ( mixed $offset , mixed $value )
abstract public void offsetUnset ( mixed $offset )
}
To implement this interface, we just declare all these methods in our class. Here is an example class:
class PrettyBasket implements ArrayAccess
{
protected $contents = array();
public function offsetExists($index) {
return isset($this->contents[$index]);
}
public function offsetGet($index) {
if($this->offsetExists($index)) {
return $this->contents[$index];
}
return false;
}
public function offsetSet($index, $value) {
if($index) {
$this->contents[$index] = $value;
} else {
$this->contents[] = $value;
}
return true;
}
public function offsetUnset($index) {
unset($this->contents[$index]);
return true;
}
public function getContents() {
return $this->contents;
}
}
In addition to accessing the properties and methods of a Basket object, we can also use array notation with it, so we can write code along these lines.
$basket = new PrettyBasket();
$basket->madeOf = 'wicker';
$basket->capacity = '14';
$basket[] = 'pie';
$basket[] = 'apples';
$basket[] = 'map';
// $contents = $basket->getContents();
//echo $contents[0];
echo $basket[0];
The $basket
variable is a Basket object, but we’re using $basket[]
notation with the object, so how does that work? In fact when we do this, PHP will check if we implement the ArrayAccess interface, and if we do then it calls our methods. This is very neat and can make for an easy way to give quick access to an array stored in one of the object properties, as we’ve done here. You can see that there’s some code commented out and replaced by the one line following it – it’s much shorter which means this is attractive for using to output data into templates. Another good example is to create behaviour such as SimpleXMLElement has, which uses this array notation to present the attributes of a tag.
ArrayObject
ArrayObject is an object, you can implement and extend it as you usually would. It implements a bunch of useful interfaces and wraps them up into an object. For creating an object to look a lot like an array, take a look at ArrayObject! It implements ArrayAccess as we saw above, but also Countable, Traversable, and others.
The upshot is a class which, out of the box, can give us the behaviour shown above, plus foreach behaviour which foreaches the array elements rather than the object properties, support for serialising the data, and more. This is very useful when we work with this kind of pattern (typically data storage patterns but I’m open to hearing stories about how you use it in your own code).
You can extend ArrayAccess and create your own class, adding properties and methods in the usual way, and using the object exactly as you usually would … except that it has all this array functionality built in as well! It’s a powerful class but do bear in mind that although we can foreach it and access its individual elements, it won’t look like an array to any of PHP’s array functions. So for many applications, you do still want an array (or an object which can return you the array it’s storing things in).
Hopefully that gives a clearer idea of what these Array* things are and when they’ll be useful. Are you implementing these yourself? I’d love some more practical case studies if you want to share.
Our configuration object implements both ArrayAccess and Iterator, allowing it to fit into almost any programming style (including camel casing, underscored, getter/setter, and direct access). It also implements magic gets, sets, call, sleep, wakeup, and set_state.
So it can be accessed like $config->session, $config[‘session’], $config->get_session(), $config->getSession(), $config->session(), foreach ($config as $key => $value)
It can also be read from, and serialized to XML, YAML, JSON, INI, and JINI (a custom JSON/INI hybrid). It supports multiple caching methods, but mostly, file based via var_export, and set_state.
“So it can be accessed like $config->session, $config[‘session’], $config->get_session(), $config->getSession(), $config->session()”
Dude, you sure that’s a good thing?
It comes down to the fact that if you are creating mashups of many PHP librarys you are bound to run into conflicting conventions, doing it this way allows you to be consistent, at least within the current library.
Seems a bit overkill don’t you think? Could you maybe only have two of them, or do all those options really get used?
Magic methods like this really need a warning the manual page
Using this method may seriously damage the readability and long term maintainability of youf code. Only use it if you document the the crap out if it…
Hello,
there is an error in your example:
if($index) wouldn’t allow to set the value of index “0”. You should use if (is_null($index)) instead.
That’s a very good point, thanks for adding a comment!
Pingback: PHPDeveloper.org: Lorna Mitchell's Blog: ArrayAccess vs ArrayObject
I was Badly searching for this difference between ArrayAccess vs ArrayObject.I have gone through many sites but no one provided me the exact solution for my problem except you .So tons of thanks to you for writing and sharing this great tutorial on ArrayAccess vs ArrayObject
Pingback: Lorna Mitchell’s Blog: ArrayAccess vs ArrayObject | Scripting4You Blog
Pingback: Lorna Mitchell Blog: ArrayAccess vs ArrayObject | PHP Boutique
Hello,
thanks for the article.
in the 3rd paragraph about ArrayObject it shouldn’t be “You can extend ArrayObject and create your own class…” instead ?
amine: You are correct. ArrayObject can be extended, not ArrayAccess since ArrayAccess is an interface.
just to be annoying :-)
when you test if a key exists in the underlying array (line 6 of the ArrayAccess class example) you do:
return isset($this->contents[$index]);
this means that if $this->contents[$index] was set to null (for whatever good reason), it will return false. Shiuldn’t it be
return array_key_exists($index,$this->contents);
?
Pingback: PHP ArrayAccess and ArrayObject | Tech Blog