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.
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.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.
<?php
class MultiArrayAccess implements ArrayAccess
{
public function offsetExists($offset)
{
echo " EXISTS ";
print_r($offset);
echo "\n";
}
public function offsetGet($offset)
{
echo " GET ";
print_r($offset);
echo "\n";
return $this;
}
public function offsetSet($offset, $value)
{
echo " SET ";
print_r($offset);
echo " ";
print_r($value);
echo "\n";
}
public function offsetUnset($offset)
{
echo " UNSET ";
print_r($offset);
echo "\n";
}
}
$multiArrayAccess = new MultiArrayAccess();
echo "EXISTS:\n";
isset($multiArrayAccess[1][2]);
echo "GET:\n";
$multiArrayAccess[3][4];
echo "SET:\n";
$multiArrayAccess[5][6] = 7;
echo "UNSET:\n";
unset($multiArrayAccess[8][9]);
The output of this little example is
EXISTS:
GET 1
EXISTS 2
GET:
GET 3
GET 4
SET:
GET 5
SET 6 7
UNSET:
GET 8
UNSET 9
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.