はじめに
PHPの Iterator
インターフェイスを実装すると、オブジェクトをforeachで回す方法を自由に定義できるようになります。これにより「どの順番で・どんな値を返すか」を自分で制御可能です。
目次
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
のような連想配列風の動作も可能