Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Treat a PHP class that implements Iterator as an array

If I have a class that implements the Iterator interface, I can manually control how iteration in a foreach loop. But are there other ways in which I could make my object behave like an array?

For instance, let's say I have a class Guestbook which implements Iterator, so that I can iterate foreach (new Guestbook() as $entry). But what if I want to, say, reverse the order?

foreach (array_reverse(new Guestbook()) as $entry) definitely won't work, because array_reverse will only accept an array.

I guess what I'm asking is, can I use Iterator for more than just foreach loops?

Thanks.

like image 505
M Miller Avatar asked Dec 13 '13 22:12

M Miller


1 Answers

The purpose of the Iterator interface is to allow your object to be used in a foreach loop, it is not intended to make your object act like an array. If you want something that acts like an array, use an array.

You can always turn your object into an array by using the iterator_to_array function, but you can't reverse that process.

If you see the need for reversing the order of the elements in your iterable object, then you could create a reverse() method that, possibly, uses array_reverse() internally. Something like this:-

class Test implements Iterator
{
    private $testing = [0,1,2,3,4,5,6,7,8,9,10];
    private $index = 0;

    public function current()
    {
        return $this->testing[$this->index];
    }

    public function next()
    {
        $this->index ++;
    }

    public function key()
    {
        return $this->index;
    }

    public function valid()
    {
        return isset($this->testing[$this->key()]);
    }

    public function rewind()
    {
        $this->index = 0;
    }

    public function reverse()
    {
        $this->testing = array_reverse($this->testing);
        $this->rewind();
    }
}

$tests = new Test();
var_dump(iterator_to_array($tests));
$tests->reverse();
var_dump(iterator_to_array($tests));

Output:-

array (size=11)
  0 => int 0
  1 => int 1
  2 => int 2
  3 => int 3
  4 => int 4
  5 => int 5
  6 => int 6
  7 => int 7
  8 => int 8
  9 => int 9
  10 => int 10

array (size=11)
  0 => int 10
  1 => int 9
  2 => int 8
  3 => int 7
  4 => int 6
  5 => int 5
  6 => int 4
  7 => int 3
  8 => int 2
  9 => int 1
  10 => int 0

I wrote the code to prove to myself that it would work before posting and thought I might as well throw it into the answer.

like image 135
vascowhite Avatar answered Oct 12 '22 05:10

vascowhite