Как определить тип HTTP-запроса (GET, POST, PUT, DELETE) в PHP?
Правильный способ определения HTTP-метода в PHP
Ваш код в целом верен — использование $_SERVER['REQUEST_METHOD'] — это стандартный и надёжный способ определить тип HTTP-запроса в PHP. Этот суперглобальный массив содержит информацию, которую сервер получает из HTTP-заголовка запроса. Однако вы столкнулись с типичной проблемой: HTML-формы и некоторые старые HTTP-клиенты не поддерживают методы PUT и DELETE напрямую.
Почему возникает проблема?
- HTML-формы поддерживают только GET и POST. Если вы укажете
method="PUT"илиmethod="DELETE"в теге<form>, браузер проигнорирует это и отправит запрос как GET. - JavaScript fetch с методом PUT или DELETE должен работать корректно, но если вы используете
fetchбез правильных заголовков или с неправильным телом запроса, сервер может интерпретировать это иначе. - Некоторые серверные конфигурации (например, старые версии Apache) могут блокировать или переопределять методы PUT и DELETE.
Решение для обработки PUT и DELETE
Есть два подхода, которые решают проблему:
1. Использование скрытого поля _method (для форм)
Это популярный паттерн в фреймворках (Laravel, Symfony). Вы отправляете форму методом POST, но добавляете скрытое поле, которое указывает реальный метод:
<form action="api.php" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="text" name="username">
<button type="submit">Обновить</button>
</form>
В PHP обрабатываете это так:
<?php
$method = $_SERVER['REQUEST_METHOD'];
if ($method === 'POST' && isset($_POST['_method'])) {
$method = strtoupper($_POST['_method']);
}
switch ($method) {
case 'GET':
// обработка GET
break;
case 'POST':
// обработка POST
break;
case 'PUT':
// для PUT данные обычно приходят в теле запроса, не в $_POST
parse_str(file_get_contents('php://input'), $putData);
var_dump($putData);
break;
case 'DELETE':
// для DELETE аналогично
parse_str(file_get_contents('php://input'), $deleteData);
break;
default:
http_response_code(405);
echo 'Метод не поддерживается';
}
?>
2. Прямая обработка через php://input
Для чистых API (без форм) используйте поток php://input, чтобы прочитать тело запроса. Это работает для PUT, DELETE и PATCH:
<?php
$method = $_SERVER['REQUEST_METHOD'];
$data = [];
if (in_array($method, ['PUT', 'DELETE', 'PATCH'])) {
$rawInput = file_get_contents('php://input');
// Если данные приходят в формате JSON
$jsonData = json_decode($rawInput, true);
if ($jsonData !== null) {
$data = $jsonData;
} else {
// Если данные в формате application/x-www-form-urlencoded
parse_str($rawInput, $data);
}
} elseif ($method === 'GET') {
$data = $_GET;
} elseif ($method === 'POST') {
$data = $_POST;
}
// Теперь $data содержит все параметры запроса
echo "Метод: $method\n";
print_r($data);
?>
Проверка в Postman
Если вы тестируете через Postman и видите GET вместо PUT/DELETE, проверьте:
- Вкладка "Headers": убедитесь, что нет лишних редиректов (если сервер перенаправляет, метод может измениться на GET).
- Вкладка "Body": для PUT и DELETE тело запроса должно быть указано явно (например, raw JSON или form-data).
- Настройки Postman: отключите "Follow original HTTP method" в настройках.
Дополнительные советы
- Всегда проверяйте
$_SERVER['REQUEST_METHOD']— это самый надёжный источник. - Для API используйте Content-Type: application/json и обрабатывайте данные через
json_decode(file_get_contents('php://input'), true). - Используйте
http_response_code()для возврата правильных кодов состояния (200 OK, 201 Created, 405 Method Not Allowed).
Альтернативный подход: использование библиотеки или микрофреймворка
Если вы не хотите вручную парсить методы и данные, рекомендую использовать готовые решения. Например, микрофреймворк Slim или Laravel уже имеют встроенную обработку HTTP-методов.
Пример на Slim 4:
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->get('/api/users', function (Request $request, Response $response) {
$response->getBody()->write("GET запрос");
return $response;
});
$app->post('/api/users', function (Request $request, Response $response) {
$data = $request->getParsedBody();
$response->getBody()->write("POST запрос");
return $response;
});
$app->put('/api/users/{id}', function (Request $request, Response $response, array $args) {
$data = $request->getParsedBody();
$response->getBody()->write("PUT запрос для ID: " . $args['id']);
return $response;
});
$app->delete('/api/users/{id}', function (Request $request, Response $response, array $args) {
$response->getBody()->write("DELETE запрос для ID: " . $args['id']);
return $response;
});
$app->run();
?>
Этот подход избавляет вас от:
- Ручной проверки
$_SERVER['REQUEST_METHOD'] - Парсинга тела запроса
- Обработки метода
_methodдля форм
Фреймворки автоматически обрабатывают все нюансы, включая поддержку PUT/DELETE через формы с _method. Для небольших проектов или обучения ручной подход (из первого ответа) тоже хорош — он даёт понимание того, как работают HTTP-запросы под капотом.
Также обратите внимание на пакет guzzlehttp/psr7, если хотите работать с PSR-7 (стандарт HTTP-сообщений в PHP) без полноценного фреймворка.
Ответов пока нет.
Войдите чтобы оставить ответ