11

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.

M Miller
  • 5,364
  • 9
  • 43
  • 65
  • Iterator is insufficient, it merely provides a way for you to control how foreach iterates over your object. If your class needs to behave like an array it will also need to implement ArrayAccess, and probably Countable as well. – GordonM Aug 18 '14 at 21:32

3 Answers3

25

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.

vascowhite
  • 18,120
  • 9
  • 61
  • 77
2

Implement ArrayAccess in your class.

See the documentation here: http://www.php.net/arrayaccess

mark.sagikazar
  • 1,032
  • 8
  • 19
1

From PHP

Introduction 
Interface for external iterators or objects that can be iterated themselves internally.

As you can see from the interface Table of Contents ¶

Iterator::current — Return the current element
Iterator::key — Return the key of the current element
Iterator::next — Move forward to next element
Iterator::rewind — Rewind the Iterator to the first element
Iterator::valid — Checks if current position is valid

The operation is designed for forward iteration. So reverse would naturally not work and is not designed for this.

For more array-object related interfaces take a look at. ArrayAccess and Countable

For a solution upon a reverse object iterator take a look at the answer here Iterate in reverse through an array with PHP - SPL solution?

Community
  • 1
  • 1
Ronni Skansing
  • 1,494
  • 1
  • 17
  • 33