Как в PHP получить тело (body) PUT-запроса с помощью file_get_contents?

«Как в PHP получить тело (body) PUT-запроса с помощью file_get_contents?» — вопрос из категории PHP Core, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В PHP для чтения "сырых" данных тела HTTP-запроса (для методов POST, PUT, PATCH, DELETE) используется поток php://input. Это предпочтительный способ, так как $_POST работает только для данных с content-type application/x-www-form-urlencoded или multipart/form-data.

Базовый пример чтения тела PUT-запроса:

if ($_SERVER['REQUEST_METHOD'] === 'PUT') {
    // Получаем необработанное тело запроса как строку
    $rawInput = file_get_contents('php://input');

    // Далее парсим в зависимости от формата
    // 1. Если ожидается JSON:
    $data = json_decode($rawInput, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        http_response_code(400); // Bad Request
        echo json_encode(['error' => 'Invalid JSON']);
        exit;
    }
    // Теперь $data — ассоциативный массив с данными
    // echo $data['name'];
}

Важные нюансы работы с php://input:

  • Доступен только один раз: Поток php://input не буферизуется. После чтения file_get_contents('php://input') он становится пустым. Если нужно использовать данные несколько раз, сохраните их в переменную.
  • Не работает с multipart/form-data: Для загрузки файлов через PUT (что редкость) стандартно используется POST. php://input не будет содержать загруженные файлы в таком случае.
  • Для больших данных: Используйте чтение чанками, чтобы не загружать всё в память.
    $putData = '';
    $handle = fopen('php://input', 'r');
    while (!feof($handle)) {
        $putData .= fread($handle, 8192);
    }
    fclose($handle);
  • Определение типа контента: Всегда проверяйте заголовок Content-Type ($_SERVER['CONTENT_TYPE']), чтобы понять, как парсить данные (JSON, XML, plain text).

Альтернативный подход с parse_str (для form-encoded данных):

if ($_SERVER['REQUEST_METHOD'] === 'PUT') {
    $input = file_get_contents('php://input');
    parse_str($input, $parsedData); // Преобразует строку 'name=John&age=30' в массив
    // $parsedData['name'] будет 'John'
}