【PHP8.x】curl_multi_errno()関数の使い方
curl_multi_errno関数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
curl_multi_errno関数は、複数のcURLリクエストを並行して処理する際に使用するマルチハンドル操作において、直近で発生したエラーのコードを取得する関数です。この関数は、curl_multi_initで作成されたcURLマルチハンドルを引数として受け取ります。例えば、curl_multi_execやcurl_multi_selectといった、複数の転送を管理する関数が期待通りに動作しなかった場合に、何らかのシステム的な問題が発生していないかを確認するために利用します。
エラーが発生していなければ、この関数はCURLM_OKに相当するゼロの値を返します。もしエラーが発生している場合は、その原因を示す具体的なエラーコード(整数値)が返されます。これにより、システムエンジニアを目指す皆さんが、並行処理中の問題を特定し、適切なエラーハンドリングを実装するための手がかりとして活用できます。この関数で取得できるエラーは、個々のHTTPリクエストの失敗ではなく、複数のリクエストを管理する「マルチハンドル」自体に起因する問題(例: メモリ不足、無効な状態遷移など)に関連するものです。個々のHTTP転送におけるエラーは、別途curl_errno関数で確認する必要があります。
構文(syntax)
1<?php 2$multiHandle = curl_multi_init(); 3$errorCode = curl_multi_errno($multiHandle); 4curl_multi_close($multiHandle); 5?>
引数(parameters)
CurlMultiHandle $multi_handle
- CurlMultiHandle $multi_handle: マルチハンドルを表すオブジェクト。
curl_multi_init()で取得したリソースを指定します。
戻り値(return)
int
実行中に発生した最新のエラーコードを整数で返します。エラーが発生しなかった場合は 0 を返します。
サンプルコード
PHP cURLマルチハンドルエラー取得
1<?php 2 3/** 4 * 複数の cURL リクエストを並行して実行し、マルチハンドルのエラーハンドリングを示す関数。 5 * 6 * @param array $urls 取得するURLの配列 7 * @return array 各URLの応答またはエラー情報を含む配列 8 */ 9function performMultiCurlRequests(array $urls): array 10{ 11 // 各 cURL ハンドルの初期化 12 $handles = []; 13 foreach ($urls as $key => $url) { 14 $ch = curl_init(); 15 if ($ch === false) { 16 echo "Error: Failed to initialize cURL handle for URL: $url\n"; 17 continue; 18 } 19 curl_setopt($ch, CURLOPT_URL, $url); 20 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 結果を文字列として返す 21 curl_setopt($ch, CURLOPT_HEADER, false); // レスポンスヘッダーを含めない 22 curl_setopt($ch, CURLOPT_TIMEOUT, 5); // タイムアウト設定 (5秒) 23 $handles[$key] = $ch; 24 } 25 26 // マルチ cURL ハンドルの初期化 27 $mh = curl_multi_init(); 28 if ($mh === false) { 29 echo "Error: Failed to initialize cURL multi handle.\n"; 30 // 既存の cURL ハンドルを閉じる 31 foreach ($handles as $ch) { 32 curl_close($ch); 33 } 34 return []; 35 } 36 37 // 各 cURL ハンドルをマルチハンドルに追加 38 foreach ($handles as $ch) { 39 curl_multi_add_handle($mh, $ch); 40 } 41 42 // --- マルチ cURL リクエストの実行 --- 43 $running = null; // まだ実行中のハンドルの数 44 $status = null; // curl_multi_exec の戻り値ステータス 45 46 do { 47 // cURLマルチハンドルの実行。$running にはまだ実行中のハンドルの数が設定される。 48 $status = curl_multi_exec($mh, $running); 49 50 // curl_multi_exec が CURLM_CALL_MULTI_PERFORM を返した場合、 51 // 内部バッファ処理のためにすぐに再度実行が必要。 52 while ($status === CURLM_CALL_MULTI_PERFORM) { 53 $status = curl_multi_exec($mh, $running); 54 } 55 56 // curl_multi_exec 自体がエラーを返した場合(例: CURLM_BAD_HANDLE など) 57 if ($status !== CURLM_OK && $status !== CURLM_CALL_MULTI_PERFORM) { 58 echo "Error: curl_multi_exec failed with status: " . $status . ".\n"; 59 // この場合、マルチハンドル全体に問題がある可能性が高いため、ループを中断。 60 break; 61 } 62 63 // まだ実行中のリクエストがある場合、IO (データ送受信) が利用可能になるまで待機する。 64 // これによりCPUリソースの無駄な消費を防ぐ。 65 if ($running > 0) { 66 curl_multi_select($mh, 1.0); // 最大1秒間待機 67 } 68 69 } while ($running > 0); // 実行中のリクエストがなくなるまでループを続ける 70 71 // --- curl_multi_errno の利用とエラーチェック --- 72 73 // curl_multi_errno は、マルチ cURL ハンドルそのものに対するエラーコードを返す。 74 // これは、個々の HTTP リクエストのエラー(例: 404 Not Found, 接続失敗)とは異なる点に注意。 75 // 例えば、curl_multi_init の失敗や、マルチハンドルへの不適切な操作などでエラーが発生する可能性がある。 76 $multi_error_code = curl_multi_errno($mh); 77 78 if ($multi_error_code !== CURLE_OK) { 79 // マルチハンドル操作でエラーが発生した場合 80 echo "Error: Multi cURL handle operation failed: " . curl_multi_strerror($multi_error_code) . "\n"; 81 } else { 82 echo "Info: No overall multi cURL handle operation errors detected.\n"; 83 } 84 85 // 各 cURL ハンドルの結果を取得し、個別のエラーをチェック 86 $results = []; 87 foreach ($handles as $key => $ch) { 88 $response = curl_multi_getcontent($ch); // 個々の cURL ハンドルの応答を取得 89 $error_code = curl_errno($ch); // 個々の cURL ハンドルのエラーコード 90 $error_message = curl_error($ch); // 個々の cURL ハンドルのエラーメッセージ 91 92 if ($error_code !== CURLE_OK) { 93 // 個別の cURL ハンドルにエラーがあった場合 (例: 接続失敗、タイムアウト) 94 $results[$key] = [ 95 'url' => $urls[$key], 96 'status' => 'error', 97 'error_code' => $error_code, 98 'error_message' => $error_message, 99 ]; 100 echo "Error for URL '{$urls[$key]}': ({$error_code}) {$error_message}\n"; 101 } else { 102 // 成功した場合 103 $results[$key] = [ 104 'url' => $urls[$key], 105 'status' => 'success', 106 'response_length' => strlen($response), 107 ]; 108 echo "Success for URL '{$urls[$key]}', response length: " . strlen($response) . "\n"; 109 } 110 111 // マルチハンドルから cURL ハンドルを削除し、閉じる 112 curl_multi_remove_handle($mh, $ch); 113 curl_close($ch); 114 } 115 116 // マルチ cURL ハンドルを閉じる 117 curl_multi_close($mh); 118 119 return $results; 120} 121 122// 実行例 123$targetUrls = [ 124 'https://www.example.com/', // 正常に取得できるURL 125 'https://httpbin.org/status/404', // HTTP 404 (Not Found) エラーを返すURL 126 'https://nonexistent.domain.xyz/', // 存在しないドメイン (cURL 接続エラーが発生するはず) 127 'https://www.php.net/', // 正常に取得できるURL 128]; 129 130echo "Starting multi cURL requests...\n"; 131$multiCurlResults = performMultiCurlRequests($targetUrls); 132echo "Multi cURL requests completed.\n"; 133 134// 結果の表示 (オプション) 135// print_r($multiCurlResults); 136
PHPのcurl_multi_errno関数は、複数のcURLリクエストを並行して実行する際に使用する「マルチcURLハンドル」の状態に関するエラーコードを取得するために利用されます。この関数は、引数としてエラーを調べたいCurlMultiHandle型のマルチハンドルを受け取り、その戻り値として整数値のエラーコードを返します。戻り値がCURLE_OKであれば、マルチハンドル自体の操作には問題がなかったことを示します。
具体的には、curl_multi_execなどで複数のcURLリクエストを実行している最中や、マルチハンドルの初期化・追加・削除といった操作において、そのマルチハンドル自体に内部的な問題が発生していないかを確認する役割を持ちます。重要な点として、この関数が報告するのは、個々のHTTPリクエストが失敗した(例えば、ウェブページが見つからない404エラーや、サーバーへの接続に失敗したなど)といったエラーとは異なります。個々のリクエストのエラーは、curl_errno関数を使って各cURLハンドルごとに確認する必要があります。curl_multi_errnoは、あくまで複数のリクエストを管理するシステム全体(マルチハンドル)に異常がないかをチェックし、安定した並行処理の実現に貢献します。
このサンプルコードは、複数のcURLリクエストを並行処理する高度なテクニックを示しています。特に注意すべきは、curl_multi_errnoがマルチハンドル全体の操作エラーを検出するのに対し、個々のHTTPリクエストにおける接続失敗やタイムアウトなどのエラーは、各cURLハンドルに対してcurl_errnoで確認する必要がある点を混同しないことです。curl_multi_execの戻り値も実行ステータスを示すため、これら三つのエラーチェックを適切に組み合わせることが重要です。また、curl_multi_selectはCPUリソースの無駄な消費を防ぐために不可欠であり、処理完了後は必ずcurl_closeとcurl_multi_closeを呼び出し、リソースを確実に解放してください。適切なタイムアウト設定も、システムがハングアップしないようにするために重要です。
PHP curl_multi_errno でマルチCURLエラーを取得する
1<?php 2 3/** 4 * 複数のCURLリクエストを並行して実行し、マルチCURLハンドルのエラーをチェックするサンプル。 5 * システムエンジニアを目指す初心者向けに、curl_multi_init から curl_multi_errno までの流れを示します。 6 */ 7function executeAndCheckMultiCurlError(): void 8{ 9 // 1. マルチCURLハンドルを初期化します。 10 // これは複数のCURLハンドルを同時に管理するためのコンテナです。 11 $multiHandle = curl_multi_init(); 12 13 if ($multiHandle === false) { 14 echo "エラー: curl_multi_init() の初期化に失敗しました。\n"; 15 return; 16 } 17 18 // 並行してリクエストするURLのリスト 19 $urls = [ 20 'https://www.example.com', 21 'https://www.php.net', 22 // 'http://invalid-url-example.local' // エラーを意図的に発生させたい場合 (名前解決失敗など) 23 ]; 24 25 $handles = []; // 個々のCURLハンドルを格納する配列 26 27 // 2. 各URLに対して個別のCURLハンドルを設定し、マルチハンドルに追加します。 28 foreach ($urls as $key => $url) { 29 $ch = curl_init(); // 個別のCURLハンドルを初期化 30 curl_setopt($ch, CURLOPT_URL, $url); 31 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // レスポンスを文字列として取得 32 curl_setopt($ch, CURLOPT_TIMEOUT, 5); // タイムアウト設定 (秒) 33 34 // 個々のCURLハンドルをマルチハンドルに追加 35 // これにより、マルチハンドルを通じてこれらのリクエストが並行して実行可能になります。 36 curl_multi_add_handle($multiHandle, $ch); 37 $handles[] = $ch; // 後で結果を取得したり閉じるために参照を保持 38 } 39 40 // 3. すべてのリクエストが完了するまで実行します。 41 $running = null; // 実行中のハンドルの数を追跡するための変数 42 do { 43 // CURLリクエストを実行し、完了したものを処理します。 44 // この関数はブロックせず、実行可能なリクエストを処理します。 45 $mrc = curl_multi_exec($multiHandle, $running); 46 47 // イベントが発生するまで待機します (ノンブロッキング)。 48 // 処理が長時間ブロックされるのを避けるため、短いタイムアウトを設定します。 49 if ($mrc === CURLM_OK && $running > 0) { 50 curl_multi_select($multiHandle, 1.0); // 1秒待機 51 } 52 53 } while ($running > 0 && $mrc === CURLM_OK); // 実行中のリクエストがある限りループを続けます 54 55 // 4. 各リクエストの結果を取得し、個々のハンドルをクリーンアップします。 56 foreach ($handles as $key => $ch) { 57 $response = curl_multi_getcontent($ch); // レスポンスボディを取得 58 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // HTTPステータスコードを取得 59 $effectiveUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); // 実際にアクセスされたURLを取得 60 61 if ($response === false) { 62 $error = curl_error($ch); // 個別のCURLハンドルでのエラーメッセージ 63 echo "URL: {$effectiveUrl} の取得中にエラーが発生しました: {$error}\n"; 64 } else { 65 echo "URL: {$effectiveUrl}\n"; 66 echo "HTTP ステータスコード: {$httpCode}\n"; 67 echo "レスポンスの取得に成功しました。\n\n"; 68 } 69 70 // 個々のCURLハンドルをマルチハンドルから削除します。 71 curl_multi_remove_handle($multiHandle, $ch); 72 // 個々のCURLハンドルを閉じます。 73 curl_close($ch); 74 } 75 76 // 5. マルチCURLハンドル全体のエラーコードを取得します。 77 // 正常に実行された場合、0が返されます。 78 $multiErrorCode = curl_multi_errno($multiHandle); 79 80 if ($multiErrorCode !== 0) { 81 // PHP 8.0 以降で利用可能な curl_multi_strerror() を使用してエラーメッセージを取得 82 $errorMessage = curl_multi_strerror($multiErrorCode); 83 echo "--- マルチCURL処理全体でエラーが発生しました ---\n"; 84 echo "エラーコード: {$multiErrorCode}\n"; 85 echo "エラーメッセージ: {$errorMessage}\n"; 86 } else { 87 echo "--- マルチCURL処理は正常に完了しました (エラーなし) ---\n"; 88 } 89 90 // 6. マルチCURLハンドルを閉じ、リソースを解放します。 91 curl_multi_close($multiHandle); 92} 93 94// サンプル関数を実行します 95executeAndCheckMultiCurlError(); 96 97?>
curl_multi_errno関数は、PHPで複数のCURLリクエストを並行して実行するマルチCURL処理において、そのマルチハンドル全体で発生したエラーコードを取得するために使用されます。システムエンジニアを目指す初心者の皆様は、この関数を使って、並行処理中に全体的な問題が発生していないかを確認できます。
この関数は、引数としてCurlMultiHandle $multi_handleを受け取ります。これは、事前にcurl_multi_init関数で初期化され、個々のCURLハンドルを追加して並行処理を実行しているマルチCURLハンドルのインスタンスです。どのマルチ処理のエラーをチェックしたいかを指定するために必要となります。
戻り値はint型で、エラーコードが数値で返されます。通常、エラーが全く発生しなかった場合は0が返されます。0以外の数値が返された場合は、何らかのマルチCURL処理上の問題が発生していることを示します。PHP 8.0以降では、このエラーコードをcurl_multi_strerror関数に渡すことで、より人間が理解しやすいエラーメッセージを取得できます。処理の最後にこの関数を呼び出すことで、リソースの解放前に全体的なエラーの有無を確認するのに役立ちます。
このサンプルコードは、複数のCURLリクエストを並行して実行する手順を説明しています。curl_multi_errnoは、個々のCURLリクエストのエラーではなく、複数のリクエストを管理するマルチCURLハンドル全体で発生したシステムレベルのエラーコードを返しますので注意が必要です。個々のリクエストに関するネットワークエラーやHTTPエラーは、それぞれのCURLハンドルに対してcurl_errorやcurl_getinfoを使用して確認してください。また、curl_multi_initでハンドルが正常に初期化されたか、そして処理完了後にcurl_multi_closeでリソースが確実に解放されているかを常に確認することが、安全なコード運用のために非常に重要です。curl_multi_errnoが返すエラーコードは、curl_multi_strerrorで人間が読めるメッセージに変換できます。