首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP Iterator 介面完整實現指南:從原理到自定義迭代器的 foreach 協議

     編輯:PHP 相關知識

Iterator 介面定義


interface Iterator extends Traversable {
    public function current(): mixed;   // 返回當前元素值
    public function key(): mixed;       // 返回當前元素鍵
    public function next(): void;       // 移動到下一個元素
    public function rewind(): void;     // 重置到第一個元素
    public function valid(): bool;      // 當前位置是否有效
}

foreach 執行流程(核心協議)

  1. rewind() — 循環開始前調用一次,重置內部指針。
  2. valid() — 每次迭代前檢查,返回 false 則結束循環。
  3. current() — 返回當前元素值供 $value 使用。
  4. key() — 返回當前元素鍵供 $key 使用。
  5. next() — 本輪結束後調用,移動指針。
  6. 回到第 2 步,直到 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) → 結束
*/

進階:IteratorAggregate 代理模式

若類本身不想實現 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,避免返回物件/資源

生成器 vs 手寫 Iterator

維度Generator (yield)手寫 Iterator
代碼量極少樣板代碼多
狀態保持自動(執行上下文)手動(屬性)
雙向通訊支援 send()/throw()需自行實現
可重置不可(一次性)可實現 rewind()
適用場景流式處理、協程、大數據可重用集合、複雜邏輯、需隨機訪問

結語

掌握 Iterator 協議是理解 PHP 遍歷機制的鑰匙。雖然 yield 生成器覆蓋了 90% 的場景,但手寫 Iterator/IteratorAggregate 在構建可重用集合類、封裝資源游標、實現隨機訪問時仍不可替代。記住 rewind → valid → current → key → next 的調用順序,即可從容應對任何遍歷需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved