【PHP8.x】curl_multi_strerror()関数の使い方
curl_multi_strerror関数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
curl_multi_strerror関数は、cURLマルチハンドルの操作中に発生したエラーコードに対応する、人間が読みやすい文字列メッセージを返す関数です。PHPのcURL拡張モジュールの一部であり、複数のHTTPリクエストなどを同時に並行処理するcURLマルチ機能を利用する際に、エラーの具体的な内容を把握するために使用されます。
この関数は、curl_multi_exec()などのcURLマルチ操作を行う関数がエラーを示すコードを返した場合に、その数値のエラーコード(例えば、CURLM_CALL_MULTI_PERFORMのような定数で表される値)を引数として受け取ります。そして、受け取ったエラーコードが具体的にどのような問題を示しているのかを説明するテキスト形式の文字列を返却します。これにより、プログラムがエラーに遭遇した際に、エラーの内容を正確に把握し、デバッグや適切なエラーハンドリングを行う手助けとなります。
システムエンジニアを目指す方にとって、Webアプリケーションなどで多数の外部サービスと連携する場面では、cURLマルチハンドルが非常に有効です。ネットワークの状況やリモートサーバーの問題により予期せぬエラーが発生した場合、この関数を使うことでエラーコードから具体的な状況を理解し、問題解決に役立てることができます。指定されたエラーコードが不明な場合はfalseが返されます。PHP 8.4環境でcURLマルチ機能を利用する際のエラー診断において重要なツールです。
構文(syntax)
1function curl_multi_strerror(int $error_code): ?string
引数(parameters)
int $error_code
- int $error_code:
CURLM定数で定義された、curl_multi_init()、curl_multi_add_handle()、curl_multi_remove_handle()、curl_multi_setopt()、curl_multi_exec()、curl_multi_wait()、curl_multi_socket_action()、curl_multi_fdset()、curl_multi_info_read()、curl_multi_getcontent()、curl_multi_errno()、curl_multi_strerror()、curl_multi_setopt()、curl_multi_close()などのcURLマルチハンドルの操作で発生したエラーコードを指定する整数。
戻り値(return)
?string
指定されたcURLマルチハンドルのエラーコードに対応する、人間が読めるエラーメッセージ文字列を返します。エラーが発生しなかった場合はnullを返します。
サンプルコード
PHP cURLマルチリクエストとエラー処理
1<?php 2 3/** 4 * 複数のURLに対して並行してcURLリクエストを実行し、結果を表示します。 5 * curl_multi_selectとcurl_multi_strerrorの使用例を含みます。 6 * 7 * @param array $urls リクエストを実行するURLの配列 8 * @return void 9 */ 10function executeMultiCurlRequests(array $urls): void 11{ 12 // cURLマルチハンドルを初期化します。 13 // 複数のcURLリクエストを同時に管理するために使用します。 14 $multiHandle = curl_multi_init(); 15 if ($multiHandle === false) { 16 echo "cURLマルチハンドルの初期化に失敗しました。\n"; 17 return; 18 } 19 20 $curlHandles = []; // 個々のcURLハンドルを格納する配列 21 22 // 各URLに対して個別のcURLハンドルを設定し、マルチハンドルに追加します。 23 foreach ($urls as $key => $url) { 24 $ch = curl_init(); 25 if ($ch === false) { 26 echo "cURLハンドルの初期化に失敗しました: {$url}\n"; 27 continue; 28 } 29 30 // cURLオプションを設定します。 31 curl_setopt($ch, CURLOPT_URL, $url); // リクエスト先のURL 32 curl_setopt($ch, CURLOPT_HEADER, 0); // レスポンスヘッダを含めない 33 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // レスポンスを文字列として返す 34 curl_setopt($ch, CURLOPT_TIMEOUT, 5); // タイムアウトを5秒に設定 35 36 // 個々のcURLハンドルをマルチハンドルに追加します。 37 curl_multi_add_handle($multiHandle, $ch); 38 $curlHandles[$key] = $ch; 39 echo "URLを追加しました: {$url}\n"; 40 } 41 42 $running = null; // アクティブなハンドルの数 43 44 // すべてのリクエストが完了するか、エラーが発生するまでループします。 45 do { 46 // cURLマルチハンドルでリクエストを実行または継続します。 47 // この関数は、現在実行中のハンドルの数を $running に格納します。 48 // 戻り値はcURLマルチインターフェースの状態コード(CURLM_OKなど)です。 49 $status = curl_multi_exec($multiHandle, $running); 50 51 // curl_multi_execでエラーが発生した場合 52 if ($status !== CURLM_CALL_MULTI_PERFORM && $status !== CURLM_OK) { 53 // curl_multi_strerror は、CURLM_XXX 定数で定義されるcURLマルチハンドルの 54 // エラーコードを人間が読める文字列に変換します。 55 $errorMessage = curl_multi_strerror($status); 56 echo "curl_multi_exec エラー: {$errorMessage} (コード: {$status})\n"; 57 break; 58 } 59 60 // アクティブなハンドルがある場合、ソケットのアクティビティを待機します。 61 if ($running > 0) { 62 // ソケットのアクティビティを監視し、指定されたタイムアウト(ここでは1秒)まで待機します。 63 // 戻り値はアクティブなソケット数、タイムアウト時は0、エラー時は-1です。 64 $selectStatus = curl_multi_select($multiHandle, 1.0); // 1秒タイムアウト 65 66 if ($selectStatus === 0) { 67 // タイムアウトしたが、ソケットのアクティビティはなかった場合 68 echo "curl_multi_select がタイムアウトしました。まだ {$running} 個のリクエストが実行中です。\n"; 69 } elseif ($selectStatus === -1) { 70 // select中にシステムレベルのエラーが発生した場合。 71 // curl_multi_strerror は curl_multi_select の -1 エラーを直接変換できません。 72 // 通常、これはシステムコール (select/poll) の失敗を示します。 73 echo "curl_multi_select エラー: システムエラーが発生しました (コード: {$selectStatus})\n"; 74 } 75 } 76 } while ($running > 0 && $status === CURLM_OK); 77 78 // すべてのリクエストが完了した後、個々のリクエストの結果を処理します。 79 foreach ($curlHandles as $ch) { 80 // 完了したリクエストの情報を読み取ります。 81 $info = curl_multi_info_read($multiHandle); 82 if ($info !== false && isset($info['result'])) { 83 $errorCode = $info['result']; // 個々の転送の結果コード(CURLE_OKなど) 84 85 if ($errorCode === CURLE_OK) { 86 // 転送が成功した場合 87 // curl_multi_getcontent でレスポンスボディを取得します。 88 $content = curl_multi_getcontent($ch); 89 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // HTTPステータスコードを取得 90 echo "URL: " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL) . " - 成功 (HTTP: {$httpCode})\n"; 91 // echo "コンテンツの一部: " . substr($content, 0, 100) . "...\n"; // 必要であればコンテンツを表示 92 } else { 93 // 転送が失敗した場合 94 // curl_multi_strerror は、CURLE_XXX 定数で定義される個々のcURL転送エラーコードを 95 // 人間が読める文字列に変換します。 96 $errorMessage = curl_multi_strerror($errorCode); 97 echo "URL: " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL) . " - 失敗: {$errorMessage} (コード: {$errorCode})\n"; 98 } 99 } else { 100 // multi_info_readで情報が取得できない場合(非常に稀なケース) 101 echo "URL: " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL) . " - 結果情報が取得できませんでした。\n"; 102 } 103 104 // 個々のcURLハンドルをマルチハンドルから削除し、クローズします。 105 curl_multi_remove_handle($multiHandle, $ch); 106 curl_close($ch); 107 } 108 109 // cURLマルチハンドルをクローズし、リソースを解放します。 110 curl_multi_close($multiHandle); 111 echo "すべてのリクエスト処理が完了しました。\n"; 112} 113 114// サンプルURLのリスト。 115// 意図的に存在しないドメインを含めることで、エラー処理の例を示します。 116$sampleUrls = [ 117 'https://www.example.com/', 118 'https://www.google.com/', 119 'https://invalid-domain-for-test.xyz/', // 存在しないドメインで名前解決エラーを発生させる 120 'https://httpbin.org/delay/2', // 2秒遅延するURLでタイムアウトや遅延処理の様子を示す 121 'https://www.php.net/', 122]; 123 124// 定義した関数を実行します。 125executeMultiCurlRequests($sampleUrls);
PHPのこのサンプルコードは、curl_multi_*関数群を用いて複数のURLに対するcURLリクエストを並行して実行し、その処理結果を扱う方法を示しています。特にcurl_multi_strerror関数は、cURL操作中に発生したエラーコード(整数値)を受け取り、人間が理解しやすいエラーメッセージの文字列に変換して返します。これにより、エラーの原因を具体的に特定し、デバッグに役立てることが可能です。
引数$error_codeには、cURLマルチハンドルの状態を示すCURLM_XXX定数や、個々のcURL転送結果のエラーを示すCURLE_XXX定数といった整数値のエラーコードを渡します。戻り値は、対応するエラーメッセージの文字列、またはエラーコードが無効な場合はnullになります。
サンプルコード内では、curl_multi_exec実行時に発生したマルチハンドルのエラーや、個々のcURL転送が完了した際のエラー結果に対してcurl_multi_strerrorを使用し、詳細なエラーメッセージを表示しています。また、curl_multi_select関数は、複数のcURLリクエストがアクティブな間にソケットのイベントを効率的に待ち受けるために利用されており、CPUリソースの有効活用に貢献します。このコードは、並行処理におけるエラーの特定とハンドリングの重要性を示す実用的な例です。
curl_multi_strerror関数は、並行処理全体のエラー(curl_multi_execの戻り値)と個々のリクエストのエラー(curl_multi_info_readで得られる結果)で渡すコードの種類が異なります。前者はCURLM_XXX定数、後者はCURLE_XXX定数であり、それぞれを適切に扱う必要があります。curl_multi_selectが返す-1はシステムエラーを示すため、curl_multi_strerrorでは詳細な文字列に変換できません。別途エラーメッセージを表示するよう考慮してください。また、複数のリクエストを扱うため、各cURLハンドルとマルチハンドルの初期化と、処理完了後の解放(クローズ)を確実に行い、メモリリークを防ぐことが重要です。
PHP curl_multi_strerrorでエラーコードを変換する
1<?php 2 3declare(strict_types=1); 4 5/** 6 * curl_multi_strerror 関数の使用例を示します。 7 * 複数のCURLリクエストを並行して処理し、マルチCURLハンドルから返されるエラーコードを 8 * 人間が読める文字列に変換する方法をデモンストレーションします。 9 * 10 * この例では、PHP の curl_multi_init() を使用してマルチCURL処理を設定し、 11 * curl_multi_exec() の実行ステータスを curl_multi_strerror() で確認します。 12 */ 13function demonstrateCurlMultiStrerrorUsage(): void 14{ 15 echo "--- マルチCURL処理の開始 ---\n"; 16 17 // 1. マルチCURLハンドルを初期化します。 18 // curl_multi_init() は失敗した場合に false を返します。 19 $mh = curl_multi_init(); 20 if ($mh === false) { 21 echo "エラー: マルチCURLハンドルの初期化に失敗しました。\n"; 22 return; 23 } 24 echo "マルチCURLハンドルを初期化しました。\n"; 25 26 // 2. 個別のCURLハンドルを2つ作成します。 27 $ch1 = curl_init(); 28 $ch2 = curl_init(); 29 30 if ($ch1 === false || $ch2 === false) { 31 echo "エラー: CURLハンドルの初期化に失敗しました。\n"; 32 curl_multi_close($mh); 33 return; 34 } 35 36 // 最初のCURLハンドル設定: 存在しないドメインへのリクエストでエラーを意図的に発生させます。 37 // 接続タイムアウトを短く設定し、エラーを明確にします。 38 curl_setopt($ch1, CURLOPT_URL, "http://nonexistent.domain.example.com/test"); 39 curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true); // 結果を文字列で返す 40 curl_setopt($ch1, CURLOPT_CONNECTTIMEOUT_MS, 500); // 500ミリ秒で接続タイムアウト 41 42 // 二番目のCURLハンドル設定: 正常なウェブサイトへのリクエストを設定します。 43 curl_setopt($ch2, CURLOPT_URL, "https://www.example.com"); 44 curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true); // 結果を文字列で返す 45 46 // 3. 個別のCURLハンドルをマルチCURLハンドルに追加します。 47 curl_multi_add_handle($mh, $ch1); 48 curl_multi_add_handle($mh, $ch2); 49 echo "2つのCURLハンドルをマルチCURLハンドルに追加しました。\n"; 50 51 $running = null; // 現在実行中のハンドルの数を保持する変数 52 53 // 4. マルチCURLリクエストの実行ループ 54 // 実行中のハンドルがなくなるまでループを続けます。 55 do { 56 // curl_multi_exec を呼び出して、マルチCURLハンドルで待機中のリクエストを実行します。 57 // $status は CURLM_* 定数のいずれかを返します。これはマルチCURL操作のステータスを示します。 58 $status = curl_multi_exec($mh, $running); 59 60 // curl_multi_strerror() を使って、curl_multi_exec が返したステータスコードを人間が読める文字列に変換します。 61 // PHP 8では戻り値が ?string なので、null の可能性を考慮して ?? 演算子を使用します。 62 $status_message = curl_multi_strerror($status); 63 echo " curl_multi_exec ステータス: " . ($status_message ?? "不明なエラー") . " (コード: $status)\n"; 64 65 // CURLM_OK ではない場合、または CURLM_CALL_MULTI_PERFORM ではない場合、致命的なエラーが発生している可能性があります。 66 // CURLM_CALL_MULTI_PERFORM は、再度 curl_multi_exec を呼び出す必要があることを示すため、エラーではありません。 67 if ($status !== CURLM_OK && $status !== CURLM_CALL_MULTI_PERFORM) { 68 echo "エラー: マルチCURL処理中に致命的なエラーが発生しました。処理を中断します。\n"; 69 break; 70 } 71 72 // 実行中のリクエストがまだある場合、ファイルディスクリプタのアクティビティを監視して待機します。 73 // これにより、CPU使用率を抑えることができます。 74 if ($running > 0) { 75 // curl_multi_select は、アクティビティがあるか、タイムアウトするまでブロックします。 76 // タイムアウトは秒単位なので、ミリ秒を秒に変換して渡します。 77 curl_multi_select($mh, 0.1); // 100ミリ秒待機 78 } 79 80 } while ($running > 0); // 実行中のハンドルがなくなるまでループを続けます。 81 82 echo "\n--- 個別のCURLハンドルの結果を確認します ---\n"; 83 84 // 5. 各CURLハンドルの結果とエラーを確認 85 // curl_errno() は個別のCURLハンドルのエラーコードを返します。 86 // curl_strerror() は curl_errno() が返すエラーコードを文字列に変換します。 87 // curl_multi_strerror() とは異なり、個別のCURLハンドルのエラーを扱います。 88 89 // ハンドル1の結果 (エラーが発生した可能性が高い) 90 $ch1_error_code = curl_errno($ch1); 91 $ch1_error_message = curl_strerror($ch1_error_code); // 個別CURLハンドルのエラーを文字列化 92 $ch1_content = curl_multi_getcontent($ch1); // 取得したデータ 93 $ch1_info = curl_getinfo($ch1); // CURLリクエストの実行情報 94 95 echo "ハンドル1 (http://nonexistent.domain.example.com/test):\n"; 96 echo " CURLエラーコード: $ch1_error_code\n"; 97 echo " CURLエラーメッセージ: " . ($ch1_error_message ?? 'なし') . "\n"; 98 echo " HTTPステータスコード: " . ($ch1_info['http_code'] ?? 'N/A') . "\n"; 99 if ($ch1_error_code !== CURLE_OK) { 100 echo " データ: (エラーにより取得できませんでした)\n"; 101 } else { 102 echo " データ: " . ($ch1_content === '' ? '(空)' : $ch1_content) . "\n"; 103 } 104 105 echo "\n"; 106 107 // ハンドル2の結果 (成功した可能性が高い) 108 $ch2_error_code = curl_errno($ch2); 109 $ch2_error_message = curl_strerror($ch2_error_code); // 個別CURLハンドルのエラーを文字列化 110 $ch2_content = curl_multi_getcontent($ch2); // 取得したデータ 111 $ch2_info = curl_getinfo($ch2); // CURLリクエストの実行情報 112 113 echo "ハンドル2 (https://www.example.com):\n"; 114 echo " CURLエラーコード: $ch2_error_code\n"; 115 echo " CURLエラーメッセージ: " . ($ch2_error_message ?? 'なし') . "\n"; 116 echo " HTTPステータスコード: " . ($ch2_info['http_code'] ?? 'N/A') . "\n"; 117 if ($ch2_error_code === CURLE_OK) { // エラーがない場合のみデータの一部を表示 118 echo " データ: " . substr($ch2_content, 0, 100) . "...\n"; // 長いので一部のみ表示 119 } else { 120 echo " データ: (エラーにより取得できませんでした)\n"; 121 } 122 123 // 6. 全てのハンドルをクローズしてリソースを解放します。 124 curl_multi_remove_handle($mh, $ch1); 125 curl_multi_remove_handle($mh, $ch2); 126 curl_close($ch1); 127 curl_close($ch2); 128 curl_multi_close($mh); 129 echo "\n全てのCURLハンドルをクローズしました。\n"; 130 echo "--- マルチCURL処理の終了 ---\n"; 131} 132 133// 関数を実行します。 134demonstrateCurlMultiStrerrorUsage(); 135
curl_multi_strerror関数は、PHPで複数のCURLリクエストを並行して処理する際に使用される「マルチCURL」操作のエラーコードを、人間が読める説明文に変換する役割を持ちます。引数には、curl_multi_exec関数などが返す、マルチCURL処理のステータスを示す整数値のエラーコード(int $error_code)を指定します。戻り値は、そのエラーコードに対応するエラーメッセージを示す文字列(string)です。対応するメッセージがない場合や不明なエラーコードの場合はnullを返します。
この関数は、curl_multi_initで開始される一連のマルチCURL処理において、curl_multi_execの実行結果として得られるステータスコードを解釈するために利用されます。これにより、処理中に発生したマルチCURL固有の問題を特定しやすくなり、システム全体の安定稼働に貢献します。サンプルコードでは、意図的にエラーを起こしたリクエストを含むマルチCURL処理を実行し、curl_multi_execのステータスを本関数で確認する様子を示しています。
curl_multi_strerror関数は、複数のCURLリクエストを並行処理するマルチCURLハンドル自体の操作エラーを文字列化します。個々のCURLリクエストで発生したエラーを確認するには、curl_strerror関数を使用しますので、この二つの使い分けを正確に理解してください。curl_multi_initやcurl_initが失敗した場合は、必ずエラーチェックを行い、後続の処理に進まないようにしてください。また、curl_multi_execがCURLM_CALL_MULTI_PERFORMを返すことがありますが、これはエラーではなく処理を継続するサインです。PHP 8ではcurl_multi_strerrorがnullを返す可能性があるため、??演算子などで適切にハンドリングすることが推奨されます。最終的には、全てのCURLハンドルとマルチCURLハンドルを確実にクローズし、リソースを解放するようにしてください。