Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Запросы к другим сайтам

Курс валют, прогноз погоды, оплата, доставка — эти данные лежат на чужих серверах. Чтобы получить их, программа сама отправляет запрос HTTP и разбирает ответ, чаще всего в формате JSON.

Примеры обращаются к сети и здесь не запускаются — выполните их у себя.

Простой запрос

Для запроса GET хватит функции file_get_contents(): она принимает не только путь к файлу, но и адрес:

<?php
// rates.php
 
$json = file_get_contents('https://api.example.com/rates');
$data = json_decode($json, true);
 
echo $data['rates']['EUR'];

Способ годится для простых случаев. Для заголовков, отправки данных и разбора ошибок используют cURL.

cURL

Запрос cURL состоит из четырёх шагов: создать, настроить, выполнить, прочитать результат:

<?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 заставляет curl_exec() вернуть ответ строкой, а не вывести его сразу. CURLOPT_TIMEOUT ограничивает ожидание пятью секундами.

Частые настройки

НастройкаЧто делает
CURLOPT_RETURNTRANSFERВернуть ответ строкой
CURLOPT_TIMEOUTНаибольшее время запроса в секундах
CURLOPT_HTTPHEADERЗаголовки запроса
CURLOPT_POST, CURLOPT_POSTFIELDSМетод POST и его данные
CURLOPT_CUSTOMREQUESTДругой метод: PUT, DELETE
CURLOPT_FOLLOWLOCATIONСледовать перенаправлениям

Отправка 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'];

Ключ доступа берут из переменной окружения, а не пишут в коде.

Обработка ошибок

Сбой бывает двух видов: запрос не дошёл или сервис ответил ошибкой. Проверять нужно оба:

<?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('Сервис недоступен: ' . curl_error($curl));
    }
 
    $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
 
    if ($status >= 400) {
        throw new RuntimeException("Сервис ответил кодом $status");
    }
 
    return json_decode($body, true, flags: JSON_THROW_ON_ERROR);
}

Функция либо возвращает массив, либо бросает исключение — вызывающему коду не нужно гадать, что пришло.

Готовые библиотеки

В больших проектах вместо «голого» cURL берут библиотеку — Guzzle или Symfony HttpClient. Они устанавливаются через Composer и делают то же самое короче:

<?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);

Частая ошибка

Без ограничения времени запрос к «зависшему» сервису держит вашу страницу открытой десятки секунд, а при наплыве посетителей останавливает весь сайт. Всегда задавайте CURLOPT_TIMEOUT и решайте заранее, что показать, если сервис не ответил: сохранённое значение, заглушку или понятное сообщение.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.