【PHP8.x】CallbackFilterIterator::rewind()メソッドの使い方
rewindメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
rewindメソッドは、CallbackFilterIteratorが内部で保持しているイテレータを、その最初の要素に巻き戻す処理を実行するメソッドです。CallbackFilterIteratorは、配列やオブジェクトの集合などを順番に処理するための仕組みであるイテレータをラップし、コールバック関数で条件に合う要素だけを抽出します。このrewindメソッドは、そのフィルタリング対象となる元のイテレータのrewindメソッドを呼び出し、内部ポインタを先頭の位置にリセットします。この操作により、イテレータはコレクションの最初の要素を指す状態になります。通常、このメソッドはforeachループのような反復処理が開始される際に、PHPエンジンによって暗黙的に呼び出されます。そのため、開発者がコード上で直接このメソッドを記述する機会は少ないですが、イテレータの反復処理を意図的に最初からやり直したい場合に明示的に呼び出すことができます。このメソッドはIteratorインターフェースで定義されているメソッドの一つであり、返り値はありません。
構文(syntax)
1<?php 2 3// フィルタリング対象のイテレータを用意します 4$innerIterator = new ArrayIterator([1, 2, 3, 4, 5, 6]); 5 6// コールバック関数でフィルタリングするイテレータを作成します 7$filterIterator = new CallbackFilterIterator($innerIterator, function ($current) { 8 // 偶数のみを許可します 9 return $current % 2 === 0; 10}); 11 12// 一度ループして、イテレータの内部ポインタを最後まで進めます 13foreach ($filterIterator as $value) { 14 // このループでは何も処理しません 15} 16 17// rewind()メソッドを呼び出して、イテレータの内部ポインタを先頭に戻します 18$filterIterator->rewind(); 19 20?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
戻り値なし
戻り値はありません
サンプルコード
PHP: CallbackFilterIteratorでジェネレータを巻き戻し可能にする
1<?php 2 3declare(strict_types=1); 4 5/** 6 * CallbackFilterIterator::rewind の動作と、 7 * 巻き戻し不可能なジェネレータを巻き戻し可能にする方法を示すサンプルコード。 8 */ 9final class RewindableGeneratorExample 10{ 11 /** 12 * サンプルを実行します。 13 */ 14 public static function run(): void 15 { 16 // 1. 1から10までの数値を生成するジェネレータ関数を定義します。 17 // ジェネレータは一度しかイテレートできず、デフォルトでは巻き戻し(rewind)できません。 18 $numberGenerator = function (): Generator { 19 for ($i = 1; $i <= 10; $i++) { 20 yield $i; 21 } 22 }; 23 24 // 2. ジェネレータを配列に変換することで、巻き戻し可能なデータ構造にします。 25 // これが「rewindable generator」を実現する一般的な方法の一つです。 26 $rewindableNumbers = iterator_to_array($numberGenerator()); 27 28 // 3. 配列を元に、巻き戻し可能な ArrayIterator を作成します。 29 $iterator = new ArrayIterator($rewindableNumbers); 30 31 // 4. 偶数のみを許可するコールバック関数を定義します。 32 $filterCallback = function (int $current): bool { 33 // $current は現在の要素の値です。 34 return $current % 2 === 0; 35 }; 36 37 // 5. ArrayIterator とコールバック関数を使って CallbackFilterIterator を作成します。 38 $filterIterator = new CallbackFilterIterator($iterator, $filterCallback); 39 40 echo "1回目のループ (偶数のみ):" . PHP_EOL; 41 // foreach ループを開始すると、内部的に rewind() メソッドが自動的に呼び出され、 42 // イテレータが先頭にセットされます。 43 foreach ($filterIterator as $number) { 44 echo $number . PHP_EOL; 45 } 46 47 echo PHP_EOL; 48 echo "イテレータを rewind() で明示的に巻き戻します。" . PHP_EOL; 49 50 // 6. rewind() を呼び出すことで、イテレータの内部ポインタを再び先頭に戻します。 51 // これにより、もう一度最初からイテレーションできます。 52 // もし元のイテレータが巻き戻し不可能(例:生のジェネレータ)な場合、ここで例外が発生します。 53 $filterIterator->rewind(); 54 55 echo "2回目のループ (巻き戻し後):" . PHP_EOL; 56 // 巻き戻されたので、再度同じ結果をループ処理で取得できます。 57 foreach ($filterIterator as $number) { 58 echo $number . PHP_EOL; 59 } 60 } 61} 62 63RewindableGeneratorExample::run();
CallbackFilterIterator::rewindメソッドは、イテレータを最初の要素に巻き戻すための機能を提供します。このメソッドは引数を取らず、何も値を返しません(戻り値なし)。foreachループが開始される際などに、PHPによって内部的に自動で呼び出されます。
このサンプルコードは、rewindメソッドの具体的な動作を示しています。PHPのジェネレータは、一度最後まで実行すると巻き戻すことができません。そこでこのコードでは、まずジェネレータが生成する値をiterator_to_array関数で配列に変換しています。配列は何度でも先頭から読み直せるため、これにより実質的に「巻き戻し可能」なデータ構造を作成しています。
この配列から偶数のみを抽出するCallbackFilterIteratorを作成し、1回目のforeachループを実行します。ループが終了した後、$filterIterator->rewind()を明示的に呼び出すことで、イテレータの内部ポインタを再び先頭に戻しています。この操作により、イテレータがリセットされるため、2回目のforeachループでも1回目と全く同じ結果を得ることができます。このように、rewindメソッドはイテレータを再利用可能にする重要な役割を担います。
rewind()メソッドは、イテレータを先頭に戻し、再度ループ処理できるようにします。foreachループは内部で自動的にこのメソッドを呼び出すため、通常は明示的な呼び出しは不要です。最も重要な注意点は、サンプルで使われているジェネレータが本来は巻き戻し不可能なことです。そのままCallbackFilterIteratorに渡して2回目のループを行おうとするとエラーになります。サンプルではiterator_to_array()で配列に変換してこの問題を回避していますが、これは全データをメモリに読み込むため、巨大なデータを扱う際はメモリ使用量が増大する点に注意してください。CallbackFilterIteratorが巻き戻せるかどうかは、内部に保持しているイテレータの性質に依存します。
PHP CallbackFilterIterator rewindで配列を再走査する
1<?php 2 3/** 4 * CallbackFilterIteratorとrewindメソッドの動作を理解するためのサンプルクラス 5 * 6 * イテレータをforeachで複数回ループさせると、その都度rewind()が内部的に 7 * 呼び出され、イテレーションが最初から開始されることを示します。 8 */ 9class RewindExample 10{ 11 /** 12 * サンプルコードの実行 13 * 14 * @return void 15 */ 16 public static function run(): void 17 { 18 // フィルタリング対象の配列 19 $numbers = [1, 2, 3, 4, 5, 6, 7, 8]; 20 21 // 配列をイテレータオブジェクトに変換 22 $arrayIterator = new ArrayIterator($numbers); 23 24 // フィルタリングのルールを定義するコールバック関数 25 // この例では、偶数のみを許可します (trueを返す) 26 $filterCallback = function (int $current): bool { 27 return $current % 2 === 0; 28 }; 29 30 // 配列イテレータとコールバック関数を使って、CallbackFilterIteratorを作成 31 $filterIterator = new CallbackFilterIterator($arrayIterator, $filterCallback); 32 33 // 1回目のループ 34 // foreachが開始されると、内部的にrewind()が呼び出され、 35 // イテレータは先頭にセットされます。 36 echo "1回目のループ (偶数のみ出力):" . PHP_EOL; 37 foreach ($filterIterator as $number) { 38 echo $number . " "; 39 } 40 echo PHP_EOL . PHP_EOL; 41 42 // 2回目のループ 43 // もう一度foreachを開始すると、再びrewind()が呼び出されます。 44 // これにより、イテレーションが最初からやり直されます。 45 echo "2回目のループ (rewind()により再度先頭から):" . PHP_EOL; 46 foreach ($filterIterator as $number) { 47 echo $number . " "; 48 } 49 echo PHP_EOL; 50 } 51} 52 53// クラスのメソッドを実行 54RewindExample::run();
このPHPサンプルコードは、CallbackFilterIteratorクラスが持つrewindメソッドの動作を解説するものです。CallbackFilterIteratorは、配列などの繰り返し可能なデータに対して、指定した条件で要素を絞り込む(フィルタリングする)機能を提供します。このコードでは、1から8までの数値の中から偶数のみを取り出すフィルタを作成しています。
rewindメソッドは、イテレータの内部的な現在位置を先頭に戻す役割を持ちます。このメソッドに引数や戻り値はありません。
PHPのforeach構文は、ループ処理を開始する際に、対象となるイテレータのrewindメソッドを内部で自動的に呼び出します。これにより、繰り返し処理が必ず先頭の要素から始まることが保証されます。
サンプルコードでは、同じCallbackFilterIteratorオブジェクトに対してforeachループを2回実行しています。1回目のループで偶数が出力された後、2回目のループが始まる際にも再びrewindメソッドが呼び出されるため、イテレータの位置がリセットされます。その結果、2回目のループでも1回目と同様に、配列の先頭から偶数が順番に出力されます。このように、rewindメソッドは、一つのイテレータを何度でも最初から使えるようにするための重要な仕組みです。
rewindメソッドは、イテレータを先頭の要素に戻す役割を持ちます。PHPのforeachループは、処理を開始する際に、対象となるイテレータのrewindメソッドを内部で自動的に呼び出します。そのため、サンプルコードのように同じフィルタイテレータを複数回foreachで処理しても、その都度データが先頭に巻き戻され、毎回最初からループが実行されます。この挙動はCallbackFilterIteratorだけでなく、Iteratorインターフェースを実装する多くのクラスに共通する仕組みです。通常はrewindを直接呼び出す必要はありませんが、foreachが自動で巻き戻しを行うことを理解しておくことが重要です。