《PHP8上級試験対策》Iteratorインターフェイスを使ったforeach制御の仕組み

  • URLをコピーしました!

はじめに

PHPの Iterator インターフェイスを実装すると、オブジェクトをforeachで回す方法を自由に定義できるようになります。これにより「どの順番で・どんな値を返すか」を自分で制御可能です。

キーワード:Iterator / Traversable / foreach制御 / current / valid /

目次

Iteratorインターフェイスとは?

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 内で呼び出される動作を自作できます。

foreach の内部処理イメージ

foreach($obj as $k => $v) が呼ばれたとき、PHPは実際には以下の順番でメソッドを実行します。

┌─────────────── foreach開始 ───────────────┐
│ rewind() → ループを最初に戻す                │
│ valid()  → 要素が存在するか確認              │
│ key()    → 現在のキーを取得                 │
│ current()→ 現在の値を取得                   │
│ (ループ本体を実行)                         │
│ next()   → 次の要素に進む                   │
└───────────────────────────────────────────┘

これを繰り返すことで「オブジェクトを配列のように回す」仕組みになっています。

サンプルコード

<?php
declare(strict_types=1);
error_reporting(-1);

class Hoge implements Iterator {
    private int $position = 0;

    public function __construct(
        private array $arr,
        public string $str,
    ){
        $this->position = 0;
    }

    public function rewind(): void {
        $this->position = 0;
    }
    public function current(): mixed {
        return $this->arr[$this->position];
    }
    public function key(): mixed {
        return $this->position;
    }
    public function next(): void {
        ++$this->position;
    }
    public function valid(): bool {
        return isset($this->arr[$this->position]);
    }
}

$obj = new Hoge([1,'2nd'], 'hello');
foreach($obj as $k => $v){
    echo "{$k}: {$v}\n";
}

実行結果

0: 1
1: 2nd

ASCIIアート図解で理解!

foreach の進行を図にすると、こうなります。

         ┌──────────┐
 start → │ rewind() │  position = 0
         └─────┬────┘
               │
               ▼
        ┌─────────────┐
        │ valid() ?    │─── no ──▶ end
        └─────┬───────┘
              │yes
              ▼
        ┌──────────┐   ┌─────────────┐
        │ key()    │→→→│ current()    │
        └──────────┘   └─────────────┘
              │               │
              └────── loop body ───────→ echo
                              │
                              ▼
                         ┌──────────┐
                         │ next()   │ position++
                         └────┬─────┘
                              │
                              └─── back to valid()

この流れを理解すると「なぜ出力が 0: 1 / 1: 2nd になるか」が腹落ちしますね。

まとめ

  • Iterator を実装すると foreachでの動きをカスタマイズ可能
  • 例では「数値インデックスで配列を順番に走査する実装」になっている
  • 実際には key() を工夫すれば "a" => 10 のような連想配列風の動作も可能

この記事が気に入ったら
いいねしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次