【PHP8.x】RecursiveDirectoryIterator::getCTime()メソッドの使い方
getCTimeメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
getCTimeメソッドは、PHP 8で提供されるRecursiveDirectoryIteratorクラスに属し、現在イテレートしているディレクトリまたはファイルのエントリに関するinode変更時刻を取得するメソッドです。このメソッドは、ファイルシステム上のファイルやディレクトリのメタデータが最後に変更された時刻を、Unixタイムスタンプ形式の整数値で返します。
inode変更時刻(ctime)とは、ファイルのデータ内容そのものの更新だけでなく、ファイルの所有者、グループ、パーミッションといったメタ情報が変更された際に更新される時刻を指します。これは、ファイルのデータ内容が最後に更新された時刻である最終更新時刻(mtime)とは異なる点にご注意ください。例えば、ファイルのパーミッションやアクセス権を変更した場合、mtimeは更新されませんが、ctimeは更新されます。
このメソッドを使用することで、ファイルやディレクトリの構造的な変更やアクセス権の変更履歴を追跡したい場合に特に役立ちます。ファイルのメタデータの変更を監視するシナリオや、セキュリティ監査の目的でファイルシステムの変更を記録したい場合などに活用できます。戻り値は成功するとUnixタイムスタンプを返し、失敗した場合にはfalseを返すことがあります。ファイルシステムの正確な変更履歴を把握するために重要な情報を提供するメソッドです。
構文(syntax)
1<?php 2$directoryIterator = new RecursiveDirectoryIterator(__DIR__); 3$cTime = $directoryIterator->getCTime(); 4?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
int|false
このメソッドは、エントリの変更時刻(ctime)を整数または false で返します。
サンプルコード
RecursiveDirectoryIterator で ctime を取得する
1<?php 2 3// 一時ディレクトリを作成し、テスト用のファイルやディレクトリを準備する関数 4function setupTestDirectory(string $baseDir): string 5{ 6 $tempDir = $baseDir . '/temp_ctime_test_' . uniqid(); 7 if (!mkdir($tempDir) && !is_dir($tempDir)) { 8 throw new \RuntimeException(sprintf('Directory "%s" was not created', $tempDir)); 9 } 10 file_put_contents($tempDir . '/file1.txt', 'Test content for file1.'); 11 mkdir($tempDir . '/subdir'); 12 file_put_contents($tempDir . '/subdir/file2.txt', 'Content for file2.'); 13 return $tempDir; 14} 15 16// 作成した一時ディレクトリとファイルを削除する関数 17function cleanupTestDirectory(string $dir): void 18{ 19 if (!is_dir($dir)) { 20 return; 21 } 22 $files = new RecursiveIteratorIterator( 23 new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), 24 RecursiveIteratorIterator::CHILD_FIRST 25 ); 26 foreach ($files as $fileinfo) { 27 if ($fileinfo->isDir()) { 28 rmdir($fileinfo->getRealPath()); 29 } else { 30 unlink($fileinfo->getRealPath()); 31 } 32 } 33 rmdir($dir); 34} 35 36// スクリプトの実行ディレクトリを基準に一時ディレクトリを設定 37$testDirectoryPath = setupTestDirectory(__DIR__); 38 39try { 40 // RecursiveDirectoryIterator を使用してディレクトリを再帰的に走査します。 41 // RecursiveDirectoryIterator::SKIP_DOTS は "." と ".." をスキップします。 42 $directoryIterator = new RecursiveDirectoryIterator( 43 $testDirectoryPath, 44 RecursiveDirectoryIterator::SKIP_DOTS 45 ); 46 47 // RecursiveIteratorIterator を使って、ディレクトリ構造を深くまで辿ります。 48 // RecursiveIteratorIterator::SELF_FIRST は、ディレクトリ自体も先に処理対象とします。 49 $iterator = new RecursiveIteratorIterator( 50 $directoryIterator, 51 RecursiveIteratorIterator::SELF_FIRST 52 ); 53 54 echo "--- ディレクトリ・ファイルの変更タイムスタンプ ---\n"; 55 56 foreach ($iterator as $path => $fileInfo) { 57 /** @var SplFileInfo $fileInfo */ 58 59 // getCTime() メソッドでファイルの inode 変更時刻 (UNIX タイムスタンプ) を取得します。 60 // Windows 環境ではファイル作成時刻となる場合があります。 61 // 戻り値は成功時に int (タイムスタンプ)、失敗時に false です。 62 $cTime = $fileInfo->getCTime(); 63 64 if ($cTime !== false) { 65 // UNIX タイムスタンプを人間が読める日付・時刻形式に変換します。 66 $formattedTime = date('Y-m-d H:i:s', $cTime); 67 echo sprintf( 68 "パス: %s | タイムスタンプ (int): %d | 日時 (formatted): %s\n", 69 $fileInfo->getPathname(), 70 $cTime, 71 $formattedTime 72 ); 73 } else { 74 echo sprintf( 75 "パス: %s | タイムスタンプの取得に失敗しました。\n", 76 $fileInfo->getPathname() 77 ); 78 } 79 } 80} catch (UnexpectedValueException $e) { 81 echo "エラー: 指定されたディレクトリが存在しないか、アクセスできません: " . $e->getMessage() . "\n"; 82} finally { 83 // 使用した一時ディレクトリとファイルを削除し、環境をクリーンアップします。 84 cleanupTestDirectory($testDirectoryPath); 85 echo "\n--- テストディレクトリのクリーンアップが完了しました ---\n"; 86} 87
PHPのRecursiveDirectoryIterator::getCTimeメソッドは、ファイルやディレクトリの「inode変更時刻」をUNIXタイムスタンプ形式で取得するために使用されます。UNIXタイムスタンプとは、1970年1月1日00:00:00 UTC(協定世界時)からの経過秒数を表す整数値です。このメソッドは引数をとりません。
戻り値は、成功した場合は整数(int)としてUNIXタイムスタンプを返しますが、情報取得に失敗した場合はfalseを返します。特にWindows環境では、このメソッドがファイルの「作成時刻」を返すことがある点に注意が必要です。
提供されたサンプルコードでは、一時的なディレクトリとファイルを作成し、RecursiveDirectoryIteratorとRecursiveIteratorIteratorを使ってその中を再帰的に走査しています。走査中に取得される各ファイルやディレクトリのSplFileInfoオブジェクトに対してgetCTime()メソッドを呼び出し、inode変更時刻のタイムスタンプを取得しています。取得したタイムスタンプがfalseでない場合、date()関数を用いて人間が読みやすい「年-月-日 時:分:秒」形式に変換して表示し、取得失敗時にはその旨を報告しています。これにより、ディレクトリ内の各要素の変更時刻を一覧で確認することができます。
getCTime()は、ファイルやディレクトリの情報を管理するデータが変更された時刻を取得します。これはファイルの内容が変更された時刻とは異なる概念です。特にWindows環境では、この時刻がファイルの作成時刻として扱われる場合がありますので、利用環境での挙動を把握しておきましょう。メソッドは成功時にUNIXタイムスタンプ(整数)、失敗時にはfalseを返します。必ず!== falseで戻り値を厳密に確認し、適切にエラーを処理することが重要です。取得したタイムスタンプはそのままでは読みにくいため、date()関数などを用いて人間が理解しやすい日付形式に変換して利用することをおすすめします。
RecursiveDirectoryIterator::getCTime()で変更時刻を取得する
1<?php 2 3/** 4 * RecursiveDirectoryIterator::getCTime() の使用例 5 * 指定されたディレクトリとそのサブディレクトリ内のファイルやディレクトリの 6 * 変更時刻(ctime: Change Time)を取得して表示します。 7 * ctime は、ファイルの inode 情報(パーミッション、所有者、最終変更時刻など)が 8 * 変更された最終時刻を示す UNIX タイムスタンプです。 9 * 10 * @return void 11 */ 12function demonstrateGetCTime(): void 13{ 14 // 1. サンプル用のディレクトリとファイルを作成します。 15 // スクリプトが実行されているディレクトリに 'sample_dir_for_ctime' を作成 16 $baseDir = __DIR__ . '/sample_dir_for_ctime'; 17 18 // ディレクトリが既に存在する場合は削除して作り直します。 19 // これにより、毎回クリーンな状態でサンプルを実行できます。 20 if (is_dir($baseDir)) { 21 deleteDirectoryRecursively($baseDir); 22 } 23 mkdir($baseDir); 24 mkdir($baseDir . '/subdir'); 25 26 // ファイルを作成し、内容を書き込みます。 27 file_put_contents($baseDir . '/file1.txt', 'This is file1.'); 28 file_put_contents($baseDir . '/subdir/file2.txt', 'This is file2 in a subdir.'); 29 30 echo "--- RecursiveDirectoryIterator::getCTime() のデモンストレーション ---\n\n"; 31 32 try { 33 // 2. RecursiveDirectoryIterator をインスタンス化します。 34 // SKIP_DOTS フラグで '.' と '..' ディレクトリをスキップします。 35 $directoryIterator = new RecursiveDirectoryIterator( 36 $baseDir, 37 RecursiveDirectoryIterator::SKIP_DOTS 38 ); 39 40 // 3. RecursiveIteratorIterator を使用して、サブディレクトリも再帰的に走査します。 41 // SELF_FIRST フラグで、ディレクトリ自体をまず処理し、次にその内容を処理します。 42 $iterator = new RecursiveIteratorIterator( 43 $directoryIterator, 44 RecursiveIteratorIterator::SELF_FIRST 45 ); 46 47 // 4. 各ファイルまたはディレクトリのエントリをループで処理します。 48 foreach ($iterator as $fileInfo) { 49 // 現在のエントリのパスを取得します。 50 $path = $fileInfo->getPathname(); 51 52 // getCTime() メソッドを呼び出し、変更時刻(ctime)を取得します。 53 // 戻り値は UNIX タイムスタンプ(int)または失敗時に false です。 54 $ctime = $fileInfo->getCTime(); 55 56 if ($ctime !== false) { 57 // 取得した UNIX タイムスタンプを、読みやすい日付時刻形式に変換します。 58 $formattedCtime = date('Y-m-d H:i:s', $ctime); 59 echo sprintf( 60 "パス: %s\n 変更時刻 (ctime): %s\n", 61 $path, 62 $formattedCtime 63 ); 64 } else { 65 echo sprintf("パス: %s\n 変更時刻 (ctime) の取得に失敗しました。\n", $path); 66 } 67 } 68 } catch (UnexpectedValueException $e) { 69 // ディレクトリが見つからない、またはアクセス権がない場合のエラー処理 70 echo "エラー: ディレクトリの走査中に問題が発生しました。 " . $e->getMessage() . "\n"; 71 } finally { 72 // 5. サンプル用に作成したディレクトリとファイルをクリーンアップします。 73 echo "\n--- クリーンアップを開始します ---\n"; 74 deleteDirectoryRecursively($baseDir); 75 echo "--- クリーンアップが完了しました ---\n"; 76 } 77} 78 79/** 80 * 指定されたディレクトリとその内容を再帰的に削除します。 81 * 82 * @param string $dir 削除するディレクトリのパス 83 * @return void 84 */ 85function deleteDirectoryRecursively(string $dir): void 86{ 87 if (!is_dir($dir)) { 88 return; 89 } 90 // scandir() でディレクトリ内の全てのファイルとディレクトリを取得し、'.' と '..' を除外 91 $files = array_diff(scandir($dir), ['.', '..']); 92 foreach ($files as $file) { 93 $path = $dir . '/' . $file; 94 // ディレクトリであれば再帰的に自身を呼び出し、ファイルであれば削除 95 (is_dir($path)) ? deleteDirectoryRecursively($path) : unlink($path); 96 } 97 // ディレクトリが空になったら削除 98 rmdir($dir); 99} 100 101// 関数の実行 102demonstrateGetCTime();
PHPのRecursiveDirectoryIterator::getCTime()メソッドは、ディレクトリを再帰的に走査する際に、各ファイルやディレクトリの「変更時刻(ctime)」を取得します。ctimeとは、ファイルのパーミッションや所有者情報といったメタデータが変更された最終時刻を示すUNIXタイムスタンプです。ファイルの内容が変更された最終時刻(mtime)とは異なる点に注意が必要です。
このメソッドは引数を必要とせず、成功するとUNIXタイムスタンプ形式の整数値(int)を返します。ファイルが存在しない、またはアクセス権がないなどの理由で時刻の取得に失敗した場合は、falseを返します。
サンプルコードでは、まず一時的に作成したディレクトリとファイルに対して、RecursiveDirectoryIteratorとRecursiveIteratorIteratorを用いて再帰的に走査しています。そして、走査で見つかった各ファイルやディレクトリについてgetCTime()を呼び出し、その変更時刻を取得しています。取得したUNIXタイムスタンプは、date()関数で人間が読みやすい形式に変換して表示しています。これにより、ディレクトリ構造内の各要素のctimeがどのように取得・表示されるかを確認できます。
RecursiveDirectoryIterator::getCTime()は、ファイルやディレクトリのinode情報が最後に変更された時刻をUNIXタイムスタンプ(整数値)で返します。ファイルのデータ更新時刻(mtime)とは異なり、パーミッションや所有者の変更でも更新される点に注意が必要です。取得に失敗した場合はfalseを返すため、必ず戻り値をチェックし、適切にエラー処理を行ってください。また、このctimeの概念は主にUNIX系システムで有効であり、Windows環境では異なる振る舞いをすることがあります。サンプルコードのように一時的に作成したディレクトリやファイルは、処理終了後にfinallyブロックなどで必ずクリーンアップし、不要なリソースを残さないようにしましょう。