← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Iterators & IteratorAggregate

PHP PHP 5.0+ Intermediate
debt(d5/e3/b3/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches' (d5). PHPStan can detect some iterator misuse patterns like type mismatches, but common mistakes like forgetting rewind() or using Iterator instead of simpler IteratorAggregate are not caught by default static analysis — requires careful code review or runtime testing to notice iterator exhaustion issues.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix indicates switching from full Iterator implementation to IteratorAggregate with a generator is a localized refactor within one class. Fixing rewind() issues or switching to generators touches the class implementing the iterator but doesn't spread across the codebase.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). Iterator implementations are typically confined to specific classes wrapping data sources. The choice applies broadly (web, cli, queue-worker) but the structural impact is localized — a poorly implemented iterator affects code consuming that specific class, not system-wide architecture. It doesn't define the system's shape.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap' (t5). The misconception field explicitly states developers wrongly believe iterators are 'only useful for custom data structures' when they're valuable for memory-efficient streaming. Common mistakes like forgetting rewind() causing silent exhaustion after first use, or not knowing generators auto-implement Iterator, are documented gotchas that most PHP devs eventually learn but initially trip over.

About DEBT scoring →

Also Known As

PHP Iterator IteratorAggregate Traversable PHP SPL iterators

TL;DR

PHP interfaces that allow custom objects to be used in foreach loops, enabling lazy and memory-efficient iteration over any data source.

Explanation

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.

Common 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.

Code Examples

✗ Vulnerable
// Broken Iterator — missing rewind:
class NumberRange implements Iterator {
    private int $current = 0;
    public function __construct(private int $start, private int $end) {
        $this->current = $start;
    }
    public function current(): int { return $this->current; }
    public function key(): int { return $this->current - $this->start; }
    public function next(): void { $this->current++; }
    public function valid(): bool { return $this->current <= $this->end; }
    // Missing: public function rewind(): void { $this->current = $this->start; }
}
✓ Fixed
// Implement Iterator to make a class foreach-able
class NumberRange implements Iterator {
    private int $current;
    public function __construct(private int $start, private int $end) {
        $this->current = $start;
    }
    public function current(): int { return $this->current; }
    public function key(): int     { return $this->current - $this->start; }
    public function next(): void   { $this->current++; }
    public function rewind(): void { $this->current = $this->start; }
    public function valid(): bool  { return $this->current <= $this->end; }
}

foreach (new NumberRange(1, 3) as $i) { echo $i; } // 1 2 3

// IteratorAggregate — simpler approach
class UserCollection implements IteratorAggregate {
    public function getIterator(): ArrayIterator {
        return new ArrayIterator($this->users);
    }
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 41
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 1 ping S 0 pings S 0 pings M 1 ping T 0 pings W 2 pings T 1 ping F 0 pings S 1 ping S 0 pings M 0 pings T 3 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 1 ping W
PetalBot 1
No pings yesterday
Amazonbot 7 Scrapy 6 Ahrefs 4 ChatGPT 4 Unknown AI 2 Google 2 Claude 2 SEMrush 2 Perplexity 1 Meta AI 1 Bing 1 PetalBot 1
crawler 28 crawler_json 5
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Medium
⚡ 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
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Class with getItems() forcing callers to foreach($obj->getItems()); manual Iterator implementation when IteratorAggregate+generator would be simpler
Auto-detectable: ✗ No phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: Class Tests: Update


✓ schema.org compliant