Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】RecursiveCallbackFilterIterator::key()メソッドの使い方

keyメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

keyメソッドは、イテレータが現在指している要素のキーを返すメソッドです。RecursiveCallbackFilterIteratorは、再帰的なデータ構造をコールバック関数によってフィルタリングするためのクラスであり、このkeyメソッドは、そのフィルタリング条件を満たした現在の要素のキーを取得するために使用されます。Iteratorインターフェースで定義されている基本的なメソッドの一つであり、foreachループなどで foreach ($iterator as $key => $value) のようにキーと値のペアを処理する際に、内部的に呼び出されます。このメソッド自体がフィルタリングを行うわけではなく、フィルタリング後のイテレータの現在の位置におけるキーを報告する役割を担います。currentメソッドが現在の要素の値を返すのに対し、keyメソッドはそれに対応するキーを返します。これにより、開発者はフィルタリングされた結果セットの中から、特定の要素が元のデータ構造においてどのキーに対応していたかを知ることができます。返されるキーの型は、元となるイテレータのキーの型に依存し、通常は整数または文字列となります。

構文(syntax)

1<?php
2
3$data = [
4    'fruit1' => 'apple',
5    'vegetable1' => 'carrot', // This will be filtered out
6    'fruit2' => 'orange',
7];
8
9$arrayIterator = new RecursiveArrayIterator($data);
10
11// Callback function to filter items. It only accepts items whose key starts with 'fruit'.
12$filterCallback = function ($current, $key, $iterator) {
13    return str_starts_with($key, 'fruit');
14};
15
16$filterIterator = new RecursiveCallbackFilterIterator($arrayIterator, $filterCallback);
17
18// Iterate through the filtered items
19foreach ($filterIterator as $value) {
20    // public RecursiveCallbackFilterIterator::key(): mixed
21    // Get the key of the current element.
22    $currentKey = $filterIterator->key();
23    
24    echo $currentKey . PHP_EOL;
25}
26
27?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

mixed

RecursiveCallbackFilterIterator::key() は、現在の要素のキーを返します。

サンプルコード

PHP RecursiveCallbackFilterIteratorでキーをフィルタリングする

1<?php
2
3declare(strict_types=1);
4
5/**
6 * RecursiveCallbackFilterIterator を使用して、
7 * 特定のキーが存在する要素を再帰的に抽出し、そのキーと値を出力します。
8 *
9 * このサンプルでは、多次元配列の中からキー名が 'path' である要素だけをフィルタリングし、
10 * フィルタリングされた要素のキーを取得して表示します。
11 */
12function filterElementsWhereKeyExists(): void
13{
14    // サンプル用の多次元配列(ファイルシステムの構造を模倣)
15    $fileSystem = [
16        'project' => [
17            'type' => 'directory',
18            'children' => [
19                'src' => [
20                    'type' => 'directory',
21                    'children' => [
22                        'app.php' => [
23                            'type' => 'file',
24                            'path' => '/project/src/app.php', // 抽出したいキー
25                        ],
26                    ],
27                ],
28                'config' => [
29                    'type' => 'directory',
30                    'children' => [
31                        'database.php' => [
32                            'type' => 'file',
33                            'path' => '/project/config/database.php', // 抽出したいキー
34                        ],
35                    ],
36                ],
37                'README.md' => [
38                    'type' => 'file',
39                    // 'path' キーが存在しない要素
40                ]
41            ],
42        ],
43    ];
44
45    // 配列を再帰的に処理するためのイテレータを作成します
46    $arrayIterator = new RecursiveArrayIterator($fileSystem);
47
48    // 特定のキーを持つ要素のみを許可するフィルタを作成します
49    $filterIterator = new RecursiveCallbackFilterIterator(
50        $arrayIterator,
51        function ($current, $key, $iterator) {
52            // 子要素を持つ配列(ディレクトリ)は、さらに走査するために常に許可します
53            if ($iterator->hasChildren()) {
54                return true;
55            }
56            // 現在の要素のキーが 'path' であるかどうかを判定します
57            return $key === 'path';
58        }
59    );
60
61    // フィルタリングされた結果を再帰的に走査するためのイテレータ
62    // NOTE: foreach でループすると、内部で filterIterator の valid(), current(), key(), next() が呼び出されます
63    $recursiveIterator = new RecursiveIteratorIterator($filterIterator);
64
65    echo "キー名が 'path' の要素:\n";
66
67    // フィルタリングされた要素をループ処理します
68    foreach ($recursiveIterator as $key => $value) {
69        // $key には、フィルタリング条件に合致した要素のキー(この場合は 'path')が格納されます。
70        // これは、内部的に RecursiveCallbackFilterIterator::key() が返した値です。
71        echo "  - Key: " . $key . ", Value: " . $value . "\n";
72    }
73}
74
75// 関数を実行して結果を表示します
76filterElementsWhereKeyExists();

RecursiveCallbackFilterIterator::key()メソッドは、フィルタリングされたイテレータが現在指している要素のキーを取得して返します。このメソッドに引数はありません。戻り値の型はmixedで、配列のキーやオブジェクトのプロパティ名など、様々な型の値が返されます。

サンプルコードでは、多次元配列$fileSystemを再帰的に走査し、キーが'path'である要素のみを抽出しています。RecursiveCallbackFilterIteratorに渡されたコールバック関数がフィルタの役割を担い、キーが'path'と一致する場合にtrueを返すことで、その要素を通過させます。

foreachループでイテレータを処理する際、ループの各処理で内部的にkey()メソッドが呼び出されます。そして、その戻り値が変数$keyに代入されます。このサンプルでは、フィルタリング条件に合致した要素のキーは常に'path'であるため、$keyには文字列'path'が格納されます。このようにkey()メソッドは、フィルタリングを通過した要素がどのキーに対応するものなのかを知るために利用されます。

このコードで最も重要なのは、フィルタ処理を定義するコールバック関数です。特に、子要素を持つ配列(サンプルでのディレクトリ階層)に対しても true を返す処理は、再帰的な探索を続けるために不可欠です。この条件を忘れると、深い階層にある目的の要素が見つからないため注意が必要です。foreachループで $key として受け取る値は、フィルタ条件に一致した要素のキー(この場合は 'path')であり、内部で key() メソッドが返した値です。また、フィルタはキーだけでなく値の内容に基づいて条件を指定することも可能です。RecursiveIteratorIteratorは、このフィルタ結果をネスト構造のままではなく、まとめてループ処理するために利用します。

PHP RecursiveCallbackFilterIterator::key() でキーと値を取得する

1<?php
2
3declare(strict_types=1);
4
5/**
6 * RecursiveCallbackFilterIterator::key() の使用例を示すクラス
7 *
8 * このサンプルでは、多次元配列を再帰的に処理し、
9 * 特定の条件に一致する要素のキー (key) と値 (value) を出力します。
10 */
11final class RecursiveFilterKeyExample
12{
13    /**
14     * サンプルコードを実行します。
15     */
16    public function run(): void
17    {
18        // サンプルとなる多次元連想配列(ファイルシステムを模したもの)
19        $fileSystem = [
20            'documents' => [
21                'report.docx' => 'content1',
22                'image.jpg' => 'content2',
23            ],
24            'source' => [
25                'app' => [
26                    'main.php' => '<?php echo "main";',
27                    'database.php' => '<?php echo "db";',
28                ],
29                'lib' => [
30                    'helper.php' => '<?php echo "helper";',
31                ],
32                'config.ini' => 'content3',
33            ],
34        ];
35
36        // 1. 多次元配列から再帰的に処理できるイテレータを作成
37        $arrayIterator = new RecursiveArrayIterator($fileSystem);
38
39        // 2. フィルタリングの条件を定義するコールバック関数
40        //    ここでは、キー(ファイル名)の拡張子が '.php' の要素のみを許可します。
41        $filterCallback = function (mixed $current, string|int $key, RecursiveIterator $iterator): bool {
42            // 子要素を持つ(ディレクトリである)場合は、その中を探索するために常に許可する
43            if ($iterator->hasChildren()) {
44                return true;
45            }
46            // キー(ファイル名)が '.php' で終わるかどうかを判定する
47            return str_ends_with((string)$key, '.php');
48        };
49
50        // 3. コールバック関数を使って、元のイテレータをフィルタリングするイテレータを作成
51        $filterIterator = new RecursiveCallbackFilterIterator($arrayIterator, $filterCallback);
52
53        // 4. 再帰的なイテレータをフラットに(一段階のループで)処理するためにラップする
54        $iterator = new RecursiveIteratorIterator($filterIterator);
55
56        echo "拡張子が '.php' のファイルのキーと値:" . PHP_EOL;
57
58        // 5. フィルタリングされた結果をループで処理
59        foreach ($iterator as $key => $value) {
60            // foreach ループの $key には、現在の要素のキーが格納されます。
61            // これは、内部で RecursiveCallbackFilterIterator::key() が呼び出された結果と同じです。
62            // $value には、current() メソッドで取得される値が格納されます。
63            printf(
64                "  - Key: %s, Value: \"%s\"" . PHP_EOL,
65                $key,
66                $value
67            );
68        }
69    }
70}
71
72// クラスのインスタンスを作成して実行
73$example = new RecursiveFilterKeyExample();
74$example->run();
75
76?>

PHPの RecursiveCallbackFilterIterator::key() メソッドは、フィルタリングされたイテレータが現在指している要素のキーを取得します。このメソッドに引数はなく、戻り値として現在のキーを返します。キーのデータ型は、元のデータ構造によって文字列や整数など様々です。

サンプルコードでは、多次元配列をファイルシステムに見立て、その中から特定の条件に合う要素を抽出しています。RecursiveCallbackFilterIteratorは、指定した条件(コールバック関数)に基づいて要素を絞り込む役割を担います。この例では「キーの文字列が .php で終わる」という条件で、PHPファイルに相当する要素だけをフィルタリングしています。

foreach ループを用いてフィルタリング後の結果を処理する際、foreach ($iterator as $key => $value) と記述すると、$key という変数に key() メソッドが取得した現在のキーが自動的に格納されます。同時に、$value には対応する値が格納されます。この仕組みにより、コード内で明示的に key() メソッドを呼び出すことなく、条件に一致した要素のキーと値を簡単かつ効率的に取り扱うことができます。

foreachループで使われる$keyは、フィルタリング条件を満たした現在の要素のキーを返すkey()メソッドの実行結果です。このコードで最も重要なのは、フィルタリングの条件を定義するコールバック関数です。再帰処理を正しく機能させるには、子要素を持つ要素(サンプルコードのディレクトリに相当)を探索対象に残すため、$iterator->hasChildren()で判定して常に許可する処理が不可欠です。この条件を忘れると、深い階層の要素が無視されてしまいます。また、キーが数値の可能性もあるため、文字列として扱う際は(string)$keyのように型を変換すると、より安全に動作します。

関連コンテンツ