Извлечение параметров запросов средствами PHP
Получение данных в PHP: обзор методов
Наиболее универсальный способ: чтение из php://input
Для получения тела HTTP запроса в виде необработанной строки используется поток php://input. Этот метод работает для любого HTTP метода (GET, POST, PUT, DELETE, PATCH) и любого Content-Type. Данные затем разбираются в зависимости от формата.
Цель: получение данных в чистом виде, когда требуется гибкость или когда Content-Type отличен от application/x-www-form-urlencoded или multipart/form-data (например, JSON, XML). Случаи использования: REST API, вебхуки, работа с AJAX запросами, отправляющими JSON.
$rawInput = file_get_contents('php://input');
// Определяем Content-Type
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
if (stripos($contentType, 'application/json') !== false) {
$data = json_decode($rawInput, true);
if (json_last_error() !== JSON_ERROR_NONE) {
// ошибка декодирования
$data = null;
}
} else {
// попытка разобрать как строку запроса
parse_str($rawInput, $data);
}
Пояснение: file_get_contents читает весь поток. Content-Type берется из заголовка. Если данные пришли как JSON, декодируем ассоциативный массив. Иначе парсим строку запроса. Важно: multipart/form-data не передается через php://input, эту часть обрабатывает PHP автоматически в $_POST и $_FILES.
Типичные ошибки: забывают проверить Content-Type, получают null при ошибочном JSON. readfile или другие функции не подходят. При multipart/form-data php://input пуст. Решение: для файлов использовать $_FILES, а для полей формы - $_POST.
Как получить параметры из строки запроса (GET)?
Суперглобальный массив $_GET содержит параметры, переданные в URL после знака вопроса. Цель: простой сбор данных из URL для отображения страниц, поиска, фильтров. Случаи: ссылки, формы с method GET.
$name = $_GET['name'] ?? null;
$page = intval($_GET['page'] ?? 1);
Ошибки: не проверено существование ключа - Warning. Решение: null coalescing operator (??). Параметры могут содержать специальные символы - PHP автоматически декодирует. Для массивов используется name[] - тогда $_GET['name'] будет массивом.
Как получить данные из POST запроса?
Массив $_POST заполняется для запросов с Method POST и Content-Type application/x-www-form-urlencoded или multipart/form-data. Цель: традиционная отправка форм, файлы - через $_FILES.
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
Ошибки: если Content-Type не указан или JSON, $_POST пуст. Для JSON используйте php://input. При multipart/form-data поля формы доступны в $_POST.
Как объединить GET и POST в один массив?
$_REQUEST содержит элементы из $_GET, $_POST и $_COOKIE (порядок зависит от конфигурации). Удобен для быстрой разработки, но не рекомендуется из-за смешения источников и безопасности.
$action = $_REQUEST['action'] ?? 'default';
Ошибки: параметр может быть переопределен (например, cookie с тем же именем). Лучше явно указывать источник.
Как получить данные PUT или DELETE запроса?
PHP не заполняет $_POST для этих методов. Используйте php://input и при необходимости разбирайте через parse_str для application/x-www-form-urlencoded.
$input = file_get_contents('php://input');
parse_str($input, $data);
$id = $data['id'] ?? null;
Ошибки: не проверен Content-Type - если данные в JSON, parse_str даст неверный результат. Решение: определять тип и декодировать соответственно.
Как получить загруженные файлы?
Массив $_FILES содержит информацию о файлах, отправленных через multipart/form-data. Каждый файл - массив с ключами name, type, tmp_name, error, size.
if ($_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
$tmpPath = $_FILES['avatar']['tmp_name'];
move_uploaded_file($tmpPath, 'uploads/' . basename($_FILES['avatar']['name']));
}
Ошибки: ошибка загрузки 0 - успех, 1 - превышение размера, 4 - файл не выбран. Нужно проверять error. Никогда не доверяйте имени файла (basename, проверка расширения).
Как получить JSON данные из запроса?
Для AJAX запросов, отправляющих JSON, используйте php://input и json_decode. Content-Type должен быть application/json.
$json = file_get_contents('php://input');
$data = json_decode($json, true);
if (json_last_error() === JSON_ERROR_NONE) {
// работа с данными
}
Ошибки: невалидный JSON - json_last_error() вернет код ошибки. Стоит логировать. Пустой ввод - file_get_contents вернет false.
Расширенные примеры получения данных
1. Обработка входящего JSON с проверкой и логированием
function getJsonInput(): ?array
{
$raw = file_get_contents('php://input');
if ($raw === false || $raw === '') {
return null;
}
$data = json_decode($raw, true);
if (json_last_error() !== JSON_ERROR_NONE) {
error_log('Invalid JSON: ' . json_last_error_msg());
return null;
}
return $data;
}
$input = getJsonInput();
if ($input !== null) {
// обработка
}
// При отправке {"name":"test"} функция вернет ['name'=>'test']
// При невалидном JSON - null и запись в лог
2. Получение данных из PUT запроса с multipart/form-data (редкий случай)
По умолчанию PHP не заполняет $_FILES для PUT. Необходимо вручную разобрать multipart-поток. Пример упрощенный (без полной реализации):
$raw = file_get_contents('php://input');
$boundary = substr($_SERVER['CONTENT_TYPE'], strpos($_SERVER['CONTENT_TYPE'], 'boundary=') + 9);
// Далее парсинг multipart (требуется сторонняя библиотека или ручной парсинг)
// Альтернатива: изменить метод на POST и использовать стандартный механизм.
3. Обработка данных в формате application/x-www-form-urlencoded для PUT
$raw = file_get_contents('php://input');
$query = [];
parse_str($raw, $query);
// $query теперь содержит ассоциативный массив, как $_POST
print_r($query);
// При отправке name=John&age=30 выведет: // Array ( [name] => John [age] => 30 )
4. Использование superglobals с учетом безопасности
function getSanitizedGet(string $key, $default = null) {
return isset($_GET[$key]) ? htmlspecialchars($_GET[$key], ENT_QUOTES, 'UTF-8') : $default;
}
$search = getSanitizedGet('q', '');
echo 'Вы искали: ' . $search;
// При ?q= выведет:
// Вы искали: <script>alert('xss')</script>
5. Комбинированное получение: GET + POST + JSON в одном обработчике
$method = $_SERVER['REQUEST_METHOD'];
$data = [];
switch ($method) {
case 'GET':
$data = $_GET;
break;
case 'POST':
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
if (stripos($contentType, 'application/json') !== false) {
$raw = file_get_contents('php://input');
$data = json_decode($raw, true) ?? [];
} else {
$data = $_POST;
}
break;
case 'PUT':
case 'DELETE':
case 'PATCH':
$raw = file_get_contents('php://input');
if (stripos($_SERVER['CONTENT_TYPE'] ?? '', 'application/json') !== false) {
$data = json_decode($raw, true) ?? [];
} else {
parse_str($raw, $data);
}
break;
}
// $data содержит входные параметры
6. Обработка массивов в GET и POST
// URL: ?ids[]=1&ids[]=2&names[0]=John&names[1]=Jane
$ids = $_GET['ids'] ?? []; // ['1','2']
$names = $_GET['names'] ?? []; // ['John','Jane']
foreach ($ids as $id) {
echo $id . "\n";
}
1 2
7. Получение необработанного тела запроса с использованием stream_get_contents
$handle = fopen('php://input', 'r');
$raw = stream_get_contents($handle);
fclose($handle);
// альтернатива file_get_contents, позволяет читать частями