Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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

OptionWhat it does
CURLOPT_RETURNTRANSFERReturn the response as a string
CURLOPT_TIMEOUTThe longest request time in seconds
CURLOPT_HTTPHEADERRequest headers
CURLOPT_POST, CURLOPT_POSTFIELDSThe POST method and its data
CURLOPT_CUSTOMREQUESTAnother method: PUT, DELETE
CURLOPT_FOLLOWLOCATIONFollow 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.

Thanks for reading!

Donate to the site — we work hard for you.