← Назад к вопросам

Откуда получается тело PUT запроса с помощью file_get_contents?

1.0 Junior🔥 141 комментариев
#API и веб-протоколы#PHP Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Отличный вопрос, который затрагивает ключевые аспекты работы с HTTP-запросами в PHP. Короткий ответ: тело (body) PUT-запроса получается из входного потока php://input, а file_get_contents('php://input') — это один из способов его чтения. Давайте разберем это подробно.

Основной механизм: php://input

В отличие от данных POST-запроса, которые часто автоматически парсятся в суперглобальные массивы $_POST и $_FILES (при использовании enctype="multipart/form-data"), тело HTTP-запросов других типов (PUT, PATCH, DELETE) не обрабатывается PHP автоматически. Оно доступно через специальный поток php://input.

php://input — это поток только для чтения, который позволяет получить "сырое" (raw) тело HTTP-запроса.

// Получение тела PUT-запроса
$putData = file_get_contents('php://input');

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

  • Это поток (stream), а не файл на диске.
  • Доступен только один раз для чтения (после чтения он "опустошается").
  • Недоступен для запросов с типом контента multipart/form-data (обычные HTML-формы с файлами). В этом случае нужно использовать другие методы.
  • Содержит именно тело запроса, заголовки (headers) доступны отдельно через getallheaders() или $_SERVER.

Практический пример обработки PUT-запроса

Наивная реализация для получения, например, JSON-данных из PUT-запроса выглядит так:

<?php
// Проверяем метод запроса
if ($_SERVER['REQUEST_METHOD'] === 'PUT') {
    // Читаем сырое тело запроса
    $rawInput = file_get_contents('php://input');

    // Пытаемся декодировать JSON (если ожидаем 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 json_encode(['success' => true, 'received' => $data]);
} else {
    http_response_code(405); // Method Not Allowed
}
?>

Альтернативы и лучшие практики

1. Использование fopen() с потоком

Для больших объемов данных, где нежелательно загружать всё в память сразу, можно читать поток частями:

$handle = fopen('php://input', 'r');
while (!feof($handle)) {
    $chunk = fread($handle, 8192); // Чтение по 8 КБ
    // Обработка чанка
}
fclose($handle);

2. Современные фреймворки и PSR-7

В реальных проектах (Symfony, Laravel, Slim и др.) используется абстракция PSR-7 (HTTP Message Interface). Тело запроса там представлено объектом, реализующим интерфейс Psr\Http\Message\StreamInterface. Работа с ним гораздо удобнее и безопаснее.

Пример в Slim Framework:

$app->put('/resource/{id}', function (Request $request, Response $response, $args) {
    // Фреймворк уже прочитал поток и предоставляет методы
    $body = $request->getBody(); // Возвращает Psr\Http\Message\StreamInterface
    $data = json_decode($body->getContents(), true);

    // Или сразу получение парсированного тела
    $data = $request->getParsedBody();

    // ... обработка
    return $response;
});

3. Массив $HTTP_RAW_POST_DATA (устаревший)

В старых версиях PHP (< 5.6) тело запроса также могло попадать в переменную $HTTP_RAW_POST_DATA, если в конфигурации php.ini была включена директива always_populate_raw_post_data. С PHP 7.0 эта переменная удалена, использовать её нельзя.

Ключевые моменты для запоминания:

  • Источник данных: Тело PUT, PATCH, DELETE и "сырых" POST-запросов хранится в потоке php://input.
  • Функция чтения: file_get_contents('php://input') — простейший способ получить всё тело как строку.
  • Одноразовость: Поток php://input можно прочитать только один раз за время выполнения скрипта. Если нужно использовать данные несколько раз, сохраните их в переменную.
  • Мультипарт-формы: Для данных с Content-Type: multipart/form-data (загрузка файлов) php://input не работает. PUT-запросы редко используют этот тип, но если необходимо, придется парсить вручную или использовать фреймворк.
  • Контекст POST: Для обычных POST-запросов с application/x-www-form-urlencoded данные удобнее брать из $_POST. Использование php://input для них оправдано, только если нужны "сырые" данные до парсинга.

Таким образом, ответ на ваш вопрос лежит в понимании архитектуры ввода-вывода PHP: file_get_contents('php://input') читает данные из специального, одноразового входного потока, в который PHP помещает тело HTTP-запроса, когда оно не обрабатывается автоматически. В современной разработке эта низкоуровневая операция обычно скрыта за абстракциями фреймворков, соответствующих стандарту PSR-7.

Откуда получается тело PUT запроса с помощью file_get_contents? | PrepBro