When using the cURL extension of PHP, the curl_multi_* series functions can execute multiple HTTP requests simultaneously. Send requests in batches via curl_multi_exec() and then close the handle using curl_multi_close() . Although these functions are powerful, they are prone to some pitfalls when used in conjunction with curl_setopt() . Below we will discuss a few common mistakes and how to avoid them.
When using curl_multi_exec() to batch process multiple requests, it is usually necessary to set individual options for each request. If curl_setopt() is not set correctly when adding multiple handles, the request may fail or return incorrect results.
$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');
// Forgot to set other necessary options,like CURLOPT_RETURNTRANSFER
Make sure to set the necessary options for each cURL handle. For example:
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_multi_close() and curl_close() are both used to close cURL handles, but their scope of action is different. curl_close() closes only a single cURL handle, while curl_multi_close() closes all handles in a multiple cURL request. Using these two functions incorrectly may cause the resource to be not released correctly, or the program will have an exception in subsequent requests.
curl_multi_close($multiHandle); // mistake,because $multiHandle Multiple handles need to be closed
When using multiple requests, you must use curl_multi_close() to close multiple handles after completing the request and processing each handle:
// Perform multiple requests
curl_multi_exec($multiHandle, $running);
// Close each individual cURL Handle
curl_close($ch1);
curl_close($ch2);
// Use correctly curl_multi_close()
curl_multi_close($multiHandle);
Sometimes, when a developer uses curl_multi_exec() to send multiple requests, they may close the connection prematurely because they do not wait for the request to complete correctly. Since curl_multi_exec() is executed asynchronously, it is necessary to ensure that all requests have been completed and then call curl_multi_close() .
// 没有等待请求完成就关闭Handle
curl_multi_close($multiHandle);
By detecting the $running parameter, make sure that all requests are completed before closing the connection:
$running = null;
do {
curl_multi_exec($multiHandle, $running);
} while ($running > 0);
curl_multi_close($multiHandle);
In some cases, developers may try to reuse the same cURL handle, which can easily lead to request errors or performance issues. Each time a new request is sent, a new cURL handle should be created and different options should be set for it.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gitbox.net/api/data1');
// 复用相同的Handle
curl_setopt($ch, CURLOPT_URL, 'https://gitbox.net/api/data2'); // mistake,应该创建新的Handle
Make sure to create a new cURL handle for each request:
$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');
When curl_multi_exec() executes a request, various network or server errors may occur. In order to be able to handle these errors correctly, curl_error() and curl_errno() should be used for error debugging.
curl_multi_exec($multiHandle, $running); // Execute a request,但没有处理mistake
After each request is completed, check and output the error message:
// Execute a request
curl_multi_exec($multiHandle, $running);
// mistake处理
foreach ($handles as $ch) {
if ($errno = curl_errno($ch)) {
echo "cURL error: " . curl_error($ch);
}
}