Как определить тип HTTP-запроса (GET, POST, PUT, DELETE) в PHP?
Правильный способ определения HTTP-метода в PHP
Для надёжного определения типа запроса используйте суперглобальный массив $_SERVER['REQUEST_METHOD']. Он всегда содержит реальный HTTP-метод, переданный клиентом, в отличие от проверок $_POST или $_GET, которые зависят от наличия данных.
<?php
// Получаем метод запроса
$method = $_SERVER['REQUEST_METHOD'];
// Обрабатываем каждый метод
switch ($method) {
case 'GET':
// Обработка GET-запроса
$data = $_GET;
echo "Получен GET-запрос с параметрами: " . print_r($data, true);
break;
case 'POST':
// Обработка POST-запроса
$data = $_POST;
echo "Получен POST-запрос с данными: " . print_r($data, true);
break;
case 'PUT':
// Обработка PUT-запроса
$input = file_get_contents('php://input');
parse_str($input, $data);
echo "Получен PUT-запрос с данными: " . print_r($data, true);
break;
case 'DELETE':
// Обработка DELETE-запроса
$input = file_get_contents('php://input');
parse_str($input, $data);
echo "Получен DELETE-запрос с данными: " . print_r($data, true);
break;
default:
// Неподдерживаемый метод
http_response_code(405);
echo "Метод $method не поддерживается";
break;
}
?>
Ключевые моменты
- $_SERVER['REQUEST_METHOD'] — единственный надёжный способ определить метод. Он возвращает строку: 'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS' и т.д.
- Проблема с PUT и DELETE: PHP не заполняет
$_POSTдля этих методов. Данные нужно читать из потокаphp://inputс помощьюfile_get_contents(). - Парсинг данных: Для PUT и DELETE используйте
parse_str(), чтобы преобразовать строку запроса в массив, аналогичный$_POST. - JSON-данные: Если API принимает JSON (например, Content-Type: application/json), обрабатывайте так:
case 'PUT':
$input = file_get_contents('php://input');
$data = json_decode($input, true); // true — как ассоциативный массив
if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400);
echo "Некорректный JSON";
exit;
}
echo "Получен PUT-запрос с JSON: " . print_r($data, true);
break;
Полный пример REST-роутера
<?php
// Определяем метод
$method = $_SERVER['REQUEST_METHOD'];
// Определяем путь (например, /api/users/123)
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$pathParts = explode('/', trim($path, '/'));
// Получаем данные запроса
$data = [];
switch ($method) {
case 'GET':
$data = $_GET;
break;
case 'POST':
$data = $_POST;
break;
case 'PUT':
case 'DELETE':
case 'PATCH':
$input = file_get_contents('php://input');
// Определяем формат данных
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
if (strpos($contentType, 'application/json') !== false) {
$data = json_decode($input, true);
} else {
parse_str($input, $data);
}
break;
}
// Пример маршрутизации
if ($path === '/api/users' && $method === 'GET') {
// Получить всех пользователей
} elseif ($path === '/api/users' && $method === 'POST') {
// Создать пользователя
} elseif (preg_match('#^/api/users/(\d+)$#', $path, $matches) && $method === 'GET') {
// Получить пользователя по ID: $matches[1]
} elseif (preg_match('#^/api/users/(\d+)$#', $path, $matches) && $method === 'PUT') {
// Обновить пользователя с ID: $matches[1]
} elseif (preg_match('#^/api/users/(\d+)$#', $path, $matches) && $method === 'DELETE') {
// Удалить пользователя с ID: $matches[1]
} else {
http_response_code(404);
echo "Маршрут не найден";
}
?>
Дополнительные советы
- Всегда проверяйте метод в начале скрипта — это повышает безопасность.
- Для сложных API используйте готовые микрофреймворки: Slim, Laravel (через routes), Symfony.
- Не забывайте про
http_response_code()для правильных HTTP-статусов. - При работе с формами HTML (которые поддерживают только GET и POST) можно эмулировать PUT/DELETE через скрытое поле
_method:
<form method="POST" action="/users/123">
<input type="hidden" name="_method" value="PUT">
<!-- остальные поля -->
</form>
// В PHP:
if ($_POST['_method'] ?? null) {
$method = strtoupper($_POST['_method']);
}
Этот подход часто используется в фреймворках для обратной совместимости с HTML-формами.
<<Альтернативный подход с использованием фильтрации и безопасности
Если вы пишете небольшое приложение и хотите добавить дополнительную защиту, можно использовать комбинацию $_SERVER['REQUEST_METHOD'] с проверкой на разрешённые методы и фильтрацией входных данных.
<?php
// Разрешённые методы
$allowedMethods = ['GET', 'POST', 'PUT', 'DELETE'];
$method = $_SERVER['REQUEST_METHOD'];
// Проверка, что метод разрешён
if (!in_array($method, $allowedMethods)) {
http_response_code(405);
header('Allow: ' . implode(', ', $allowedMethods));
die("Метод $method не поддерживается");
}
// Получаем данные в зависимости от метода
function getRequestData($method) {
switch ($method) {
case 'GET':
return $_GET;
case 'POST':
return $_POST;
case 'PUT':
case 'DELETE':
$input = file_get_contents('php://input');
// Пробуем распарсить как JSON, иначе как URL-encoded
$data = json_decode($input, true);
if (json_last_error() !== JSON_ERROR_NONE) {
parse_str($input, $data);
}
return $data;
default:
return [];
}
}
$data = getRequestData($method);
// Пример безопасной обработки
$id = isset($data['id']) ? (int)$data['id'] : null;
$name = isset($data['name']) ? htmlspecialchars($data['name'], ENT_QUOTES, 'UTF-8') : '';
echo "Метод: $method, ID: $id, Имя: $name";
?>
Почему этот подход хорош?
- Явно проверяет, что метод входит в белый список.
- Автоматически обрабатывает и JSON, и URL-encoded данные.
- Фильтрует входные данные (приведение к int, экранирование HTML).
- Возвращает правильный HTTP-статус 405 для неподдерживаемых методов.
Этот вариант идеально подходит для небольших API, где не хочется подключать тяжёлые фреймворки, но нужна минимальная защита от некорректных запросов.