【PHP8.x】RecursiveFilterIterator::current()メソッドの使い方
currentメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『currentメソッドは、フィルタリングされたイテレータの現在位置にある有効な要素を取得する処理を実行するメソッドです。このメソッドは、RecursiveFilterIteratorクラスが実装するIteratorインターフェースの一部であり、イテレータの基本的な操作を担います。RecursiveFilterIteratorは、多次元配列やディレクトリ構造のような再帰的なデータ構造を走査しながら、特定の条件に基づいて要素をフィルタリングする際に利用されます。currentメソッドを呼び出すと、内部のイテレータが指す現在の要素が、acceptメソッドで定義されたフィルタリング条件を満たすかどうかが評価されます。条件を満たす場合、その要素の値が返されます。もし現在の要素が条件を満たさない場合は、イテレータは条件を満たす次の要素まで自動的に進み、その要素が返されます。foreach構文などでイテレータを反復処理する際には、各ループで現在の要素の値を取得するために、このcurrentメソッドが内部的に呼び出されています。
構文(syntax)
1<?php 2 3// RecursiveFilterIteratorを継承したカスタムフィルタクラスを定義 4// 'A'で始まる文字列のみを許可する 5class FilterStartsWithA extends RecursiveFilterIterator 6{ 7 public function accept(): bool 8 { 9 // current()メソッドは、現在位置の要素を取得してフィルタ条件を評価するために使われる 10 return str_starts_with($this->current(), 'A'); 11 } 12} 13 14$data = [ 15 'Apple', 16 'Banana', 17 'Avocado', 18 'Cherry', 19]; 20 21// 配列からイテレータを作成 22$arrayIterator = new RecursiveArrayIterator($data); 23 24// カスタムフィルタを適用 25$iterator = new FilterStartsWithA($arrayIterator); 26 27// フィルタされたイテレータをループ処理 28foreach ($iterator as $key => $value) { 29 // 現在の要素を取得する構文 30 $currentElement = $iterator->current(); 31 32 // $valueと$currentElementは同じ値を保持する 33 printf("Key: %s, Value: %s\n", $key, $currentElement); 34} 35 36?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
mixed
RecursiveFilterIterator::currentメソッドは、現在の要素を返します。返される型はmixedです。
サンプルコード
PHPカレントディレクトリのPHPファイル検索
1<?php 2 3declare(strict_types=1); 4 5/** 6 * PHP ファイルのみをフィルタリングするイテレータクラス。 7 * RecursiveFilterIterator を継承し、特定の条件に合う要素だけを抽出します。 8 */ 9class PhpFileFilter extends RecursiveFilterIterator 10{ 11 /** 12 * このメソッドが true を返す要素のみがイテレーションの対象となります。 13 * 14 * @return bool 15 */ 16 public function accept(): bool 17 { 18 // current() メソッドで現在のイテレータ要素(ファイルやディレクトリ情報)を取得します。 19 // ここでは SplFileInfo オブジェクトが返されます。 20 $item = $this->current(); 21 22 // ディレクトリの場合は、その中を再帰的に探索するため true を返します。 23 if ($item->isDir()) { 24 return true; 25 } 26 27 // ファイルであり、かつ拡張子が 'php' の場合に true を返します。 28 return $item->isFile() && $item->getExtension() === 'php'; 29 } 30} 31 32/** 33 * 指定されたディレクトリ(ここではカレントディレクトリ配下)内のPHPファイルを 34 * 再帰的に検索し、そのパス一覧を表示します。 35 * 36 * この関数は自己完結しており、実行後に作成したディレクトリやファイルを自動でクリーンアップします。 37 */ 38function displayPhpFilesFromCurrentDirectory(): void 39{ 40 // 検索対象のディレクトリパス (このスクリプトと同じ階層に作成) 41 $basePath = __DIR__ . '/project_root'; 42 43 // --- 準備: サンプル用のディレクトリとファイルを作成 --- 44 if (!is_dir($basePath)) { 45 mkdir($basePath . '/src/Controllers', 0777, true); 46 } 47 file_put_contents($basePath . '/index.php', '<?php echo "Hello";'); 48 file_put_contents($basePath . '/config.ini', '[database]'); 49 file_put_contents($basePath . '/src/Model.php', '<?php class Model {}'); 50 file_put_contents($basePath . '/src/Controllers/UserController.php', '<?php class UserController {}'); 51 52 echo "Searching for PHP files in '{$basePath}'..." . PHP_EOL . PHP_EOL; 53 54 try { 55 // 1. ディレクトリを再帰的に読み込むイテレータを生成 56 $dirIterator = new RecursiveDirectoryIterator( 57 $basePath, 58 RecursiveDirectoryIterator::SKIP_DOTS 59 ); 60 61 // 2. 作成したカスタムフィルタ (PhpFileFilter) を適用 62 $filterIterator = new PhpFileFilter($dirIterator); 63 64 // 3. フィルタリングされた結果をフラットに処理するためのイテレータ 65 $recursiveIterator = new RecursiveIteratorIterator($filterIterator); 66 67 // 4. フィルタリングされた各要素をループ処理 68 foreach ($recursiveIterator as $fileInfo) { 69 // このループで取得できる $fileInfo は、フィルタを通過した現在の要素です。 70 // これは内部的に filterIterator->current() が返す値 (SplFileInfo) に相当します。 71 echo $fileInfo->getPathname() . PHP_EOL; 72 } 73 } catch (Exception $e) { 74 echo 'Error: ' . $e->getMessage() . PHP_EOL; 75 } finally { 76 // --- 後片付け: 作成したサンプル用のディレクトリとファイルを削除 --- 77 $cleanupIterator = new RecursiveIteratorIterator( 78 new RecursiveDirectoryIterator($basePath, RecursiveDirectoryIterator::SKIP_DOTS), 79 RecursiveIteratorIterator::CHILD_FIRST 80 ); 81 foreach ($cleanupIterator as $file) { 82 $file->isDir() ? rmdir($file->getRealPath()) : unlink($file->getRealPath()); 83 } 84 rmdir($basePath); 85 echo PHP_EOL . "Cleanup complete." . PHP_EOL; 86 } 87} 88 89// 関数を実行 90displayPhpFilesFromCurrentDirectory(); 91 92/* 93期待される出力例 (パスは環境によって異なります): 94 95Searching for PHP files in '/path/to/your/script/project_root'... 96 97/path/to/your/script/project_root/index.php 98/path/to/your/script/project_root/src/Controllers/UserController.php 99/path/to/your/script/project_root/src/Model.php 100 101Cleanup complete. 102*/
RecursiveFilterIterator::current()メソッドは、イテレータが現在指し示している要素を取得するために使用されます。このメソッドは引数を必要としません。
戻り値の型はmixedであり、元となるイテレータがどのような値を返すかによって決まります。サンプルコードでは、ディレクトリを走査するRecursiveDirectoryIteratorをフィルタリングしているため、current()メソッドは現在のファイルやディレクトリの情報をカプセル化したSplFileInfoオブジェクトを返します。
サンプルコードのPhpFileFilterクラス内では、フィルタリング条件を定義するacceptメソッドの中で$this->current()が呼び出されています。これにより現在のアイテム(ファイルまたはディレクトリ)を取得し、そのアイテムがディレクトリであるか、あるいは拡張子が.phpのファイルであるかを判定しています。このようにcurrent()メソッドは、フィルタリングの条件分岐において、判定対象となる要素そのものを取得するための重要な役割を担っています。
RecursiveFilterIteratorを継承したクラスでは、acceptメソッドを自分で実装する必要があります。このメソッド内で使うcurrent()は、現在調べているファイルやディレクトリの情報を取得します。今回のサンプルコードでは、RecursiveDirectoryIteratorと組み合わせているため、current()はファイル情報を扱うSplFileInfoオブジェクトを返します。このオブジェクトが持つisDir()やgetExtension()といったメソッドを使い、フィルタリングの条件を記述します。acceptメソッドがtrueを返した要素だけが、最終的な結果に含まれます。特に、ディレクトリの場合にtrueを返すことで、その中身も再帰的に探索される点が重要です。このように複数のイテレータを組み合わせることで、特定の条件に合うファイルだけを効率的に検索できます。
PHP RecursiveFilterIteratorでタイムスタンプフィルタリングする
1<?php 2 3/** 4 * 指定されたタイムスタンプより新しいファイルのみをフィルタリングする再帰イテレータ。 5 * 6 * このクラスは RecursiveFilterIterator を拡張し、accept() メソッドを実装して 7 * ファイルの更新日時 (タイムスタンプ) に基づいてフィルタリングを行います。 8 */ 9class TimestampFilterIterator extends RecursiveFilterIterator 10{ 11 /** 12 * @var int フィルタリングの基準となるUNIXタイムスタンプ 13 */ 14 private int $timestamp; 15 16 /** 17 * コンストラクタ 18 * 19 * @param RecursiveIterator $iterator 走査対象のイテレータ 20 * @param int $timestamp このタイムスタンプより新しいファイルが対象となる 21 */ 22 public function __construct(RecursiveIterator $iterator, int $timestamp) 23 { 24 parent::__construct($iterator); 25 $this->timestamp = $timestamp; 26 } 27 28 /** 29 * フィルタリングのロジックを定義します。 30 * ディレクトリ、または指定されたタイムスタンプより新しいファイルの場合に true を返します。 31 * 32 * @return bool このアイテムを結果に含める場合は true、除外する場合は false 33 */ 34 public function accept(): bool 35 { 36 // current() メソッドで現在のイテレータ要素 (SplFileInfo オブジェクト) を取得します。 37 $fileInfo = $this->current(); 38 39 // 対象がディレクトリの場合は、常に true を返して再帰的に探索を続けます。 40 if ($fileInfo->isDir()) { 41 return true; 42 } 43 44 // ファイルの最終更新タイムスタンプが、指定されたタイムスタンプより新しいかチェックします。 45 return $fileInfo->getMTime() > $this->timestamp; 46 } 47} 48 49// --- 以下、サンプルコードの実行部分 --- 50 51// テスト用のディレクトリとファイル構造を準備します。 52$baseDir = __DIR__ . '/recursive_filter_test'; 53if (!is_dir($baseDir)) { 54 mkdir($baseDir . '/subdir', 0777, true); 55 // 最近のファイル 56 touch($baseDir . '/recent.txt'); 57 // 古いファイル (3日前に設定) 58 touch($baseDir . '/old.log', time() - (3 * 24 * 60 * 60)); 59 touch($baseDir . '/subdir/another_recent.md'); 60} 61 62echo "過去24時間以内に更新されたファイルを検索します...\n\n"; 63 64try { 65 // フィルタリングの基準となる「24時間前のタイムスタンプ」を計算します。 66 $oneDayAgoTimestamp = time() - (24 * 60 * 60); 67 68 // 1. ディレクトリを再帰的に走査するイテレータを作成します。 69 // '.' や '..' をスキップするオプションを指定しています。 70 $directoryIterator = new RecursiveDirectoryIterator( 71 $baseDir, 72 RecursiveDirectoryIterator::SKIP_DOTS 73 ); 74 75 // 2. 作成したイテレータとタイムスタンプを使い、カスタムフィルタを適用します。 76 $filterIterator = new TimestampFilterIterator($directoryIterator, $oneDayAgoTimestamp); 77 78 // 3. フィルタリングされた結果をフラットに処理するためのイテレータを作成します。 79 $iterator = new RecursiveIteratorIterator($filterIterator); 80 81 // 4. フィルタリングされた結果をループ処理して表示します。 82 foreach ($iterator as $file) { 83 // $file は SplFileInfo オブジェクトです。 84 printf( 85 "- %s (更新日時: %s)\n", 86 $file->getPathname(), 87 date('Y-m-d H:i:s', $file->getMTime()) 88 ); 89 } 90} catch (Exception $e) { 91 echo "エラーが発生しました: " . $e->getMessage() . "\n"; 92} finally { 93 // 後片付け: テスト用に作成したディレクトリとファイルを削除します。 94 if (is_dir($baseDir)) { 95 $files = new RecursiveIteratorIterator( 96 new RecursiveDirectoryIterator($baseDir, RecursiveDirectoryIterator::SKIP_DOTS), 97 RecursiveIteratorIterator::CHILD_FIRST 98 ); 99 foreach ($files as $file) { 100 $file->isDir() ? rmdir($file->getRealPath()) : unlink($file->getRealPath()); 101 } 102 rmdir($baseDir); 103 } 104}
RecursiveFilterIterator::current() メソッドは、イテレータが現在指し示している要素を取得するために使用します。このメソッドに引数はありません。戻り値の型は mixed で、現在の要素そのものを返します。
このサンプルコードでは、ファイルの更新日時(タイムスタンプ)を基準にフィルタリングを行う TimestampFilterIterator という独自のクラスを定義しています。フィルタリングの具体的な条件は accept メソッド内に記述されており、その中で $this->current() が呼び出されています。これにより、現在処理対象となっているファイルやディレクトリの情報を持つ SplFileInfo オブジェクトが取得されます。
コードでは、current() で取得したオブジェクトの isDir() メソッドを使ってディレクトリかどうかを確認したり、getMTime() メソッドでファイルの最終更新タイムスタンプを取得したりしています。このように current() は、イテレータ内の個々の要素にアクセスし、その内容に基づいて結果に含めるか除外するかを判断するための起点となる重要な役割を担っています。
RecursiveFilterIteratorを継承したクラスでは、acceptメソッドに独自のフィルタ条件を記述します。このメソッド内で呼び出されるcurrent()は、現在処理対象となっているアイテムを取得するメソッドです。サンプルではRecursiveDirectoryIteratorを元にしているため、current()はファイルやディレクトリの情報を持つSplFileInfoオブジェクトを返します。acceptメソッドの重要な点は、ディレクトリの場合は常にtrueを返し、その配下も探索対象に含めることです。もしfalseを返すと、そのディレクトリ内のファイルは一切チェックされなくなりますので注意が必要です。また、日時の比較はtime()やgetMTime()が返すUNIXタイムスタンプという数値で行っているため、単純な大小比較が可能です。