curl_multi_*関数は、PHPでの同時HTTP要求にCurl拡張機能を使用する場合、適切なサポートを提供します。特に、2つの関数curl_multi_closeとcurl_getinfoは、複数のリクエストの応答を処理するために一緒に使用する必要があることがよくあります。ただし、実際の開発では、特に各リクエストの応答情報を取得するためにcurl_getinfoを使用する場合、開発者はいくつかの落とし穴に遭遇する可能性があります。注意しないと、予期しないエラーにつながる可能性があります。また、正しい情報を取得できない場合があります。
curl_multi_closeは、複数のCurlセッションハンドルを閉じるために使用されます。リクエストが完了したら、この関数を呼び出してすべてのリソースを解放する必要があります。 CURL_GETINFOを使用してセッションを閉じる前にリクエストの詳細情報を取得すると、問題が発生する可能性があります。セッションを閉じた後、これらのセッションハンドルに関連するリソースが破壊され、 Curl_getInfoを呼び出すことで正しい応答情報を取得することはできません。
// サンプルコード:間違った方法
$mh = curl_multi_init();
$ch1 = curl_init("https://gitbox.net/api/v1/resource1");
$ch2 = curl_init("https://gitbox.net/api/v1/resource2");
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);
do {
$mrc = curl_multi_exec($mh, $active);
} while ($active);
// 間違い:セッションハンドルを閉じる前に呼び出されます curl_getinfo
$info1 = curl_getinfo($ch1); // ここでエラーが発生します,セッションが閉鎖されているためです
$info2 = curl_getinfo($ch2);
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);
上記の例では、 curl_multi_closeの前にcurl_getinfoを呼び出し、返された情報は利用できなくなり、PHPエラーにつながる可能性があります。
上記の問題を回避するには、 curl_multi_closeを呼び出す前に、各リクエストの応答情報を取得するためにcurl_getinfoを使用する必要があります。修正後の正しいデモンストレーションは次のとおりです。
// それを行う正しい方法
$mh = curl_multi_init();
$ch1 = curl_init("https://gitbox.net/api/v1/resource1");
$ch2 = curl_init("https://gitbox.net/api/v1/resource2");
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);
do {
$mrc = curl_multi_exec($mh, $active);
} while ($active);
// 正しい:セッションを閉じる前に応答情報を取得します
$info1 = curl_getinfo($ch1);
$info2 = curl_getinfo($ch2);
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);
// これで、安全に使用できます $info1 そして $info2 その
この変更されたバージョンでは、すべてのセッションハンドルを閉じる前に、各リクエストの応答情報がcurl_getinfoを介して取得されるようにします。これにより、セッションハンドルを閉じた後、既にリリースされたリソースにアクセスしようとすることで、エラーが発生します。
複数のリクエストを同時に送信し、各リクエストの応答情報を取得したい場合は、通常、ループを使用します。現時点では、 curl_multi_closeの前に要求された各curl_getinfoが取得されることを確認する必要があります。そうしないと、リソースの損失が発生します。
// 正しい的做法:ループを使用して、各リクエストの情報を1つずつ取得します
$mh = curl_multi_init();
$channels = [];
$urls = [
"https://gitbox.net/api/v1/resource1",
"https://gitbox.net/api/v1/resource2"
];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_multi_add_handle($mh, $ch);
$channels[] = $ch;
}
do {
$mrc = curl_multi_exec($mh, $active);
} while ($active);
foreach ($channels as $ch) {
$info = curl_getinfo($ch); // ここで情報を一つ一つ入手してください
// 対処する $info
}
foreach ($channels as $ch) {
curl_multi_remove_handle($mh, $ch);
}
curl_multi_close($mh);
この例では、配列を使用して、各Curlセッションハンドルを保存し、各要求の応答情報をCurl_multi_closeの前に1つずつ取得します。このアプローチは、前述の問題を回避します。
すべての要求が同時に完了するわけではない場合があります。未完成のリクエストでcurl_getinfoを呼び出すことを避けるために、 curl_multi_select関数を使用して、どのリクエストが完了したかを検出し、完了したリクエストでcurl_getinfoのみに電話することを確認できます。
// より複雑な状況:使用 curl_multi_select 対処する完成的请求
$mh = curl_multi_init();
$channels = [];
$urls = [
"https://gitbox.net/api/v1/resource1",
"https://gitbox.net/api/v1/resource2"
];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_multi_add_handle($mh, $ch);
$channels[] = $ch;
}
do {
$mrc = curl_multi_exec($mh, $active);
if ($active) {
curl_multi_select($mh); // リクエストが完了するのを待ちます
}
} while ($active);
foreach ($channels as $ch) {
$info = curl_getinfo($ch); // ここで完了した要求情報を取得します
// 対処する $info
}
foreach ($channels as $ch) {
curl_multi_remove_handle($mh, $ch);
}
curl_multi_close($mh);
curl_multi_selectを使用すると、リクエストが完了したときに情報が取得されるようになり、待機またはタイムアウトの問題によるデータ損失を回避できます。
PHPでcurl_multi_*関数を使用する場合、 curl_getinfoおよびcurl_multi_closeが一般的に使用されるツールです。一般的な落とし穴を避けるための鍵は、複数のセッションを閉じる前に、各セッションの応答情報がcurl_getinfoを通じて取得されたことを確認することです。適切なコード構造とリクエスト管理により、プログラムの安定性と正確性を確保できます。