Skip to content

Instantly share code, notes, and snippets.

@vyspiansky
Last active March 18, 2025 12:12
Show Gist options
  • Save vyspiansky/b9ec4e259cb1f4522dbdcdbf37ba5109 to your computer and use it in GitHub Desktop.
Save vyspiansky/b9ec4e259cb1f4522dbdcdbf37ba5109 to your computer and use it in GitHub Desktop.
Concurrent HTTP requests in PHP 8.1+

cURL Multi

Native cURL multi-handle API for parallel requests.

Using separate cURL requests

<?php
// File: separate_curl_requests.php

function makeRequest($url) {
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($curl);
    curl_close($curl);
    
    return $response;
}

$timeStart = microtime(true);

$response1 = makeRequest('https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b1b15e88fa797225412429c1c50c122a1');

$response2 = makeRequest('https://v2.jokeapi.dev/joke/Any?type=single');

echo 'Total execution time: '. (microtime(true) - $timeStart) . " secs\n";

Using cURL Multi Handle

<?php
// File: curl_multi_handle.php

function makeRequests($urls) {
    $multiHandle = curl_multi_init();
    $curlHandles = [];

    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);
    } while ($running > 0);

    $results = [];
    foreach ($curlHandles as $ch) {
        $results[] = curl_multi_getcontent($ch);
        curl_multi_remove_handle($multiHandle, $ch);
    }

    curl_multi_close($multiHandle);

    return $results;
}

$timeStart = microtime(true);

// Define API endpoints
$urls = [
    'https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b1b15e88fa797225412429c1c50c122a1',
    'https://v2.jokeapi.dev/joke/Any?type=single'
];

$responses = makeRequests($urls);

echo 'Total execution time: '. (microtime(true) - $timeStart) . " secs\n";

Total execution time

Separate cURL requests output:

0.37845802307129 secs
0.29587197303772 secs
0.30531406402588 secs

cURL Multi Handle output:

0.13005685806274 secs
0.14811396598816 secs
0.15142297744751 secs

Guzzle HTTP client

This HTTP client supports async requests.

Separate requests

<?php
// File: guzzle_separate_requests.php

require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Promise;

$client = new Client();

$timeStart = microtime(true);

$response1 = $client->get('https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b1b15e88fa797225412429c1c50c122a1');

$response2 = $client->get('https://v2.jokeapi.dev/joke/Any?type=single');

echo 'Total execution time: '. (microtime(true) - $timeStart) . " secs\n";

Concurrent requests

<?php
// File: guzzle_concurrent_requests.php

require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Promise;

$client = new Client();

$timeStart = microtime(true);

$promises = [
    'openweathermap' => $client->getAsync('https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b1b15e88fa797225412429c1c50c122a1'),
    'jokeapi' => $client->getAsync('https://v2.jokeapi.dev/joke/Any?type=single'),
];

$results = Promise\Utils::unwrap($promises);

echo 'Total execution time: '. (microtime(true) - $timeStart) . " secs\n";

Total execution time

Separate requests output:

0.28913497924805 secs
0.29575800895691 secs
0.34573984146118 secs

Concurrent requests output:

0.14498805999756 secs
0.16652989387512 secs
0.13500905036926 secs

Amp

A coroutine-based concurrency library...

ReactPHP

An event-driven, non-blocking I/O library...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment