在使用PHP 的cURL擴展時, curl_multi_*系列函數可以同時執行多個HTTP 請求。通過curl_multi_exec()來批量發送請求,然後使用curl_multi_close()關閉句柄。雖然這些函數強大,但如果與curl_setopt()配合使用時,也容易出現一些坑。下面我們將討論幾個常見的錯誤以及如何避免它們。
當使用curl_multi_exec()來批量處理多個請求時,通常需要為每個請求單獨設置選項。如果在添加多個句柄時沒有正確設置curl_setopt() ,可能會導致請求失敗或返回不正確的結果。
$ch1 = curl_init();
$ch2 = curl_init();
curl_setopt($ch1, CURLOPT_URL, 'https://gitbox.net/api/data1');
curl_setopt($ch2, CURLOPT_URL, 'https://gitbox.net/api/data2');
// 忘記設置其他必要的選項,如 CURLOPT_RETURNTRANSFER
確保在為每個cURL句柄設置必要的選項。例如:
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_multi_close()和curl_close()都是用來關閉cURL 句柄的,但它們的作用範圍不同。 curl_close()僅關閉單個cURL 句柄,而curl_multi_close()關閉一個多重cURL 請求中的所有句柄。錯誤地使用這兩個函數可能會導致資源未正確釋放,或者程序在後續請求中出現異常。
curl_multi_close($multiHandle); // 錯誤,因為 $multiHandle 需要關閉的是多個句柄
在使用多重請求時,必須在完成請求並處理好每個句柄後,使用curl_multi_close()來關閉多個句柄:
// 執行多個請求
curl_multi_exec($multiHandle, $running);
// 關閉每個單獨的 cURL 句柄
curl_close($ch1);
curl_close($ch2);
// 正確使用 curl_multi_close()
curl_multi_close($multiHandle);
有時候,開發者在使用curl_multi_exec()發送多個請求時,可能會因為沒有正確等待請求完成而過早地關閉連接。由於curl_multi_exec()是異步執行的,因此需要確保所有請求都已經完成,再調用curl_multi_close() 。
// 沒有等待請求完成就關閉句柄
curl_multi_close($multiHandle);
通過檢測$running參數,確保所有請求完成後再關閉連接:
$running = null;
do {
curl_multi_exec($multiHandle, $running);
} while ($running > 0);
curl_multi_close($multiHandle);
在某些情況下,開發者可能會嘗試復用同一個cURL 句柄,這樣做很容易導致請求錯誤或性能問題。每次發送新的請求時,都應該創建新的cURL 句柄,並為其設置不同的選項。
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gitbox.net/api/data1');
// 復用相同的句柄
curl_setopt($ch, CURLOPT_URL, 'https://gitbox.net/api/data2'); // 錯誤,應該創建新的句柄
確保為每個請求創建新的cURL 句柄:
$ch1 = curl_init();
curl_setopt($ch1, CURLOPT_URL, 'https://gitbox.net/api/data1');
$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_URL, 'https://gitbox.net/api/data2');
當curl_multi_exec()執行請求時,可能會出現各種網絡或服務器錯誤。為了能夠正確處理這些錯誤,應該使用curl_error()和curl_errno()來進行錯誤調試。
curl_multi_exec($multiHandle, $running); // 執行請求,但没有处理錯誤
在每個請求完成後,檢查並輸出錯誤信息:
// 執行請求
curl_multi_exec($multiHandle, $running);
// 錯誤处理
foreach ($handles as $ch) {
if ($errno = curl_errno($ch)) {
echo "cURL error: " . curl_error($ch);
}
}