【PHP8.x】FilterIterator::current()メソッドの使い方
currentメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『currentメソッドは、フィルタリング後のイテレータで現在位置にある要素を取得するために実行するメソッドです』
このメソッドは、PHPのIteratorインターフェースで定義されている基本的なメソッドの一つであり、FilterIteratorクラスで利用されます。FilterIteratorは、配列や他のイテレータオブジェクトを元にして、特定の条件を満たす要素だけを抽出するためのものです。currentメソッドは、その抽出条件(acceptメソッドで定義)を通過した要素のうち、イテレータが現在指し示している要素の値を返します。foreachループでFilterIteratorのインスタンスを反復処理する場合、ループの各サイクルで変数に代入される値は、このcurrentメソッドが返す値そのものです。返される値のデータ型は、元のイテレータに含まれる要素の型に依存するため、文字列、数値、オブジェクトなど様々です。もしイテレータが有効な要素を指していない場合、例えば反復処理が終了した後などに呼び出されると、nullなどを返すことがあります。
構文(syntax)
1<?php 2// 偶数のみを許可するカスタムフィルタクラス 3class EvenNumberFilter extends FilterIterator 4{ 5 // このメソッドが true を返した要素のみがイテレーションの対象となる 6 public function accept(): bool 7 { 8 // 親イテレータの現在の値を取得し、偶数かどうかを判定 9 $currentValue = parent::current(); 10 return $currentValue % 2 === 0; 11 } 12} 13 14// フィルタリング対象のデータを持つイテレータ 15$arrayIterator = new ArrayIterator([1, 2, 3, 4, 5, 6, 7, 8]); 16 17// フィルタを適用したイテレータを作成 18$filterIterator = new EvenNumberFilter($arrayIterator); 19 20// フィルタされたイテレータをループで処理する 21// foreachループは、内部で valid(), current(), next() を自動的に呼び出す 22foreach ($filterIterator as $value) { 23 // この $value には、FilterIterator::current() が返した値が格納される 24 echo $value . PHP_EOL; 25} 26?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
mixed
現在のイテレータが指している要素を返します。要素が存在しない場合は null を返します。
サンプルコード
PHPのcurrent()でPHPファイル一覧を取得する
1<?php 2 3/** 4 * 現在のディレクトリからPHPファイルのみをフィルタリングするためのカスタムイテレータクラス。 5 * 6 * FilterIteratorを継承し、accept()メソッドを実装することで、 7 * どの要素をイテレーションに含めるかのロジックを定義します。 8 */ 9class PhpFileFilter extends FilterIterator 10{ 11 /** 12 * イテレータの現在の要素が有効かどうかを判定します。 13 * 14 * このメソッドが true を返した要素だけが、ループ処理の対象となります。 15 * 16 * @return bool この要素を含める場合は true、スキップする場合は false。 17 */ 18 public function accept(): bool 19 { 20 // FilterIterator::current() は、元となるイテレータの現在の要素を返します。 21 // このサンプルでは、FilesystemIteratorが返すSplFileInfoオブジェクトが該当します。 22 $file = $this->current(); 23 24 // それがファイルであり、かつ拡張子が 'php' の場合にのみ true を返します。 25 return $file->isFile() && $file->getExtension() === 'php'; 26 } 27} 28 29// 1. 現在のディレクトリ(このスクリプトファイルがある場所)を走査するイテレータを作成します。 30$directoryIterator = new FilesystemIterator(__DIR__); 31 32// 2. 作成したディレクトリイテレータを、カスタムフィルタでラップ(包み込み)します。 33$phpFileIterator = new PhpFileFilter($directoryIterator); 34 35echo "現在のディレクトリにあるPHPファイル一覧:\n"; 36 37// 3. フィルタリングされたイテレータをforeachでループ処理します。 38// ループの各反復で、内部的に FilterIterator::current() が呼び出され、 39// accept() メソッドの条件を満たした要素が $fileInfo に代入されます。 40foreach ($phpFileIterator as $fileInfo) { 41 echo $fileInfo->getFilename() . "\n"; 42}
このPHPコードは、指定したディレクトリ内から特定の条件に合致するファイルだけを一覧表示するサンプルです。この例では、プログラムが置かれている現在のディレクトリから、拡張子が「.php」のファイルのみを検索して表示します。
この処理で中心的な役割を果たすのが、FilterIteratorクラスです。これは、既存のイテレータ(ファイル一覧などの繰り返し処理を行う仕組み)に対して、フィルタリング機能を追加するためのクラスです。サンプルでは、ファイルシステムを走査するFilesystemIteratorを、自作のPhpFileFilterクラスで包み込むことでフィルタをかけています。
FilterIteratorクラスのcurrent()メソッドは、フィルタリング対象となっている元のイテレータが、現在指し示している要素を取得します。このメソッドに引数はなく、戻り値は元のイテレータの要素、この場合はファイル情報を表すSplFileInfoオブジェクトです。accept()メソッド内でこのcurrent()を呼び出し、取得したファイルが条件(PHPファイルであるか)を満たすか判定します。条件を満たした要素だけが、最終的な繰り返し処理の対象となります。このようにcurrent()は、フィルタリングの条件判定を行うために、現在の要素を提供する重要な役割を担います。
このコードのポイントは、FilterIteratorを継承して独自のフィルタールールを定義する点です。注意すべきはacceptメソッド内の$this->current()です。これはPhpFileFilterクラスのメソッドですが、実際には元となるイテレータ(この場合はFilesystemIterator)の現在の要素、つまりファイル情報を取得します。そのため、戻り値はSplFileInfoオブジェクトとなり、isFile()やgetExtension()といったメソッドが使えます。acceptメソッドは、このファイル情報をもとに条件判定を行い、trueを返した要素だけがループ処理の対象となります。また、__DIR__はスクリプトファイルがあるディレクトリの絶対パスを返すため、どこから実行しても対象ディレクトリが固定され、意図しない動作を防げます。
PHP FilterIterator current()でタイムスタンプをフィルタリングする
1<?php 2 3declare(strict_types=1); 4 5/** 6 * 指定されたタイムスタンプより新しいタイムスタンプのみをフィルタリングするイテレータ。 7 * 8 * FilterIteratorを継承し、独自のフィルタリングロジックを実装します。 9 * キーワード「timestamp」と「current」を関連付けるサンプルです。 10 */ 11class RecentTimestampFilterIterator extends FilterIterator 12{ 13 /** 14 * @var int フィルタリングの基準となるタイムスタンプ 15 */ 16 private int $thresholdTimestamp; 17 18 /** 19 * コンストラクタ 20 * 21 * @param Iterator $iterator ラップするイテレータ 22 * @param int $thresholdTimestamp フィルタリングの基準となるタイムスタンプ 23 */ 24 public function __construct(Iterator $iterator, int $thresholdTimestamp) 25 { 26 parent::__construct($iterator); 27 $this->thresholdTimestamp = $thresholdTimestamp; 28 } 29 30 /** 31 * 現在の要素をフィルタリングに含めるかどうかを判断します。 32 * このメソッドはイテレーション中に内部的に呼び出されます。 33 * 34 * @return bool 現在の要素が有効な場合は true、そうでない場合は false 35 */ 36 public function accept(): bool 37 { 38 // FilterIterator::current() を使って現在の要素(タイムスタンプ)を取得します。 39 $currentTimestamp = $this->getInnerIterator()->current(); 40 41 // 取得した値が整数であり、かつ基準のタイムスタンプより大きい(新しい)場合のみ true を返します。 42 return is_int($currentTimestamp) && $currentTimestamp > $this->thresholdTimestamp; 43 } 44} 45 46// --- サンプル実行コード --- 47 48// 現在時刻のタイムスタンプを取得 49$currentTimestamp = time(); 50 51// サンプルデータとなるタイムスタンプの配列 52$timestamps = [ 53 $currentTimestamp - 7200, // 2時間前 54 $currentTimestamp - 3600, // 1時間前 55 $currentTimestamp, // 現在 56 $currentTimestamp + 3600, // 1時間後 57 $currentTimestamp + 7200, // 2時間後 58]; 59 60// 配列からArrayIteratorを作成します 61$arrayIterator = new ArrayIterator($timestamps); 62 63// FilterIteratorを継承したカスタムクラスのインスタンスを生成します。 64// フィルタの基準として「現在のタイムスタンプ」を渡します。 65$iterator = new RecentTimestampFilterIterator($arrayIterator, $currentTimestamp); 66 67echo "基準時刻: " . date('Y-m-d H:i:s', $currentTimestamp) . " ({$currentTimestamp})\n"; 68echo "--- フィルタリング結果 ---\n"; 69 70// イテレータをループ処理します。 71// accept()メソッドがtrueを返した要素のみがループの対象となります。 72foreach ($iterator as $filteredTimestamp) { 73 // foreach ループ内で $filteredTimestamp を使うのが一般的です。 74 // ここでは、メソッドの動作を示すために明示的に current() を呼び出します。 75 // この時点での current() の戻り値は $filteredTimestamp と同じです。 76 $currentValue = $iterator->current(); 77 78 echo "取得した値: " . $currentValue . " (" . date('Y-m-d H:i:s', $currentValue) . ")\n"; 79}
PHPの FilterIterator::current() メソッドは、フィルタリング条件を通過したイテレータの現在の要素を取得するために使用されます。FilterIterator は、配列のような繰り返し可能なデータの中から、特定の条件に合うものだけを選び出す機能を提供します。current() は、その選び出された要素の値を返す役割を持ちます。
このメソッドに引数はありません。戻り値は mixed 型であり、これは元のデータに含まれる要素の型によって決まります。例えば、元のデータが数値の配列であれば数値を、文字列の配列であれば文字列を返します。
サンプルコードでは、指定した時刻よりも新しいタイムスタンプだけを抽出するカスタムイテレータを作成しています。foreach ループを使ってこのイテレータを処理すると、内部では条件に合うタイムスタンプだけが選ばれます。ループの中で $iterator->current() を呼び出すと、その時点で選択されている「条件を満たしたタイムスタンプ」の値を取得できます。foreach ($iterator as $value) のようにループ変数を指定した場合、その $value と $iterator->current() の結果は同じ値になります。このように、current() はフィルタリング後の現在の要素にアクセスするための基本的なメソッドです。
このコードは、FilterIteratorクラスを継承して、条件に合うデータだけを取り出す独自のフィルター機能を作る例です。注意点として、フィルターの条件はacceptメソッドに記述します。このメソッドがtrueを返した要素だけが、foreachなどのループ処理の対象となります。acceptメソッド内では、getInnerIterator()->current()を呼び出すことで、フィルター対象となる元のイテレータの現在の値を取得できます。currentメソッドの戻り値は様々な型を取りうるため、サンプルコードのようにis_int()などで型をチェックしてから扱うと、より安全なコードになります。なお、foreachループ内では、フィルターを通過した値が自動的に変数(この例では$filteredTimestamp)に格納されるため、通常は改めて$iterator->current()を呼び出す必要はありません。