Multidimensional ArrayAccess in PHP is impossible

I'm working on NumPHP again and for the next version I would like to give this library a little bit more syntactic sugar. For example the get and set functions look like this at the moment.

$column = $matrix->get('1:3', 5);
$matrix->set(3, '1:', $vector);
Not bad, but something like this would be better.
$column = $matrix['1:3'][5];
$matrix[3]['1:'] = $vector;
So I have found the interface ArrayAccess, but it has one big problem. It is not for multidimensional objects.

How ArrayAccess works

The interface can help you to access elements of a class like entries of an array. You just have to implement the interface functions offsetExists, offsetGet, offsetSet and offsetUnset. The problem is, you can't get it working for multidimensional objects. If you implement offsetExists it could look like this.

public function offsetExists($offset)
    // do something with the $offset value and return a boolean value
and you trigger the function with code like this.
/** @var ArrayAccess $arrayaccess */
$bool = isset($arrayaccess[6]);
The parameter $offset has now the value 6 in the function offsetExists.

How ArrayAccess didn't work

Let's assume you have written something like a Matrix class that implements ArrayAccess and you want to check if a matrix entry exists with a code snipped like this.

$bool = isset($matrix[4][5]);
It would be pretty cool if the $offset value in the function offsetExists would be an array with the value 4 and 5. Depending on the implementation of offsetGet you will only get 5 as $offset value in the function offsetGet. If you want an array as $offset value you have to call it like this.
$bool = isset($matrix[[4, 5]]);
As you may has figured out, for every k-dimensional call of offsetExists, offsetSet or offsetUnset you will have k-1 calls of offsetGet in front. Here is a little example that will show you how it works.
class MultiArrayAccess implements ArrayAccess
    public function offsetExists($offset)
        echo "  EXISTS ";
        echo "\n";
    public function offsetGet($offset)
        echo "  GET ";
        echo "\n";
        return $this;
    public function offsetSet($offset, $value)
        echo "  SET ";
        echo " ";
        echo "\n";
    public function offsetUnset($offset)
        echo "  UNSET ";
        echo "\n";
$multiArrayAccess = new MultiArrayAccess();
echo "EXISTS:\n";
echo "GET:\n";
echo "SET:\n";
$multiArrayAccess[5][6] = 7;
echo "UNSET:\n";
The output of this little example is
  GET 1
  GET 3
  GET 4
  GET 5
  SET 6 7
  GET 8


There is no real solution for this problem. I thought about a protected variable that collects the $offset values. If the user of your class only uses offsetExists, offsetSet or offsetUnset this would work. But you can never know if the current call of offsetGet is the last one or if there will be one more. There is the same issue on stackoverflow with some solutions. But none of them is a real ArrayAccess solution. So I will end up with something like this

$matrix[[4, 5]];
Maybe I can't see the wood for the trees (german phrase). If you find a solution, please let me know.

Next Previous