【PHP8.x】RecursiveCallbackFilterIterator::__construct()メソッドの使い方
__constructメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
__constructメソッドは、RecursiveCallbackFilterIteratorクラスの新しいインスタンスを生成するために実行するメソッドです。このメソッドは、フィルタリングの対象となる再帰イテレータと、フィルタリングのルールを定義したコールバック関数の2つを引数として受け取ります。第1引数には、RecursiveDirectoryIteratorのような、再帰的な処理が可能なイテレータオブジェクトを指定します。これにより、ディレクトリの階層構造のようなネストされたデータを走査の対象とすることができます。第2引数には、各要素をイテレーションに含めるかどうかを判定するためのコールバック関数を指定します。このコールバック関数は、現在の要素、キー、イテレータ自身を引数として受け取り、論理値(trueまたはfalse)を返す必要があります。コールバック関数がtrueを返した要素は有効なものとして残り、falseを返した要素はフィルタリングによって除外されます。この仕組みにより、開発者は独自の複雑な条件に基づいて、再帰的なデータセットから必要な要素だけを効率的に抽出できます。
構文(syntax)
1public __construct(RecursiveIterator $iterator, callable $callback)
引数(parameters)
RecursiveIterator $iterator, callable $callback
- RecursiveIterator $iterator: フィルター処理を行うRecursiveIteratorオブジェクト
- callable $callback: 各要素に対して呼び出されるコールバック関数
戻り値(return)
戻り値なし
戻り値はありません
サンプルコード
PHP RecursiveCallbackFilterIterator コンストラクタでデータフィルタリング
1<?php 2 3/** 4 * RecursiveCallbackFilterIterator のコンストラクタを使用して、 5 * 多次元配列から特定の条件に合う要素のみを再帰的に抽出するクラスの例です。 6 */ 7class DataFilter 8{ 9 /** 10 * 指定されたデータから10以上の数値を持つ要素のみをフィルタリングして表示します。 11 * 12 * @param array $data フィルタリング対象の多次元配列 13 */ 14 public function displayFilteredData(array $data): void 15 { 16 // 1. 多次元配列を再帰的に走査するためのイテレータを作成します。 17 $recursiveArrayIterator = new RecursiveArrayIterator($data); 18 19 // 2. RecursiveCallbackFilterIterator のインスタンスを生成します。 20 // コンストラクタは、イテレータとコールバック関数を引数に取ります。 21 // このコールバック関数がフィルタリングのルールを定義します。 22 $filterIterator = new RecursiveCallbackFilterIterator( 23 $recursiveArrayIterator, 24 /** 25 * フィルタリングを行うコールバック関数。 26 * @param mixed $current 現在の要素の値 27 * @param mixed $key 現在の要素のキー 28 * @param RecursiveIterator $iterator 現在のイテレータ 29 * @return bool 要素を残す場合は true、除外する場合は false を返す 30 */ 31 function ($current, $key, $iterator) { 32 // 現在の要素が子要素(=配列)を持つ場合、その階層は常に表示対象とします。 33 if ($iterator->hasChildren()) { 34 return true; 35 } 36 // 子要素を持たない場合(=値)、その値が数値かつ10以上か判定します。 37 return is_numeric($current) && $current >= 10; 38 } 39 ); 40 41 // 3. フィルタリングされた結果を再帰的に走査し、キーと値を表示します。 42 // RecursiveIteratorIterator は、再帰的なイテレータをフラットに展開して処理しやすくします。 43 $iterator = new RecursiveIteratorIterator($filterIterator); 44 45 echo "10以上の値を持つ要素のみ:\n"; 46 foreach ($iterator as $key => $value) { 47 echo "{$key} => {$value}\n"; 48 } 49 } 50} 51 52// フィルタリングする多次元配列データ 53$sampleData = [ 54 'product_a' => 5, 55 'product_b' => 20, 56 'category_x' => [ 57 'product_c' => 8, 58 'product_d' => 15, 59 ], 60 'category_y' => [ 61 'subcategory_z' => [ 62 'product_e' => 30, 63 ], 64 'product_f' => 9, 65 ], 66]; 67 68// クラスのインスタンスを生成し、メソッドを実行 69$filter = new DataFilter(); 70$filter->displayFilteredData($sampleData); 71 72?>
RecursiveCallbackFilterIteratorのコンストラクタは、再帰的なデータ構造をフィルタリングするための新しいイテレータオブジェクトを生成します。このメソッドは、クラスのインスタンスが作成される際に自動的に呼び出されます。
第1引数$iteratorには、フィルタリングの対象となる多次元配列などを順番にたどるためのRecursiveIteratorオブジェクトを指定します。サンプルコードではRecursiveArrayIteratorを使い、配列を走査可能なオブジェクトに変換して渡しています。
第2引数$callbackには、フィルタリングのルールを定義したコールバック関数を指定します。この関数はデータ構造の各要素に対して実行され、trueを返した要素は結果に残り、falseを返した要素は除外されます。サンプルコードのコールバック関数では、要素が配列の場合は常にtrueを返し、値の場合はそれが10以上かどうかを判定するルールを定義しています。
このコンストラクタ自体に戻り値はありませんが、指定されたルールでフィルタリングを行う準備ができたRecursiveCallbackFilterIteratorの新しいインスタンスを生成します。
このクラスのコンストラクタは、フィルタリング対象のイテレータと、そのルールを定義したコールバック関数を引数に取ります。コールバック関数は、要素を残す場合にtrue、除外する場合にfalseを返すように実装する必要があります。サンプルコードのように多次元のデータを扱う場合、目的の値が含まれる親の配列自体を除外しないよう、$iterator->hasChildren()で配列かどうかを判定し、trueを返す処理が重要です。これがないと、深い階層にある値が正しくフィルタリングされません。また、コンストラクタの第一引数には、配列を直接渡すのではなく、RecursiveArrayIteratorなどでイテレータに変換したオブジェクトを渡してください。
RecursiveCallbackFilterIteratorコンストラクタでログファイルを探す
1<?php 2 3/** 4 * RecursiveCallbackFilterIterator のコンストラクタを使用して、 5 * 再帰的にディレクトリを探索し、特定の条件(拡張子が .log)に一致するファイルのみを抽出するサンプルクラスです。 6 */ 7class LogFileFinder 8{ 9 /** 10 * 指定されたディレクトリパス 11 * @var string 12 */ 13 private string $directory; 14 15 /** 16 * コンストラクタ 17 * テスト用のディレクトリとファイルを作成します。 18 * 19 * @param string $directory テスト用のディレクトリ名 20 */ 21 public function __construct(string $directory = 'test_logs_dir') 22 { 23 $this->directory = $directory; 24 $this->setupTestDirectory(); 25 } 26 27 /** 28 * デストラクタ 29 * テスト用のディレクトリとファイルをクリーンアップします。 30 */ 31 public function __destruct() 32 { 33 $this->cleanupTestDirectory(); 34 } 35 36 /** 37 * .log ファイルを検索して表示します。 38 */ 39 public function findAndDisplay(): void 40 { 41 try { 42 // 1. 再帰的にディレクトリを走査するイテレータを作成 43 $directoryIterator = new RecursiveDirectoryIterator( 44 $this->directory, 45 FilesystemIterator::SKIP_DOTS 46 ); 47 48 // 2. RecursiveCallbackFilterIterator のコンストラクタを呼び出す 49 // 第1引数: 対象となる再帰イテレータ 50 // 第2引数: フィルタリング条件を定義したコールバック関数 51 $filterIterator = new RecursiveCallbackFilterIterator($directoryIterator, function ($current, $key, $iterator) { 52 // ディレクトリの場合は、再帰的に中を探索するため true を返す 53 if ($iterator->hasChildren()) { 54 return true; 55 } 56 // ファイルの場合、ファイル名が '.log' で終わるかチェックする 57 // isFile() でファイルであることを確認し、str_ends_with() で拡張子を判定 58 return $current->isFile() && str_ends_with($current->getFilename(), '.log'); 59 }); 60 61 // 3. フィルタリングされた結果を簡単にループ処理するためのイテレータ 62 $recursiveIterator = new RecursiveIteratorIterator($filterIterator); 63 64 echo "Found .log files:" . PHP_EOL; 65 foreach ($recursiveIterator as $fileInfo) { 66 // SplFileInfo オブジェクトからリアルパスを取得して表示 67 echo $fileInfo->getRealPath() . PHP_EOL; 68 } 69 } catch (Exception $e) { 70 echo "An error occurred: " . $e->getMessage() . PHP_EOL; 71 } 72 } 73 74 /** 75 * テスト用のディレクトリ構造とファイルを作成するヘルパーメソッド。 76 */ 77 private function setupTestDirectory(): void 78 { 79 if (!is_dir($this->directory)) { 80 mkdir($this->directory . '/subdir', 0777, true); 81 } 82 // テスト用のファイルを作成 83 touch($this->directory . '/access.log'); 84 touch($this->directory . '/error.log'); 85 touch($this->directory . '/system.txt'); 86 touch($this->directory . '/subdir/debug.log'); 87 touch($this->directory . '/subdir/config.json'); 88 } 89 90 /** 91 * テスト用のディレクトリとファイルを削除するヘルパーメソッド。 92 */ 93 private function cleanupTestDirectory(): void 94 { 95 if (!is_dir($this->directory)) { 96 return; 97 } 98 // 再帰的にファイルを削除 99 $iterator = new RecursiveIteratorIterator( 100 new RecursiveDirectoryIterator($this->directory, FilesystemIterator::SKIP_DOTS), 101 RecursiveIteratorIterator::CHILD_FIRST 102 ); 103 foreach ($iterator as $file) { 104 if ($file->isDir()) { 105 rmdir($file->getRealPath()); 106 } else { 107 unlink($file->getRealPath()); 108 } 109 } 110 rmdir($this->directory); 111 } 112} 113 114// クラスのインスタンスを作成し、メソッドを実行 115$finder = new LogFileFinder(); 116$finder->findAndDisplay(); 117
RecursiveCallbackFilterIteratorのコンストラクタは、再帰的なイテレータ(フォルダ構造など、入れ子になったデータ)を特定の条件でフィルタリングするための新しいインスタンスを生成します。この処理は、インスタンスが new キーワードで作成される際に自動的に呼び出されます。
コンストラクタは2つの引数を取ります。第1引数 $iterator には、フィルタリングの対象となる RecursiveDirectoryIterator のような、再帰的な処理が可能なイテレータオブジェクトを指定します。これにより、どのデータ構造を走査するのかを決定します。
第2引数 $callback には、フィルタリングのルールを定義したコールバック関数を指定します。この関数は、イテレータが各要素(ファイルやディレクトリ)を指すたびに呼び出されます。関数が true を返した要素だけが結果に残り、false を返した要素は除外されます。サンプルコードでは、ディレクトリは常に true を返し、ファイルの場合は拡張子が .log のものだけを true とすることで、ログファイルのみを抽出しています。
このコンストラクタに戻り値はありません。インスタンスの生成と初期化が目的だからです。
RecursiveCallbackFilterIteratorのコンストラクタに渡すコールバック関数の挙動が最も重要です。再帰的に処理するため、ディレクトリの場合は必ずtrueを返し、サブディレクトリ内の探索を継続させる必要があります。もしディレクトリでfalseを返してしまうと、その配下のファイルは一切フィルタリングの対象になりません。また、コールバック関数が受け取る3つの引数(現在の要素、キー、イテレータ自身)を正しく理解し、条件分岐に利用することが求められます。このコードで使われているstr_ends_with()関数はPHP 8.0からの機能なので、古いバージョンでは代替の関数を使用する必要があります。