【PHP8.x】curl_multi_setopt()関数の使い方
curl_multi_setopt関数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
curl_multi_setopt関数は、cURL multiハンドルのオプションを設定する関数です。cURL multiハンドルは、複数のcURL転送を非同期的に実行するために使用されます。この関数を使用することで、タイムアウト時間、接続数制限、エラー処理など、multiハンドル全体の動作を制御する様々なオプションを設定できます。
具体的には、$multi_handle引数に設定対象のcURL multiハンドルを指定し、$option引数に設定したいオプションの種類を指定します。そして、$value引数に設定する値を指定します。設定可能なオプションは、CURLMOPT_で始まる定数として定義されており、例えばCURLMOPT_MAX_TOTAL_CONNECTIONSは、multiハンドルが同時に確立できる最大接続数を設定します。
この関数を使用することで、並列処理の効率を向上させたり、リソースの使用量を調整したり、特定のエラー発生時の動作を定義したりすることが可能です。例えば、大量のURLを並行してダウンロードする場合、CURLMOPT_MAXCONNECTSオプションで接続数を調整することで、サーバーへの負荷を軽減できます。また、CURLMOPT_PIPELININGオプションを有効にすることで、HTTPパイプライン処理を有効にし、パフォーマンスを向上させることができます。
関数が成功した場合は true、失敗した場合は false を返します。関数の利用時は、設定するオプションの種類と値が適切であることを確認してください。誤ったオプションや値を設定すると、予期しない動作を引き起こす可能性があります。
構文(syntax)
1curl_multi_setopt(CurlMultiHandle $multi_handle, int $option, mixed $value): bool
引数(parameters)
CurlMultiHandle $multi_handle, int $option, mixed $value
- CurlMultiHandle $multi_handle: 実行中の複数のcURL転送を管理するためのリソースハンドル
- int $option: 設定したいオプションの定数(例: CURLMOPT_MAXCONNECTS)
- mixed $value: $optionで指定したオプションに対応する値
戻り値(return)
bool
curl_multi_setopt関数は、指定されたcURLマルチハンドルにオプションを設定します。成功した場合はTRUEを、失敗した場合はFALSEを返します。
サンプルコード
PHPでcurl_multi_selectを使った並列リクエスト
1<?php 2 3/** 4 * 複数のURLに対して並行してHTTPリクエストを実行し、結果を取得する関数。 5 * curl_multi_setopt を使ってマルチCURLハンドルのオプションを設定する例も含む。 6 * 7 * @param array $urls リクエストを送るURLの配列 8 * @return array 各URLの応答ボディまたはエラー情報を含む配列 (URL => 結果) 9 * @throws RuntimeException マルチCURLハンドルの初期化に失敗した場合 10 */ 11function fetch_multiple_urls_parallel(array $urls): array 12{ 13 // 1. マルチCURLハンドルを初期化 14 $multi_handle = curl_multi_init(); 15 if ($multi_handle === false) { 16 throw new RuntimeException("Failed to initialize curl_multi."); 17 } 18 19 // 2. curl_multi_setopt を使用してマルチハンドルのオプションを設定 20 // ここでは、HTTP/1.1のパイプライン処理とHTTP/2の多重化を有効に設定します。 21 // これにより、同じホストへの複数のリクエストが効率的に処理される可能性があり、 22 // ネットワークの効率が向上することが期待されます。 23 // オプション設定は成功すると true を返します。 24 if (!curl_multi_setopt($multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX)) { 25 // オプション設定に失敗した場合でも、多くの場合処理は続行できますが、ログに残すのが良いでしょう。 26 error_log("Failed to set CURLMOPT_PIPELINING option."); 27 } 28 29 $curl_handles = []; 30 $results = []; 31 32 // 3. 各URLに対してCURLハンドルを作成し、マルチハンドルに追加 33 foreach ($urls as $id => $url) { 34 $ch = curl_init(); 35 if ($ch === false) { 36 error_log("Failed to initialize curl for URL: " . $url); 37 continue; 38 } 39 curl_setopt($ch, CURLOPT_URL, $url); 40 curl_setopt($ch, CURLOPT_HEADER, 0); // レスポンスヘッダは取得しない 41 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 戻り値を文字列として取得する 42 curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 各リクエストのタイムアウトを10秒に設定 43 curl_setopt($ch, CURLOPT_FAILONERROR, true); // HTTPステータスコードが400以上の場合にエラーとする 44 45 curl_multi_add_handle($multi_handle, $ch); 46 $curl_handles[$id] = $ch; 47 } 48 49 $running_handles = null; // アクティブなハンドル数を格納する変数 50 $mrc = null; // curl_multi_exec の戻り値 51 52 // 4. 全てのリクエストが完了するまでループで待機・処理 53 do { 54 // 並列リクエストを実行し、完了したハンドル数を更新 55 // curl_multi_exec は、処理の完了を待たずにすぐに制御を返します。 56 // CURLM_CALL_MULTI_PERFORM が返された場合、さらに呼び出しが必要であることを示します。 57 while (($mrc = curl_multi_exec($multi_handle, $running_handles)) === CURLM_CALL_MULTI_PERFORM); 58 59 // アクティブなリクエストがあり、かつエラーがない場合 60 if ($running_handles > 0 && $mrc === CURLM_OK) { 61 // curl_multi_select を使用して、I/Oイベントの発生を効率的に待機します。 62 // これにより、CPU使用率を抑えつつ、データが利用可能になるまでプログラムをブロックします。 63 // タイムアウトを1秒に設定し、イベントがない場合でも定期的にチェックします。 64 $select_timeout_seconds = 1; 65 $num_ready = curl_multi_select($multi_handle, $select_timeout_seconds); 66 67 if ($num_ready === -1) { 68 // select エラーが発生した場合(通常は非常に稀なケース) 69 error_log("curl_multi_select returned -1, likely an error."); 70 // エラーが発生した場合でも、無限ループを防ぐために少し待機する 71 usleep(100000); // 100ms 72 } 73 } 74 } while ($running_handles > 0 && $mrc === CURLM_OK); 75 76 // 5. 各リクエストの結果を取得 77 foreach ($curl_handles as $id => $ch) { 78 $error = curl_error($ch); 79 $errno = curl_errno($ch); 80 81 if ($errno === 0) { 82 $content = curl_multi_getcontent($ch); 83 // 成功した場合は、URLと内容の最初の部分を保存 84 $results[$urls[$id]] = "Success: " . mb_strcut($content, 0, 100) . "..."; 85 } else { 86 // エラーが発生した場合は、URLとエラー情報を保存 87 $results[$urls[$id]] = "Error (code {$errno}): {$error}"; 88 } 89 90 // 6. マルチハンドルから個々のCURLハンドルを削除し、閉じる 91 curl_multi_remove_handle($multi_handle, $ch); 92 curl_close($ch); 93 } 94 95 // 7. マルチCURLハンドルを閉じる 96 curl_multi_close($multi_handle); 97 98 return $results; 99} 100 101// サンプル使用例 102$target_urls = [ 103 "https://www.google.com", 104 "https://www.php.net", 105 "https://example.com", 106 "https://invalid.domain.xyz" // 意図的に失敗するURLの例 107]; 108 109echo "--- Fetching URLs in parallel ---\n"; 110try { 111 $fetched_data = fetch_multiple_urls_parallel($target_urls); 112 foreach ($fetched_data as $url => $data) { 113 echo "URL: {$url}\n"; 114 echo "Result: {$data}\n"; 115 echo "---------------------------\n"; 116 } 117} catch (RuntimeException $e) { 118 echo "An error occurred: " . $e->getMessage() . "\n"; 119} 120 121?>
このPHPサンプルコードは、CURL拡張機能を用いて複数のURLに対してHTTPリクエストを並行実行し、結果を一括で取得する方法を解説しています。主な焦点となるcurl_multi_setopt関数は、複数のCURLリクエストを同時に管理する「マルチCURLハンドル」全体に、共通の動作オプションを設定する際に用います。引数として、curl_multi_init()で初期化された$multi_handle、設定したいオプションの種類を示す$option(例: CURLMOPT_PIPELINING)、そしてそのオプションに与える値$valueを受け取ります。設定が成功するとtrueを、失敗するとfalseを戻り値として返します。サンプルでは、CURLMOPT_PIPELININGオプションにCURLPIPE_MULTIPLEXを設定し、HTTP/1.1のパイプライン処理やHTTP/2の多重化を有効にしています。この設定により、同一ホストへの複数の接続がより効率的に行われ、ネットワーク通信の最適化が期待できます。curl_multi_setoptで全体設定を行った後、個々のURLに対するCURLハンドルをマルチハンドルに追加し、curl_multi_execとcurl_multi_selectで非同期にリクエストを進行させ、最終的にすべての応答結果を取得しています。
curl_multi_setoptは、複数のHTTPリクエストを並行して扱うマルチCURLハンドルの全体的な動作を設定する関数です。個別のリクエスト設定を行うcurl_setoptとは異なり、ネットワーク効率を改善するオプションを設定します。本サンプルのように、HTTP/2多重化を有効にすることで、特に同じホストへの複数のリクエストにおいてパフォーマンス向上が期待できます。この関数の戻り値はブール値で、設定の成否を示します。失敗しても処理が続く場合がありますが、期待通りの動作のためにエラーログを記録することが重要です。また、並列処理では初期化の失敗や個々のリクエストのエラー、さらにリソースの解放漏れに注意が必要です。特にcurl_multi_selectは、CPUを無駄に消費せず効率的にイベント発生を待機するために不可欠ですので、必ず適切に利用してください。
PHP cURLで複数URLを並行取得する
1<?php 2 3/** 4 * 複数のURLに並行してGETリクエストを送信し、結果を取得します。 5 * 6 * この関数では、複数のcURLリクエストを効率的に管理するために 7 * `curl_multi_init` を使用します。 8 * 各個別リクエストには `curl_setopt_array` を用いて複数のオプションを一度に設定し、 9 * 並行処理全体の設定には `curl_multi_setopt` を使用します。 10 * 11 * @param array $urls リクエストを送信するURLの配列。例: ['https://example.com', 'https://www.php.net'] 12 * @return array 各URLに対するレスポンスボディ、またはエラーメッセージの連想配列。 13 */ 14function fetchMultipleUrlsConcurrently(array $urls): array 15{ 16 // 複数のcURLハンドルを管理するためのマルチハンドルを初期化します。 17 $multiHandle = curl_multi_init(); 18 19 // 各個別cURLハンドルと、それに対応するURLを格納する配列です。 20 $individualHandles = []; 21 $results = []; 22 23 // 各URLに対して個別のcURLハンドルを設定します。 24 foreach ($urls as $key => $url) { 25 $ch = curl_init(); // 個別のcURLハンドルを初期化 26 27 // curl_setopt_array を使って、このHTTPリクエストに関する複数のオプションを一度に設定します。 28 // これは、個々のリクエストがどのように行われるかを定義します。 29 curl_setopt_array($ch, [ 30 CURLOPT_URL => $url, // リクエスト先のURL 31 CURLOPT_RETURNTRANSFER => true, // レスポンスを文字列として返すように設定 32 CURLOPT_HEADER => false, // レスポンスヘッダを含めない 33 CURLOPT_TIMEOUT => 5, // タイムアウトを5秒に設定 34 ]); 35 36 // 設定した個別のcURLハンドルをマルチハンドルに追加します。 37 curl_multi_add_handle($multiHandle, $ch); 38 $individualHandles[$key] = $ch; // 後で結果を取得するために保存 39 } 40 41 // curl_multi_setopt を使って、マルチハンドル自体のオプションを設定します。 42 // これは、複数のリクエストを並行してどのように処理するかを定義します。 43 // 例: HTTP/1.1パイプラインまたはHTTP/2多重化を有効にして通信効率を向上させる。 44 // 成功した場合は true、失敗した場合は false を返しますが、ここでは簡潔化のため戻り値のチェックを省略します。 45 curl_multi_setopt($multiHandle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); 46 47 // すべてのリクエストが完了するまでマルチハンドルを実行します。 48 $runningHandles = null; 49 do { 50 // マルチハンドルを実行し、アクティブなハンドル数を更新します。 51 curl_multi_exec($multiHandle, $runningHandles); 52 53 // まだ実行中のハンドルがある場合、新しいアクティビティがあるまで、またはタイムアウトするまで待機します。 54 if ($runningHandles > 0) { 55 curl_multi_select($multiHandle, 1.0); // 最大1.0秒待機 56 } 57 } while ($runningHandles > 0); 58 59 // 全てのリクエストが完了したら、個々のハンドルの結果を取得します。 60 foreach ($individualHandles as $key => $ch) { 61 $error = curl_error($ch); 62 if ($error) { 63 $results[$urls[$key]] = "Error: " . $error; 64 } else { 65 $results[$urls[$key]] = curl_multi_getcontent($ch); // レスポンスボディを取得 66 } 67 // マルチハンドルから個別cURLハンドルを削除し、個別cURLハンドルをクローズします。 68 curl_multi_remove_handle($multiHandle, $ch); 69 curl_close($ch); 70 } 71 72 // マルチcURLハンドルをクローズしてリソースを解放します。 73 curl_multi_close($multiHandle); 74 75 return $results; 76} 77 78// --- サンプル使用例 --- 79$targetUrls = [ 80 'https://example.com', 81 'https://www.php.net', 82 'https://httpbin.org/get', // GETリクエストの情報を返すテストサイト 83 'https://invalid.url.example.com', // 存在しないURLでエラーをテスト 84]; 85 86echo "--- 並行リクエスト開始 ---\n"; 87$responses = fetchMultipleUrlsConcurrently($targetUrls); 88 89foreach ($responses as $url => $content) { 90 echo "\n--- レスポンス for " . $url . " ---\n"; 91 if (str_starts_with($content, "Error:")) { 92 echo $content . "\n"; 93 } else { 94 // コンテンツが長すぎる場合、最初の200文字のみ表示 95 echo substr($content, 0, 200) . (strlen($content) > 200 ? "..." : "") . "\n"; 96 } 97} 98echo "--- 並行リクエスト終了 ---\n"; 99 100?>
PHPのcurl_multi_setopt関数は、複数のcURLリクエストを並行して管理するための「マルチハンドル」に対して、全体的な動作オプションを設定する際に使用します。
提供されたサンプルコードのfetchMultipleUrlsConcurrently関数では、複数のURLに並行してGETリクエストを送信しています。この処理において、各URLへの個別リクエストの設定にはcurl_setopt_arrayが使われますが、curl_multi_setoptは並行処理全体の通信効率を向上させるために、HTTP/1.1パイプラインまたはHTTP/2多重化を有効にする設定(CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX)を行っています。これにより、個々のリクエストではなく、複数のリクエストをより効率的に処理できるようになります。
この関数の第一引数$multi_handleには、curl_multi_init()で初期化されたマルチハンドルを指定します。第二引数$optionには、設定したいオプションを示す定数を指定し、第三引数$valueには、そのオプションに対する値を設定します。設定が成功した場合はtrue、失敗した場合はfalseが戻り値として返されます。このように、curl_multi_setoptは、並行処理のパフォーマンスや挙動を制御するための重要な役割を担っています。
このコードでは、curl_multi_setoptが複数のHTTPリクエストを並行して効率良く処理するための全体設定を行うのに対し、curl_setopt_arrayは各個別リクエストのURLやタイムアウトなどの詳細を設定することに注意してください。それぞれが異なるレベルのオプションを管理します。並行処理を行う際は、curl_multi_initで開始したマルチハンドルと、curl_initで生成した個別のcURLハンドルの両方を、処理の最後に必ずcurl_multi_closeとcurl_closeで閉じてリソースを解放することが重要です。curl_multi_setoptのような関数の戻り値は、設定が成功したかを示すため、実際のアプリケーションではエラーチェックを行うとより安全です。これにより、意図しない動作やリソースリークを防ぎ、安定したシステムを構築できます。