interface Iterator extends Traversable {
public function current(): mixed; // 返回當前元素值
public function key(): mixed; // 返回當前元素鍵
public function next(): void; // 移動到下一個元素
public function rewind(): void; // 重置到第一個元素
public function valid(): bool; // 當前位置是否有效
}
rewind() — 循環開始前調用一次,重置內部指針。valid() — 每次迭代前檢查,返回 false 則結束循環。current() — 返回當前元素值供 $value 使用。key() — 返回當前元素鍵供 $key 使用。next() — 本輪結束後調用,移動指針。valid() 為 false。
class MyIterator implements Iterator {
private $position = 0;
private $data = ['first', 'second', 'third'];
public function __construct() {
$this->position = 0;
}
public function rewind(): void {
var_dump(__METHOD__);
$this->position = 0;
}
public function current(): mixed {
var_dump(__METHOD__);
return $this->data[$this->position];
}
public function key(): mixed {
var_dump(__METHOD__);
return $this->position;
}
public function next(): void {
var_dump(__METHOD__);
++$this->position;
}
public function valid(): bool {
var_dump(__METHOD__);
return isset($this->data[$this->position]);
}
}
// 使用
$it = new MyIterator();
foreach ($it as $key => $value) {
echo "$key => $value\n";
}
/*
輸出順序:
rewind → valid → current → key → (loop body)
next → valid → current → key → (loop body)
next → valid → current → key → (loop body)
next → valid(false) → 結束
*/
若類本身不想實現 5 個方法,可實現 IteratorAggregate,僅需 getIterator() 返回任意 Traversable(如 ArrayIterator、Generator)。
class DataCollection implements IteratorAggregate {
private $items = [];
public function add($item) { $this->items[] = $item; }
public function getIterator(): Traversable {
return new ArrayIterator($this->items); // 或 return new MyIterator($this->items);
// 甚至可用 Generator:
// foreach ($this->items as $k => $v) yield $k => $v;
}
}
$coll = new DataCollection();
$coll->add('a'); $coll->add('b');
foreach ($coll as $k => $v) echo "$k:$v\n";
| 問題 | 解決 |
|---|---|
valid() 邏輯錯誤導致死循環 | 嚴格檢查指針邊界,return $this->position < count($this->data); |
rewind() 重置不徹底 | 確保所有內部狀態(指針、緩存、文件句柄)歸零 |
| 資源洩漏(文件、數據庫游標) | 在 __destruct 或顯式 close() 中釋放,或實現 Countable 配合 |
| 鍵類型不一致 | key() 應返回 int|string,避免返回物件/資源 |
| 維度 | Generator (yield) | 手寫 Iterator |
|---|---|---|
| 代碼量 | 極少 | 樣板代碼多 |
| 狀態保持 | 自動(執行上下文) | 手動(屬性) |
| 雙向通訊 | 支援 send()/throw() | 需自行實現 |
| 可重置 | 不可(一次性) | 可實現 rewind() |
| 適用場景 | 流式處理、協程、大數據 | 可重用集合、複雜邏輯、需隨機訪問 |
掌握 Iterator 協議是理解 PHP 遍歷機制的鑰匙。雖然 yield 生成器覆蓋了 90% 的場景,但手寫 Iterator/IteratorAggregate 在構建可重用集合類、封裝資源游標、實現隨機訪問時仍不可替代。記住 rewind → valid → current → key → next 的調用順序,即可從容應對任何遍歷需求。