【PHP8.x】CURLKHMATCH_LAST定数の使い方
CURLKHMATCH_LAST定数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
CURLKHMATCH_LAST定数は、PHPのcURL拡張機能において、SSH/SFTP接続時に利用する既知ホストの検証(Known Hosts Matching)に関する定数群の「最後の要素」を示す定数です。cURLは、ウェブページへのアクセスやファイル転送など、さまざまなプロトコルを通じてデータ通信を行うための強力なライブラリであり、PHPではcURL拡張機能を通じてその機能を利用できます。
この定数群は、CURLOPT_SSH_KNOWNHOSTSオプションを設定する際に、ホストキーのマッチング動作をどのように行うかを指定するために使用されます。例えば、既知ホストファイルに登録されていないホストに遭遇した場合の挙動などを細かく制御できます。CURLKHMATCH_LAST定数自体は、特定の検証方法を直接指定するものではなく、CURLKHMATCH_NONEやCURLKHMATCH_ANYといった具体的なマッチングオプション定数の集合の中で、その範囲の終わりを示すマーカーとしての役割を果たすことが一般的です。
システムエンジニアを目指す方にとって、このような_LASTがサフィックスにつく定数は、APIが提供するオプションの総数を把握したり、内部的なループ処理などで定数群を走査する際の終端条件として利用されることがあることを理解しておくと役立ちます。通常、アプリケーションコードでこの定数自体を直接指定して、SSH/SFTP接続の既知ホスト検証を設定することは稀で、具体的な検証ルールを表す他のCURLKHMATCH系の定数を使用します。この定数は、cURL拡張機能が提供する既知ホストマッチング関連のオプションがどこまで存在するかを示す目印として機能します。
構文(syntax)
1<?php 2echo CURLKHMATCH_LAST; 3?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
戻り値なし
戻り値はありません
サンプルコード
PHP: curl_multi_execで並行HTTPリクエスト
1<?php 2 3/** 4 * 複数のHTTPリクエストを並行して実行し、結果を返す関数。 5 * 6 * この関数は、PHPのcURL Multiインターフェースを使用し、複数のURLへのリクエストを同時に処理します。 7 * PHP 8.1以降で削除された `curlm_call_multi_perform` 関数の機能を実現するために、 8 * `curl_multi_exec` と `curl_multi_select` の組み合わせを使用しています。 9 * 10 * @param array $urls リクエストを送信するURLの配列。 11 * @return array 各URLのレスポンス内容を格納した配列。エラーが発生した場合は'error'キーに詳細が格納されます。 12 */ 13function performConcurrentHttpRequests(array $urls): array 14{ 15 // マルチcURLハンドルを初期化 16 $multiHandle = curl_multi_init(); 17 if ($multiHandle === false) { 18 // マルチハンドル初期化に失敗した場合、空の配列を返す 19 return []; 20 } 21 22 $handles = []; // 個々のcURLハンドルを格納する配列 23 $results = []; // 各リクエストの結果を格納する配列 24 25 // 各URLに対してcURLハンドルを作成し、マルチハンドルに追加 26 foreach ($urls as $index => $url) { 27 $ch = curl_init(); 28 if ($ch === false) { 29 // cURLハンドル作成に失敗した場合、エラー情報と共にスキップ 30 $results[$index] = [ 31 'url' => $url, 32 'httpCode' => 0, 33 'response' => '', 34 'error' => 'Failed to initialize cURL handle.', 35 'errno' => CURLE_OUT_OF_MEMORY, // cURLエラーコードの一例 36 ]; 37 continue; 38 } 39 40 // cURLオプションを設定 41 curl_setopt($ch, CURLOPT_URL, $url); 42 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // レスポンスを文字列として返す 43 curl_setopt($ch, CURLOPT_HEADER, false); // レスポンスヘッダーを含めない 44 curl_setopt($ch, CURLOPT_TIMEOUT, 30); // タイムアウト設定 (秒) 45 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // 接続タイムアウト設定 (秒) 46 // PHPのcURL拡張機能にはCURLKHMATCH_LASTなど、様々な定数があります。 47 // これらは特定のcURLオプション(例: SSH/SFTP関連)で利用されます。 48 49 // マルチハンドルに個々のcURLハンドルを追加 50 curl_multi_add_handle($multiHandle, $ch); 51 $handles[$index] = $ch; 52 } 53 54 // 実行中のハンドル数を管理する変数 55 $running = 0; 56 if (!empty($handles)) { 57 // すべてのリクエストが完了するまで待機し、実行 58 do { 59 // cURLリクエストを実行し、実行中のハンドル数を更新 60 // PHP 8.1以降では curl_multi_exec() は CURLM_CALL_MULTI_PERFORM を返しません。 61 $status = curl_multi_exec($multiHandle, $running); 62 63 // 実行中にエラーが発生した場合 64 if ($status !== CURLM_OK) { 65 // エラーハンドリング 66 break; 67 } 68 69 // 実行中のハンドルがあり、かつイベントが発生していない場合、一定時間待機してCPU負荷を軽減 70 if ($running > 0) { 71 curl_multi_select($multiHandle, 1.0); // 1秒間待機 72 } 73 74 } while ($running > 0); // 実行中のハンドルがなくなるまでループ 75 } 76 77 // 各cURLハンドルの結果を取得し、後処理を行う 78 foreach ($handles as $index => $ch) { 79 // レスポンスボディを取得 80 $response = curl_multi_getcontent($ch); 81 // HTTPステータスコードを取得 82 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 83 84 $results[$index] = [ 85 'url' => curl_getinfo($ch, CURLINFO_EFFECTIVE_URL), 86 'httpCode' => $httpCode, 87 'response' => (string)$response, // レスポンスは文字列として扱う 88 'error' => curl_error($ch), 89 'errno' => curl_errno($ch), 90 ]; 91 92 // マルチハンドルから個々のcURLハンドルを削除 93 curl_multi_remove_handle($multiHandle, $ch); 94 // 個々のcURLハンドルを閉じる 95 curl_close($ch); 96 } 97 98 // 元のURLのインデックスに対応するように結果を整理 99 $finalResults = []; 100 foreach ($urls as $index => $url) { 101 $finalResults[$index] = $results[$index] ?? [ 102 'url' => $url, 103 'httpCode' => 0, 104 'response' => '', 105 'error' => 'Request was not processed (e.g., cURL handle creation failed).', 106 'errno' => CURLE_FAILED_INIT, // cURLエラーコードの一例 107 ]; 108 } 109 110 // マルチcURLハンドルを閉じる 111 curl_multi_close($multiHandle); 112 113 return $finalResults; 114} 115 116// --- サンプルコードの利用例 (CLIから実行することを想定) --- 117if (php_sapi_name() === 'cli') { 118 // 複数のダミーURLを定義 119 $urlsToFetch = [ 120 'https://jsonplaceholder.typicode.com/posts/1', 121 'https://jsonplaceholder.typicode.com/comments/1', 122 'https://jsonplaceholder.typicode.com/users/1', 123 'https://jsonplaceholder.typicode.com/todos/1', 124 'https://httpbin.org/status/404', // 404エラーの例 125 'https://nonexistent-domain.invalid/', // 存在しないドメインの例 126 ]; 127 128 echo "--- 並行HTTPリクエストの開始 ---\n"; 129 $startTime = microtime(true); 130 131 // 関数を呼び出してリクエストを実行 132 $allResponses = performConcurrentHttpRequests($urlsToFetch); 133 134 $endTime = microtime(true); 135 echo "--- 並行HTTPリクエストの終了 (実行時間: " . round($endTime - $startTime, 3) . "秒) ---\n\n"; 136 137 // 各レスポンスの結果を表示 138 foreach ($allResponses as $response) { 139 echo "URL: " . $response['url'] . "\n"; 140 echo "HTTP Status: " . $response['httpCode'] . "\n"; 141 if ($response['error']) { 142 echo "Error (" . $response['errno'] . "): " . $response['error'] . "\n"; 143 } else { 144 echo "Response Snippet: " . substr($response['response'], 0, 100) . "...\n"; 145 } 146 echo "----------------------------------------\n"; 147 } 148}
このサンプルコードは、PHPのcURL Multiインターフェースを利用して、複数のHTTPリクエストを並行して実行し、その結果を一括で取得する関数performConcurrentHttpRequestsを定義しています。引数$urlsにはリクエストを送信するURLの配列を渡し、戻り値としては各URLからのレスポンス内容やエラー情報をまとめた配列が返されます。
処理はまず、並行処理を行うためのマルチcURLハンドルを初期化し、その後、引数で受け取った各URLに対し、個別のcURLハンドルを作成してHTTPリクエストのオプションを設定します。これらの個別ハンドルはマルチハンドルに追加され、curl_multi_execとcurl_multi_selectを組み合わせて実際に並行処理が実行されます。特に、PHP 8.1以降で削除されたcurlm_call_multi_perform関数の機能は、この2つの関数をループ内で使用することで実現しています。
リクエスト完了後、各ハンドルのレスポンスデータやHTTPステータスコード、エラー情報などを取得し、個々のハンドルおよびマルチハンドルを適切にクローズしてリソースを解放します。PHPのcURL拡張機能には、CURLKHMATCH_LASTのような様々な定数が存在し、これらはSSH/SFTP関連など特定のcURLオプションで使用されることがあります。
このサンプルコードは、PHP 8.1以降で削除されたcurlm_call_multi_performの代わりにcurl_multi_execとcurl_multi_selectを組み合わせ、複数のHTTPリクエストを並行して実行する方法を示しています。バージョンによる関数の違いを理解し、現在のPHPバージョンに合わせた実装をすることが重要です。並行処理では、各cURLハンドルとマルチハンドルを適切に初期化し、処理後は必ずリソースを解放する(curl_close、curl_multi_close)習慣を身につけてください。エラー発生時の詳細な情報取得や、curl_multi_selectによるCPU負荷の軽減も安定運用には欠かせません。CURLKHMATCH_LASTのような定数は、cURLの様々なオプションで利用され、複雑な通信制御を行う際に役立ちます。
PHP curl_multi_execで並行リクエストを実行する
1<?php 2 3/** 4 * 複数のURLに対してCURLリクエストを並行して実行し、その結果を返します。 5 * システムエンジニアを目指す初心者向けに、curl_multi_exec の基本的な使い方を示すサンプルです。 6 * 7 * @param array<string> $urls 取得するURLの配列。 8 * @return array<string, string|false> 各URLに対するレスポンスの配列。キーは元のURLに対応します。 9 * エラーが発生した場合は false が返されることがあります。 10 */ 11function executeMultiCurlRequests(array $urls): array 12{ 13 // CURLマルチハンドルの初期化 14 // 複数のCURLリクエストを並行して処理するために使用します。 15 $multiHandle = curl_multi_init(); 16 17 // 各CURLハンドルの格納用配列 18 $curlHandles = []; 19 20 // リクエスト結果の格納用配列 21 $responses = []; 22 23 // 各URLに対してCURLハンドルを作成し、マルチハンドルに追加します。 24 foreach ($urls as $url) { 25 $ch = curl_init(); 26 if ($ch === false) { 27 // curl_init() が失敗した場合の処理 28 error_log("Failed to initialize cURL for URL: " . $url); 29 $responses[$url] = false; 30 continue; 31 } 32 33 curl_setopt($ch, CURLOPT_URL, $url); 34 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // レスポンスを文字列として取得 35 curl_setopt($ch, CURLOPT_HEADER, false); // レスポンスヘッダーを含めない 36 37 // 例: HTTPSサイトへのアクセスでSSL証明書のエラーが発生する場合、 38 // 開発環境やテスト目的でのみ以下のオプションを使用することがあります。 39 // 本番環境ではセキュリティリスクがあるため、推奨されません。 40 // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 41 // curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 42 43 curl_multi_add_handle($multiHandle, $ch); 44 $curlHandles[(string)$ch] = $ch; // ハンドルをキーとして保存 45 } 46 47 // 全てのリクエストが完了するまで待機し、実行します。 48 $running = null; // 実行中のハンドルの数 49 do { 50 // curl_multi_exec() を呼び出して、アクティブなCURLハンドルの状態を更新します。 51 $status = curl_multi_exec($multiHandle, $running); 52 53 // 進行中のリクエストがある場合、CPUを占有しすぎないように短い時間スリープします。 54 if ($running > 0) { 55 // curl_multi_select() は、イベントが発生するまで待機します。 56 // 第2引数はタイムアウト(秒)です。0.1秒待機することでポーリング間隔を調整します。 57 curl_multi_select($multiHandle, 0.1); 58 } 59 } while ($running > 0 && $status === CURLM_OK); // 全てのリクエストが完了するか、エラーが発生するまでループ 60 61 // 各CURLハンドルの結果を取得し、クローズします。 62 foreach ($curlHandles as $ch) { 63 $info = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); 64 $responses[$info] = curl_multi_getcontent($ch); // レスポンス内容を取得 65 curl_multi_remove_handle($multiHandle, $ch); // マルチハンドルから削除 66 curl_close($ch); // CURLハンドルをクローズ 67 } 68 69 // マルチハンドルのクローズ 70 curl_multi_close($multiHandle); 71 72 return $responses; 73} 74 75// このスクリプトがCLI(コマンドラインインターフェース)から実行された場合のみ、以下のサンプルを実行します。 76if (php_sapi_name() === 'cli') { 77 // リファレンス情報として提示された定数 CURLKHMATCH_LAST の値を確認します。 78 // この定数はCURLのSSH Known Hostsのマッチングに関連するもので、 79 // 今回のHTTPリクエストの並行処理では直接使用されません。 80 // PHPのCURL拡張機能がHTTPだけでなく、SFTPなど様々なプロトコルを扱えることを示しています。 81 echo "CURLKHMATCH_LAST constant value: " . CURLKHMATCH_LAST . "\n\n"; 82 83 // 取得するURLのリスト 84 // 公開されている軽量なAPIエンドポイントなどを使用すると、テストが容易です。 85 $targetUrls = [ 86 'https://jsonplaceholder.typicode.com/posts/1', 87 'https://jsonplaceholder.typicode.com/posts/2', 88 'https://jsonplaceholder.typicode.com/comments/1', 89 'https://httpbin.org/delay/1' // 1秒遅延するURLを追加 90 ]; 91 92 echo "複数のCURLリクエストを並行実行中...\n"; 93 $startTime = microtime(true); 94 95 $results = executeMultiCurlRequests($targetUrls); 96 97 $endTime = microtime(true); 98 echo "全リクエスト完了。所要時間: " . round($endTime - $startTime, 2) . "秒\n\n"; 99 100 // 取得した結果を表示 101 foreach ($results as $url => $data) { 102 echo "--- 結果 from " . $url . " ---\n"; 103 if ($data === false) { 104 echo "データ取得失敗。\n"; 105 } else { 106 // 結果が長い場合は、最初の100文字のみ表示 107 echo "データ: " . substr($data, 0, 100) . (strlen($data) > 100 ? "..." : "") . "\n"; 108 } 109 echo "\n"; 110 } 111}
このPHPコードは、curl_multi_exec 関数を用いて複数のURLに対するWebリクエストを同時に実行し、その結果を効率的に取得する基本的な方法を示しています。
executeMultiCurlRequests 関数は、引数として取得したいURLのリスト(配列)を受け取ります。内部では、まず curl_multi_init() で複数のCURLリクエストを管理するための「マルチハンドル」を作成します。次に、リスト内の各URLに対して curl_init() で個別のCURLハンドルを作り、CURLOPT_RETURNTRANSFER でレスポンスを文字列として取得する設定などを行い、curl_multi_add_handle() でマルチハンドルに追加します。
リクエストの実行フェーズでは、do-while ループ内で curl_multi_exec() を繰り返し呼び出します。これにより、追加された全てのリクエストが並行して処理され、進行中のリクエストがなくなるまでループが続きます。ループ中には curl_multi_select() を使用し、イベントが発生するまで待機することでCPUの無駄な消費を抑えています。
全てのリクエストが完了した後、各CURLハンドルから curl_multi_getcontent() で実際のWebページの応答内容を取得し、curl_multi_remove_handle() と curl_close() で個別のハンドルを閉じます。最終的に curl_multi_close() でマルチハンドルも閉じられ、取得した応答内容がURLをキーとする連想配列として関数の戻り値となります。エラーが発生した場合は、false が返されることがあります。
提供されたリファレンス情報にある CURLKHMATCH_LAST 定数は、CURLのSSH Known Hostsのマッチングに関連するものであり、このHTTPリクエストの並行処理のサンプルコードでは直接使用されていませんが、PHPのCURL拡張機能がHTTPだけでなく様々なプロトコルを扱えることを示しています。このコードは、WebAPIからのデータ取得など、複数のネットワーク通信を効率的に行いたい場合に役立ちます。
このサンプルコードは、PHPで複数のCURLリクエストを並行処理する基本的な方法を示しています。特にcurl_multi_execのループ処理では、CPU負荷を軽減するためにcurl_multi_selectで適切な待機時間を設けることが重要です。また、CURLOPT_SSL_VERIFYPEERやCURLOPT_SSL_VERIFYHOSTをfalseに設定すると、SSL証明書の検証をスキップしセキュリティリスクを高めるため、本番環境での使用は絶対に避けてください。各CURLハンドルの初期化失敗や、curl_multi_execのエラー状態のチェックなど、適切なエラーハンドリングを実装することが堅牢なシステムには不可欠です。リファレンスで提示された定数CURLKHMATCH_LASTは、CURLのSSH関連の機能で使用されるもので、今回のHTTPリクエスト並行処理のサンプルとは直接関係ありませんが、CURL拡張機能が非常に広範なプロトコルに対応していることを示しています。