What It Is
The Iterator pattern walks through a collection without exposing how it is stored. The caller asks for one item at a time — whether the data lives in an array, a tree or a database stays private.
PHP builds the pattern right in: foreach accepts any object implementing the built-in Iterator interface, and a generator — a function with yield — implements it for you. For plain arrays, foreach already is your iterator; the pattern matters when the storage is hidden or the walk is complicated.
Example: Walking a Playlist
The playlist keeps its songs private. play() is a generator: it hands out one song per loop turn — the storage behind it could change completely without breaking any caller.
A generator yields one song at a time
The loop never touches the array inside the playlist. Each yield pauses the function until foreach asks for the next song. Swap the array for a linked list or lazy loading, and this loop still runs unchanged.
Output: PHP script
<?php
class Playlist {
/** @var string[] */
private array $songs;
public function __construct(string ...$songs) {
$this->songs = $songs;
}
// A generator: pauses at every yield until the loop asks again.
public function play(): \Generator {
foreach ($this->songs as $song) {
yield $song;
}
}
}
$playlist = new Playlist("intro", "verse", "chorus");
foreach ($playlist->play() as $song) {
echo "playing: ", $song, "\n";
}
When to Use It
Use it when the collection's insides must stay private, when walking is nontrivial (trees, pages from an API), or when items should be produced lazily, one at a time.
Skip it for plain arrays in your own code — foreach over the array is shorter, faster and known to every reader.
Pros and Cons
Pros: storage stays private and changeable; generators make an iterator out of one function; complicated traversal is written once.
Cons: more machinery than a plain array walk; a live iterator over a changing collection is a classic source of subtle bugs.