【PHP8.x】RecursiveDirectoryIterator::__construct()メソッドの使い方
__constructメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
__constructメソッドは、RecursiveDirectoryIteratorクラスの新しいインスタンスを初期化(作成)するメソッドです。
このクラスは、指定されたディレクトリとその中のサブディレクトリをすべて含めて、ファイルやディレクトリの情報を効率的に繰り返し処理(走査)するために使用されます。__constructメソッドを呼び出すことで、プログラマーは特定のディレクトリを起点として、再帰的なファイルシステム操作を行うための準備ができます。
このメソッドには、主に二つの引数を渡すことができます。一つ目は必須の引数である$directoryで、これは文字列で走査を開始したいディレクトリのパスを指定します。例えば、「/var/www/html」のようなパスを渡します。二つ目はオプションの引数である$flagsで、これはイテレータの動作をカスタマイズするための整数値です。例えば、特別なファイルである「.」(カレントディレクトリ)や「..」(親ディレクトリ)をスキップするかどうか(FilesystemIterator::SKIP_DOTS)、イテレータが返す要素のキーや値をどのように表現するか(FilesystemIterator::KEY_AS_PATHNAME、FilesystemIterator::CURRENT_AS_FILEINFO)などを指定できます。これらのフラグを組み合わせることで、目的に応じた柔軟なディレクトリ走査が可能になります。この__constructメソッドによって作成されたRecursiveDirectoryIteratorのインスタンスを使用すると、foreachループなどを用いて、指定ディレクトリ以下のすべてのファイルやサブディレクトリを順番に処理していくことができます。
構文(syntax)
1new RecursiveDirectoryIterator(string $path, int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS)
引数(parameters)
string $directory, int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO
- string $directory: 反復処理を開始するディレクトリのパスを指定します。
- int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO: イテレータの動作を制御するフラグを指定します。デフォルトでは、キーはパス名、値はSplFileInfoオブジェクトになります。
戻り値(return)
戻り値なし
戻り値はありません
サンプルコード
PHP 8コンストラクタプロモーションでRecursiveDirectoryIteratorを扱う
1<?php 2 3// このコードは、PHP 8で導入されたコンストラクタプロモーションと 4// RecursiveDirectoryIterator::__constructの使用例を示します。 5 6// --- 単体で動作可能なサンプルにするための一時ディレクトリ作成 --- 7// 実行環境で一時的なディレクトリとファイルを作成します。 8$tempDirPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'php_recursive_iterator_test_' . uniqid(); 9mkdir($tempDirPath, 0777, true); // ディレクトリを再帰的に作成 10file_put_contents($tempDirPath . DIRECTORY_SEPARATOR . 'file1.txt', 'Content of file1'); 11mkdir($tempDirPath . DIRECTORY_SEPARATOR . 'sub_dir', 0777, true); 12file_put_contents($tempDirPath . DIRECTORY_SEPARATOR . 'sub_dir' . DIRECTORY_SEPARATOR . 'file2.txt', 'Content of file2'); 13// --- 一時ディレクトリ作成終了 --- 14 15/** 16 * RecursiveDirectoryIterator を内部で使用し、PHP 8 のコンストラクタプロモーションを活用するクラス。 17 * このクラスは、指定されたディレクトリの内容を再帰的に走査する機能を提供します。 18 */ 19class DirectoryExplorer 20{ 21 /** 22 * @var RecursiveDirectoryIterator 再帰的なディレクトリ走査のための内部イテレータ 23 */ 24 private RecursiveDirectoryIterator $internalIterator; 25 26 /** 27 * コンストラクタプロモーションを使用して、ディレクトリパスとフラグをプロパティとして定義します。 28 * PHP 8以降では、引数にアクセス修飾子 (public, protected, private) をつけることで、 29 * 自動的に同名のプロパティが宣言され、初期化されます。 30 * 31 * @param string $directoryPath 走査するディレクトリのパス。 32 * @param int $flags ディレクトリの走査方法を定義するフラグ。 33 * FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO は、 34 * イテレータのキーをパス名とし、値を SplFileInfo オブジェクトとするデフォルト設定です。 35 */ 36 public function __construct( 37 private string $directoryPath, // コンストラクタプロモーションにより、$this->directoryPath プロパティが自動的に定義・初期化されます。 38 private int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO // 同様に、$this->flags プロパティが定義・初期化されます。 39 ) { 40 // プロモートされたプロパティ ($this->directoryPath と $this->flags) を使用して 41 // RecursiveDirectoryIterator のインスタンスを初期化します。 42 // これは、リファレンス情報にある RecursiveDirectoryIterator::__construct の呼び出しです。 43 $this->internalIterator = new RecursiveDirectoryIterator($this->directoryPath, $this->flags); 44 } 45 46 /** 47 * 初期化された RecursiveDirectoryIterator を使用して、ディレクトリ内のファイルとディレクトリを 48 * 再帰的にリストアップします。 49 * 50 * @return array<string> 見つかったすべてのファイルおよびディレクトリのパスのリスト。 51 */ 52 public function listAllRecursively(): array 53 { 54 $items = []; 55 // RecursiveIteratorIterator を使用することで、RecursiveDirectoryIterator が提供する 56 // ネストされた構造をフラットに処理できます。 57 $recursiveIterator = new RecursiveIteratorIterator($this->internalIterator, RecursiveIteratorIterator::SELF_FIRST); 58 59 foreach ($recursiveIterator as $fileInfo) { 60 // カレントディレクトリ (.) と親ディレクトリ (..) はスキップ 61 if ($fileInfo->isDot()) { 62 continue; 63 } 64 $items[] = $fileInfo->getPathname(); 65 } 66 return $items; 67 } 68} 69 70// --- DirectoryExplorer クラスの使用例 --- 71// 上記で作成した一時ディレクトリをパスとして DirectoryExplorer のインスタンスを作成します。 72// ここで DirectoryExplorer::__construct が呼び出され、内部で RecursiveDirectoryIterator::__construct が実行されます。 73$explorer = new DirectoryExplorer($tempDirPath); 74 75// ディレクトリ内のすべてのアイテムを再帰的にリストアップします。 76$foundItems = $explorer->listAllRecursively(); 77 78// サンプルコード以外の出力は行わないため、結果の表示は含めません。 79// 開発やデバッグ時には、例えば var_dump($foundItems); のようにして結果を確認できます。 80// --- 使用例終了 --- 81 82// --- 単体で動作可能なサンプルにするための一時ディレクトリクリーンアップ --- 83/** 84 * 指定されたディレクトリとその内容を再帰的に削除するヘルパー関数。 85 * @param string $dirPath 削除するディレクトリのパス。 86 * @return bool 削除が成功した場合は true、それ以外は false。 87 */ 88function deleteRecursiveDirectory(string $dirPath): bool 89{ 90 if (!file_exists($dirPath)) { 91 return true; 92 } 93 if (!is_dir($dirPath)) { 94 return unlink($dirPath); 95 } 96 foreach (scandir($dirPath) as $item) { 97 if ($item === '.' || $item === '..') { 98 continue; 99 } 100 // パスを結合する際にDIRECTORY_SEPARATORを使用し、OS間の互換性を保ちます。 101 if (!deleteRecursiveDirectory($dirPath . DIRECTORY_SEPARATOR . $item)) { 102 return false; 103 } 104 } 105 return rmdir($dirPath); 106} 107 108// サンプル実行後、作成した一時ディレクトリをクリーンアップします。 109deleteRecursiveDirectory($tempDirPath); 110// --- 一時ディレクトリクリーンアップ終了 ---
このサンプルコードは、PHP 8で導入されたコンストラクタプロモーションと、RecursiveDirectoryIteratorクラスのコンストラクタである__constructの使用例を示しています。
RecursiveDirectoryIterator::__constructは、指定されたディレクトリの内容を再帰的に走査するためのオブジェクトを初期化する役割を持ちます。第一引数$directoryには、走査の対象とするディレクトリのパスを文字列で渡します。第二引数$flagsはオプションの引数で、ディレクトリの情報をどのように取得するかを制御する整数値を指定します。デフォルト値は、イテレータのキーをファイルのパス名とし、値をファイルに関する情報(SplFileInfoオブジェクト)として取得する設定です。このメソッドはコンストラクタのため、特定の戻り値はありません。
PHP 8以降で利用できるコンストラクタプロモーションは、クラスのコンストラクタの引数にpublicやprivateなどのアクセス修飾子を記述することで、その引数を自動的にクラスの同名プロパティとして定義し、かつ初期化まで行う便利な機能です。これにより、プロパティの宣言とコンストラクタ内での代入処理を省略でき、コードを簡潔に保つことができます。
サンプルコード中のDirectoryExplorerクラスでは、このコンストラクタプロモーションを利用して$directoryPathと$flagsをプライベートプロパティとして定義・初期化しています。そして、これらのプロモートされたプロパティを使用して、内部的にRecursiveDirectoryIterator::__constructを呼び出し、再帰的なディレクトリ走査の準備を行っています。listAllRecursivelyメソッドは、初期化されたイテレータを用いて、ディレクトリ内のすべてのファイルやディレクトリのパスをリストアップする具体例です。
このサンプルコードはPHP 8のコンストラクタプロモーションを活用しており、コンストラクタ引数でプロパティの定義と初期化が同時に行われ、コードを簡潔に記述できる点が特徴です。RecursiveDirectoryIterator::__constructは指定されたディレクトリのイテレータを初期化しますが、サブディレクトリの中身まで再帰的に走査するには、通常RecursiveIteratorIteratorと組み合わせて使うことが一般的です。第一引数で指定するディレクトリパスは、実際に存在し、読み込み権限があるか事前に確認することが重要です。第二引数の$flagsはイテレータの挙動を細かく制御しますが、デフォルト値で問題ない場合が多いでしょう。サンプル中の一時ディレクトリ作成・削除はコード動作確認のためであり、実際のアプリケーション実装では不要です。
PHP 8 プロパティ昇格でディレクトリを走査する
1<?php 2 3/** 4 * RecursiveDirectoryIterator の機能を利用し、PHP 8 から導入された 5 * コンストラクタプロパティ昇格 (Constructor Property Promotion) を使って 6 * ディレクトリを処理するサンプルコードです。 7 * 8 * コンストラクタプロパティ昇格は、PHP 8 で導入された機能で、 9 * コンストラクタの引数を直接クラスのプロパティとして宣言し、 10 * 初期化の記述を大幅に簡潔にすることができます。 11 * `$this->property = $argument;` のような代入が不要になります。 12 */ 13 14// ヘルパー関数: 一時ディレクトリを作成します。 15function createTempDirectory(string $prefix = 'test_dir_'): string 16{ 17 $tempFile = tempnam(sys_get_temp_dir(), $prefix); 18 if ($tempFile === false) { 19 throw new RuntimeException("Failed to create temporary file for directory name."); 20 } 21 unlink($tempFile); // tempnamはファイルを作成するので、ディレクトリとして使うために削除 22 if (!mkdir($tempFile)) { 23 throw new RuntimeException("Failed to create temporary directory '{$tempFile}'."); 24 } 25 return $tempFile; 26} 27 28// ヘルパー関数: ディレクトリとその内容を再帰的に削除します。 29function cleanupTempDirectory(string $dir): void 30{ 31 if (!is_dir($dir)) { 32 return; 33 } 34 $files = array_diff(scandir($dir), ['.', '..']); 35 foreach ($files as $file) { 36 $path = $dir . DIRECTORY_SEPARATOR . $file; 37 if (is_dir($path)) { 38 cleanupTempDirectory($path); 39 } else { 40 unlink($path); 41 } 42 } 43 rmdir($dir); 44} 45 46/** 47 * MyDirectoryProcessor クラス 48 * RecursiveDirectoryIterator を内部で使用し、PHP 8 の Property Promotion を実演します。 49 */ 50class MyDirectoryProcessor 51{ 52 // RecursiveDirectoryIterator のインスタンスを保持するプロパティ 53 private RecursiveDirectoryIterator $directoryIterator; 54 55 /** 56 * コンストラクタ。 57 * PHP 8 のコンストラクタプロパティ昇格を使って、引数 $directoryPath と $flags を 58 * 直接プロパティとして宣言しています。これにより、クラスプロパティの事前定義と、 59 * コンストラクタ内での明示的な代入が不要になります。 60 * 61 * RecursiveDirectoryIterator のコンストラクタは `string $directory, int $flags` を受け取ります。 62 * ここではその引数名とデフォルト値をそのまま利用しています。 63 * 64 * @param string $directoryPath 処理するディレクトリのパス。privateプロパティとして昇格されます。 65 * @param int $flags RecursiveDirectoryIterator に渡すフラグ。デフォルト値は昇格後も保持されます。 66 * `FilesystemIterator::KEY_AS_PATHNAME` はイテレータのキーをパス名に設定します。 67 * `FilesystemIterator::CURRENT_AS_FILEINFO` はイテレータの値をSplFileInfoオブジェクトに設定します。 68 */ 69 public function __construct( 70 private string $directoryPath, 71 private int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO 72 ) { 73 // 昇格されたプロパティ ($this->directoryPath, $this->flags) を使用して 74 // RecursiveDirectoryIterator のインスタンスを初期化します。 75 // ここで RecursiveDirectoryIterator の __construct メソッドが呼び出されます。 76 $this->directoryIterator = new RecursiveDirectoryIterator($this->directoryPath, $this->flags); 77 } 78 79 /** 80 * ディレクトリの内容を再帰的に走査し、表示します。 81 * RecursiveDirectoryIterator は、RecursiveIteratorIterator と組み合わせることで、 82 * サブディレクトリも再帰的に走査できるようになります。 83 */ 84 public function processDirectory(): void 85 { 86 echo "Processing directory: '{$this->directoryPath}'\n"; 87 echo "Using flags (integer value): '{$this->flags}'\n"; 88 89 // RecursiveIteratorIterator と組み合わせて、サブディレクトリも再帰的に走査します。 90 $recursiveIterator = new RecursiveIteratorIterator( 91 $this->directoryIterator, 92 RecursiveIteratorIterator::SELF_FIRST // 親ディレクトリ自身も最初に表示します 93 ); 94 95 foreach ($recursiveIterator as $fileInfo) { 96 // ファイルのパス、タイプ、そして現在の階層レベルを表示 97 $path = $fileInfo->getPathname(); 98 $type = $fileInfo->isDir() ? 'DIR' : 'FILE'; 99 $indent = str_repeat(' ', $recursiveIterator->getDepth()); // 階層に応じたインデント 100 echo "{$indent}- {$type}: {$path}\n"; 101 } 102 } 103} 104 105// --- サンプルコードの実行 --- 106$tempDir = ''; 107try { 108 // 処理対象となる一時ディレクトリとその内容を作成 109 $tempDir = createTempDirectory('recursive_test_'); 110 file_put_contents($tempDir . '/file1.txt', 'This is content of file1.'); 111 mkdir($tempDir . '/subdir1'); 112 file_put_contents($tempDir . '/subdir1/file2.txt', 'This is content of file2.'); 113 mkdir($tempDir . '/subdir1/subdir2'); 114 file_put_contents($tempDir . '/subdir1/subdir2/file3.txt', 'This is content of file3.'); 115 116 echo "--- PHP 8 Constructor Property Promotion を利用した例 (デフォルトフラグ) --- \n"; 117 118 // MyDirectoryProcessor のインスタンスを生成 119 // コンストラクタ引数 ($tempDir, デフォルトフラグ) は、直接プロパティとして昇格されます。 120 $processor = new MyDirectoryProcessor($tempDir); 121 $processor->processDirectory(); 122 123 echo "\n--- カスタムフラグを使用した例 (FilesystemIterator::SKIP_DOTS) --- \n"; 124 // 異なるフラグ (例: . と .. をスキップする FilesystemIterator::SKIP_DOTS) でインスタンス化 125 $processorWithCustomFlags = new MyDirectoryProcessor( 126 $tempDir, 127 FilesystemIterator::SKIP_DOTS | FilesystemIterator::CURRENT_AS_FILEINFO 128 ); 129 $processorWithCustomFlags->processDirectory(); 130 131} catch (Exception $e) { 132 echo "エラーが発生しました: " . $e->getMessage() . "\n"; 133} finally { 134 // 後処理: 作成した一時ディレクトリとファイルを削除します。 135 if ($tempDir && is_dir($tempDir)) { 136 cleanupTempDirectory($tempDir); 137 echo "\n一時ディレクトリ '{$tempDir}' をクリーンアップしました。\n"; 138 } 139} 140
PHP 8のRecursiveDirectoryIteratorは、指定したディレクトリ内のファイルやサブディレクトリを、再帰的に効率よく順に処理(走査)するための機能を提供します。その__constructメソッドは、このクラスのインスタンスを生成する際に自動的に呼び出される初期化処理です。
このメソッドの引数$directoryには、走査したいディレクトリのパスを文字列で指定します。引数$flagsは、走査の際にどのような情報を取得するかや、ファイルの種類をどう扱うかなどを制御するオプション値を整数で渡します。例えば、デフォルト値であるFilesystemIterator::KEY_AS_PATHNAMEはキーをフルパスとして扱い、FilesystemIterator::CURRENT_AS_FILEINFOは各要素をファイル情報オブジェクトとして取得するよう設定します。__constructメソッドはインスタンスを生成するだけで、明示的な戻り値はありません。
サンプルコードでは、PHP 8で導入された「コンストラクタプロパティ昇格」という機能が使われています。これは、コンストラクタの引数をprivateやpublicといったアクセス修飾子付きで宣言することで、その引数を直接クラスのプロパティとして定義し、初期化も同時に行える機能です。これにより、クラスのプロパティを事前に宣言したり、コンストラクタ内で$this->property = $argument;のように代入する記述が不要となり、コードがより簡潔になります。
MyDirectoryProcessorクラスは、このコンストラクタプロパティ昇格を用いて、渡されたディレクトリパスとフラグを内部プロパティとして保持しつつ、RecursiveDirectoryIteratorを効率的に初期化し、ディレクトリの内容を再帰的に処理しています。
PHP 8のコンストラクタプロパティ昇格は、コンストラクタの引数をprivate string $pathのように宣言するだけで、プロパティ定義と初期化を簡潔にする機能です。これによりコードがすっきりし、記述ミスも減らせます。RecursiveDirectoryIteratorのコンストラクタは、対象ディレクトリのパスと、動作を制御する整数値のフラグを受け取ります。フラグはFilesystemIterator定数を組み合わせて指定し、.や..のスキップなど細かな設定が可能です。ディレクトリを再帰的に走査するには、RecursiveDirectoryIteratorをRecursiveIteratorIteratorと組み合わせて使うことが一般的です。ファイルシステム操作を含むため、エラーハンドリングとクリーンアップ処理を必ず実装し、安全に利用してください。