POST запросы форм в PHP: полное руководство с примерами
Раздел: Веб-разработка на PHP -> Работа с HTML формами
Основной подход: обработка POST запроса с валидацией и безопасностью
Наиболее эффективное решение заключается в использовании суперглобального массива $_POST вместе со встроенными функциями фильтрации и проверки. Рассмотрим пошаговый пример.
Пример формы
<form method='post' action='handler.php'>
<label>Имя: <input type='text' name='name' required></label><br>
<label>Email: <input type='email' name='email' required></label><br>
<input type='hidden' name='csrf_token' value='<?= $csrfToken ?>'>
<button type='submit'>Отправить</button>
</form>Обработчик handler.php
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('Метод не разрешен');
}
$token = $_POST['csrf_token'] ?? '';
if (!hash_equals($_SESSION['csrf_token'], $token)) {
die('Неверный токен');
}
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if (!$name || !$email) {
header('Location: form.php?error=1');
exit;
}
// сохранение данных в БД через PDO...
$_SESSION['success'] = 'Данные сохранены';
header('Location: success.php');
exit;
?>Пояснение шагов:
- Проверка метода запроса (только POST).
- Валидация CSRF токена для защиты от межсайтовой подделки.
- Фильтрация входных данных: удаление нежелательных символов и проверка формата.
- Если данные корректны, выполняется сохранение и редирект.
Типичные проблемы и их решение:
- Проблема: данные не приходят, пустой $_POST - чаще всего из-за неправильного атрибута action или использования GET. Решение - проверить атрибуты формы и метод.
- Проблема: XSS и SQL инъекции - использовать функции фильтрации и подготовленные запросы.
- Проблема: дублирование отправки при обновлении страницы - использовать редирект после POST (PRG-шаблон).
Как валидировать несколько полей одной функцией?
Вместо вызова filter_input для каждого поля можно использовать filter_input_array с массивом правил.
$filters = [
'name' => FILTER_SANITIZE_STRING,
'email' => FILTER_VALIDATE_EMAIL,
'age' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 1, 'max_range' => 120]]
];
$inputs = filter_input_array(INPUT_POST, $filters);Цель:
упростить код и повысить читаемость. Случаи использования: формы с большим количеством полей.Проблема:
filter_input_array возвращаетnull или false при ошибке; типы значений могут отличаться. Необходима дополнительная проверка каждого элемента массива.Как отправить форму без перезагрузки страницы?
Используем JavaScript fetch API для асинхронной отправки. PHP обрабатывает данные и возвращает JSON.
// Фрагмент JS
const form = document.getElementById('myForm');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(form);
const response = await fetch('handler.php', { method: 'POST', body: formData });
const result = await response.json();
if (result.success) {
alert('Успешно');
} else {
alert('Ошибка: ' + result.error);
}
});// PHP (handler.php)
<?php
header('Content-Type: application/json');
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
if (!$name) {
echo json_encode(['success' => false, 'error' => 'Имя обязательно']);
exit;
}
// сохранение...
echo json_encode(['success' => true]);
?>Цель:
улучшение пользовательского опыта, отсутствие полной перезагрузки. Случаи: формы обратной связи, регистрация.Проблемы:
необходимо правильно обрабатывать ошибки на клиенте, а также настройки CORS при разделении фронтенда и бэкенда.Как безопасно сохранять данные из формы в базу данных?
Используем PDO с подготовленными выражениями для защиты от SQL инъекций.
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8';
$pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
$stmt->execute([':name' => $name, ':email' => $email]);Цель:
надёжная защита от инъекций, совместимость с разными СУБД. Случаи: любые формы, сохраняющие данные в БД.Проблема:
забыть использовать подготовленные запросы и конкатенировать значения напрямую - критическая уязвимость.Как защитить форму от CSRF атак?
Генерируем уникальный токен в сессии и включаем его в форму в скрытом поле. При обработке проверяем совпадение.
// Генерация токена
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
// В форме: <input type='hidden' name='csrf_token' value='<?= $_SESSION['csrf_token'] ?>'>
// Проверка в обработчике
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'] ?? '')) {
die('CSRF detected');
}Цель:
предотвращение выполнения нежелательных действий от имени аутентифицированного пользователя. Обязательно для форм, изменяющих данные.Проблема:
токен может истечь, необходимо обновлять его после использования. Также нужно экранировать вывод токена в HTML.Расширенные примеры обработки POST запросов
Пример 1: обработка формы с массивом (чекбоксы)
Пример
<form method='post' action='handler.php'>
<input type='checkbox' name='interests[]' value='php'> PHP
<input type='checkbox' name='interests[]' value='js'> JavaScript
<input type='checkbox' name='interests[]' value='python'> Python
<button type='submit'>Отправить</button>
</form>
// Обработчик
$interests = $_POST['interests'] ?? [];
if (is_array($interests)) {
$clean = array_map('htmlspecialchars', $interests);
echo 'Выбранные интересы: ' . implode(', ', $clean);
}Выбранные интересы: PHP, JavaScript
Пример 2: обработка формы с загрузкой файла
Пример
<form method='post' enctype='multipart/form-data'>
<input type='file' name='avatar' accept='image/*'>
<button type='submit'>Загрузить</button>
</form>
// PHP
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['avatar'])) {
$tmp = $_FILES['avatar']['tmp_name'];
$name = basename($_FILES['avatar']['name']);
$allowed = ['image/jpeg', 'image/png'];
if (!in_array(mime_content_type($tmp), $allowed)) {
die('Недопустимый тип файла');
}
move_uploaded_file($tmp, 'uploads/' . $name);
echo 'Файл загружен: ' . $name;
}Файл загружен: photo.jpg
Пример 3: использование filter_input_array с кастомными проверками
Пример
$filters = [
'username' => [
'filter' => FILTER_VALIDATE_REGEXP,
'options' => ['regexp' => '/^[a-zA-Z0-9_]{3,20}$/']
],
'website' => FILTER_VALIDATE_URL,
'agree' => ['filter' => FILTER_VALIDATE_BOOLEAN, 'flags' => FILTER_NULL_ON_FAILURE]
];
$result = filter_input_array(INPUT_POST, $filters);
if ($result['username'] === false || !$result['website'] || $result['agree'] === null) {
echo 'Ошибка валидации';
} else {
echo 'Данные прошли проверку';
}Данные прошли проверку
Пример 4: работа с подготовленными запросами PDO и транзакциями
Пример
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare('INSERT INTO orders (user_id, total) VALUES (?, ?)');
$stmt->execute([$userId, $total]);
$orderId = $pdo->lastInsertId();
foreach ($items as $item) {
$stmt2 = $pdo->prepare('INSERT INTO order_items (order_id, product_id, quantity) VALUES (?, ?, ?)');
$stmt2->execute([$orderId, $item['id'], $item['qty']]);
}
$pdo->commit();
echo 'Заказ успешно оформлен';
} catch (Exception $e) {
$pdo->rollBack();
echo 'Ошибка: ' . $e->getMessage();
}Заказ успешно оформлен
Пример 5: обработка AJAX с возвратом JSON и обработкой ошибок
Пример
// PHP
header('Content-Type: application/json');
$input = json_decode(file_get_contents('php://input'), true);
if (!$input) {
http_response_code(400);
echo json_encode(['error' => 'Некорректный JSON']);
exit;
}
$name = $input['name'] ?? '';
if (!$name) {
echo json_encode(['error' => 'Имя не может быть пустым']);
exit;
}
// обработка...
echo json_encode(['success' => true, 'message' => 'Привет, ' . htmlspecialchars($name)]);
// JS fetch
fetch('ajax.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name: 'Алекс'})
}).then(r => r.json()).then(data => console.log(data));{success: true, message: 'Привет, Алекс'}Отправка формы методом POST в PHP - comments
En
Php form post (php)