【PHP8.x】curl_multi_init関数の使い方

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

作成日: 更新日:

基本的な使い方

curl_multi_init関数は、複数のcURL転送(HTTPリクエストなど)を同時に管理・実行するための「マルチcURLハンドル」を初期化する関数です。この関数を使用することで、ウェブページのデータを並行して取得したり、複数のAPIエンドポイントに同時にリクエストを送信したりすることが可能になります。例えば、複数の異なるウェブサイトから情報を集める際や、多数のデータを一度に処理する必要がある場合に、個々のリクエストを順番に処理するよりも全体の処理時間を大幅に短縮できます。

具体的には、まずこの関数を呼び出してマルチcURLハンドルを作成します。次に、個々のHTTPリクエストを表す通常のcURLハンドル(curl_init関数で作成)を、作成したマルチcURLハンドルに追加していきます。すべてのハンドルが追加された後、curl_multi_exec関数などを使用して実際の転送を開始し、処理の進捗を管理します。

関数が成功すると、後続のマルチcURL関連関数で使用するリソース(マルチcURLハンドル)を返します。もし初期化に失敗した場合は、論理値のfalseが返されます。この関数には引数はありません。複数のネットワークリクエストを効率的に処理するための基盤となる重要な関数であり、高度なネットワークプログラミングにおいてパフォーマンスを向上させるために活用されます。

構文(syntax)

1curl_multi_init();

引数(parameters)

引数なし

引数はありません

戻り値(return)

CurlMultiHandle

CurlMultiHandleという型のリソースを返します。これは、複数のcURL転送を同時に管理するために使用されます。

サンプルコード

PHP curl_multi_init() を使って複数リクエストを並行実行する

1<?php
2
3/**
4 * PHP cURL Multi API の基本的な使用例。
5 * 複数のHTTPリクエストを並行して実行し、結果を取得します。
6 * curl_multi_init() 関数は、複数の cURL ハンドルを管理するためのマルチ cURL ハンドルを初期化します。
7 */
8function runCurlMultiExample(): void
9{
10    echo "--- cURL Multi Example - Start ---\n";
11
12    // 1. マルチ cURL ハンドルを初期化します。
13    // これにより、複数の cURL リクエストを同時に管理するための CurlMultiHandle オブジェクトが作成されます。
14    $mh = curl_multi_init();
15    if ($mh === false) {
16        echo "エラー: マルチ cURL ハンドルの初期化に失敗しました。\n";
17        return;
18    }
19
20    $ch = []; // 個々の cURL ハンドルを格納する配列
21    $urls = [
22        "https://httpbin.org/get?param=one",
23        "https://httpbin.org/get?param=two",
24        "https://httpbin.org/get?param=three",
25    ];
26
27    // 2. 複数の cURL ハンドルを作成し、オプションを設定し、マルチハンドルに追加します。
28    foreach ($urls as $index => $url) {
29        $ch[$index] = curl_init(); // 個々の cURL ハンドルを初期化
30        if ($ch[$index] === false) {
31            echo "エラー: URL '{$url}' の cURL ハンドルの初期化に失敗しました。\n";
32            continue;
33        }
34
35        curl_setopt($ch[$index], CURLOPT_URL, $url);
36        curl_setopt($ch[$index], CURLOPT_RETURNTRANSFER, true); // 結果を文字列として取得
37        curl_setopt($ch[$index], CURLOPT_HEADER, false);      // レスポンスヘッダを含めない
38
39        // 個々の cURL ハンドルをマルチ cURL ハンドルに追加します。
40        curl_multi_add_handle($mh, $ch[$index]);
41        echo "追加: URL '{$url}' の cURL ハンドルをマルチハンドルに追加しました。\n";
42    }
43
44    // 追加されたハンドルがない場合は終了
45    if (empty($ch)) {
46        echo "エラー: 処理する cURL ハンドルがありません。終了します。\n";
47        curl_multi_close($mh);
48        return;
49    }
50
51    // 3. すべてのリクエストが完了するまで実行します。
52    // $running には、まだ処理中のリクエストの数が格納されます。
53    $running = null;
54    do {
55        // curl_multi_exec() は、アクティブなリクエストを同時に実行し、ステータスを更新します。
56        $status = curl_multi_exec($mh, $running);
57
58        // まだ実行中のリクエストがある場合、ネットワーク I/O を待機します。
59        // curl_multi_select() は、ソケットアクティビティがあるまでブロックします。
60        if ($running > 0) {
61            curl_multi_select($mh);
62        }
63    } while ($running > 0 && $status === CURLM_OK);
64
65    // エラーチェック
66    if ($status !== CURLM_OK) {
67        echo "エラー: cURL multi exec が失敗しました。ステータス: " . $status . "\n";
68    }
69
70    echo "\nすべての cURL リクエストが完了しました。結果を取得します。\n";
71
72    // 4. 各リクエストの結果を取得します。
73    foreach ($ch as $index => $handle) {
74        // curl_multi_getcontent() で、完了した cURL ハンドルからレスポンスボディを取得します。
75        $response = curl_multi_getcontent($handle);
76        $info = curl_getinfo($handle); // リクエストに関する詳細情報を取得
77
78        if ($response === false) {
79            $error = curl_error($handle);
80            echo "--- URL '{$urls[$index]}' のエラー ---\n";
81            echo "エラーメッセージ: $error\n";
82        } else {
83            echo "--- URL '{$urls[$index]}' のレスポンス (HTTP {$info['http_code']}) ---\n";
84            // JSON レスポンスの場合、デコードして整形すると見やすくなります。
85            $decodedResponse = json_decode($response, true);
86            if ($decodedResponse !== null) {
87                echo json_encode($decodedResponse, JSON_PRETTY_PRINT) . "\n";
88            } else {
89                echo $response . "\n";
90            }
91        }
92        echo "---------------------------------------------------\n";
93
94        // 5. 個々の cURL ハンドルをマルチ cURL ハンドルから削除し、閉じます。
95        curl_multi_remove_handle($mh, $handle);
96        curl_close($handle);
97    }
98
99    // 6. マルチ cURL ハンドルを閉じます。
100    // これにより、関連するリソースが解放されます。
101    curl_multi_close($mh);
102
103    echo "--- cURL Multi Example - End ---\n";
104}
105
106// 関数を実行します。
107runCurlMultiExample();
108
109?>

curl_multi_init関数は、PHPで複数のHTTPリクエストを並行して効率的に処理するための「マルチcURLハンドル」を初期化する際に使用されます。この関数は引数を必要とせず、呼び出すと、複数のcURLリクエストを同時に管理できるCurlMultiHandle型のオブジェクトを戻り値として返します。

システムエンジニアを目指す初心者の方にとって、ウェブサイトの構築などで、複数の外部APIから同時にデータを取得したい場合などに非常に有効な機能です。個々のリクエストを順番に処理するのではなく、並行して実行することで、全体の処理時間を大幅に短縮できるメリットがあります。

サンプルコードでは、まずこのcurl_multi_init()関数を呼び出してマルチcURLハンドル $mh を作成しています。これは、複数のcURLリクエストをまとめるための「親」のような役割を果たします。その後、個々のURLに対してcurl_init()で作成した通常のcURLハンドルを、curl_multi_add_handle()関数を使ってこの $mh に追加していきます。最終的に、curl_multi_exec()関数を使って、追加されたすべてのリクエストを同時に実行し、処理が完了したらcurl_multi_close()でリソースを解放します。curl_multi_init()は、この並行処理の起点となる重要な関数です。

curl_multi_initは複数のHTTPリクエストを並行して実行し、処理時間を短縮するのに役立ちます。最も重要な注意点は、処理完了後に作成したすべてのcURLハンドル(個別のハンドルとマルチハンドル)を、それぞれcurl_close()およびcurl_multi_close()で確実に解放することです。これを忘れるとメモリリークやリソース枯渇の原因となります。また、curl_multi_exec()を含むループ処理では、予期せぬ状況での無限ループを防ぐために、エラーチェックやタイムアウト設定を適切に行う必要があります。各関数の戻り値を確認し、失敗時に適切にエラー処理を記述する習慣をつけましょう。PHP 8.1以降ではCurlMultiHandleオブジェクトが返されますので、型に注意してください。

関連コンテンツ

【PHP8.x】curl_multi_init関数の使い方 | いっしー@Webエンジニア