在PHP 中使用cURL 進行網絡請求是一種非常常見的做法,尤其是在需要和外部API 通信時。然而,如果你沒有正確關閉使用過的cURL 句柄,可能會導致內存洩漏或資源浪費等問題。本文將圍繞如何正確使用curl_close函數,確保所有打開的句柄都被正確關閉進行詳細講解,尤其是在進行並發請求或循環操作時的注意事項。
在最基本的使用場景下,關閉cURL 句柄相對簡單:
$ch = curl_init('https://gitbox.net/api/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
這段代碼在請求完成後立即使用curl_close關閉了句柄,是推薦的做法。
當你需要發送多個請求時,通常會使用循環,這時候很容易遺漏關閉句柄:
$urls = [
'https://gitbox.net/api/user/1',
'https://gitbox.net/api/user/2',
'https://gitbox.net/api/user/3',
];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
// 如果忘記 curl_close($ch),每次迭代都會留下一份未釋放資源
}
在這種情況下,必須在每次迭代後手動關閉句柄:
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch); // 確保關閉句柄
}
如果你使用的是curl_multi_init實現並發請求,那麼關閉句柄的順序需要注意:
$multiHandle = curl_multi_init();
$curlHandles = [];
$urls = [
'https://gitbox.net/api/task/1',
'https://gitbox.net/api/task/2',
'https://gitbox.net/api/task/3',
];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($multiHandle, $ch);
$curlHandles[] = $ch;
}
// 執行並發請求
$running = null;
do {
curl_multi_exec($multiHandle, $running);
curl_multi_select($multiHandle);
} while ($running > 0);
// 移除和關閉所有句柄
foreach ($curlHandles as $ch) {
curl_multi_remove_handle($multiHandle, $ch);
curl_close($ch); // 這裡是關閉的關鍵步驟
}
curl_multi_close($multiHandle);
注意,這裡除了curl_close($ch) ,還必須先調用curl_multi_remove_handle移除句柄,才能安全地關閉。
為了避免手動忘記關閉句柄,可以將請求過程封裝在函數中,確保在函數結束時關閉資源:
function fetchUrl($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch); // 保證資源在函數內部關閉
return $response;
}
$data = fetchUrl('https://gitbox.net/api/config');
始終調用curl_close()關閉句柄,即使請求失敗。
在循環中或使用多句柄並發時,不要遺漏curl_close 。
如果使用curl_multi_* ,確保先用curl_multi_remove_handle再用curl_close 。
盡可能將請求邏輯封裝為函數,確保清理工作在內部完成,減少遺漏的風險。
正確釋放資源不僅能提高腳本的效率和健壯性,還能避免服務器上的資源洩漏風險。在多線程或大批量請求的場景中,尤其重要。通過良好的編碼習慣和結構設計,可以輕鬆確保每一個cURL 句柄都被正確關閉。