【PHP8.x】RecursiveDirectoryIterator::CURRENT_MODE_MASK定数の使い方
CURRENT_MODE_MASK定数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
CURRENT_MODE_MASK定数は、PHPのRecursiveDirectoryIteratorクラスにおいて、現在のイテレータモードに関する情報を抽出するためのビットマスク定数を表します。
RecursiveDirectoryIteratorは、指定されたディレクトリとそのサブディレクトリの内容を再帰的に反復処理(イテレート)するための便利なクラスです。このクラスは、ディレクトリの走査方法や取得する要素の種類(ファイルのみ、ディレクトリのみ、または両方など)を制御するための様々なオプション、いわゆる「フラグ」を持っています。これらのフラグの設定状態は、getFlags()メソッドによって取得することができます。
getFlags()メソッドが返す値は、複数のフラグがビット論理和(OR演算)によって結合された単一の整数値です。CURRENT_MODE_MASK定数は、この複合的なフラグ値の中から、特に現在のイテレータの「モード」を示す部分だけを効率的に抜き出す(マスクする)ために設計されています。
具体的には、getFlags()の戻り値とCURRENT_MODE_MASK定数をビット論理積(AND演算)で組み合わせることで、現在のイテレータがどのモードで動作しているか、例えばファイルのみを返すモードなのか、ディレクトリも含むモードなのかといった情報を正確に判断することが可能になります。これは、複雑なフラグの状態から特定の意味を持つ情報だけを選び出して利用する際の補助的な役割を果たし、イテレータの動作を詳細に分析する際に非常に役立ちます。
構文(syntax)
1RecursiveDirectoryIterator::CURRENT_MODE_MASK;
引数(parameters)
引数なし
引数はありません
戻り値(return)
int
RecursiveDirectoryIterator::CURRENT_MODE_MASKは、現在のエントリのモードを取得するためのマスク値を示す整数です。
サンプルコード
PHP RecursiveDirectoryIterator::current() のモード別挙動
1<?php 2 3/** 4 * RecursiveDirectoryIterator の current() メソッドの挙動をデモンストレーションします。 5 * RecursiveDirectoryIterator::CURRENT_MODE_MASK 定数は、 6 * current() メソッドの戻り値の形式を制御するフラグのグループを示すマスク値です。 7 * 直接この定数を指定するのではなく、関連する CURRENT_AS_* 定数を使用することで、 8 * current() が返す値の形式(SplFileInfo オブジェクト、パス名文字列、ファイル名文字列など)を決定します。 9 * このサンプルでは、異なるフラグを設定した場合の current() の戻り値の違いを示します。 10 */ 11function demonstrateRecursiveDirectoryIteratorModes(): void 12{ 13 // 一時ディレクトリとダミーファイルを作成 14 $tempDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'php_test_dir_' . uniqid('rdit_'); 15 if (!mkdir($tempDir) && !is_dir($tempDir)) { 16 echo "一時ディレクトリの作成に失敗しました: $tempDir\n"; 17 return; 18 } 19 file_put_contents($tempDir . DIRECTORY_SEPARATOR . 'file1.txt', 'これはファイル1のテストデータです。'); 20 mkdir($tempDir . DIRECTORY_SEPARATOR . 'subdir'); 21 file_put_contents($tempDir . DIRECTORY_SEPARATOR . 'subdir' . DIRECTORY_SEPARATOR . 'file2.txt', 'これはサブディレクトリ内のファイル2のテストデータです。'); 22 23 echo "--- RecursiveDirectoryIterator の current() メソッドの挙動デモンストレーション ---\n"; 24 echo "一時ディレクトリ: $tempDir\n\n"; 25 26 // 1. デフォルトモード (CURRENT_AS_FILEINFO に相当) 27 // current() メソッドは SplFileInfo オブジェクトを返します。 28 echo "1. モード: デフォルト (RecursiveDirectoryIterator::CURRENT_AS_FILEINFO)\n"; 29 echo " current() メソッドは SplFileInfo オブジェクトを返します。\n"; 30 try { 31 // SKIP_DOTS フラグで '.' と '..' エントリをスキップ 32 $iterator = new RecursiveDirectoryIterator($tempDir, RecursiveDirectoryIterator::SKIP_DOTS); 33 foreach ($iterator as $name => $fileInfo) { 34 // ファイルのみを対象として情報を表示 35 if ($fileInfo->isFile()) { 36 echo " パス: " . $fileInfo->getPathname() . "\n"; 37 echo " current() の戻り値の型: " . get_class($fileInfo) . "\n"; 38 echo " ファイル名: " . $fileInfo->getFilename() . "\n"; 39 echo " ファイルサイズ: " . $fileInfo->getSize() . " バイト\n"; 40 } 41 } 42 } catch (UnexpectedValueException $e) { 43 echo "エラー: " . $e->getMessage() . "\n"; 44 } 45 echo "\n"; 46 47 // 2. CURRENT_AS_PATHNAME モード 48 // current() メソッドはファイルまたはディレクトリの完全なパス名を文字列で返します。 49 echo "2. モード: RecursiveDirectoryIterator::CURRENT_AS_PATHNAME\n"; 50 echo " current() メソッドはファイルまたはディレクトリの完全なパス名を文字列で返します。\n"; 51 try { 52 // CURRENT_AS_PATHNAME と SKIP_DOTS を組み合わせて指定 53 $iterator = new RecursiveDirectoryIterator($tempDir, RecursiveDirectoryIterator::CURRENT_AS_PATHNAME | RecursiveDirectoryIterator::SKIP_DOTS); 54 foreach ($iterator as $name => $pathname) { 55 // イテレータ自身の isFile() メソッドで現在の要素がファイルか判定 56 if ($iterator->isFile()) { 57 echo " パス: " . $pathname . "\n"; 58 echo " current() の戻り値の型: string\n"; 59 echo " current() の戻り値: " . $pathname . "\n"; 60 } 61 } 62 } catch (UnexpectedValueException $e) { 63 echo "エラー: " . $e->getMessage() . "\n"; 64 } 65 echo "\n"; 66 67 // 3. CURRENT_AS_FILENAME モード 68 // current() メソッドはファイルまたはディレクトリの名前を文字列で返します。 69 echo "3. モード: RecursiveDirectoryIterator::CURRENT_AS_FILENAME\n"; 70 echo " current() メソッドはファイルまたはディレクトリの名前を文字列で返します。\n"; 71 try { 72 // CURRENT_AS_FILENAME と SKIP_DOTS を組み合わせて指定 73 $iterator = new RecursiveDirectoryIterator($tempDir, RecursiveDirectoryIterator::CURRENT_AS_FILENAME | RecursiveDirectoryIterator::SKIP_DOTS); 74 foreach ($iterator as $name => $filename) { 75 // イテレータ自身の isFile() メソッドで現在の要素がファイルか判定 76 if ($iterator->isFile()) { 77 // current() はファイル名のみを返すため、元のパスを補完して表示 78 echo " パス (推定): " . $tempDir . DIRECTORY_SEPARATOR . $filename . "\n"; 79 echo " current() の戻り値の型: string\n"; 80 echo " current() の戻り値: " . $filename . "\n"; 81 } 82 } 83 } catch (UnexpectedValueException $e) { 84 echo "エラー: " . $e->getMessage() . "\n"; 85 } 86 echo "\n"; 87 88 // 一時ディレクトリとファイルをクリーンアップ 89 try { 90 $files = new RecursiveIteratorIterator( 91 new RecursiveDirectoryIterator($tempDir, RecursiveDirectoryIterator::SKIP_DOTS), 92 RecursiveIteratorIterator::CHILD_FIRST 93 ); 94 95 foreach ($files as $fileinfo) { 96 $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink'); 97 if (!$todo($fileinfo->getRealPath())) { 98 throw new RuntimeException("ファイルの削除に失敗しました: " . $fileinfo->getRealPath()); 99 } 100 } 101 if (!rmdir($tempDir)) { 102 throw new RuntimeException("ディレクトリの削除に失敗しました: " . $tempDir); 103 } 104 echo "一時ディレクトリをクリーンアップしました: $tempDir\n"; 105 } catch (Throwable $e) { 106 echo "クリーンアップ中にエラーが発生しました: " . $e->getMessage() . "\n"; 107 } 108} 109 110// デモンストレーション関数を実行 111demonstrateRecursiveDirectoryIteratorModes();
PHP 8のRecursiveDirectoryIterator::CURRENT_MODE_MASKは、ファイルシステムを再帰的に走査するRecursiveDirectoryIteratorのcurrent()メソッドが返す値の形式を制御するためのマスク値です。この定数自体は直接使用せず、RecursiveDirectoryIteratorのコンストラクタで、CURRENT_AS_FILEINFO、CURRENT_AS_PATHNAME、CURRENT_AS_FILENAMEといった関連定数を組み合わせて指定することで、current()の挙動をカスタマイズします。
current()メソッドは、イテレータが現在指し示しているファイルやディレクトリの情報を返します。サンプルコードでは、これらの異なるモードを設定した場合にcurrent()の戻り値がどう変わるかを具体的に示しています。例えば、CURRENT_AS_FILEINFO(デフォルト)を設定するとcurrent()はSplFileInfoオブジェクトを返し、ファイルパス、サイズ、名前などの詳細情報にアクセスできます。一方、CURRENT_AS_PATHNAMEを指定するとcurrent()はファイルまたはディレクトリの完全なパス名を文字列で返し、CURRENT_AS_FILENAMEを指定するとファイル名またはディレクトリ名のみを文字列で返します。このように、CURRENT_MODE_MASKに関連する定数を利用することで、current()から取得する情報の形式を柔軟に選択できます。
RecursiveDirectoryIterator::CURRENT_MODE_MASKは、current()メソッドの戻り値の形式を制御するフラグ群を示すマスク値であり、直接指定せず、CURRENT_AS_FILEINFOのような具体的なモード定数をコンストラクタに渡して使います。これにより、current()が返す値の型(SplFileInfoオブジェクト、完全なパス名、ファイル名など)が決まります。戻り値の型によって、情報の取得方法やその後の処理が変わるため注意が必要です。例えば、文字列を返すモードでは、要素がファイルかどうかの判別にはイテレータのisFile()メソッドなどが必要です。複数のフラグは|演算子で組み合わせられますが、定数の意味を理解して正しく利用しましょう。一時ディレクトリなどの外部リソースを扱う際は、エラー処理と確実なクリーンアップを必ず実装してください。
PHPでディレクトリを再帰走査し、更新タイムスタンプを表示する
1<?php 2 3/** 4 * 指定されたディレクトリを再帰的に走査し、ファイルとその最終更新タイムスタンプを表示します。 5 * RecursiveDirectoryIterator::CURRENT_MODE_MASK を使用してファイルの種類を判別します。 6 * 7 * @param string $directoryPath 走査するディレクトリのパス 8 */ 9function listFilesWithModificationTimestamps(string $directoryPath): void 10{ 11 echo "--- ディレクトリの再帰的な走査とファイルのタイムスタンプ表示 ---" . PHP_EOL; 12 echo "対象ディレクトリ: " . realpath($directoryPath) . PHP_EOL . PHP_EOL; 13 14 try { 15 // RecursiveDirectoryIterator を使用してディレクトリを再帰的に走査します。 16 // SKIP_DOTS フラグは、'.' (現在のディレクトリ) と '..' (親ディレクトリ) のエントリをスキップします。 17 $iterator = new RecursiveDirectoryIterator( 18 $directoryPath, 19 RecursiveDirectoryIterator::SKIP_DOTS 20 ); 21 // RecursiveIteratorIterator は、RecursiveDirectoryIterator のような再帰的なイテレータを 22 // 単一のフラットなイテレータとして操作できるようにします。 23 // SELF_FIRST は、サブディレクトリに入る前にディレクトリ自身を返します。 24 $recursiveIterator = new RecursiveIteratorIterator( 25 $iterator, 26 RecursiveIteratorIterator::SELF_FIRST 27 ); 28 29 foreach ($recursiveIterator as $path => $fileInfo) { 30 // RecursiveDirectoryIterator::CURRENT_MODE_MASK を使用して、 31 // 現在のエントリがファイル、ディレクトリ、シンボリックリンクのいずれであるかを判別します。 32 // getFlags() メソッドはイテレータの現在のモードフラグを返します。 33 // CURRENT_MODE_MASK でビットマスクをかけることで、ファイルの種類に関する情報のみを抽出します。 34 $mode = $fileInfo->getFlags() & RecursiveDirectoryIterator::CURRENT_MODE_MASK; 35 36 if ($mode === RecursiveDirectoryIterator::CURRENT_MODE_DIR) { 37 echo "[DIR]: " . $path . PHP_EOL; 38 } elseif ($mode === RecursiveDirectoryIterator::CURRENT_MODE_FILE) { 39 // ファイルの場合、最終更新タイムスタンプを取得し表示します。 40 // getMTime() はUnixタイムスタンプ形式 (1970年1月1日 00:00:00 GMTからの秒数) で返します。 41 $modifiedTimestamp = $fileInfo->getMTime(); 42 // DateTimeImmutable を使用して、読みやすい日付時刻形式に変換します。 43 $dateTime = new DateTimeImmutable(); 44 $dateTime = $dateTime->setTimestamp($modifiedTimestamp); 45 46 echo "[FILE]: " . $path . PHP_EOL; 47 echo " 最終更新タイムスタンプ (Unix): " . $modifiedTimestamp . PHP_EOL; 48 echo " 最終更新日時: " . $dateTime->format('Y-m-d H:i:s') . PHP_EOL; 49 } 50 // CURRENT_MODE_LINK (シンボリックリンク) の判別も可能ですが、この例では割愛しています。 51 // 例: elseif ($mode === RecursiveDirectoryIterator::CURRENT_MODE_LINK) { ... } 52 } 53 } catch (UnexpectedValueException $e) { 54 echo "エラー: ディレクトリを読み込めませんでした。パスを確認してください - " . $e->getMessage() . PHP_EOL; 55 } 56 57 echo PHP_EOL . "--- 処理終了 ---" . PHP_EOL; 58} 59 60// --- サンプルコードの実行のための準備 --- 61// テスト用に一時ディレクトリを作成し、ファイルとサブディレクトリを用意します。 62$tempTestDir = __DIR__ . '/recursive_timestamp_test'; 63if (!is_dir($tempTestDir)) { 64 mkdir($tempTestDir); 65} 66file_put_contents($tempTestDir . '/sample_file1.txt', 'This is a test file.'); 67sleep(1); // タイムスタンプに差をつけるため、少し待機します。 68file_put_contents($tempTestDir . '/sample_file2.log', 'Another log entry.'); 69mkdir($tempTestDir . '/sub_directory'); 70file_put_contents($tempTestDir . '/sub_directory/nested_file.csv', '1,2,3'); 71 72// 作成した一時ディレクトリを走査する関数を実行します。 73listFilesWithModificationTimestamps($tempTestDir); 74 75// --- 後処理 --- 76// テスト後に作成した一時ディレクトリとファイルを削除するためのヘルパー関数です。 77function cleanupTestDirectory(string $dir): void 78{ 79 if (is_dir($dir)) { 80 $objects = scandir($dir); 81 foreach ($objects as $object) { 82 if ($object != "." && $object != "..") { 83 if (is_dir($dir . "/" . $object)) { 84 cleanupTestDirectory($dir . "/" . $object); 85 } else { 86 unlink($dir . "/" . $object); 87 } 88 } 89 } 90 rmdir($dir); 91 } 92} 93// テストディレクトリをクリーンアップします。 94cleanupTestDirectory($tempTestDir); 95 96?>
PHP 8のRecursiveDirectoryIterator::CURRENT_MODE_MASKは、ファイルシステムを再帰的に走査する際に、現在処理しているエントリがファイル、ディレクトリ、またはシンボリックリンクのいずれであるかを判別するためのビットマスク定数です。この定数はRecursiveDirectoryIteratorクラスに属し、引数はなく、int型の値を返します。
サンプルコードでは、listFilesWithModificationTimestamps関数が、指定されたディレクトリをRecursiveDirectoryIteratorとRecursiveIteratorIteratorを使用して深く走査します。ループ内で各エントリの情報($fileInfo)を取得し、$fileInfo->getFlags()の結果とCURRENT_MODE_MASKをビット論理積 (&) で組み合わせることで、エントリの正確な種類を判別しています。
判別結果がディレクトリ (CURRENT_MODE_DIR) であればそのパスを表示し、ファイル (CURRENT_MODE_FILE) であれば、パスに加えてgetMTime()メソッドで最終更新タイムスタンプ(Unixタイムスタンプ形式)を取得します。このタイムスタンプは、DateTimeImmutableクラスで人間が読みやすい形式の日付時刻に変換され、php current_timestampとして表示されます。このように、本定数を用いることで、ファイルの種類に応じた処理を正確に行い、ファイル管理や情報の取得を効率的に実現できます。
指定するディレクトリパスは実際に存在し、適切なアクセス権があることを確認してください。サンプルコードのようにtry-catchでUnexpectedValueExceptionを捕捉し、エラーハンドリングを行うことは安全なプログラミングにおいて非常に重要です。RecursiveDirectoryIterator::CURRENT_MODE_MASKは、getFlags()メソッドが返すイテレータの現在のモード情報から、エントリがファイル、ディレクトリ、シンボリックリンクのどれであるかを判別するために使用するビットマスク定数です。これとビット論理積演算子&を組み合わせることで、ファイルの種類に関する情報のみを正確に抽出できます。getMTime()で取得できる最終更新タイムスタンプはUnixタイムスタンプ形式のため、DateTimeImmutableクラスなどを用いて可読性の高い日付形式に変換して利用すると良いでしょう。また、非常に大規模なディレクトリツリーを再帰的に走査する場合、処理のパフォーマンスやメモリ使用量に注意が必要です。テスト用に作成した一時ファイルやディレクトリは、実際のシステム運用では不要なリソースとして残らないよう、確実にクリーンアップする仕組みを整えることが重要です。