PHP - PHP Iterators and the Iterator Interface
PHP Iterators provide a structured way to traverse through a collection of data one element at a time without requiring the collection to be exposed directly. They are especially useful when working with custom collections, large datasets, objects, and data structures where normal foreach iteration is not sufficient.
1. What Is an Iterator in PHP?
An iterator is an object that allows you to move through a collection sequentially.
Normally, PHP arrays can be traversed easily:
$students = ["John", "Mary", "David"];
foreach ($students as $student) {
echo $student . "<br>";
}
For arrays, PHP already knows how to move from one element to the next.
However, suppose you create your own collection class containing student records. You may want that object to work naturally with foreach. PHP provides the Iterator interface for this purpose.
An iterator controls:
-
Which element is currently selected
-
How to retrieve the current element
-
How to move to the next element
-
How to determine whether another element exists
-
How to reset the iteration
2. The PHP Iterator Interface
The built-in Iterator interface defines five important methods:
interface Iterator extends Traversable
{
public function current(): mixed;
public function key(): mixed;
public function next(): void;
public function rewind(): void;
public function valid(): bool;
}
Each method has a specific responsibility.
| Method | Purpose |
|---|---|
current() |
Returns the current element |
key() |
Returns the key of the current element |
next() |
Moves to the next element |
rewind() |
Moves the iterator back to the first element |
valid() |
Checks whether the current position is valid |
These methods work together when PHP executes a foreach loop.
3. Understanding current()
The current() method returns the value at the iterator's current position.
For example:
public function current(): mixed
{
return $this->students[$this->position];
}
If the current position is 0, this method returns the first student.
If the position is 1, it returns the second student.
4. Understanding key()
The key() method returns the key associated with the current element.
public function key(): mixed
{
return $this->position;
}
For example, if the iterator is currently positioned at the third element, key() might return:
2
because PHP arrays commonly use zero-based indexing.
The key does not necessarily have to be a number. It can also be a string or another appropriate key type.
5. Understanding next()
The next() method moves the iterator to the next element.
public function next(): void
{
$this->position++;
}
If the current position is 0, calling next() changes it to 1.
If the current position is 1, it changes to 2.
This allows the iterator to move through the collection sequentially.
6. Understanding rewind()
The rewind() method resets the iterator to the beginning.
public function rewind(): void
{
$this->position = 0;
}
When a foreach loop starts, PHP calls rewind() so that iteration begins from the first element.
7. Understanding valid()
The valid() method determines whether the current iterator position contains a valid element.
public function valid(): bool
{
return isset($this->students[$this->position]);
}
It returns:
true
when the current position contains an element.
It returns:
false
when the iterator has moved beyond the available elements.
This tells PHP when to stop the foreach loop.
8. Creating a Custom Iterator
Consider a collection of students:
class StudentCollection implements Iterator
{
private array $students = [
"John",
"Mary",
"David",
"Sarah"
];
private int $position = 0;
public function current(): mixed
{
return $this->students[$this->position];
}
public function key(): mixed
{
return $this->position;
}
public function next(): void
{
$this->position++;
}
public function rewind(): void
{
$this->position = 0;
}
public function valid(): bool
{
return isset($this->students[$this->position]);
}
}
Now the collection can be used with foreach:
$students = new StudentCollection();
foreach ($students as $key => $student) {
echo $key . ": " . $student . "<br>";
}
The output would be:
0: John
1: Mary
2: David
3: Sarah
The important point is that StudentCollection is an object, but it can still be traversed using foreach because it implements Iterator.
9. How foreach Works With an Iterator
When PHP encounters:
foreach ($students as $student) {
echo $student;
}
PHP internally performs operations similar to the following sequence:
rewind()
|
v
valid()
|
v
current()
|
v
next()
|
v
valid()
|
v
current()
|
v
next()
|
v
...
The process continues until:
valid()
returns false.
This is the fundamental mechanism behind custom iteration.
10. Using IteratorAggregate
PHP also provides the IteratorAggregate interface.
It is useful when you do not want your collection class to implement all five iterator methods itself.
The interface provides:
interface IteratorAggregate extends Traversable
{
public function getIterator(): Traversable;
}
Example:
class StudentCollection implements IteratorAggregate
{
private array $students = [
"John",
"Mary",
"David",
"Sarah"
];
public function getIterator(): Traversable
{
return new ArrayIterator($this->students);
}
}
Now you can write:
$students = new StudentCollection();
foreach ($students as $student) {
echo $student . "<br>";
}
This approach is often simpler because PHP's ArrayIterator handles the actual iteration.
11. Iterator vs IteratorAggregate
Both interfaces make objects traversable, but they work differently.
Iterator requires the class to control the iteration process directly.
class MyCollection implements Iterator
You must implement:
current()
key()
next()
rewind()
valid()
IteratorAggregate delegates iteration to another iterable object.
class MyCollection implements IteratorAggregate
You mainly implement:
getIterator()
For example:
public function getIterator(): Traversable
{
return new ArrayIterator($this->students);
}
12. When Should You Use Iterator?
A custom Iterator is useful when you need precise control over how the collection is traversed.
For example, you may want to:
-
Skip certain records
-
Traverse data in a special order
-
Calculate values while iterating
-
Read data from an external source
-
Implement custom navigation logic
-
Maintain a complex internal position
-
Traverse a custom data structure
13. When Should You Use IteratorAggregate?
IteratorAggregate is generally convenient when your class already contains an iterable collection.
For example:
class ProductCollection implements IteratorAggregate
{
private array $products;
public function __construct(array $products)
{
$this->products = $products;
}
public function getIterator(): Traversable
{
return new ArrayIterator($this->products);
}
}
Usage:
$products = new ProductCollection([
"Laptop",
"Keyboard",
"Mouse"
]);
foreach ($products as $product) {
echo $product . "<br>";
}
This keeps the collection class simple while still allowing foreach.
14. Iterators and Large Data
Iterators can be particularly useful when dealing with large amounts of data.
Suppose a program needs to process thousands or millions of records. Loading everything into a large array can consume significant memory.
An iterator can provide one item at a time.
Conceptually:
Database
|
v
Iterator
|
+---- Record 1
|
+---- Record 2
|
+---- Record 3
|
+---- ...
Instead of requiring the entire dataset to be loaded into memory simultaneously, an iterator can process data progressively.
This concept is closely related to lazy processing.
15. Iterator Example With Objects
Consider a collection of employee objects:
class Employee
{
public function __construct(
public string $name,
public string $department
) {}
}
A collection could contain:
$employees = [
new Employee("John", "IT"),
new Employee("Mary", "HR"),
new Employee("David", "Finance")
];
Using an iterator allows the collection to expose employees through foreach without exposing the internal implementation of the collection.
foreach ($employees as $employee) {
echo $employee->name . " - " . $employee->department;
}
This provides a clean separation between the collection's internal structure and the code that consumes it.
16. Advantages of Iterators
Iterators provide several important benefits.
Encapsulation
The internal structure of a collection can remain private.
The user of the class does not need to know whether the data is stored in:
-
An array
-
A database result
-
A file
-
Another collection
-
A custom data structure
They simply use:
foreach
Memory Efficiency
Iterators can process data progressively rather than requiring an entire dataset to be stored in memory.
Reusable Traversal Logic
Once an iterator is created, the same traversal logic can be reused throughout an application.
Cleaner Code
Consumers can use familiar syntax:
foreach ($collection as $item) {
// Process item
}
instead of directly manipulating internal indexes or data structures.
Separation of Responsibilities
The collection manages its data, while the iterator manages how that data is traversed.
17. Important Difference Between Arrays and Iterators
An array is primarily a data structure that stores values.
An iterator is primarily a mechanism for traversing data.
For example:
$students = ["John", "Mary", "David"];
The array stores the students.
An iterator determines how those students can be accessed sequentially.
This distinction becomes particularly important when working with custom collections and large datasets.
18. Practical Example
A simple product collection can be created as follows:
class ProductCollection implements Iterator
{
private array $products;
private int $position = 0;
public function __construct(array $products)
{
$this->products = $products;
}
public function current(): mixed
{
return $this->products[$this->position];
}
public function key(): mixed
{
return $this->position;
}
public function next(): void
{
$this->position++;
}
public function rewind(): void
{
$this->position = 0;
}
public function valid(): bool
{
return $this->position < count($this->products);
}
}
$products = new ProductCollection([
"Laptop",
"Monitor",
"Keyboard",
"Mouse"
]);
foreach ($products as $key => $product) {
echo $key . ": " . $product . "<br>";
}
Output:
0: Laptop
1: Monitor
2: Keyboard
3: Mouse
Here, the ProductCollection controls the iteration process through the five methods required by Iterator.
19. Key Points to Remember
PHP's Iterator interface provides a standard mechanism for traversing custom objects and collections.
The five primary methods are:
current() → returns the current value
key() → returns the current key
next() → moves to the next element
rewind() → moves to the beginning
valid() → checks whether the current position is valid
IteratorAggregate provides an alternative approach where a class returns another iterable object through getIterator().
The main advantage of iterators is that they allow objects and custom collections to work naturally with foreach, while keeping their internal data structures encapsulated. They are also useful for efficient processing of large or dynamically generated datasets.