


Implementing `Iterator` and `IteratorAggregate` for Custom Object Iteration
To make PHP custom objects iterable, you can choose IteratorAggregate or Iterator interface; 1. When using IteratorAggregate, you only need to implement the getIterator() method and return a Traversable object, which is suitable for simply wrapping existing collections; 2. When using Iterator, you need to implement five methods: rewind, current, key, next and valid, which are suitable for scenarios where it requires fine control of the iteration process; you should choose the appropriate method based on whether complex iteration logic is needed, both of which ensure that the object can be used in foreach.
When working with custom objects in PHP, you may want to make them iterable—so they can be used in foreach
loops just like arrays or other built-in iterable types. PHP provides two primary interfaces for this: Iterator
and IteratorAggregate
. Each offer a different level of control and simplicity depending on your use case.

Let's explore both approaches and how to implement them effectively.
Using IteratorAggregate
(Simpler Approach)
The IteratorAggregate
interface is ideal when you want to wrap an existing iterable (like an array or ArrayObject
) and expose it for iteration without managing internal state manually.

You only need to implement one method: getIterator()
, which returns an Traversable
object.
class BookCollection implements IteratorAggregate { private array $books; public function __construct(array $books) { $this->books = $books; } public function getIterator(): Traversable { return new ArrayIterator($this->books); } }
Now you can iterate over the object:

$collection = new BookCollection(['PHP Basics', 'Design Patterns', 'Advanced OOP']); foreach ($collection as $book) { echo $book . PHP_EOL; }
This outputs:
PHP Basics Design Patterns Advanced OOP
✅ Pros :
- Simple to implement
- Reuses existing iterators like
ArrayIterator
- Less error-prone
❌ Cons :
- Less control over iteration logic
- Not suitable if you need complex iteration behavior
Using Iterator
(Fine-Grained Control)
If you need full control over how iteration procedures (eg, lazy loading, computed values, or complex data structures), implement the Iterator
interface directly.
It requires five methods:
-
current()
– returns the current element -
key()
– returns the current key -
next()
– moves to the next element -
rewind()
– resets the iterator to the beginning -
valid()
– checks if the current position is valid
Here's an example of a custom iterator that lazy generates even numbers:
class EvenNumberGenerator implements Iterator { private int $current; private int $max; private int $position; public function __construct(int $max) { $this->max = $max; } public function rewind(): void { $this->current = 0; $this->position = 0; } public function current(): int { return $this->current; } public function key(): int { return $this->position; } public function next(): void { $this->current = 2; $this->position ; } public function valid(): bool { return $this->current <= $this->max; } }
Usage:
$evens = new EvenNumberGenerator(10); foreach ($evens as $index => $value) { echo "[$index] => $value" . PHP_EOL; }
Output:
[0] => 0 [1] => 2 [2] => 4 [3] => 6 [4] => 8 [5] => 10
✅ Pros :
- Full control over iteration process
- Can support lazy evaluation, infinite sequences, or dynamic data
- Efficient for large or generated datasets
❌ Cons :
- More boilerplate code
- Risk of bugs if state management is incorrect
When to Use Which?
- Use
IteratorAggregate
when your object wraps a collection or you can delegate iteration to another object. It's cleaner and safer. - Use
Iterator
when you need custom iteration logic, such as filtering on-the-fly, generating values, or managing complex internal state.
You can even combine both — for example, having a class implement IteratorAggregate
that returns a custom Iterator
instance for advanced logic.
A Note on Traversable
Both Iterator
and IteratorAggregate
extend Traversable
(though not directly — it's a built-in engine interface). This means any class implementing either can be used in foreach
. However, Traversable
cannot be implemented directly; you must use one of the two.
Basically, chosen based on your needs: wrap and reuse with IteratorAggregate
, or build from scratch with Iterator
.
The above is the detailed content of Implementing `Iterator` and `IteratorAggregate` for Custom Object Iteration. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

When traversing an array with reference, the reference variable must be destroyed immediately after the loop to avoid unexpected modification; 1. After the loop, the reference still points to the last element of the original array, and subsequent assignments will accidentally change the array. The solution is to use unset($value); 2. Repeating the same reference variable in a nested loop will cause warning or unpredictable behavior, and unset must be unset after each loop; 3. Modifying the array structure (such as unset element) during traversal will cause unpredictable iteration behavior, and you should avoid or use a for loop instead; alternatives include using array_map or modifying the array through key names, which is safer and clearer. In short, use reference traversal to be cautious, and you must unset after each use to ensure safety.

Loop-invariantcodemotion(LICM)mustbeappliedmanuallyinPHPbecausetheZendEnginedoesnotautomaticallyoptimizeloop-invariantexpressions.1.Cachecount()resultsbeforethelooptoavoidrepeatedcalls.2.MoveinvariantfunctioncallslikegetUserEmail($user)outsideconditi

Use array_map and array_reduce to replace overused foreach, making PHP code simpler, readable and easier to test. 1. Use array_map instead of loops to convert data, avoid manually managing arrays and mutable states, and make the intention clearer; 2. Use array_reduce to aggregate arrays as a single value or structure, and avoid external variables and side effects through initial values and accumulators; 3. Use array_map, array_filter and array_reduce to build a readable data processing pipeline to improve composition and expression; 4. Pay attention to always providing initial values for array_reduce to understand the advanced nature of array_map

It will cause problems when traversing the array, because the deletion or insertion of elements will change the index structure, while the loop variables or iterators are not updated synchronously, resulting in skipping elements or exceptions; for example, when traversing from front to back in JavaScript and deleting elements, subsequent elements move forward but incrementing indexes will skip the next element; directly modifying the list in Python may raise a RuntimeError or behavioral exception; methods to avoid this problem include: 1. Reverse traversal, deleting elements does not affect unprocessed low-index items; 2. Collect the index or elements to be modified first, and then process them uniformly after iteration, and the deletion requires reverse order operation; 3. Use functional methods such as filter and map to generate a new array to avoid mutation of the original array; also pay attention to forE

NaivelyawaitinginsideloopsinasyncPHPcausessequentialexecution,defeatingconcurrency;2.InAmp,useAmp\Promise\all()torunalloperationsinparallelandwaitforcompletion,orAmp\Iterator\fromIterable()toprocessresultsastheyarrive;3.InReactPHP,useReact\Promise\al

PHP supports array deconstruction in foreach loops. 1. It can directly deconstruct index subarrays such as [$x,$y] to extract coordinates; 2. It supports ['key'=>$var] syntax deconstructing associative arrays; 3. It can provide default values for missing values through $var=default; 4. It can combine key names to capture such as $key=>[$a,$b] to process nested structures, which makes the code more concise, safe and easy to read.

To make PHP custom objects iterable, you can choose IteratorAggregate or Iterator interface; 1. When using IteratorAggregate, you only need to implement the getIterator() method and return a Traversable object, which is suitable for simply wrapping existing collections; 2. When using Iterator, you need to implement five methods: rewind, current, key, next and valid, which are suitable for scenarios where it requires fine control of the iteration process; you should choose the appropriate method based on whether complex iteration logic is needed, both of which ensure that the object can be used in foreach.

Extract nested logic to independent functions to reduce complexity and improve readability; 2. Use list comprehensions or generator expressions when applicable to make the code concise; 3. Flatten the data structure through iterative tools or data preprocessing to reduce nesting; 4. Use built-in library functions such as itertools to optimize loop structures; 5. Consider object-oriented or functional programming mode to encapsulate repetitive logic; the ultimate goal is to make the code intention clear through clear abstraction and naming, avoid understanding difficulties caused by deep nesting, thereby improving maintainability and readability.
