Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】RecursiveRegexIterator::rewind()メソッドの使い方

rewindメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

rewindメソッドは、RecursiveRegexIteratorオブジェクトの処理対象となるイテレータを、その先頭要素に巻き戻す処理を実行するメソッドです。このメソッドは、PHPの標準インターフェースであるIteratorで定義されているもので、イテレータが持つ要素の集合を最初から順に処理できるようにするために不可欠な役割を担います。通常、foreachループでRecursiveRegexIteratorオブジェクトを処理する際に、ループの開始時にPHPエンジンによって内部的に自動で呼び出されます。これにより、ループは常にイテレータの先頭から開始されることが保証されます。開発者がこのメソッドを直接呼び出すことは稀ですが、何らかの理由で同じイテレータの処理をもう一度最初から実行したい場合には、手動で呼び出すことも可能です。このメソッドを実行すると、RecursiveRegexIteratorによる正規表現フィルタリングの状態もリセットされ、改めて先頭の要素から評価が開始されます。なお、このメソッドは値を返しません。

構文(syntax)

1<?php
2
3$arrayIterator = new RecursiveArrayIterator(['test1', 'test2', 'another']);
4$regexIterator = new RecursiveRegexIterator($arrayIterator, '/^test/');
5
6$regexIterator->rewind();

引数(parameters)

引数なし

引数はありません

戻り値(return)

void

RecursiveRegexIterator::rewindメソッドは、イテレータを最初の要素に戻します。戻り値はありません。

サンプルコード

PHP RecursiveRegexIterator::rewind() でイテレータを巻き戻す

1<?php
2
3/**
4 * RecursiveRegexIterator::rewind() メソッドの動作を示すサンプルコード。
5 *
6 * RecursiveRegexIterator は、RecursiveIterator を正規表現でフィルタリングするためのイテレータです。
7 * rewind() メソッドは、イテレータの内部ポインタを先頭(最初の要素)に巻き戻すために使用されます。
8 * これにより、一度イテレートした後に再度同じデータを最初から読み取ることが可能になります。
9 *
10 * この例では、現在のディレクトリにあるPHPファイルを再帰的に検索し、
11 * その結果のリストを2回イテレートすることで、rewind() の動作を示します。
12 *
13 * PHPのジェネレータはPHP 7以降で巻き戻し可能になりましたが、
14 * RecursiveRegexIterator は RecursiveIterator を操作するため、ジェネレータを直接ラップすることはできません。
15 * しかし、どちらも「巻き戻し可能 (rewindable)」という共通の特性を持ちます。
16 */
17function demonstrateRecursiveRegexIteratorRewind(): void
18{
19    // 1. 現在のディレクトリを再帰的に走査するイテレータを作成します。
20    // RecursiveDirectoryIterator は RecursiveIterator インターフェースを実装しており、
21    // ディレクトリツリーを深く探索することができます。
22    // RecursiveDirectoryIterator::SKIP_DOTS は、'.' と '..' エントリを無視します。
23    $directoryIterator = new RecursiveDirectoryIterator('.', RecursiveDirectoryIterator::SKIP_DOTS);
24
25    // 2. RecursiveRegexIterator を使用して、RecursiveDirectoryIterator の結果をフィルタリングします。
26    // ここでは、ファイル名が '.php' で終わるものだけを抽出する正規表現を使用します。
27    // RecursiveRegexIterator もまた RecursiveIterator を実装しています。
28    // RecursiveRegexIterator::GET_MATCH を指定すると、マッチした文字列の配列が返されます。
29    $regexIterator = new RecursiveRegexIterator(
30        $directoryIterator,
31        '/^.+\.php$/i', // 正規表現パターン: ファイル名が '.php' で終わるもの (大文字小文字を区別しない)
32        RecursiveRegexIterator::GET_MATCH
33    );
34
35    // 3. RecursiveIteratorIterator で RecursiveRegexIterator をラップし、再帰的な構造をフラット化します。
36    // これにより、サブディレクトリ内のマッチしたファイルも foreach ループで直接イテレートできるようになります。
37    $flatIterator = new RecursiveIteratorIterator($regexIterator);
38
39    echo "--- 最初のイテレーション ---\n";
40    $paths1 = [];
41    foreach ($flatIterator as $match) {
42        // GET_MATCH を指定したため、$match は正規表現にマッチした文字列の配列です。
43        // $match[0] が完全なマッチ文字列(ここではファイルパス)です。
44        $paths1[] = $match[0];
45        echo $match[0] . "\n";
46    }
47    echo "最初のイテレーションで見つかったファイル数: " . count($paths1) . "\n\n";
48
49    // イテレータを巻き戻します。
50    // RecursiveRegexIterator の rewind() メソッドは引数を取りません。
51    // イテレータの内部状態をリセットし、最初の要素から再度イテレートできるようにします。
52    // $flatIterator は $regexIterator をラップしているため、$flatIterator->rewind() を呼び出すと、
53    // 内部的に $regexIterator->rewind() も呼び出されます。
54    $flatIterator->rewind();
55
56    echo "--- 2回目のイテレーション (rewind() 後) ---\n";
57    $paths2 = [];
58    foreach ($flatIterator as $match) {
59        $paths2[] = $match[0];
60        echo $match[0] . "\n";
61    }
62    echo "2回目のイテレーションで見つかったファイル数: " . count($paths2) . "\n";
63
64    // 2回のイテレーションで同じ結果が得られたかを確認します。
65    if (count($paths1) > 0 && $paths1 === $paths2) {
66        echo "\nイテレータは正常に巻き戻され、同じ結果を生成しました。\n";
67    } elseif (count($paths1) === 0) {
68        echo "\n指定された条件に一致するPHPファイルは見つかりませんでした。\n";
69    } else {
70        echo "\nイテレータの巻き戻しに問題があったか、結果が一致しませんでした。\n";
71    }
72}
73
74// 関数を実行して、RecursiveRegexIterator::rewind() の動作を確認します。
75demonstrateRecursiveRegexIteratorRewind();
76
77?>

RecursiveRegexIterator::rewind() メソッドは、PHPのイテレータが持つ「巻き戻し可能 (rewindable)」という重要な特性を示すものです。このメソッドは引数を一切取らず、戻り値もありません(void)。その役割は、一度イテレート(繰り返し処理)したイテレータの内部ポインタを、最初の要素を指す位置にリセットすることです。これにより、イテレータを繰り返し利用して、同じデータを何度でも最初から処理できるようになります。

サンプルコードでは、まず現在のディレクトリにあるPHPファイルを再帰的に検索するイテレータを構築しています。具体的には、RecursiveDirectoryIterator でディレクトリを走査し、RecursiveRegexIterator でファイル名が.phpで終わるものだけをフィルタリングしています。最初のforeachループで検索されたPHPファイルを表示した後、$flatIterator->rewind()を呼び出しています。この呼び出しにより、イテレータの状態がリセットされ、再びforeachループを実行すると、最初のループと同じ順序と内容でファイルリストが再取得されます。PHP 7以降、ジェネレータも巻き戻し可能になりましたが、RecursiveRegexIteratorのような標準的なイテレータもこのrewind()メソッドによって巻き戻しが可能となり、データの再利用が容易になります。

RecursiveRegexIterator::rewind()メソッドは、イテレータの内部ポインタをデータセットの最初の要素に巻き戻す役割を持ちます。このメソッドは引数を取らず、何も値を返しません。通常、foreachループの開始時には自動的にrewind()が呼び出されますが、一度イテレートを終えた後に同じデータセットを最初からもう一度処理したい場合には、手動でrewind()を呼び出す必要があります。サンプルコードのように複数のイテレータをネストしている場合でも、一番外側のイテレータのrewind()を呼び出すことで、内部のイテレータも連動して適切に巻き戻されます。これにより、イテレータが「巻き戻し可能」な特性を活かし、同じデータを複数回安全に利用できます。

RecursiveRegexIterator rewind() で再走査する

1<?php
2
3/**
4 * RecursiveRegexIterator::rewind() メソッドのサンプルコード
5 *
6 * このスクリプトは、指定されたディレクトリ内のPHPファイルを検索し、
7 * そのリストを複数回イテレートする方法を示します。
8 * rewind() メソッドは、イテレータの内部ポインタを最初の要素にリセットするために使用されます。
9 *
10 * 実行前に、このスクリプトと同じディレクトリにいくつかのPHPファイル(例: example1.php, my_script.php)を
11 * 作成しておくことをお勧めします。そうしないと、出力は空になる可能性があります。
12 */
13
14// 1. 現在のディレクトリを対象とした RecursiveDirectoryIterator を作成します。
15//    これにより、ディレクトリ内の要素(ファイルやサブディレクトリ)を再帰的に走査できます。
16$directoryIterator = new RecursiveDirectoryIterator(__DIR__);
17
18// 2. RecursiveRegexIterator で RecursiveDirectoryIterator をラップし、正規表現でフィルタリングします。
19//    ここでは、ファイル名が '.php' で終わるファイルのみを対象とします。
20//    RecursiveRegexIterator::MATCH は、正規表現に一致した要素(この場合は SplFileInfo オブジェクト)を
21//    元の形式でそのまま返します。
22$regexIterator = new RecursiveRegexIterator(
23    $directoryIterator,
24    '/^.+\.php$/i', // 大文字小文字を区別しない正規表現でPHPファイルを検索します
25    RecursiveRegexIterator::MATCH
26);
27
28echo "--- 最初のイテレーション (PHPファイルのみを列挙) ---\n";
29// 3. 最初のイテレーションを開始します。
30//    foreach ループは、イテレータの要素を最初から最後まで自動的に順に処理します。
31foreach ($regexIterator as $file) {
32    // SplFileInfo オブジェクトからファイル名を取得して表示します。
33    echo $file->getFilename() . "\n";
34}
35
36echo "\n--- rewind() を呼び出し、イテレータを最初に戻します ---\n";
37// 4. rewind() メソッドを明示的に呼び出します。
38//    これにより、イテレータの内部ポインタがリセットされ、
39//    次のイテレーションが最初から開始されるようになります。
40$regexIterator->rewind();
41
42echo "\n--- 2回目のイテレーション (再度PHPファイルのみを列挙) ---\n";
43// 5. 2回目のイテレーションを開始します。
44//    もし rewind() を呼び出していなければ、イテレータは既に終端に達しているため、
45//    このループは何も出力しません。
46//    rewind() を呼び出したことにより、再度最初から要素が列挙されます。
47foreach ($regexIterator as $file) {
48    echo $file->getFilename() . "\n";
49}
50

このPHPサンプルコードは、RecursiveRegexIteratorクラスに属するrewind()メソッドの機能と使い方を説明しています。

RecursiveRegexIteratorは、指定されたディレクトリ内の要素(ファイルやサブディレクトリ)を再帰的に走査し、特定の正規表現に一致するものをフィルタリングして提供するイテレータです。一般的なイテレータと同様に、foreachループなどで一度最後まで要素を処理すると、イテレータの内部ポインタは終端に達します。この状態では、再度同じイテレータを使って最初から要素を列挙することはできません。

ここでrewind()メソッドが重要な役割を果たします。rewind()は引数を取らず、イテレータの内部ポインタを最初の要素の位置にリセットします。これにより、一度終端に達したイテレータでも、再度最初から要素を走査できるようになります。このメソッドの戻り値はvoidであり、呼び出し元に値を返しません。

サンプルコードでは、まずPHPファイルの一覧を一度目のforeachループで表示しています。その後、$regexIterator->rewind();を明示的に呼び出すことでイテレータを初期状態に戻しています。その結果、二度目のforeachループでも、同じPHPファイルの一覧を最初から再度表示することが可能になっている様子が確認できます。もしrewind()を呼び出さなければ、二度目のループは何も処理しないまま終了します。

RecursiveRegexIterator::rewind()メソッドは、イテレータの内部ポインタを最初の要素にリセットするために使用されます。一度foreachループなどでイテレータを走査し終えると、イテレータは終端に達してしまい、そのままでは再度最初からデータを読み込むことはできません。同じイテレータを使って複数回データを走査したい場合には、このrewind()メソッドを明示的に呼び出す必要があります。これにより、同じデータを効率的に繰り返し処理することが可能になります。サンプルコードを試す際は、対象のディレクトリにPHPファイルを事前に作成しておかないと、期待通りの出力が得られない点にご注意ください。

PHP: RecursiveRegexIterator::rewind でイテレータを戻す

1<?php
2
3/**
4 * RecursiveRegexIterator::rewind の使用例
5 *
6 * このコードは、指定されたディレクトリとそのサブディレクトリ内のファイルを再帰的に走査し、
7 * ファイル名が特定の正規表現パターンに一致するものをフィルタリングします。
8 * rewind() メソッドの動作をデモンストレーションするために、イテレーションを複数回実行します。
9 *
10 * 注意: RecursiveRegexIterator は直接データベースの結果セットを扱いません。
11 * しかし、「イテレータのポインタを先頭に戻す」という概念は、
12 * MySQLの結果セットを巻き戻す `mysqli_result::data_seek(0)` などと類似しており、
13 * イテレータを再利用する際に重要な操作です。
14 */
15
16/**
17 * RecursiveRegexIteratorを使用してファイルシステムを走査し、rewindの動作を示す関数
18 *
19 * @param string $directoryPath 走査するディレクトリのパス
20 * @param string $regexPattern  ファイル名に適用する正規表現パターン
21 */
22function demonstrateRecursiveRegexIteratorRewind(string $directoryPath, string $regexPattern): void
23{
24    // テスト用のディレクトリが存在しない場合、作成しダミーファイルも配置します。
25    // これにより、サンプルコードが単体で動作可能になります。
26    if (!is_dir($directoryPath)) {
27        mkdir($directoryPath, 0777, true);
28        file_put_contents($directoryPath . '/file_alpha.txt', 'Content for file alpha');
29        file_put_contents($directoryPath . '/document_beta.log', 'Content for document beta');
30        mkdir($directoryPath . '/sub_dir', 0777);
31        file_put_contents($directoryPath . '/sub_dir/another_file_gamma.csv', 'Content for file gamma');
32        file_put_contents($directoryPath . '/sub_dir/image_delta.jpg', 'Content for image delta');
33        echo "テスト用のディレクトリとファイルを作成しました: " . realpath($directoryPath) . PHP_EOL . PHP_EOL;
34    }
35
36    // RecursiveDirectoryIterator を使って指定されたディレクトリを再帰的に走査します。
37    $directoryIterator = new RecursiveDirectoryIterator($directoryPath);
38    $recursiveIterator = new RecursiveIteratorIterator($directoryIterator);
39
40    // RecursiveRegexIterator でファイル名を正規表現でフィルタリングします。
41    // ここでは、ファイル名に特定のパターンが含まれるものを探します。
42    // RecursiveRegexIterator::GET_MATCH は、正規表現に一致した部分の配列を返します。
43    $regexIterator = new RecursiveRegexIterator(
44        $recursiveIterator,
45        $regexPattern,
46        RecursiveRegexIterator::GET_MATCH
47    );
48
49    echo "--- 最初のイテレーション ---" . PHP_EOL;
50    $foundCount = 0;
51    // イテレータを走査し、正規表現にマッチしたファイル名を表示します。
52    foreach ($regexIterator as $path => $match) {
53        $foundCount++;
54        echo "  マッチしたファイル: " . $path . PHP_EOL;
55    }
56
57    if ($foundCount === 0) {
58        echo "  パターン '{$regexPattern}' に一致するファイルは見つかりませんでした。" . PHP_EOL;
59    }
60    // この時点でイテレータのポインタは末尾に到達しています。
61
62    // rewind() メソッドを呼び出してイテレータのポインタを先頭に戻します。
63    // これにより、イテレータを最初から再度走査できるようになります。
64    echo PHP_EOL . "--- rewind() 後、2回目のイテレーション ---" . PHP_EOL;
65    $regexIterator->rewind();
66
67    $foundCount = 0;
68    // rewind() によってポインタが先頭に戻ったため、再度イテレーションが可能です。
69    foreach ($regexIterator as $path => $match) {
70        $foundCount++;
71        echo "  マッチしたファイル (2回目): " . $path . PHP_EOL;
72    }
73
74    if ($foundCount === 0) {
75        echo "  パターン '{$regexPattern}' に一致するファイルは見つかりませんでした。" . PHP_EOL;
76    }
77
78    // テスト用に作成したディレクトリとファイルを削除します。
79    if (is_dir($directoryPath)) {
80        // RecursiveIteratorIterator を使用してディレクトリの内容を効率的に削除します。
81        $files = new RecursiveIteratorIterator(
82            new RecursiveDirectoryIterator($directoryPath, RecursiveDirectoryIterator::SKIP_DOTS),
83            RecursiveIteratorIterator::CHILD_FIRST
84        );
85        foreach ($files as $fileinfo) {
86            if ($fileinfo->isDir()) {
87                rmdir($fileinfo->getRealPath());
88            } else {
89                unlink($fileinfo->getRealPath());
90            }
91        }
92        rmdir($directoryPath);
93        echo PHP_EOL . "テスト用のディレクトリとファイルを削除しました。" . PHP_EOL;
94    }
95}
96
97// 実行例: 'file' または 'document' という文字列を含むファイルを検索します。
98$tempDir = __DIR__ . '/temp_files_for_regex_test';
99$pattern = '/(file|document)/i'; // 'file' または 'document' を含むファイル名にマッチ
100
101demonstrateRecursiveRegexIteratorRewind($tempDir, $pattern);
102
103?>

RecursiveRegexIterator::rewind() メソッドは、PHPのイテレータ(反復子)が持つ内部ポインタをコレクションの先頭に戻す役割を果たします。このメソッドは引数を受け取らず、何も値を返しません(void)。

通常、イテレータは一度最後まで走査すると、そのポインタは終端に到達します。そのため、同じイテレータオブジェクトを使って再度最初から要素を処理したい場合、rewind() を呼び出してポインタを先頭に「巻き戻す」必要があります。

サンプルコードでは、RecursiveRegexIterator を使用して、特定のディレクトリとそのサブディレクトリ内のファイルを正規表現でフィルタリングしています。最初のイテレーションで一致するファイルを表示した後、rewind() を実行することでイテレータのポインタが先頭に戻され、二度目のイテレーションでも再び同じファイル群を処理できる様子が示されています。

この「ポインタを先頭に戻す」という概念は、例えばMySQLの結果セットで mysqli_result::data_seek(0) を使って結果の先頭に戻る操作と類似しており、一度取得したデータを複数回利用する際に非常に重要な操作となります。これにより、効率的にデータを再処理することが可能になります。

RecursiveRegexIterator::rewind() は、イテレータが一度最後まで走査された後、ポインタを先頭に戻し、最初から再度要素を処理可能にするために不可欠なメソッドです。これを呼び出さないと、イテレータを再利用してデータを取得することはできません。本メソッドは引数を取らず、戻り値もありません(void)ので、結果を変数で受け取る必要はありません。

このクラスはファイルシステムを再帰的に処理するイテレータであり、直接データベースのデータを扱うものではありません。キーワードにあるMySQLの例は、「イテレータのポインタを先頭に戻す」という概念的な類似性を示すものです。サンプルコードはテスト用ディレクトリの作成と削除を行いますが、実際のアプリケーションでファイルパスを指定する際は十分ご注意ください。

関連コンテンツ