You might be wondering whether implementing an ArrayAccess interface makes the class iterable. It is, after all, an "array". The answer is no, it doesn't. Additionally there are a couple of subtle gotchas if you add both and want it to be an associate array. The below is a class that has both ArrayAccess AND Iterator interfaces. And Countable as well just to be complete.
<?php
class HandyClass implements ArrayAccess, Iterator, Countable {
private $container = array(); private $keys = array(); private $position; public function __construct() {
$position = 0;
$this->container = array( "a" => 1, "b" => 2,
"c" => 3,
);
$this->keys = array_keys($this->container);
}
public function count() : int { return count($this->keys); }
public function rewind() { $this->position = 0; }
public function current() { return $this->container[$this->keys[$this->position]];
}
public function key() { return $this->keys[$this->position];
}
public function next() { ++$this->position;
}
public function valid() { return isset($this->keys[$this->position]);
}
public function offsetSet($offset, $value) { if(is_null($offset)) {
$this->container[] = $value;
$this->keys[] = array_key_last($this->container); } else {
$this->container[$offset] = $value;
if(!in_array($offset, $this->keys)) $this->keys[] = $offset;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
unset($this->keys[array_search($offset,$this->keys)]);
$this->keys = array_values($this->keys); } public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
?>
Example usages:
<?php
$myClass = new HandyClass();
echo('Number of elements: ' . count($myClass) . "\n\n");
echo("Foreach through the built in test elements:\n");
foreach($myClass as $key => $value) {
echo("$value\n");
}
echo("\n");
$myClass['d'] = 4;
$myClass['e'] = 5;
echo('Number of elements after adding two: ' . count($myClass) . "\n\n");
unset($myClass['a']);
echo('Number of elements after removing one: ' . count($myClass) . "\n\n");
echo("Accessing an element directly:\n");
echo($myClass['b'] . "\n\n");
$myClass['b'] = 5;
echo("Foreach after changing an element:\n");
foreach($myClass as $key => $value) {
echo("$value\n");
}
echo("\n");
?>