PHP Iterator Interface
In this page:
class ClassName implements Iterator {
function current() { } // value at the current position
function key() { }
function next() { }
function rewind() { }
function valid() { } // is the position valid?
}
foreach ($object as $key => $value) { }
What Is the Iterator Interface?
PHP's built-in Iterator interface lets a custom object define exactly how it behaves inside a foreach loop, by implementing five specific methods.
Without it, foreach only works on plain arrays and objects with public properties -- Iterator lets you control iteration over any internal data structure, including ones that aren't stored as a simple array.
Example: What Is the Iterator Interface?
<?php
// Define the class `Numbers`, implementing `Iterator`
class Numbers implements Iterator {
// Declare the private property `$items`, set to `[10, 20, 30]`
private $items = [10, 20, 30];
// Declare the private property `$pos`, set to `0`
private $pos = 0;
// Define the function `current` with no parameters
function current() { return $this->items[$this->pos]; }
// Define the function `key` with no parameters
function key() { return $this->pos; }
// Define the function `next` with no parameters
function next() { $this->pos++; }
// Define the function `rewind` with no parameters
function rewind() { $this->pos = 0; }
// Define the function `valid` with no parameters
function valid() { return isset($this->items[$this->pos]); }
}
// Loop over `new Numbers()`, binding each item to `$n`
foreach (new Numbers() as $n) {
// Print `$n . "\n"` to the output
echo $n . "\n";
}
?>
Login to try C/C++/Java/PHP code in the editor
The Five Required Methods
current() returns the value at the current position, key() returns its key, next() advances the internal pointer, rewind() resets it to the start (called once, before the first iteration), and valid() returns a boolean telling foreach whether to keep looping.
PHP calls these in a specific sequence automatically every time your object is used in a foreach.
Example: The Five Required Methods
<?php
// Define the class `Numbers`, implementing `Iterator`
class Numbers implements Iterator {
// Declare the private property `$items`, set to `[10, 20]`
private $items = [10, 20];
// Declare the private property `$pos`, set to `0`
private $pos = 0;
// Define the function `current` with no parameters
function current() { return $this->items[$this->pos]; }
// Define the function `key` with no parameters
function key() { return $this->pos; }
// Define the function `next` with no parameters
function next() { $this->pos++; }
// Define the function `rewind` with no parameters
function rewind() { $this->pos = 0; }
// Define the function `valid` with no parameters
function valid() { return isset($this->items[$this->pos]); }
}
// Create a new `Numbers` instance, stored in `$it`
$it = new Numbers();
$it->rewind();
// Keep looping while `$it->valid()` holds
while ($it->valid()) {
echo $it->key() . ": " . $it->current() . "\n";
$it->next();
}
?>
Login to try C/C++/Java/PHP code in the editor
Implementing a Custom Iterator
A typical implementation wraps an internal array and an integer position pointer, delegating each interface method to simple operations on those two properties.
This pattern lets you add validation, lazy computation, or filtering logic inside current() or valid() that a plain array could never do.
Example: Implementing a Custom Iterator
<?php
// Define the class `EvenNumbers`, implementing `Iterator`
class EvenNumbers implements Iterator {
// Declare the private property `$items`
private $items;
// Declare the private property `$pos`, set to `0`
private $pos = 0;
// Define the constructor `__construct` taking `$items`
function __construct($items) { $this->items = $items; }
// Define the function `current` with no parameters
function current() { return $this->items[$this->pos]; }
// Define the function `key` with no parameters
function key() { return $this->pos; }
// Define the function `next` with no parameters
function next() { $this->pos++; }
// Define the function `rewind` with no parameters
function rewind() { $this->pos = 0; }
// Define the function `valid` with no parameters
function valid() {
// Return `isset($this->items[$this->pos]) && $this->items[$this->pos] % 2 === 0` from this function
return isset($this->items[$this->pos]) && $this->items[$this->pos] % 2 === 0;
}
}
foreach (new EvenNumbers([2, 4, 6]) as $n) {
echo $n . "\n";
}
?>
Login to try C/C++/Java/PHP code in the editor
IteratorAggregate as a Shortcut
Implementing all five Iterator methods by hand is verbose when your class just wraps an existing array or object.
IteratorAggregate requires only one method, getIterator(), which returns an Iterator (often an ArrayIterator wrapping your internal data) -- PHP delegates the actual iteration to whatever you return.
Example: IteratorAggregate as a Shortcut
<?php
// Define the class `Collection`, implementing `IteratorAggregate`
class Collection implements IteratorAggregate {
// Declare the private property `$items`, set to `["a", "b", "c"]`
private $items = ["a", "b", "c"];
// Define the function `getIterator` with no parameters
function getIterator(): Iterator {
// Return `new ArrayIterator($this->items)` from this function
return new ArrayIterator($this->items);
}
}
// Loop over `new Collection()`, binding each item to `$item`
foreach (new Collection() as $item) {
// Print `$item . "\n"` to the output
echo $item . "\n";
}
?>
Login to try C/C++/Java/PHP code in the editor
When to Use a Custom Iterator
Custom iterators matter when the underlying data isn't a plain array -- for example, iterating over database result rows one at a time without loading them all into memory, or walking a tree/linked-list structure in a defined traversal order.
For a class that's just a thin wrapper around an array, IteratorAggregate with ArrayIterator is almost always simpler.
Example: When to Use a Custom Iterator
<?php
class SimpleList implements IteratorAggregate {
private $items = [1, 2, 3];
function getIterator(): Iterator {
return new ArrayIterator($this->items);
}
}
// A thin array wrapper is simpler with IteratorAggregate than a full Iterator
foreach (new SimpleList() as $item) {
echo $item . "\n";
}
?>
Login to try C/C++/Java/PHP code in the editor
- Not implementing all five methods
current,key,next,rewindandvalid, which causes a fatal error. - Forgetting to reset the position in
rewind, so a second loop finds nothing. - Returning the wrong value from
valid, so the loop never ends or ends immediately.
Chapter Quiz — Complete all 14 topics to unlock
0/14 topics done
Complete these topics first: