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

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

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

作成日: 更新日:

基本的な使い方

rewindメソッドは、イテレータを最初の要素に巻き戻すメソッドです。

このメソッドは、PHPの標準ライブラリであるSpl(Standard PHP Library)に属するRecursiveDirectoryIteratorクラスに実装されています。RecursiveDirectoryIteratorは、指定されたディレクトリとその中のサブディレクトリを再帰的に走査し、ファイルやディレクトリの情報を順番に取得するための特別なオブジェクト(イテレータ)です。rewindメソッドを呼び出すことで、現在イテレータが指している位置に関わらず、走査の対象となるディレクトリ構造の最初の項目に内部ポインタがリセットされます。

これにより、一度ディレクトリ内のすべての要素を処理した後で、再度最初から要素を取得し直したい場合や、途中で処理を中断した後に再び初期状態から開始したい場合に利用されます。例えば、あるディレクトリ内の全てのファイルを一度リストアップした後、もう一度同じイテレータを使って最初からファイル名だけを取得するといった場面で、rewindメソッドはイテレータを効率的に再利用するために役立ちます。このメソッドは、ディレクトリコンテンツの複数回の走査を可能にし、柔軟なファイルシステム操作を実現します。

構文(syntax)

1<?php
2$directoryIterator = new RecursiveDirectoryIterator('.');
3$directoryIterator->rewind();

引数(parameters)

引数なし

引数はありません

戻り値(return)

戻り値なし

戻り値はありません

サンプルコード

PHP RecursiveDirectoryIterator の rewind() を実演する

1<?php
2
3/**
4 * RecursiveDirectoryIterator が rewind 可能であることを示すサンプルコード。
5 *
6 * PHP の通常のジェネレータ (yield キーワードを使用) は一度しかイテレートできませんが、
7 * RecursiveDirectoryIterator のような Spl Iterators は rewind() メソッドを
8 * 使用して内部ポインタを先頭に戻し、複数回イテレートすることが可能です。
9 * この特性を「rewindable」と呼びます。
10 *
11 * この関数は一時ディレクトリを作成し、RecursiveDirectoryIterator の動作を実演後、
12 * その一時ディレクトリをクリーンアップします。
13 */
14function demonstrateRewindableIterator(): void
15{
16    // 一時ディレクトリのパスを生成し、ディレクトリとテストファイルを作成します。
17    $tempBase = sys_get_temp_dir();
18    $testDirName = 'php_rewind_test_' . uniqid();
19    $testDir = $tempBase . DIRECTORY_SEPARATOR . $testDirName;
20
21    // ディレクトリが存在しない場合は作成
22    if (!is_dir($testDir) && !mkdir($testDir, 0777, true)) {
23        echo "エラー: 一時ディレクトリ '{$testDir}' の作成に失敗しました。\n";
24        return;
25    }
26
27    // テスト用のファイルをいくつか作成
28    file_put_contents($testDir . DIRECTORY_SEPARATOR . 'file1.txt', 'Content for file1');
29    file_put_contents($testDir . DIRECTORY_SEPARATOR . 'file2.txt', 'Content for file2');
30    mkdir($testDir . DIRECTORY_SEPARATOR . 'sub_dir', 0777);
31    file_put_contents($testDir . DIRECTORY_SEPARATOR . 'sub_dir' . DIRECTORY_SEPARATOR . 'file3.txt', 'Content for file3');
32
33    echo "--- ディレクトリ構成の準備 ---\n";
34    echo "作成された一時ディレクトリ: " . $testDir . "\n";
35    echo "---------------------------\n\n";
36
37    try {
38        // RecursiveDirectoryIterator のインスタンスを作成します。
39        // SKIP_DOTS フラグは "." と ".." を結果から除外します。
40        $iterator = new RecursiveDirectoryIterator(
41            $testDir,
42            RecursiveDirectoryIterator::SKIP_DOTS
43        );
44
45        echo "--- 1回目のイテレーション ---\n";
46        foreach ($iterator as $item) {
47            echo "  パス: " . $item->getPathname() . "\n";
48        }
49        echo "---------------------------\n\n";
50
51        // rewind() メソッドを呼び出して、イテレータの内部ポインタを先頭に戻します。
52        // これにより、イテレータは最初から要素を再度提供できるようになります。
53        echo "--- rewind() を呼び出し、イテレータを先頭に戻します ---\n\n";
54        $iterator->rewind();
55
56        echo "--- 2回目のイテレーション (rewind() 後) ---\n";
57        foreach ($iterator as $item) {
58            echo "  パス: " . $item->getPathname() . "\n";
59        }
60        echo "--------------------------------------\n\n";
61
62    } catch (UnexpectedValueException $e) {
63        // 指定されたパスがディレクトリではない場合などに発生する可能性のあるエラーを処理します。
64        echo "エラー: ディレクトリが見つからないか、アクセスできません。 " . $e->getMessage() . "\n";
65    } finally {
66        // テストで使用した一時ディレクトリとファイルをクリーンアップします。
67        if (is_dir($testDir)) {
68            // RecursiveIteratorIterator を使ってディレクトリ内のすべての要素を削除
69            $files = new RecursiveIteratorIterator(
70                new RecursiveDirectoryIterator($testDir, RecursiveDirectoryIterator::SKIP_DOTS),
71                RecursiveIteratorIterator::CHILD_FIRST
72            );
73            foreach ($files as $fileinfo) {
74                if ($fileinfo->isDir()) {
75                    rmdir($fileinfo->getRealPath());
76                } else {
77                    unlink($fileinfo->getRealPath());
78                }
79            }
80            rmdir($testDir); // 空になった一時ディレクトリ自体を削除
81            echo "一時ディレクトリ '{$testDir}' を削除しました。\n";
82        }
83    }
84}
85
86// 関数を実行して動作を確認します。
87demonstrateRewindableIterator();

PHP 8のRecursiveDirectoryIteratorクラスに属するrewind()メソッドは、引数を取らず、戻り値もありません。このメソッドは、イテレータの内部ポインタをコレクションの先頭に戻す役割を持ちます。

PHPの通常のジェネレータは一度しかイテレートできませんが、RecursiveDirectoryIteratorのようなSpl Iteratorsはrewind()メソッドを呼び出すことで、すでに一度最後まで処理されたイテレータを再度最初から繰り返し処理できるようになります。これにより、同じディレクトリ構造を複数回走査することが可能になり、この特性を「rewindable(リワインダブル)」と呼びます。

提供されたサンプルコードでは、まず一時ディレクトリとファイルを作成し、RecursiveDirectoryIteratorを使って一度ディレクトリの内容を走査します。その後、$iterator->rewind()を呼び出すことでイテレータのポインタを先頭に戻し、再度同じディレクトリ内容を問題なく走査できることを実演しています。これは、ファイルシステムを扱うアプリケーションで、一度スキャンしたディレクトリを別の目的で再度処理する際に非常に役立ちます。

rewind()メソッドは、RecursiveDirectoryIteratorのような巻き戻し可能な(rewindable)イテレータを、一度イテレートした後に内部ポインタを先頭に戻し、再度最初から要素を処理するために使用します。PHPの通常のジェネレータとは異なり、この特性によりイテレータを複数回利用できます。

ファイルシステムを扱うため、指定したパスが存在しない場合やアクセス権がない場合などにUnexpectedValueExceptionが発生する可能性があります。そのため、必ずtry-catch構文でエラーハンドリングを行い、例外発生時の処理を記述してください。また、サンプルコードにある一時ディレクトリの作成や削除処理はテスト目的のものであり、実際のアプリケーションで不用意なファイル操作を行うと、システムへの予期せぬ影響やセキュリティリスクにつながる可能性があるため、利用には十分な注意が必要です。

PHP: RecursiveDirectoryIterator rewind() で再走査する

1<?php
2
3/**
4 * RecursiveDirectoryIterator の rewind() メソッドの動作を示すサンプルコード。
5 *
6 * この関数は一時的なディレクトリ構造を作成し、その内容を RecursiveDirectoryIterator で走査します。
7 * rewind() メソッドを使ってイテレータを先頭に巻き戻し、再度走査することで、
8 * イテレータが最初からやり直せることを具体的に示します。
9 */
10function demonstrateRecursiveDirectoryIteratorRewind(): void
11{
12    // 一時的なテストディレクトリのパスを定義
13    // このスクリプトと同じディレクトリ内に 'temp_test_dir' という名前で作成します。
14    $testDir = __DIR__ . DIRECTORY_SEPARATOR . 'temp_test_dir';
15
16    // もし既存のテストディレクトリがあれば、まず削除してクリーンな状態にする
17    if (is_dir($testDir)) {
18        // RecursiveIteratorIterator を使って、ディレクトリ内の全てのファイルとサブディレクトリを処理
19        // CHILD_FIRST は、子要素を先に処理してから親ディレクトリを処理するモードです。
20        $files = new RecursiveIteratorIterator(
21            new RecursiveDirectoryIterator($testDir, RecursiveDirectoryIterator::SKIP_DOTS),
22            RecursiveIteratorIterator::CHILD_FIRST
23        );
24        foreach ($files as $fileinfo) {
25            // ファイルかディレクトリかに応じて削除
26            if ($fileinfo->isDir()) {
27                rmdir($fileinfo->getRealPath());
28            } else {
29                unlink($fileinfo->getRealPath());
30            }
31        }
32        rmdir($testDir); // 空になったルートディレクトリを削除
33    }
34
35    // テスト用のディレクトリとファイルを作成
36    // mkdir() の第3引数 true で、存在しない親ディレクトリもまとめて作成します。
37    mkdir($testDir, 0777, true);
38    file_put_contents($testDir . DIRECTORY_SEPARATOR . 'file1.txt', 'Content for file1');
39    mkdir($testDir . DIRECTORY_SEPARATOR . 'subdir', 0777, true);
40    file_put_contents($testDir . DIRECTORY_SEPARATOR . 'subdir' . DIRECTORY_SEPARATOR . 'file2.txt', 'Content for file2');
41    file_put_contents($testDir . DIRECTORY_SEPARATOR . 'file3.txt', 'Content for file3');
42
43    echo "--- 最初のイテレーション ---" . PHP_EOL;
44
45    // RecursiveDirectoryIterator をインスタンス化
46    // これはディレクトリとその中のファイル、サブディレクトリを再帰的に走査するための基本イテレータです。
47    // RecursiveDirectoryIterator::SKIP_DOTS フラグは、特殊なディレクトリである '.' と '..' をスキップします。
48    $directoryIterator = new RecursiveDirectoryIterator($testDir, RecursiveDirectoryIterator::SKIP_DOTS);
49
50    // RecursiveIteratorIterator を使って、サブディレクトリ内のファイルも再帰的に走査できるようにします。
51    // SELF_FIRST は、ディレクトリ自身を、その内容の前に返すことを意味します。
52    $recursiveIterator = new RecursiveIteratorIterator($directoryIterator, RecursiveIteratorIterator::SELF_FIRST);
53
54    // 最初のイテレーションでディレクトリの内容を表示
55    // このループが実行されることで、イテレータの内部ポインタは最後まで進みます。
56    foreach ($recursiveIterator as $name => $splFileInfo) {
57        // 現在の要素のパスと種類を表示
58        echo ($splFileInfo->isDir() ? 'DIR: ' : 'FILE: ') . $splFileInfo->getPathname() . PHP_EOL;
59    }
60
61    echo PHP_EOL . "--- rewind() を呼び出し中 ---" . PHP_EOL;
62
63    // RecursiveIteratorIterator の rewind() メソッドを呼び出します。
64    // これにより、イテレータの内部カーソルがコレクションの先頭(最初の要素)に巻き戻されます。
65    // RecursiveDirectoryIterator は RecursiveIteratorIterator に包まれているため、
66    // 親である RecursiveIteratorIterator の rewind() を呼び出すことで全体がリセットされます。
67    $recursiveIterator->rewind();
68
69    echo "--- 2回目のイテレーション (rewind() 呼び出し後) ---" . PHP_EOL;
70
71    // rewind() を呼び出した後に再度イテレーションを行い、最初から走査されることを確認します。
72    // 出力される順序は最初のイテレーションと全く同じになるはずです。
73    foreach ($recursiveIterator as $name => $splFileInfo) {
74        // 現在の要素のパスと種類を表示
75        echo ($splFileInfo->isDir() ? 'DIR: ' : 'FILE: ') . $splFileInfo->getPathname() . PHP_EOL;
76    }
77
78    // テスト後に作成した一時ディレクトリとその内容をクリーンアップ
79    if (is_dir($testDir)) {
80        // 再度 RecursiveIteratorIterator を利用して全てのファイルとサブディレクトリを削除
81        $files = new RecursiveIteratorIterator(
82            new RecursiveDirectoryIterator($testDir, 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($testDir); // 空になったルートディレクトリを削除
93    }
94
95    echo PHP_EOL . "--- クリーンアップ完了 ---" . PHP_EOL;
96}
97
98// サンプルコードを実行する関数を呼び出し
99demonstrateRecursiveDirectoryIteratorRewind();
100
101?>

PHP 8のRecursiveDirectoryIteratorクラスに属するrewind()メソッドは、ディレクトリ構造を再帰的に走査するイテレータの内部ポインタを先頭に巻き戻す役割を持ちます。このメソッドは引数を必要とせず、戻り値もありません。rewind()を呼び出すことで、イテレータは初期状態に戻り、再度最初から要素を走査できるようになります。

サンプルコードでは、まず一時的なテストディレクトリとファイルを作成し、走査対象を準備しています。その後、RecursiveDirectoryIteratorRecursiveIteratorIteratorを組み合わせてディレクトリ内のファイルやサブディレクトリを再帰的に走査するイテレータを生成します。最初のループでイテレータを最後まで進めて全ての要素を表示すると、内部ポインタは終端に達します。ここで$recursiveIterator->rewind()を呼び出すことで、イテレータの内部カーソルはコレクションの最初の要素を指す状態に戻ります。そのため、その後の2回目のループでは、最初のループと全く同じ順序でディレクトリの内容が再度表示され、イテレータがリセットされたことを確認できます。これにより、一度終端まで進んだイテレータをrewind()メソッドで簡単に初期化し、繰り返し利用できることが示されています。テスト終了後には、作成した一時ディレクトリが削除され、環境がクリーンアップされます。

rewind()メソッドは、イテレータの内部ポインタをコレクションの先頭に戻し、一度最後まで走査したイテレータでも、再度最初から要素を処理できるようにします。サンプルコードのようにRecursiveDirectoryIteratorRecursiveIteratorIteratorに包まれている場合、上位のRecursiveIteratorIteratorに対してrewind()を呼び出すことで、全体を効果的にリセットできます。このメソッドには戻り値がありませんので、実行結果を変数で受け取ろうとしないように注意が必要です。ファイルシステムを扱うイテレータでは、rewind()時にファイルやディレクトリの最新の状態が反映される点も覚えておくと良いでしょう。

PHP RecursiveDirectoryIterator rewind() で先頭に戻す

1<?php
2
3/**
4 * RecursiveDirectoryIterator クラスの rewind() メソッドの動作をデモンストレーションします。
5 * このメソッドは、イテレータの内部ポインタをコレクションの先頭に戻すために使用されます。
6 */
7function demonstrateRecursiveDirectoryIteratorRewind(): void
8{
9    // 一時的なテストディレクトリを作成します。
10    // このディレクトリはサンプルコードの実行後に削除されます。
11    $testDir = 'temp_rewind_test_dir';
12    if (!file_exists($testDir)) {
13        mkdir($testDir);
14    }
15
16    // テストディレクトリ内にいくつかのダミーファイルを作成します。
17    file_put_contents($testDir . '/report_jan.txt', 'レポート1月のデータ');
18    file_put_contents($testDir . '/data_feb.csv', 'データ2月分');
19    file_put_contents($testDir . '/image_mar.png', '画像3月分');
20
21    // RecursiveDirectoryIterator をインスタンス化します。
22    // RecursiveDirectoryIterator::SKIP_DOTS フラグは、'.' と '..' エントリをスキップするために使用します。
23    $iterator = new RecursiveDirectoryIterator($testDir, RecursiveDirectoryIterator::SKIP_DOTS);
24
25    echo "--- 最初のイテレーション (ディレクトリの先頭から順に処理) ---" . PHP_EOL;
26    // イテレータを使ってディレクトリ内のファイル名を順番に表示します。
27    foreach ($iterator as $fileInfo) {
28        echo 'ファイル名: ' . $fileInfo->getFilename() . PHP_EOL;
29    }
30
31    echo PHP_EOL . "--- rewind() メソッドを呼び出し、イテレータを先頭に戻します ---" . PHP_EOL;
32    // rewind() メソッドを呼び出すことで、イテレータの内部ポインタが
33    // ディレクトリの最初の要素 (この場合は 'report_jan.txt') に戻ります。
34    $iterator->rewind();
35
36    echo PHP_EOL . "--- 2回目のイテレーション (rewind() 後、再び先頭から処理) ---" . PHP_EOL;
37    // rewind() が正常に機能したことを確認するため、再度イテレーションを実行します。
38    // ポインタが先頭に戻っているため、最初のイテレーションと同じ結果が再び表示されます。
39    foreach ($iterator as $fileInfo) {
40        echo 'ファイル名: ' . $fileInfo->getFilename() . PHP_EOL;
41    }
42
43    // テスト後に作成した一時ファイルとディレクトリをクリーンアップします。
44    unlink($testDir . '/report_jan.txt');
45    unlink($testDir . '/data_feb.csv');
46    unlink($testDir . '/image_mar.png');
47    rmdir($testDir);
48    echo PHP_EOL . "--- 一時ディレクトリとファイルをクリーンアップしました ---" . PHP_EOL;
49}
50
51// 上記のデモンストレーション関数を実行します。
52demonstrateRecursiveDirectoryIteratorRewind();

PHP 8のRecursiveDirectoryIterator::rewind()メソッドは、ディレクトリ内のファイルやフォルダを順番に処理する「イテレータ」の内部ポインタを、再びコレクションの先頭に戻すための機能です。このメソッドは引数を一切取らず、特別な戻り値もありません。

例えば、ディレクトリ内のファイルを一つずつ読み進めた後で、もう一度最初のファイルから処理をやり直したい場合にrewind()を利用します。サンプルコードでは、まずRecursiveDirectoryIteratorを使ってテストディレクトリ内のファイル名を順に表示しています。一度最後まで処理が進んだ後、$iterator->rewind();を実行することで、イテレータのポインタがディレクトリの最初の要素(ファイル)へと戻されます。その結果、再度イテレーションを行うと、もう一度先頭から同じファイルリストが順番に表示されることが確認できます。このように、繰り返し処理の途中でポインタをリセットし、最初から再開したい場面で非常に役立つメソッドです。

RecursiveDirectoryIterator::rewind()メソッドは、イテレータの内部ポインタを先頭に戻し、同じコレクションを複数回走査したい場合に利用します。戻り値はありませんが、呼び出し後に再度イテレーションを行うことで、先頭から処理が再開されることを確認できます。ただし、データベースの結果セットなど、一部のイテレータは一度しか順方向の走査を許可せず、rewind()が機能しない場合がありますので注意が必要です。サンプルコードの一時ファイル操作はデモンストレーション用で、実システムでは適切なエラー処理やアクセス権限の管理が不可欠です。イテレータのオプション(SKIP_DOTSなど)も活用し、目的に応じた安全な処理を心がけましょう。

関連コンテンツ