【PHP8.x】FilterIterator::rewind()メソッドの使い方
rewindメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『rewindメソッドは、FilterIteratorを最初の要素に巻き戻す処理を実行するメソッドです』 このメソッドは、Iteratorインターフェースで定められた要件を満たすために実装されていますが、FilterIteratorではフィルタリングの特性を考慮した特別な動作をします。rewindが呼び出されると、まず内部的に保持している元のイテレータのrewindメソッドを実行し、そのポインタを先頭に戻します。その後、フィルタリング条件を定義したacceptメソッドを満たす最初の要素が見つかるまで、イテレータを順に進めていきます。条件に合致する要素が最初に見つかった時点で、内部ポインタはその位置で停止します。もし、イテレータの最後まで条件を満たす要素が一つも存在しなかった場合、イテレータは有効な状態ではなくなります。通常、このメソッドを直接呼び出すことは少なく、foreachループなどでFilterIteratorオブジェクトを走査する際に、PHPの内部処理として自動的に呼び出されます。これにより、常にフィルタリング後の結果セットの先頭から処理を開始することが保証されます。このメソッドは値を返しません。
構文(syntax)
1<?php 2// 偶数のみをフィルタリングするカスタムイテレータクラスを定義します 3class EvenNumberFilter extends FilterIterator 4{ 5 public function accept(): bool 6 { 7 // 親イテレータの現在の値が偶数であれば true を返します 8 return $this->getInnerIterator()->current() % 2 === 0; 9 } 10} 11 12// 元となるデータを持つイテレータを作成します 13$numbers = new ArrayIterator([1, 2, 3, 4, 5, 6]); 14 15// カスタムイテレータをインスタンス化します 16$iterator = new EvenNumberFilter($numbers); 17 18// foreach は内部で rewind() を呼び出し、先頭から処理を開始します 19// 最初の有効な要素は 2 です 20 21// next() を呼び出して、イテレータを次の有効な要素 (4) へ進めます 22$iterator->next(); 23 24// この時点での現在の要素は 4 です 25// echo $iterator->current(); 26 27// rewind() メソッドを呼び出し、イテレータを先頭に巻き戻します 28$iterator->rewind(); 29 30// 巻き戻されたため、現在の要素は最初の有効な要素である 2 に戻ります 31echo $iterator->current(); // 2
引数(parameters)
引数なし
引数はありません
戻り値(return)
戻り値なし
戻り値はありません
サンプルコード
PHP FilterIteratorで巻き戻し可能な走査
1<?php 2 3/** 4 * 偶数のみをフィルタリングするカスタムイテレータ。 5 * 6 * FilterIteratorを継承し、accept()メソッドでフィルタリングの条件を定義します。 7 */ 8class EvenNumberFilter extends FilterIterator 9{ 10 /** 11 * 現在の要素が受け入れ可能かどうかを判定します。 12 * 13 * @return bool 現在の要素が偶数の場合はtrue、それ以外はfalseを返します。 14 */ 15 public function accept(): bool 16 { 17 // current()メソッドで内部イテレータの現在の値を取得し、偶数かどうかを判定 18 return $this->current() % 2 === 0; 19 } 20} 21 22/** 23 * FilterIteratorとrewind()メソッドの動作を確認する関数。 24 * 25 * ジェネレータは通常、一度しか走査できません(巻き戻し不可)。 26 * しかし、ArrayIteratorのような巻き戻し可能なイテレータをFilterIteratorでラップすると、 27 * rewind()メソッドによってイテレータが先頭に戻され、何度も走査できます。 28 */ 29function demonstrateRewindableFilterIterator(): void 30{ 31 // 1. 元となるデータと、巻き戻し可能なArrayIteratorを作成 32 $numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 33 $iterator = new ArrayIterator($numbers); 34 35 // 2. 作成したイテレータをEvenNumberFilterでラップ 36 $evenFilter = new EvenNumberFilter($iterator); 37 38 echo "1回目の走査(偶数のみ表示):\n"; 39 // foreachループは内部で自動的にrewind()を呼び出してから処理を開始します 40 foreach ($evenFilter as $number) { 41 echo $number . ' '; 42 } 43 echo "\n\n"; 44 45 echo "2回目の走査(rewind()呼び出し後):\n"; 46 // 3. rewind()を明示的に呼び出し、イテレータを先頭に戻す 47 $evenFilter->rewind(); 48 49 // もう一度ループを実行しても、正しく先頭から処理が再開されることを確認 50 foreach ($evenFilter as $number) { 51 echo $number . ' '; 52 } 53 echo "\n"; 54} 55 56// 関数を実行して動作を確認 57demonstrateRewindableFilterIterator(); 58 59?>
FilterIteratorクラスのrewindメソッドは、イテレータを最初の要素に巻き戻すために使用されます。このメソッドは引数を取らず、戻り値もありません。その役割は、イテレータの内部的な現在位置を示すポインタを、コレクションの先頭に戻すことです。
サンプルコードでは、数値の配列を元にしたArrayIteratorを、偶数のみを通過させるEvenNumberFilterで包んでいます。foreachループでイテレータを処理する際、ループの開始時にPHPが内部で自動的にrewindメソッドを呼び出します。これにより、イテレータは必ず先頭から走査を開始し、結果として偶数「2 4 6 8 10」が出力されます。
次に、コード中で明示的に$evenFilter->rewind()を呼び出しています。この操作により、一度最後まで処理が進んだイテレータが、再び強制的に先頭の状態に戻されます。そのため、2回目のforeachループを実行した際も、もう一度最初から走査が始まり、同じ偶数の結果が出力されます。このようにrewindメソッドは、一度フィルタリングした結果を再利用したり、繰り返し処理したりする場合に不可欠な機能です。
FilterIteratorは、内部に持つ元のイテレータの性質に依存します。rewindメソッドはイテレータを先頭に戻す機能ですが、foreachループは処理開始時に自動でこのメソッドを呼び出すため、サンプル中の2回目のループ前にある明示的な呼び出しは通常不要です。最も重要な注意点は、FilterIteratorを何度も利用できるかは、ラップしている元のイテレータが巻き戻し可能かどうかにかかっている点です。この例ではArrayIteratorなので問題ありませんが、一度しか走査できないジェネレータなどを渡すと、2回目のforeachは空になるかエラーを引き起こすため注意してください。
PHP FilterIterator rewind()で先頭に戻す
1<?php 2 3/** 4 * 偶数のみを通過させるカスタムフィルタクラス 5 * 6 * FilterIteratorを継承し、accept()メソッドでフィルタリングの条件を定義します。 7 * rewind()メソッドは、このイテレータがforeachなどで使われる際に、 8 * 内部で自動的に呼び出され、イテレータを最初の位置に戻します。 9 */ 10class EvenNumberFilter extends FilterIterator 11{ 12 /** 13 * 現在の要素が受け入れられるかどうかを判定します。 14 * 15 * @return bool 現在の要素が偶数の場合はtrue、それ以外はfalseを返します。 16 */ 17 public function accept(): bool 18 { 19 // current()メソッドでイテレータの現在の値を取得し、偶数かどうかをチェックします。 20 return $this->current() % 2 === 0; 21 } 22} 23 24// フィルタリング対象のデータとなる配列 25$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 26 27// 配列からイテレータオブジェクトを作成します 28$arrayIterator = new ArrayIterator($numbers); 29 30// 作成したイテレータをカスタムフィルタでラップします 31$iterator = new EvenNumberFilter($arrayIterator); 32 33echo "1回目のループ処理:\n"; 34// foreachループは、最初に内部でrewind()を呼び出し、イテレータを先頭から処理します。 35foreach ($iterator as $key => $value) { 36 echo "{$key} => {$value}\n"; 37} 38// 出力: 39// 1 => 2 40// 3 => 4 41// 5 => 6 42// 7 => 8 43// 9 => 10 44 45echo "\n"; 46 47// rewind()メソッドを明示的に呼び出し、イテレータを最初の位置に戻します。 48echo "rewind() を呼び出しました。\n"; 49$iterator->rewind(); 50 51echo "\n"; 52 53echo "2回目のループ処理:\n"; 54// rewind()によってイテレータが先頭に戻っているため、もう一度同じ結果をループで取得できます。 55foreach ($iterator as $key => $value) { 56 echo "{$key} => {$value}\n"; 57} 58// 出力: 59// 1 => 2 60// 3 => 4 61// 5 => 6 62// 7 => 8 63// 9 => 10 64
PHPのFilterIterator::rewind()メソッドは、イテレータを最初の位置、つまり先頭に巻き戻すための機能を提供します。このメソッドは、データの集まりを最初からもう一度繰り返し処理したい場合などに使用されます。
このメソッドは引数を取らず、戻り値もありません。その役割は、イテレータの内部的な状態を「先頭に戻す」という操作そのものです。
foreachループでイテレータを処理する場合、ループが開始される際にPHPが内部で自動的にrewind()メソッドを呼び出します。そのため、普段は意識しなくても、イテレータは常にデータの先頭から処理されます。サンプルコードの1回目のループは、この自動的な呼び出しによって偶数だけを順番に出力しています。
一度ループ処理が完了したイテレータは、通常はデータの終端を指しています。しかし、サンプルコードのように$iterator->rewind()と明示的に呼び出すことで、その位置を強制的に先頭に戻すことができます。その結果、2回目のforeachループでも、1回目と全く同じデータを先頭から取得することが可能になります。このようにrewind()は、イテレータを再利用する際に重要な役割を果たします。
rewind()メソッドは、イテレータを最初の位置に戻す機能です。foreachループでイテレータを利用する際には、ループの開始時にPHPが内部で自動的にこのメソッドを呼び出すため、開発者が自分でrewind()を呼び出す必要はほとんどありません。サンプルコードの2回目のループ前にある明示的なrewind()呼び出しは、このメソッドの機能を説明するためのものです。もしこの呼び出しがなくても、次のforeachループが始まる際に自動的に先頭に戻されます。一度ループ処理を終えたイテレータを、foreach以外の方法で再度先頭から処理したい場合に、手動でrewind()を呼び出すことを覚えておくと良いでしょう。