Avatar ·

Как конвертировать запрос из Postman в PHP cURL код: полное руководство

Всем привет! Я начинающий PHP разработчик, и у меня возникла проблема. Я использую Postman для тестирования API, и там всё работает отлично. Но когда я пытаюсь перенести этот же запрос в свой PHP код с помощью cURL, у меня ничего не получается. Вот мой запрос в Postman: - Метод: POST - URL: https://api.example.com/v1/users - Headers: Content-Type: application/json, Authorization: Bearer my_token_123 - Body (raw JSON): {"name": "Иван", "email": "ivan@example.com"} Я нажимаю в Postman кнопку "Code" и выбираю "PHP - cURL". Мне выдаётся такой код: ```php 'https://api.example.com/v1/users', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS =>'{"name": "Иван", "email": "ivan@example.com"}', CURLOPT_HTTPHEADER => array( 'Content-Type: application/json', 'Authorization: Bearer my_token_123' ), )); $response = curl_exec($curl); curl_close($curl); echo $response; ?> ``` Но когда я запускаю этот код, сервер возвращает ошибку 400 Bad Request. Я проверил все заголовки, URL и тело запроса — вроде бы всё совпадает с Postman. В чём может быть проблема? Может быть, я неправильно использую cURL? Или есть какой-то подвох с кодировкой JSON? Буду благодарен за подробное объяснение, как правильно конвертировать Postman запросы в PHP cURL, и что я делаю не так. <<>>

Почему ваш код не работает и как это исправить

Проблема, с которой вы столкнулись, очень распространена среди разработчиков, переносящих запросы из Postman в PHP. Дело в том, что сгенерированный Postman код часто содержит избыточные опции, которые могут мешать корректной работе. Давайте разберёмся по шагам.

Основные причины ошибки

  • Избыточные опции cURL: CURLOPT_ENCODING, CURLOPT_MAXREDIRS, CURLOPT_FOLLOWLOCATION и CURLOPT_HTTP_VERSION часто не нужны для простых POST-запросов и могут вызывать неожиданное поведение.
  • Проблемы с JSON: В вашем коде JSON передаётся как строка, но если в данных есть специальные символы или кириллица, могут возникнуть проблемы с кодировкой.
  • Отсутствие обработки ошибок: Вы не проверяете, выполнился ли запрос успешно, и не выводите информацию об ошибках cURL.

Правильный минимальный код для POST-запроса с JSON

<?php
// Данные для отправки
$data = [
    'name' => 'Иван',
    'email' => 'ivan@example.com'
];

// Инициализация cURL
$ch = curl_init('https://api.example.com/v1/users');

// Настройка опций
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,  // Возвращать ответ как строку
    CURLOPT_POST => true,            // Метод POST
    CURLOPT_POSTFIELDS => json_encode($data, JSON_UNESCAPED_UNICODE), // Тело запроса
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer my_token_123'
    ],
    CURLOPT_TIMEOUT => 30,           // Таймаут в секундах
]);

// Выполнение запроса
$response = curl_exec($ch);

// Проверка на ошибки
if (curl_errno($ch)) {
    echo 'Ошибка cURL: ' . curl_error($ch);
} else {
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    echo "HTTP код: $httpCode\n";
    echo "Ответ сервера:\n$response";
}

// Закрытие соединения
curl_close($ch);
?>

Ключевые изменения и объяснения

  • Используйте json_encode(): Всегда преобразуйте массив PHP в JSON с помощью json_encode(). Это гарантирует правильное форматирование и кодировку. Флаг JSON_UNESCAPED_UNICODE сохраняет кириллицу в читаемом виде.
  • Явно указывайте метод POST: CURLOPT_POST => true — это более надёжный способ, чем CURLOPT_CUSTOMREQUEST.
  • Убирайте лишние опции: CURLOPT_ENCODING, CURLOPT_MAXREDIRS, CURLOPT_FOLLOWLOCATION не нужны для простого POST-запроса. Они могут мешать.
  • Добавьте обработку ошибок: curl_errno() и curl_error() покажут, что пошло не так. curl_getinfo() с CURLINFO_HTTP_CODE даст HTTP-статус ответа.

Как правильно конвертировать запрос из Postman

  1. В Postman нажмите "Code" (обычно справа, под кнопкой Send).
  2. Выберите "PHP - cURL" как язык.
  3. Не копируйте код blindly. Возьмите только URL, метод, заголовки и тело запроса.
  4. Перепишите запрос вручную, используя минимальный набор опций, как показано выше.
  5. Для GET-запросов используйте CURLOPT_URL с параметрами в строке запроса и уберите CURLOPT_POST.
  6. Для запросов с form-data используйте CURLOPT_POSTFIELDS с массивом (не JSON) и заголовок Content-Type: multipart/form-data.

Этот подход гарантирует, что ваш PHP-код будет работать так же, как запрос в Postman. Помните: Postman генерирует "универсальный" код, который часто избыточен. Лучше писать минимальный и понятный код самостоятельно.

<<>>

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

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

Пример с Guzzle

composer require guzzlehttp/guzzle
<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client([
    'base_uri' => 'https://api.example.com',
    'timeout'  => 30,
]);

try {
    $response = $client->post('/v1/users', [
        'headers' => [
            'Authorization' => 'Bearer my_token_123',
        ],
        'json' => [
            'name' => 'Иван',
            'email' => 'ivan@example.com'
        ],
    ]);

    $body = $response->getBody()->getContents();
    $statusCode = $response->getStatusCode();
    
    echo "HTTP код: $statusCode\n";
    echo "Ответ: $body";
    
} catch (\Exception $e) {
    echo 'Ошибка: ' . $e->getMessage();
}
?>

Почему Guzzle лучше?

  • Автоматическая сериализация JSON: Опция 'json' сама преобразует массив в JSON и устанавливает правильный заголовок.
  • Чистый и читаемый код: Нет десятков CURLOPT_* констант.
  • Обработка ошибок через исключения: Легко отлавливать и обрабатывать ошибки HTTP.
  • Поддержка PSR-18: Совместимость с другими библиотеками.

Guzzle идеально подходит для проектов, где используется Composer. Если ваш проект без фреймворка и вы не хотите подключать библиотеки, используйте нативный cURL из первого ответа.