Working with multiple API requests efficiently has always been a challenge in PHP. While cURL multi-handle provides powerful parallel execution, it often comes with complex handle management.
With PHP 8.5, a new utility function — curl_multi_get_handles() — is introduced to simplify this process.
In this detailed guide, we’ll cover:
- What cURL multi-handle is
- Problems in current implementations
- Introduction to curl_multi_get_handles()
- Before vs After comparison
- Real-world examples
- Best practices
What is cURL Multi-Handle?
The **cURL multi-handle API allows you to execute multiple HTTP requests in parallel instead of sequentially.
Sequential Example (Slow)
$response1 = file_get_contents("https://api1.com");
$response2 = file_get_contents("https://api2.com");
Each request waits → total time increases.
Parallel Example (Fast with cURL Multi)
$mh = curl_multi_init();
$ch1 = curl_init("https://api1.com");
$ch2 = curl_init("https://api2.com");
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);
Now both requests run simultaneously.
Problem in Current cURL Multi Usage
Before PHP 8.5, developers had to manually track all handles.
Typical Pattern (Complex)
$handles = [];
foreach ($urls as $key => $url) {
$ch = curl_init($url);
curl_multi_add_handle($mh, $ch);
$handles[$key] = $ch;
}
Later:
foreach ($handles as $ch) {
$response = curl_multi_getcontent($ch);
}
Issues:
× Need to maintain separate $handles array
× Risk of losing reference to handles
× Harder debugging
× Extra boilerplate code
New in PHP 8.5: curl_multi_get_handles()
The new function:
curl_multi_get_handles(CurlMultiHandle $multi_handle): array
What it does:
✔ Returns all active handles from a multi-handle
✔ Eliminates manual tracking
✔ Cleaner and safer code
Simple Example Using curl_multi_get_handles()
$urls = [
"https://api1.com",
"https://api2.com",
"https://api3.com"
];
$mh = curl_multi_init();
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
}
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running);
// NEW: No need to track handles manually
$handles = curl_multi_get_handles($mh);
$responses = [];
foreach ($handles as $ch) {
$responses[] = curl_multi_getcontent($ch);
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
print_r($responses);
Before vs After Comparison
| Feature | Before PHP 8.5 | PHP 8.5 |
|---|---|---|
| Handle tracking | Manual array | Automatic |
| Code complexity | High | Reduced |
| Risk of bugs | Higher | Lower |
| Maintainability | Hard | Easier |
Real-World Use Case
API Aggregation Service
Imagine you are building a dashboard:
- Weather API
- Payment API
- User data API
With Old Method:
You manually track handles → more code.
With curl_multi_get_handles():
Cleaner and scalable:
foreach (curl_multi_get_handles($mh) as $ch) {
$data[] = json_decode(curl_multi_getcontent($ch), true);
}
Advanced Example: Utility Class (Modern Approach)
class CurlMultiHelper
{
public static function fetch(array $urls): array
{
$mh = curl_multi_init();
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10
]);
curl_multi_add_handle($mh, $ch);
}
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running);
$results = [];
foreach (curl_multi_get_handles($mh) as $ch) {
$results[] = curl_multi_getcontent($ch);
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
return $results;
}
}
Usage
$data = CurlMultiHelper::fetch([
"https://api1.com",
"https://api2.com"
]);
print_r($data);
Benefits of curl_multi_get_handles()
✔ Less boilerplate code
✔ No need for external handle storage
✔ Cleaner loops
✔ Safer resource management
✔ Better readability
Best Practices
- Always use CURLOPT_RETURNTRANSFER
- Set timeout:
CURLOPT_TIMEOUT => 10
- Remove handles after use
- Close all handles
- Handle errors using curl_error()
Future of Async in PHP
With improvements like:
- Object-based handles (CurlHandle)
- Cleaner utilities like curl_multi_get_handles()
PHP is moving toward modern async patterns, similar to:
- ReactPHP
- Amp (PHP library)
curl_multi_get_handles() in PHP 8.5 is a small but powerful improvement.
It simplifies one of the most complex parts of cURL multi-handle programming — managing handles.
For developers working with:
- APIs
- microservices
- scraping tools
This feature makes code:
✔ Cleaner
✔ Safer
✔ Easier to maintain
Frequently Asked Questions
1. What is curl_multi_get_handles() in PHP 8.5?
2. Why was curl_multi_get_handles() introduced?
3. How is curl_multi_get_handles() different from curl_multi_exec()?
4. Is curl_multi_get_handles() backward compatible?
5. What are the benefits of using curl_multi_get_handles()?
- Removes need for manual handle tracking
- Reduces boilerplate code
- Improves readability and maintainability
- Lowers risk of bugs
6. Can I use curl_multi_get_handles() for API integrations?
7. Does curl_multi_get_handles() improve performance?
8. What is the best use case for cURL multi-handle in PHP?
9. What are common issues with cURL multi-handle?
- Complex execution loops
- Manual resource management
- Error handling complexity
- Blocking behavior in some cases
10. What are best practices for using cURL multi-handle?
- Always close handles after use
- Use timeouts to avoid hanging requests
- Use curl_multi_select() to reduce CPU usage
- Wrap logic in reusable utility classes