Avatar ·

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

Всем привет! Я новичок в PHP и пытаюсь разобраться с отправкой POST-запросов через cURL. У меня есть простой скрипт, который должен отправлять данные на внешний API, но я постоянно получаю ошибки или пустой ответ. Вот мой текущий код: ```php 'Иван', 'email' => 'ivan@example.com' ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` Проблема в том, что: 1. Иногда приходит пустой ответ 2. Нет обработки ошибок — если запрос не удался, я об этом не узнаю 3. Не понимаю, как правильно передавать JSON вместо обычных данных 4. На некоторых серверах запрос просто зависает Я перепробовал разные варианты, но везде примеры либо слишком простые, либо слишком сложные для моего уровня. Можете показать рабочий пример с нормальной обработкой ошибок и пояснить, что делает каждая строчка? Особенно интересует, как правильно настроить таймауты и заголовки. <<>>

Полный рабочий пример POST-запроса через cURL с обработкой ошибок

Вот правильный и надёжный способ отправки POST-запроса через cURL в PHP. Я разберу каждую часть кода.

<?php
function sendPostRequest($url, $data, $useJson = false) {
    // Инициализируем сессию cURL
    $ch = curl_init();
    
    // Базовые настройки
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,                    // URL назначения
        CURLOPT_POST => true,                    // Метод POST
        CURLOPT_RETURNTRANSFER => true,          // Возвращать ответ как строку
        CURLOPT_TIMEOUT => 30,                   // Таймаут выполнения (сек)
        CURLOPT_CONNECTTIMEOUT => 10,            // Таймаут соединения (сек)
        CURLOPT_FOLLOWLOCATION => true,          // Следовать редиректам
        CURLOPT_MAXREDIRS => 5,                  // Максимум редиректов
        CURLOPT_SSL_VERIFYPEER => true,          // Проверять SSL сертификат
        CURLOPT_SSL_VERIFYHOST => 2,             // Проверять имя хоста
    ]);
    
    // Подготовка данных
    if ($useJson) {
        // Если нужно отправить JSON
        $jsonData = json_encode($data, JSON_UNESCAPED_UNICODE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($jsonData)
        ]);
    } else {
        // Обычная POST-форма (application/x-www-form-urlencoded)
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    }
    
    // Выполняем запрос
    $response = curl_exec($ch);
    
    // Проверяем на ошибки
    $error = '';
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
    if (curl_errno($ch)) {
        $error = 'cURL Error: ' . curl_error($ch);
    } elseif ($httpCode >= 400) {
        $error = "HTTP Error: {$httpCode}. Response: " . substr($response, 0, 200);
    }
    
    // Закрываем сессию
    curl_close($ch);
    
    // Возвращаем результат
    return [
        'success' => empty($error),
        'http_code' => $httpCode,
        'data' => $response,
        'error' => $error
    ];
}

// Пример использования для обычных POST-данных
$result = sendPostRequest('https://api.example.com/submit', [
    'name' => 'Иван',
    'email' => 'ivan@example.com'
]);

// Пример для JSON
$resultJson = sendPostRequest('https://api.example.com/json-endpoint', [
    'user' => ['name' => 'Иван', 'role' => 'admin']
], true);

// Обработка результата
if ($result['success']) {
    echo "Успешно! Код: {$result['http_code']}<br>";
    echo "Ответ: " . htmlspecialchars($result['data']);
} else {
    echo "Ошибка: {$result['error']}";
}
?>

Объяснение ключевых моментов:

  • CURLOPT_RETURNTRANSFER = true — обязательно! Без этого curl_exec() выводит ответ сразу в браузер, а не возвращает его в переменную.
  • http_build_query() — правильно кодирует массив для передачи как form-data. Без этого могут быть проблемы с кириллицей и спецсимволами.
  • Таймауты — CURLOPT_TIMEOUT и CURLOPT_CONNECTTIMEOUT спасут от зависания скрипта, если сервер не отвечает.
  • Проверка ошибок — curl_errno() ловит технические ошибки (нет соединения, таймаут), а HTTP-код >= 400 — ошибки сервера.
  • SSL проверка — отключать CURLOPT_SSL_VERIFYPEER крайне не рекомендуется в production, это уязвимость.

Дополнительные полезные настройки:

// Если нужно отправить файл
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    'file' => new CURLFile('/path/to/file.pdf', 'application/pdf', 'document.pdf')
]);

// Если нужно отправить сырые данные
curl_setopt($ch, CURLOPT_POSTFIELDS, 'raw_data_here');

// Если нужно добавить кастомные заголовки
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer token123',
    'X-Custom-Header: value'
]);

Этот код надёжно работает с любыми API и обрабатывает все типичные ошибки. Сохраните его как вспомогательную функцию в вашем проекте.

<<>>

Альтернативный подход: использование библиотеки Guzzle

Если вы часто работаете с HTTP-запросами, рекомендую перейти на Guzzle — это современная PHP-библиотека, которая делает код чище и безопаснее.

// Установка: composer require guzzlehttp/guzzle

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

$client = new Client([
    'timeout' => 30,
    'verify' => true  // SSL проверка
]);

try {
    // Обычный POST
    $response = $client->post('https://api.example.com/submit', [
        'form_params' => [
            'name' => 'Иван',
            'email' => 'ivan@example.com'
        ]
    ]);
    
    // Или JSON
    $response = $client->post('https://api.example.com/json', [
        'json' => [
            'user' => ['name' => 'Иван']
        ],
        'headers' => [
            'Authorization' => 'Bearer token123'
        ]
    ]);
    
    echo $response->getBody();
    echo "HTTP код: " . $response->getStatusCode();
    
} catch (RequestException $e) {
    echo "Ошибка: " . $e->getMessage();
    if ($e->hasResponse()) {
        echo "Ответ сервера: " . $e->getResponse()->getBody();
    }
}

Преимущества Guzzle:

  • Автоматическая обработка JSON (сериализация/десериализация)
  • Понятные исключения вместо ручной проверки ошибок
  • Поддержка асинхронных запросов
  • Автоматическое управление соединениями (keep-alive)
  • Лучшая безопасность (защита от SSRF, правильная валидация URL)

Guzzle — это стандарт де-факто для HTTP-запросов в современном PHP. Он используется в Laravel, Symfony и большинстве фреймворков.