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

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

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

作成日: 更新日:

基本的な使い方

『acceptメソッドは、CallbackFilterIteratorがイテレータの現在の要素をフィルタリングするかどうかを判定するために実行するメソッドです。このメソッドは、FilterIteratorクラスから継承されたものであり、通常、開発者が直接呼び出すことはありません。foreach文などでイテレータをループ処理する際に、各要素に対してPHPの内部処理によって自動的に呼び出されます。このメソッドの主な役割は、CallbackFilterIteratorのインスタンス作成時にコンストラクタで指定されたコールバック関数を実行することです。コールバック関数には、現在の要素の値、キー、そして元のイテレータ自身が引数として渡されます。そして、acceptメソッドはコールバック関数が返した真偽値(trueまたはfalse)を、そのまま自身の戻り値として返します。戻り値がtrueであれば、現在の要素は有効と判断され、イテレーションの結果として残ります。逆にfalseが返された場合、その要素は条件に合わないものとして除外されます。この仕組みによって、複雑なループ処理を記述することなく、指定した条件に基づいて要素を柔軟に絞り込むことが可能になります。』

構文(syntax)

1<?php
2
3$iterator = new ArrayIterator([10, 20, 30, 40, 50]);
4
5// CallbackFilterIteratorのaccept()メソッドは、
6// コンストラクタの第2引数で渡されたコールバック関数を実行します。
7$acceptLogic = function (int $current, int $key, Iterator $iterator): bool {
8    // このコールバックがtrueを返した要素のみが有効となります。
9    return $current > 25;
10};
11
12$filteredIterator = new CallbackFilterIterator($iterator, $acceptLogic);

引数(parameters)

引数なし

引数はありません

戻り値(return)

bool

このメソッドは、現在の要素がフィルタリング条件を満たすかどうかを示す真偽値(trueまたはfalse)を返します。

サンプルコード

PHPで画像アップロードファイルをacceptする

1<?php
2
3/**
4 * アップロードされたファイルの中から画像ファイルのみを受け入れるサンプルコード
5 *
6 * このサンプルでは、実際のファイルアップロードをシミュレートするために
7 * $_FILES スーパーグローバルと同じ構造のダミーデータを使用します。
8 * CallbackFilterIterator を使って、特定のMIMEタイプを持つファイルのみを抽出します。
9 */
10function filterUploadedImageFiles(): void
11{
12    // --- ファイルアップロードをシミュレートするためのダミーデータ ---
13    // 実際には、HTMLフォームから送信された $_FILES 変数を使用します。
14    $dummyUploadedFiles = [
15        'userfile' => [
16            'name' => [
17                'document.pdf',
18                'photo.jpg',
19                'archive.zip',
20                'logo.png',
21                'report.docx',
22            ],
23            'type' => [
24                'application/pdf',
25                'image/jpeg',
26                'application/zip',
27                'image/png',
28                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
29            ],
30            'tmp_name' => [
31                '/tmp/php1aaa',
32                '/tmp/php2bbb',
33                '/tmp/php3ccc',
34                '/tmp/php4ddd',
35                '/tmp/php5eee',
36            ],
37            'error' => [
38                UPLOAD_ERR_OK,
39                UPLOAD_ERR_OK,
40                UPLOAD_ERR_OK,
41                UPLOAD_ERR_OK,
42                UPLOAD_ERR_OK,
43            ],
44            'size' => [
45                102400,
46                204800,
47                512000,
48                51200,
49                30720,
50            ],
51        ],
52    ];
53
54    // 複数のアップロードファイルを扱いやすい形式の配列に再構成します。
55    $files = [];
56    foreach ($dummyUploadedFiles['userfile']['name'] as $key => $name) {
57        if ($dummyUploadedFiles['userfile']['error'][$key] === UPLOAD_ERR_OK) {
58            $files[] = [
59                'name' => $name,
60                'type' => $dummyUploadedFiles['userfile']['type'][$key],
61            ];
62        }
63    }
64
65    // 配列をイテレータに変換します。
66    $iterator = new ArrayIterator($files);
67
68    // イテレータをフィルタリングするための CallbackFilterIterator を作成します。
69    // 第2引数には、フィルタリング条件を定義したコールバック関数を渡します。
70    // このコールバック関数が true を返した要素のみが残ります。
71    $imageFileIterator = new CallbackFilterIterator(
72        $iterator,
73        function (array $currentFile): bool {
74            // 受け入れたいMIMEタイプのリスト
75            $allowedMimeTypes = ['image/jpeg', 'image/png'];
76            // 現在のファイルのMIMEタイプがリストに含まれていれば true を返す
77            return in_array($currentFile['type'], $allowedMimeTypes, true);
78        }
79    );
80
81    echo "受け入れられた画像ファイル:\n";
82
83    // フィルタリングされたイテレータをループ処理します。
84    // このループの内部で、CallbackFilterIterator::accept() メソッドが自動的に呼び出され、
85    // 上記のコールバック関数を実行して各要素を評価します。
86    foreach ($imageFileIterator as $acceptedFile) {
87        echo "- " . htmlspecialchars($acceptedFile['name'], ENT_QUOTES, 'UTF-8') . "\n";
88    }
89}
90
91// 関数を実行して結果を表示します。
92filterUploadedImageFiles();
93
94?>

このサンプルコードは、アップロードされた複数のファイルの中から、特定の条件(この場合は画像ファイル)に一致するものだけを効率的に抽出する方法を示しています。ここで中心的な役割を担うのが CallbackFilterIterator クラスです。

CallbackFilterIterator は、配列のような繰り返し処理が可能なデータ(イテレータ)を受け取り、指定した条件でフィルタリングを行うためのクラスです。インスタンスを作成する際に、フィルタリングのルールを定義した関数(コールバック関数)を渡します。このサンプルでは、ファイルのMIMEタイプが画像(image/jpeg または image/png)であるかを判定する関数を定義しています。

foreach ループでフィルタリングされた結果を処理する際、CallbackFilterIteratoraccept メソッドが各要素に対して内部で自動的に呼び出されます。この accept メソッドは引数を取らず、bool型(true または false)の値を返します。その具体的な動作は、インスタンス作成時に指定されたコールバック関数を実行し、その結果をそのまま返すというものです。

コールバック関数が true を返した要素は「受け入れる(accept)」と判断され、ループ内の処理対象となります。一方、false を返した要素は無視されます。このように、開発者が直接 accept メソッドを呼び出すことなく、ループ処理の中で自動的にフィルタリングが実行される仕組みになっています。

このサンプルコードではacceptメソッドを直接呼び出していません。foreachでイテレータを処理する際、PHPが内部でacceptメソッドを呼び出し、フィルタリング用の関数を実行します。注意点として、ファイルのMIMEタイプはユーザーが偽装できるため、セキュリティを高めるにはfinfo_file関数などでサーバー側でファイル内容を検証することが不可欠です。また、このコードは実際のファイル操作を省略しています。本番環境ではis_uploaded_filemove_uploaded_file関数を使い、ファイルを安全な場所に移動させる処理が必要です。アップロード時の各種エラー(ファイルサイズ超過など)に対応する処理も忘れずに追加してください。

PHP POST JSON ユーザーフィルタリング

1<?php
2
3declare(strict_types=1);
4
5/**
6 * POSTリクエストで送信されたJSONデータから、特定の条件を満たすユーザーをフィルタリングします。
7 *
8 * このサンプルは、POSTリクエストボディとして送信されたユーザーリスト(JSON形式)の中から、
9 * 特定の条件(アクティブで、かつロールが 'user')を満たすユーザーのみを抽出します。
10 *
11 * CallbackFilterIterator は、指定されたコールバック関数を使ってイテレータの要素を絞り込みます。
12 * foreach でループする際、各要素に対して内部的に accept() メソッドが呼び出されます。
13 * accept() メソッドは、コールバック関数の戻り値 (bool) を返し、
14 * true だった要素のみがループの処理対象となります。
15 */
16function filterUsersFromPostRequest(): void
17{
18    // 1. POSTリクエストでJSONデータを受け取ったと仮定します。
19    // 実際のアプリケーションでは file_get_contents('php://input') でボディを取得しますが、
20    // このサンプルでは単体で動作させるためにJSON文字列を直接定義します。
21    $jsonPostData = <<<JSON
22    [
23        {"id": 1, "name": "Alice", "role": "admin", "active": true},
24        {"id": 2, "name": "Bob", "role": "user", "active": false},
25        {"id": 3, "name": "Charlie", "role": "user", "active": true},
26        {"id": 4, "name": "Dave", "role": "guest", "active": true}
27    ]
28    JSON;
29
30    // 2. JSON文字列をPHPの連想配列にデコードします。
31    $users = json_decode($jsonPostData, true);
32
33    // データが不正な場合は処理を中断します。
34    if (!is_array($users)) {
35        echo "Invalid JSON data received." . PHP_EOL;
36        return;
37    }
38
39    // 3. 配列からイテレータを作成します。
40    // CallbackFilterIteratorはイテレータを引数に取るため、まず配列をArrayIteratorに変換します。
41    $iterator = new ArrayIterator($users);
42
43    // 4. フィルタリング条件を定義し、CallbackFilterIteratorのインスタンスを生成します。
44    // このコールバック関数が、内部的に呼び出される accept() メソッドの本体ロジックです。
45    // ここでは「アクティブ(active: true)で、かつロールが 'user' のユーザー」を抽出します。
46    $filterCallback = function (array $currentUser): bool {
47        $isActive = isset($currentUser['active']) && $currentUser['active'] === true;
48        $isUserRole = isset($currentUser['role']) && $currentUser['role'] === 'user';
49        return $isActive && $isUserRole;
50    };
51
52    $filteredIterator = new CallbackFilterIterator($iterator, $filterCallback);
53
54    // 5. フィルタリングされた結果をループ処理して出力します。
55    // このループでは、コールバック関数がtrueを返した要素だけが処理されます。
56    echo "Filtered Users (Active and Role is 'user'):" . PHP_EOL;
57    foreach ($filteredIterator as $user) {
58        printf(
59            "- ID: %d, Name: %s\n",
60            $user['id'],
61            $user['name']
62        );
63    }
64}
65
66// 関数を実行します。
67filterUsersFromPostRequest();
68
69?>

CallbackFilterIteratoracceptメソッドは、イテレータが持つ要素を特定の条件でフィルタリング(絞り込み)する際に、内部的に呼び出されるメソッドです。開発者がこのメソッドを直接呼び出すことは通常ありません。 このサンプルコードでは、POSTリクエストで受け取ったJSON形式のユーザーリストから、条件に一致するユーザーだけを抽出しています。まず、JSONデータをPHPの配列に変換後、ArrayIteratorというイテレータオブジェクトに変換します。次に、このイテレータと、フィルタリング条件を定義したコールバック関数をCallbackFilterIteratorに渡してインスタンスを生成します。このコールバック関数が、acceptメソッドが内部で実行するロジックそのものになります。 foreach文でこのイテレータをループ処理すると、各要素についてacceptメソッドが自動的に実行されます。acceptメソッドは引数を持たず、コールバック関数の判定結果であるbool値(trueまたはfalse)を戻り値として返します。戻り値がtrueだった要素のみがループの処理対象となり、falseだった要素は無視されます。 この仕組みによって、サンプルでは「アクティブ」かつ「ロールが'user'」であるユーザーだけが効率的に絞り込まれ、出力されています。

このコードでは、外部から受け取るJSONデータを安全に扱うため、json_decodeの結果が配列であることや、コールバック関数内でissetを使い各キーが存在することを確認しています。これは、予期せぬデータ形式によるエラーを防ぐための重要な作法です。特に、json_decodeの第二引数にtrueを指定しない場合、データは連想配列ではなくオブジェクトとして扱われるため、['key']形式のアクセスができなくなる点に注意が必要です。また、CallbackFilterIteratorは配列を直接扱えないため、事前にnew ArrayIterator()でイテレータに変換する手順が必須となります。

関連コンテンツ