Avatar ·

Как правильно вызвать REST API на PHP? Простой пример с cURL и обработкой ошибок

Всем привет! Я начинающий PHP-разработчик, и мне нужно вызвать внешний REST API (например, получить данные о погоде или список пользователей). Я прочитал, что для этого используют cURL, но у меня ничего не получается. Вот что я пробую: ```php $url = "https://api.example.com/users"; $ch = curl_init($url); $response = curl_exec($ch); curl_close($ch); echo $response; ``` Но на экране просто пустота, или выводится "false". Если я использую file_get_contents(), то выходит ошибка "failed to open stream". Подскажите, как правильно отправлять GET и POST запросы к REST API? Нужно ли добавлять заголовки (headers), например, для авторизации? Как обрабатывать JSON-ответ и ошибки (если сервер вернул 404 или 500)? Буду благодарен за простой рабочий пример с пояснениями. P.S. Версия PHP 8.1, на локальном сервере OpenServer. cURL вроде включён (extension=curl в php.ini раскомментирован). <<>>

Правильный вызов REST API через cURL в PHP

Ваша проблема в том, что код неполный. curl_exec() возвращает false при ошибке, но вы не проверяете результат. Кроме того, для работы с API нужно настроить опции cURL, особенно CURLOPT_RETURNTRANSFER, чтобы получить ответ в переменную, а не выводить сразу. Вот полный рабочий пример для GET-запроса:

<?php
$url = "https://jsonplaceholder.typicode.com/users";

// 1. Инициализация
$ch = curl_init($url);

// 2. Настройка опций
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,   // вернуть ответ как строку
    CURLOPT_SSL_VERIFYPEER => true,   // проверять SSL (для https)
    CURLOPT_TIMEOUT => 30,            // таймаут в секундах
    CURLOPT_HTTPHEADER => [           // заголовки
        'Accept: application/json',
        'Content-Type: application/json',
        'User-Agent: MyApp/1.0'
    ]
]);

// 3. Выполнение
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // код ответа (200, 404 и т.д.)
$error = curl_error($ch);
curl_close($ch);

// 4. Обработка ошибок
if ($error) {
    die("cURL Error: " . $error);
}

if ($httpCode !== 200) {
    die("HTTP Error: " . $httpCode . " - " . $response);
}

// 5. Декодируем JSON
$data = json_decode($response, true); // true = ассоциативный массив
if (json_last_error() !== JSON_ERROR_NONE) {
    die("JSON parse error: " . json_last_error_msg());
}

// 6. Работаем с данными
print_r($data);
?>

POST-запрос (отправка данных)

Для отправки данных (например, создание нового пользователя) добавьте CURLOPT_POST и CURLOPT_POSTFIELDS:

$postData = [
    'name' => 'John Doe',
    'email' => 'john@example.com'
];

$ch = curl_init("https://jsonplaceholder.typicode.com/users");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($postData), // обязательно кодируем в JSON
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Accept: application/json'
    ]
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 201) { // 201 Created — успешное создание
    $user = json_decode($response, true);
    echo "Создан пользователь ID: " . $user['id'];
} else {
    echo "Ошибка: " . $httpCode;
}

Авторизация (API-ключ или Bearer токен)

Если API требует авторизации, добавьте заголовок Authorization:

$token = "ваш_токен_или_ключ";
$headers = [
    'Authorization: Bearer ' . $token,
    'Accept: application/json'
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

Почему не работает file_get_contents?

  • Включена директива allow_url_fopen (обычно да, но на многих хостингах отключена из соображений безопасности).
  • Нужен контекст для заголовков и метода запроса — это сложнее и менее гибко, чем cURL.
  • cURL — стандарт де-факто для работы с API в PHP.

Проверка включения cURL

Создайте файл info.php с кодом <?php phpinfo(); ?> и найдите секцию curl. Если её нет — проверьте, что в php.ini раскомментирована строка extension=curl и перезапустите сервер.

<<>>

Альтернатива: встроенная обёртка file_get_contents() с контекстом

Если у вас нет возможности установить cURL (например, на общем хостинге), можно использовать file_get_contents() с потоковым контекстом. Это чуть сложнее, но работает без дополнительных расширений:

$url = "https://jsonplaceholder.typicode.com/users";

$options = [
    'http' => [
        'method' => 'GET',
        'header' => implode("\r\n", [
            'Accept: application/json',
            'User-Agent: MyApp/1.0'
        ]),
        'ignore_errors' => true // чтобы получить ответ даже при 404/500
    ],
    'ssl' => [
        'verify_peer' => true,
        'verify_peer_name' => true
    ]
];

$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);

// Получаем HTTP-код из заголовков
$httpLine = $http_response_header[0];
preg_match('/\d{3}/', $httpLine, $matches);
$httpCode = (int)$matches[0];

if ($httpCode !== 200) {
    echo "HTTP Error: $httpCode";
} else {
    $data = json_decode($response, true);
    print_r($data);
}

Минусы этого подхода:

  • Сложнее настраивать POST-запросы (нужно добавлять поле content и длину Content-Length).
  • Меньше контроля над таймаутами и редиректами.
  • Не подходит для больших файлов (загрузка/скачивание).

Поэтому я рекомендую cURL как основной инструмент, а file_get_contents — только как запасной вариант, когда cURL недоступен.