{
    "slug": "iterator_pattern",
    "term": "Iterator Pattern",
    "category": "quality",
    "difficulty": "intermediate",
    "short": "Provides a uniform way to traverse a collection without exposing its internal structure — the foundation of PHP's foreach and SPL iterators.",
    "long": "The Iterator pattern defines traversal behaviour (current(), key(), next(), rewind(), valid()) separately from the collection, allowing the same collection to be traversed in multiple ways. PHP builds this into the language: foreach works on any class implementing Iterator or IteratorAggregate. SPL provides specialised iterators: ArrayIterator, RecursiveIteratorIterator, LimitIterator, FilterIterator, and AppendIterator. Custom iterators enable lazy evaluation — a DatabaseIterator fetches rows one at a time rather than loading all into memory. Generators (yield) provide a simpler alternative for most custom iteration needs.",
    "aliases": [
        "iterator",
        "PHP Iterator interface",
        "traversal pattern"
    ],
    "tags": [
        "design-pattern",
        "oop",
        "php",
        "behavioural"
    ],
    "misconception": "PHP's foreach already makes the iterator pattern unnecessary. Implementing the Iterator interface lets custom objects participate in foreach, generators provide lazy iteration for large datasets, and the pattern enables uniform traversal across different collection types.",
    "why_it_matters": "The Iterator pattern provides a standard traversal interface without exposing internal collection structure — clients iterate uniformly over arrays, database results, or file lines without knowing the source.",
    "common_mistakes": [
        "Loading an entire dataset into memory when a lazy iterator would do — a database cursor or generator is more efficient.",
        "Not implementing rewind() correctly — a second foreach produces no results because the iterator is exhausted.",
        "Implementing Iterator directly when PHP's IteratorAggregate is simpler for wrapping an existing traversable.",
        "Not using yield in generators when implementing lazy sequences — generators are PHP's lightweight iterator."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "php_iterators",
        "generators",
        "composite_pattern",
        "spl_data_structures"
    ],
    "prerequisites": [
        "php_spl_data_structures",
        "generators",
        "interfaces"
    ],
    "refs": [
        "https://refactoring.guru/design-patterns/iterator",
        "https://www.php.net/manual/en/class.iterator.php"
    ],
    "bad_code": "// Loading 1M rows into memory instead of iterating lazily:\nfunction getAllOrders(): array {\n    return $this->db->query('SELECT * FROM orders')->fetchAll(); // Loads everything\n}\nforeach (getAllOrders() as $order) { /* processes one at a time but fetched all */ }",
    "good_code": "// Iterator provides sequential access without exposing internal structure\nclass UserCursor implements Iterator {\n    private int \\$position = 0;\n    public function __construct(private array \\$users) {}\n    public function current(): User  { return \\$this->users[\\$this->position]; }\n    public function key(): int       { return \\$this->position; }\n    public function next(): void     { \\$this->position++; }\n    public function rewind(): void   { \\$this->position = 0; }\n    public function valid(): bool    { return isset(\\$this->users[\\$this->position]); }\n}\n\nforeach (new UserCursor(\\$users) as \\$user) {\n    \\$user->notify(\\$message);\n}\n\n// Generator alternative — memory efficient for large datasets:\nfunction userStream(PDO \\$pdo): \\Generator {\n    \\$stmt = \\$pdo->query('SELECT * FROM users');\n    while (\\$row = \\$stmt->fetch()) yield \\$row;\n}",
    "quick_fix": "Implement PHP's Iterator interface (current, key, next, rewind, valid) to make any custom collection work with foreach — or use a generator function which is simpler for most cases",
    "severity": "low",
    "effort": "medium",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/iterator_pattern",
        "html_url": "https://codeclaritylab.com/glossary/iterator_pattern",
        "json_url": "https://codeclaritylab.com/glossary/iterator_pattern.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Iterator Pattern](https://codeclaritylab.com/glossary/iterator_pattern) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/iterator_pattern"
            }
        }
    }
}