Calling other sites
Exchange rates, a weather forecast, payments, delivery — this data lives on other people's servers. To get it, a program sends an HTTP request itself and parses the response, most often JSON.
The examples use the network and do not run here — run them on your machine.
A simple request
For a GET request file_get_contents() is enough: it accepts not only a file path but an address too:
<?php
// rates.php
$json = file_get_contents('https://api.example.com/rates');
$data = json_decode($json, true);
echo $data['rates']['EUR'];This suits simple cases. For headers, sending data and inspecting errors use cURL.
cURL
A cURL request has four steps: create, configure, execute, read the result:
<?php
// rates.php
$curl = curl_init('https://api.example.com/rates');
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
]);
$body = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
echo $status, "\n";
echo $body;CURLOPT_RETURNTRANSFER makes curl_exec() return the response as a string instead of printing it at once. CURLOPT_TIMEOUT limits the wait to five seconds.
Common options
| Option | What it does |
|---|---|
CURLOPT_RETURNTRANSFER | Return the response as a string |
CURLOPT_TIMEOUT | The longest request time in seconds |
CURLOPT_HTTPHEADER | Request headers |
CURLOPT_POST, CURLOPT_POSTFIELDS | The POST method and its data |
CURLOPT_CUSTOMREQUEST | Another method: PUT, DELETE |
CURLOPT_FOLLOWLOCATION | Follow redirects |
Sending JSON
<?php
// create-order.php
$payload = json_encode(['product_id' => 42, 'quantity' => 2]);
$curl = curl_init('https://api.example.com/orders');
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . getenv('API_TOKEN'),
],
]);
$order = json_decode(curl_exec($curl), true);
echo $order['id'];The access key comes from an environment variable instead of being written in the code.
Handling errors
A failure comes in two kinds: the request did not get through, or the service answered with an error. Both must be checked:
<?php
// api.php
function apiGet(string $url): array
{
$curl = curl_init($url);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
]);
$body = curl_exec($curl);
if ($body === false) {
throw new RuntimeException('Service unavailable: ' . curl_error($curl));
}
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($status >= 400) {
throw new RuntimeException("The service answered with code $status");
}
return json_decode($body, true, flags: JSON_THROW_ON_ERROR);
}The function either returns an array or throws an exception — the calling code does not have to guess what arrived.
Ready-made libraries
Large projects use a library instead of bare cURL — Guzzle or Symfony HttpClient. They are installed through Composer and do the same thing more briefly:
<?php
// guzzle.php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client(['timeout' => 5]);
$response = $client->get('https://api.example.com/rates');
$data = json_decode($response->getBody(), true);Common mistake
Without a time limit, a request to a hung service keeps your page open for tens of seconds, and under a rush of visitors stops the whole site. Always set CURLOPT_TIMEOUT and decide in advance what to show when the service does not answer: a saved value, a placeholder or a clear message.