{
    "slug": "php_iterators",
    "term": "Iterators & IteratorAggregate",
    "category": "php",
    "difficulty": "intermediate",
    "short": "PHP interfaces that allow custom objects to be used in foreach loops, enabling lazy and memory-efficient iteration over any data source.",
    "long": "PHP's Iterator interface requires five methods: current(), key(), next(), rewind(), valid(). IteratorAggregate requires just getIterator(), which returns an Iterator or Traversable — simpler for delegation. Custom iterators enable foreach over database result sets (fetching row by row), API paginated responses, filesystem trees, and infinite sequences — all with O(1) memory. PHP's SPL provides useful built-in iterators: DirectoryIterator, FilesystemIterator, RecursiveIteratorIterator, ArrayIterator, and LimitIterator. Generators (yield) are often a simpler alternative to manual Iterator implementation.",
    "aliases": [
        "PHP Iterator",
        "IteratorAggregate",
        "Traversable",
        "PHP SPL iterators"
    ],
    "tags": [
        "php",
        "oop",
        "spl",
        "performance"
    ],
    "misconception": "PHP iterators are only useful for custom data structures. Iterators enable memory-efficient processing of large datasets, lazy evaluation pipelines, and make any object usable in foreach — they are particularly valuable for streaming database results without loading everything into memory.",
    "why_it_matters": "PHP's Iterator and IteratorAggregate interfaces enable objects to be traversed with foreach — custom iterators allow lazy loading, filtering, and transformation without loading full datasets into memory.",
    "common_mistakes": [
        "Implementing Iterator but forgetting rewind() — the iterator works once then is silently exhausted.",
        "Not implementing IteratorAggregate when you just need to wrap an existing array or Traversable — it's simpler.",
        "Returning false from current() on an empty iterator instead of returning null — both work but false is less predictable.",
        "Not using generators (yield) for lazy sequences — they automatically implement the Iterator protocol."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "generators",
        "spl_data_structures",
        "array_functions"
    ],
    "prerequisites": [
        "generators",
        "php_spl_data_structures",
        "interfaces"
    ],
    "refs": [
        "https://www.php.net/manual/en/class.iterator.php",
        "https://www.php.net/manual/en/class.iteratoraggregate.php"
    ],
    "bad_code": "// Broken Iterator — missing rewind:\nclass NumberRange implements Iterator {\n    private int $current = 0;\n    public function __construct(private int $start, private int $end) {\n        $this->current = $start;\n    }\n    public function current(): int { return $this->current; }\n    public function key(): int { return $this->current - $this->start; }\n    public function next(): void { $this->current++; }\n    public function valid(): bool { return $this->current <= $this->end; }\n    // Missing: public function rewind(): void { $this->current = $this->start; }\n}",
    "good_code": "// Implement Iterator to make a class foreach-able\nclass NumberRange implements Iterator {\n    private int \\$current;\n    public function __construct(private int \\$start, private int \\$end) {\n        \\$this->current = \\$start;\n    }\n    public function current(): int { return \\$this->current; }\n    public function key(): int     { return \\$this->current - \\$this->start; }\n    public function next(): void   { \\$this->current++; }\n    public function rewind(): void { \\$this->current = \\$this->start; }\n    public function valid(): bool  { return \\$this->current <= \\$this->end; }\n}\n\nforeach (new NumberRange(1, 3) as \\$i) { echo \\$i; } // 1 2 3\n\n// IteratorAggregate — simpler approach\nclass UserCollection implements IteratorAggregate {\n    public function getIterator(): ArrayIterator {\n        return new ArrayIterator(\\$this->users);\n    }\n}",
    "quick_fix": "Implement IteratorAggregate (simpler) rather than Iterator directly — return a generator from getIterator() and your class instantly works with foreach without implementing all 5 Iterator methods",
    "severity": "low",
    "effort": "medium",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/php_iterators",
        "html_url": "https://codeclaritylab.com/glossary/php_iterators",
        "json_url": "https://codeclaritylab.com/glossary/php_iterators.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": "[Iterators & IteratorAggregate](https://codeclaritylab.com/glossary/php_iterators) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/php_iterators"
            }
        }
    }
}