At what points does ArrayAccess not resemble the native PHP array?

1

I know that ArrayAccess exposes an interface to access some elements of the object as if it were a array

Example:

class ListObject implements ArrayAccess{

    protected $storage;

    public function offsetSet($key, $value)
    {
        $this->storage[$key] = $value;
    }

    public function &offsetGet($key)
    {
        return $this->storage[$key];
    }   

    public function offsetUnset($key)
    {
        unset($this->storage[$key]);
    }   

    public function offsetExists($key)
    {
        return array_key_exists($key, $this->storage);
    }
}

$list = new ListObject;

$list[1] = 'Primeiro';

$list[2] = 'Segundo';

However, when I test the existence of some elements, this is the return:

var_dump(array_key_exists(2, $list)); // retorna false e não gera erros :\

var_dump(isset($list[2])); // true

And in some other functions there were also errors when trying to use the object that implements ArrayAccess .

  • If I were on a system where database data was returned by an array and I wanted to implement this ListObject , I might have trouble changing only the return (without having to change checks like in_array and array_search or array_key_exists in that system)?

Or would you have to do more implementations - such as Countable , IteratorAggregate , and the like?

Example:

 DB::table('tabela')->get();

    // array(0 => array('id' => 1, 'nome' => 2))

 DB::table('tabela')->get(); 
 // ListObject(['id' => 1, 'nome' => 2]);
  • ArrayAccess only "simulates" the interface of an array, but does it not return the expected results for the functions of the array native?

Finally, what are the limitations of an implementor object of ArrayAccess relative to array native?

    
asked by anonymous 09.07.2015 / 18:19

1 answer

2

In direct answer to the question ...

One of the great limitations of this interface that gives way, is with regard to multi-dimensional arrays . In other words, its implementation can not be direct.

example:

$bool = isset($arr[1][2]);

Valid in a common array in PHP and handled simply and directly, but the same can not happen with ArrayAccess. For me the only way to resolve it will be:

$bool = isset($arr[[1, 2]]);

You will have to internally implement the mechanism that allows this form and there are stackoverflow some solutions. But none of them is a pure ArrayAccess solution.

UPDATE:

I found this open-ended question to which I replied. It seems there was doubt in what I described. I found a code that can exemplify what I mentioned, so here I add to my answer:

The class in PHP that implements the one described:

<?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";
    }
}

after its use:

<?php
    $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]);

result:

EXISTS:
  GET 1
  EXISTS 2
GET:
  GET 3
  GET 4
SET:
  GET 5
  SET 6 7
UNSET:
  GET 8
  UNSET 9

As I mentioned before, there is no real solution to 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 call or if there is one more.

So I know there are several solutions to the problem, but none is a pure implementation of ArrayAccess as I mentioned.

    
09.07.2015 / 21:47