本文目录导读:

是的,PHP 的迭代器模式(Iterator Pattern) 正是用于遍历集合的一种设计模式。
它提供了一种统一的方法来顺序访问一个聚合对象(如数组、对象集合、数据库结果集等)中的各个元素,而又不需要暴露该对象的内部表示。
核心思想
将遍历行为与集合本身分离,集合只需提供一个返回迭代器的方法,而迭代器负责实现具体的遍历逻辑(如下一个、当前、是否有效等)。
为什么需要迭代器模式?
- 隐藏内部结构:不需要知道集合是用数组、链表还是数据库游标实现的。
- 统一遍历接口:无论集合内部多复杂,都可以用相同的
foreach或while循环遍历。 - 支持多种遍历方式:可以轻松实现不同的迭代器(如正序、倒序、过滤、分页迭代器)。
PHP 中的内置支持
PHP 已经内建了 Iterator 和 IteratorAggregate 接口,foreach 会自动调用它们。
使用 IteratorAggregate(推荐,更简单)
你只需要在集合类中实现一个 getIterator() 方法,返回一个 Traversable 对象(如 ArrayIterator)。
<?php
class MyCollection implements IteratorAggregate {
private array $items = [];
public function __construct(array $items) {
$this->items = $items;
}
// 只需返回一个迭代器对象
public function getIterator(): Traversable {
return new ArrayIterator($this->items);
}
}
// 使用
$collection = new MyCollection(['apple', 'banana', 'cherry']);
foreach ($collection as $item) {
echo $item . "\n";
}
// 输出: apple banana cherry
手动实现 Iterator 接口(更灵活,可自定义逻辑)
如果你需要自定义遍历方式(如只遍历偶数索引、延迟加载、树形结构深度遍历),需要实现以下 5 个方法:
<?php
class MyIterator implements Iterator {
private array $items;
private int $position = 0;
public function __construct(array $items) {
$this->items = array_values($items); // 重新索引
}
// 1. 返回当前元素
#[\ReturnTypeWillChange]
public function current() {
return $this->items[$this->position];
}
// 2. 返回当前键
public function key(): int {
return $this->position;
}
// 3. 移动到下一个元素
public function next(): void {
$this->position++;
}
// 4. 重置到第一个元素
public function rewind(): void {
$this->position = 0;
}
// 5. 检查当前位置是否有效
public function valid(): bool {
return isset($this->items[$this->position]);
}
}
// 使用
$data = ['a', 'b', 'c'];
$iterator = new MyIterator($data);
foreach ($iterator as $key => $value) {
echo "{$key}: {$value}\n";
}
// 输出: 0:a 1:b 2:c
更实际的例子:遍历数据库 ResultSet
很多 ORM(如 Doctrine、Eloquent)的查询结果集就是迭代器模式的实现,当你使用 foreach 遍历查询结果时,实际上就是在使用迭代器。
// 假设这是 Eloquent 的用法
$users = User::where('active', 1)->get(); // 返回一个集合对象
// 内部实现了 IteratorAggregate,因此可以直接 foreach
foreach ($users as $user) {
echo $user->name;
}
// 甚至可以用光标逐条处理大数据集
$cursor = User::where('active', 1)->cursor();
foreach ($cursor as $user) {
// 每次只从数据库取一条,内存占用极低
}
迭代器 vs. 普通数组遍历
| 特性 | 普通数组 foreach |
迭代器模式 |
|---|---|---|
| 数据结构 | 只能是数组 | 可以是数组、对象、数据库、文件等 |
| 遍历时能否修改集合 | 可以(但危险) | 可以自定义(如跳过已删除项) |
| 延迟加载 | 一次性加载全部 | 支持 yield 或分步加载 |
| 自定义遍历逻辑 | 需要手动写循环 | 封装在迭代器类中,可复用 |
高级技巧:使用 Generator(生成器)
生成器是迭代器的一种优雅实现,尤其适合大数据量或无限序列的遍历,它实现了 Iterator 接口,但代码更简洁。
function getItems(): Generator {
yield 'first';
yield 'second';
yield 'third';
}
$iterator = getItems();
foreach ($iterator as $item) {
echo $item;
}
// 或者实现一个可过滤的迭代器
function filterIterator(iterable $items, callable $callback): Generator {
foreach ($items as $item) {
if ($callback($item)) {
yield $item;
}
}
}
是的,迭代器模式在 PHP 中就是为遍历集合而生的。
PHP 的核心库通过 Iterator、IteratorAggregate 和 Generator 为开发者提供了强大且灵活的支持,无论是简单的数组遍历,还是复杂的树形结构、数据库游标,迭代器模式都能让你的代码更清晰、更可维护。