Запросы к другим сайтам
Курс валют, прогноз погоды, оплата, доставка — эти данные лежат на чужих серверах. Чтобы получить их, программа сама отправляет запрос 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 и решайте заранее, что показать, если сервис не ответил: сохранённое значение, заглушку или понятное сообщение.