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

【PHP8.x】iterator_apply()関数の使い方

iterator_apply関数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

iterator_apply関数は、指定されたイテレータの各要素に対して、ユーザーが定義したコールバック関数を実行する関数です。イテレータとは、配列やオブジェクトの中身を一つずつ順番に処理するための仕組みを指します。この関数は、foreachループを使って各要素を処理する代わりに、より簡潔な方法で共通の処理を適用したい場合に役立ちます。

主な用途としては、例えば、特定の条件を満たす要素に対して何らかの操作を行ったり、各要素の値を変換したりする場面で利用されます。この関数を使用する際には、まず処理の対象となるIteratorオブジェクトを指定し、次に各要素に適用したい処理を記述したコールバック関数を渡します。コールバック関数は、現在のイテレータの要素を引数として受け取ります。オプションとして、コールバック関数に追加で渡したい引数も指定できます。

iterator_apply関数は、すべての要素への適用が成功した場合にtrueを返します。しかし、もし途中でコールバック関数がfalseを返した場合、処理は中断され、この関数自体もfalseを返します。これにより、特定の条件で処理を停止させることも可能です。この関数は、ループ処理を抽象化し、コードの可読性を高めることにも貢献します。

構文(syntax)

1<?php
2
3$arrayData = ['apple', 'banana', 'orange'];
4$myIterator = new ArrayIterator($arrayData);
5
6$myCallback = function (Iterator $iterator): bool {
7    // イテレータの現在の要素とキーはここで利用可能
8    // $iterator->current();
9    // $iterator->key();
10    return true; // trueを返すとイテレーションが継続、falseを返すと停止
11};
12
13$processedCount = iterator_apply($myIterator, $myCallback);
14
15?>

引数(parameters)

Traversable $iterator, callable $callback, array $args = []

  • Traversable $iterator: 処理対象となるイテレータブルなオブジェクト
  • callable $callback: $iterator の各要素に対して実行するコールバック関数
  • array $args = []: コールバック関数に渡す追加の引数配列

戻り値(return)

int

指定されたイテレータに対してコールバック関数を適用し、処理された要素の数を整数で返します。

サンプルコード

PHP IteratorAggregate と iterator_apply の活用

1<?php
2
3/**
4 * MyCollection クラスは IteratorAggregate インターフェースを実装し、
5 * 内部のデータを外部からTraversable(反復可能)な形で提供します。
6 * これにより、コレクションの要素を foreach ループなどで順次処理できるようになります。
7 */
8class MyCollection implements IteratorAggregate
9{
10    private array $items;
11
12    /**
13     * コンストラクタでコレクションの初期データを設定します。
14     *
15     * @param array $items コレクションに含める要素の配列
16     */
17    public function __construct(array $items)
18    {
19        $this->items = $items;
20    }
21
22    /**
23     * IteratorAggregate インターフェースのメソッドを実装します。
24     * このメソッドは、コレクションを反復処理するためのイテレータオブジェクトを返します。
25     * ここでは、PHP標準の ArrayIterator を使用して内部配列を反復可能にします。
26     *
27     * @return Traversable イテレータオブジェクト
28     */
29    public function getIterator(): Traversable
30    {
31        return new ArrayIterator($this->items);
32    }
33}
34
35/**
36 * コレクションの各要素に対して実行されるコールバック関数です。
37 * iterator_apply の第二引数として渡されます。
38 *
39 * @param string $item 現在処理中の要素
40 * @param string $prefix オプションで追加するプレフィックス
41 * @return bool trueを返すと次の要素の処理を続行し、falseを返すと処理を中断します。
42 */
43function processItem(string $item, string $prefix = ''): bool
44{
45    echo $prefix . "処理中: " . $item . "\n";
46    // 常にtrueを返すことで、すべての要素が処理されるようにします。
47    // 特定の条件でfalseを返すと、その時点で要素の処理が中断されます。
48    return true;
49}
50
51// ------------------------------------------------------------------
52// 以下は MyCollection クラスと processItem 関数を使用したサンプルコードです。
53// ------------------------------------------------------------------
54
55// 1. MyCollection クラスのインスタンスを作成し、データを初期化します。
56$data = ['リンゴ', 'バナナ', 'チェリー', 'デーツ'];
57$myCollection = new MyCollection($data);
58
59echo "--- iterator_apply による MyCollection の処理開始 ---\n";
60
61// 2. iterator_apply 関数を使用して、コレクションの各要素に processItem 関数を適用します。
62//    - 第一引数: Traversable オブジェクト(ここでは MyCollection のインスタンス)
63//    - 第二引数: 各要素に対して実行されるコールバック関数(文字列で関数名を指定)
64//    - 第三引数: コールバック関数に追加で渡す引数の配列(オプション)
65//      この例では '項目: ' という文字列をプレフィックスとして processItem 関数に渡します。
66//    iterator_apply の戻り値は、コールバック関数が true を返した回数になります。
67$processedCount = iterator_apply($myCollection, 'processItem', ['項目: ']);
68
69echo "--- 処理が完了しました ---\n";
70echo "処理された項目の総数: " . $processedCount . "\n";

PHP 8のiterator_apply関数は、Traversableインターフェースを実装した反復可能なオブジェクトの各要素に対し、指定したコールバック関数を適用するために使用されます。

サンプルコードでは、MyCollectionクラスがIteratorAggregateインターフェースを実装し、内部の配列をArrayIteratorとして提供することで、自身を反復可能なオブジェクトとしています。これにより、MyCollectionのインスタンスをiterator_applyの第一引数に渡すことが可能になります。

processItem関数は、コレクションの各要素に対して実行されるコールバック関数です。この関数は、現在処理中の要素と、オプションでiterator_applyから渡された追加の引数を受け取ります。コールバック関数がtrueを返すと次の要素の処理が続行され、falseを返すと、その時点で要素の処理が中断されます。

iterator_applyを呼び出す際には、第一引数にMyCollectionのインスタンスのような反復可能なオブジェクトを、第二引数にprocessItemのような実行したいコールバック関数を指定します。第三引数はオプションで、コールバック関数に追加で渡したい引数を配列として指定できます。この例では「項目: 」という文字列をprocessItem関数に渡しています。

iterator_apply関数の戻り値は整数値で、コールバック関数がtrueを返した回数を示します。これにより、いくつの要素が正常に処理されたかを正確に把握できます。この関数を使うことで、反復処理と各要素への特定の処理を簡潔かつ柔軟に記述できる点が特徴です。

iterator_applyの第一引数には、Traversableインターフェースを実装したオブジェクト(例:IteratorAggregateを実装したMyCollectionArrayIteratorなど)を渡す必要があります。第二引数のコールバック関数は要素ごとに実行され、trueを返すと次の要素の処理が続行され、falseを返すとその時点で処理が中断されます。第三引数はコールバック関数に渡す追加引数を配列で指定します。iterator_applyの戻り値は、コールバック関数がtrueを返した回数を示します。これにより、すべての要素が処理されたか、途中で中断されたかを判断できます。コールバック関数内で意図せずfalseを返すと、期待通りに全要素が処理されない可能性があるため注意が必要です。

PHP iterator_applyとiterator_to_arrayでイテレータを操作する

1<?php
2
3/**
4 * PHPのiterator_apply関数とiterator_to_array関数の使用例。
5 * iterator_applyでイテレータの各要素にコールバックを適用し、
6 * その後iterator_to_arrayで元のイテレータの内容が変化しないことを示します。
7 */
8function demonstrateIteratorApplyAndToArray(): void
9{
10    // サンプルデータの定義
11    $data = ['apple', 'banana', 'orange', 'grape'];
12    echo "--- データの初期状態 ---" . PHP_EOL;
13    print_r($data);
14
15    // ArrayIteratorを作成し、配列をイテレータとして扱えるようにします。
16    $iterator = new ArrayIterator($data);
17
18    // iterator_applyに渡すコールバック関数を定義します。
19    // このコールバックは各要素の値を表示しますが、イテレータの要素自体は変更しません。
20    // 引数には、iterator_applyから渡されるイテレータインスタンスと、
21    // 追加で指定した文字列プレフィックスを受け取ります。
22    $displayCallback = function (Iterator $itemIterator, string $prefix): bool {
23        echo $prefix . "要素: " . $itemIterator->current() . " (キー: " . $itemIterator->key() . ")" . PHP_EOL;
24        // trueを返すことで、イテレーションを継続します。
25        // falseを返すと、iterator_applyはそこで処理を停止します。
26        return true;
27    };
28
29    echo PHP_EOL . "--- iterator_applyによる各要素の処理 ---" . PHP_EOL;
30    // iterator_applyを適用し、イテレータの各要素に対して$displayCallbackを実行します。
31    // 第1引数: 処理対象のイテレータ
32    // 第2引数: 各要素に適用するコールバック関数
33    // 第3引数 (オプション): コールバック関数に渡す追加引数の配列
34    $appliedCount = iterator_apply($iterator, $displayCallback, [$iterator, "  - "]);
35
36    echo "コールバックが適用された回数: " . $appliedCount . "回" . PHP_EOL;
37
38    echo PHP_EOL . "--- iterator_to_arrayでイテレータの最終状態を確認 ---" . PHP_EOL;
39    // iterator_to_arrayを使って、現在のイテレータの内容を配列に変換します。
40    // iterator_applyはイテレータの要素自体を変更しないため、
41    // ここで取得される配列は元のデータと同じ内容です。
42    $arrayFromIterator = iterator_to_array($iterator);
43    print_r($arrayFromIterator);
44
45    echo PHP_EOL . "--- 別の利用例: iterator_applyで特定の条件を満たす要素をカウント ---" . PHP_EOL;
46    // 数値の配列で偶数を数える例を示します。
47    $numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
48    $numbersIterator = new ArrayIterator($numbers);
49
50    $evenNumbers = []; // 偶数を格納する配列
51    $countEvenCallback = function (Iterator $itemIterator) use (&$evenNumbers): bool {
52        $currentValue = $itemIterator->current();
53        if (is_int($currentValue) && $currentValue % 2 === 0) {
54            $evenNumbers[] = $currentValue;
55        }
56        return true;
57    };
58
59    // イテレータを巻き戻して再度最初から処理できるようにします。
60    $numbersIterator->rewind();
61    iterator_apply($numbersIterator, $countEvenCallback, [$numbersIterator]);
62
63    echo "元の数値データ: " . implode(', ', $numbers) . PHP_EOL;
64    echo "偶数の要素: " . implode(', ', $evenNumbers) . PHP_EOL;
65}
66
67// 上記の関数を実行し、iterator_applyとiterator_to_arrayの動作をデモンストレーションします。
68demonstrateIteratorApplyAndToArray();

PHP 8のiterator_apply関数は、配列のように順に要素を辿れる「イテレータ」と呼ばれるオブジェクトの各要素に対して、特定の処理(コールバック関数)を実行する際に使われます。この関数はイテレータの要素を一つずつ巡回し、指定されたコールバック関数を適用します。第1引数には処理対象のイテレータを、第2引数には各要素に適用するコールバック関数を指定します。第3引数はオプションで、コールバック関数に追加で渡す引数を配列で指定できます。コールバック関数は、イテレーションを継続する場合はtrueを、途中で停止したい場合はfalseを返す必要があります。iterator_applyの戻り値は、コールバック関数が適用された要素の数を整数で返します。

サンプルコードでは、ArrayIteratorで作成したイテレータの各要素に対して、値を表示するコールバック関数をiterator_applyで実行しています。この関数はイテレータの要素自体を変更するわけではないため、処理後にiterator_to_array関数を使ってイテレータの内容を配列に変換すると、元のデータがそのまま保持されていることが確認できます。iterator_to_arrayは、イテレータのすべての要素を新しい配列として取得する関数です。iterator_applyは、特定の条件を満たす要素を数えたり、収集したりするような処理にも活用でき、例えば数値の配列から偶数のみを抽出する用途などにも利用可能です。これらの関数を組み合わせることで、イテレータを柔軟に操作できます。

iterator_apply関数は、イテレータの各要素に対して指定したコールバック関数を実行しますが、イテレータの要素自体を直接変更するわけではありません。コールバック関数がtrueを返すとイテレーションが継続し、falseを返すとその時点で処理が停止しますので注意が必要です。一度iterator_applyを実行するとイテレータの内部ポインタが進んだ状態になるため、同じイテレータで再度最初から処理を行いたい場合は、必ずrewind()メソッドを呼び出して巻き戻してください。また、コールバック関数に渡される引数は、常にイテレータ自身が最初の引数となり、その後にiterator_applyの第3引数で指定した追加の引数が順に渡されます。コールバックの引数の型と順序を正しく定義しているか確認することが重要です。

関連コンテンツ

関連プログラミング言語