At which points does Arrayaccess not resemble the native PHP array?

Asked

Viewed 65 times

1

I know that the ArrayAccess exposes an access interface to 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 will 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 the database data was returned by an array and I wanted to implement this ListObject, I could have trouble changing just the return (without having to change checks like in_array and array_search or array_key_exists existing in that system)?

Or you’d have to do more implementations - like 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 it does not return the expected results for the functions of the array native?

Finally, what are the limitations of an implement object of ArrayAccess in relation to the array native?

1 answer

2

In direct answer to the question...

One of the great limitations of this interface that gives so much way, is in relation to multi-dimensional arrays. That is, its implementation cannot be direct.

example :

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

Valid in a common PHP array and treated simply and directly, but the same cannot happen with Arrayaccess. For me the only way to solve it will be:

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

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

UPDATING:

I found this question open to which I answered. From what I seem to have doubts in what I described. I found a code that can exemplify what I mentioned, so here I add to my answer:

The PHP class that implements the 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]);

outworking:

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 values of $ offset. If the user in your class only uses offsetExists, offsetSet or offsetUnset that would work. But you can never know if the current call from offsetGet is the last or if there will be one more.

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

  • Friend, $arr[[1, 2]] generates a Illegal offset type so much for array as for ArrayAccess. What did you mean ?

  • @Wallacemaxters of course it generates... as I mentioned the implementation can not be direct! You need to implement the logic to get the offset of an array and not a variable as expected by Arrayaccess. The only way respecting the Arrayaccess interface is the way I put it. understand? I answered was the question.... What are the limitations!

  • @Wallacemaxters updated my answer to see if I can "illuminate" you for the problem I described... I hope I’ve helped!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.