Обработка данных форм на PHP: полное руководство с примерами
Основы отправки форм в PHP
Обработка данных формы на стороне сервера начинается с выбора метода отправки (GET или POST) и настройки атрибутов action и method в HTML. Наиболее эффективное решение предполагает использование $_POST для получения данных, их фильтрацию и валидацию, а также защиту от межсайтовой подделки запросов (CSRF).
Базовый обработчик формы (POST)
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if ($name && $email) {
// дальнейшая обработка (сохранение, отправка письма)
echo 'Данные получены: ' . htmlspecialchars($name) . ', ' . htmlspecialchars($email);
} else {
echo 'Ошибка валидации';
}
}
?>
<form method="post">
<input type="text" name="name" required>
<input type="email" name="email" required>
<button type="submit">Отправить</button>
</form>
отправка форм php (отправка форм в php)
При заполнении полей и отправке: Данные получены: Иван, ivan@example.com
Этот пример проверяет метод запроса, очищает ввод от лишних пробелов и проверяет email. Фильтрация через filter_input предотвращает некорректные данные. htmlspecialchars защищает от XSS при выводе.
Когда использовать GET вместо POST?
GET подходит для нечувствительных данных и поисковых запросов. Данные передаются в URL. Пример:
<form method="get" action="search.php">
<input type="text" name="q">
<button>Поиск</button>
</form>
В PHP данные доступны через $_GET['q']. Ограничение: длина URL (около 2000 символов).
Типичная ошибка: использование GET для логинов или паролей – они видны в истории браузера и логах сервера. Решение: всегда POST для конфиденциальных данных.
Как обработать загрузку файлов?
Для файлов требуется атрибут enctype="multipart/form-data". Обработка через $_FILES:
<form method="post" enctype="multipart/form-data">
<input type="file" name="file">
<button>Загрузить</button>
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$file = $_FILES['file'];
if ($file['error'] === UPLOAD_ERR_OK) {
move_uploaded_file($file['tmp_name'], 'uploads/' . basename($file['name']));
echo 'Файл загружен';
}
}
?>
Проблема: не проверено расширение и MIME-тип. Злоумышленник может загрузить PHP-скрипт. Решение: проверять mime_content_type и расширение, ограничивать размер через upload_max_filesize в php.ini.
Как отправить форму через AJAX?
Это позволяет не перезагружать страницу. Пример на fetch с JSON:
// JavaScript
fetch('handler.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name: 'Анна', email: 'anna@test.com'})
}).then(r => r.text()).then(console.log);
<?php
// handler.php
$data = json_decode(file_get_contents('php://input'), true);
echo 'Получено: ' . htmlspecialchars($data['name']);
?>
Вывод в консоли: Получено: Анна
Ошибка: забывают установить заголовок Content-Type в fetch. Без него PHP не сможет прочитать JSON из php://input. Решение: явно указывать заголовок.
Как защитить форму от CSRF?
Создать токен, хранить в сессии, вставить в форму скрытое поле. На сервере сравнить:
<?php
session_start();
if (empty($_SESSION['csrf'])) $_SESSION['csrf'] = bin2hex(random_bytes(32));
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!hash_equals($_SESSION['csrf'], $_POST['csrf'] ?? '')) {
die('CSRF атака');
}
// обработка
}
?>
<form method="post">
<input type="hidden" name="csrf" value="<?= $_SESSION['csrf'] ?>">
<!-- поля -->
</form>
Проблема: токен не обновляется после отправки. Для критичных операций лучше генерировать новый токен после каждого использования.
Как отправить письмо с данными формы?
Использовать mail() или PHPMailer (для вложений и SMTP). Простейший пример:
<?php
if ($_POST['submit']) {
$to = 'admin@site.com';
$subject = 'Новая заявка';
$message = 'Имя: ' . $_POST['name'] . '\nEmail: ' . $_POST['email'];
$headers = 'From: no-reply@site.com' . "\r\n" . 'Reply-To: ' . $_POST['email'];
mail($to, $subject, $message, $headers);
}
?>
Типичная ошибка: заголовки инъекции через переносы строк в поле email. Решение: проверять email фильтром и удалять нежелательные символы.
Как обработать массив полей формы?
Имена полей с квадратными скобками name="items[]" создают массив:
<input type="text" name="items[]" value="1">
<input type="text" name="items[]" value="2">
<?php print_r($_POST['items']); // Array([0]=>1,[1]=>2) ?>
Ошибка: если поле необязательное, при отсутствии отправки элемента индекс может сместиться. Решение: проверять через isset или array_filter.
Расширенные примеры обработки форм
1. Форма с проверкой капчи (Google reCAPTCHA v3)
<form method="post">
<input type="text" name="name" required>
<button type="submit" class="g-recaptcha" data-sitekey="ваш_ключ" data-action="submit">Отправить</button>
</form>
<script src="https://www.google.com/recaptcha/api.js"></script>
<?php
if ($_POST) {
$recaptcha = $_POST['g-recaptcha-response'] ?? '';
$secret = 'ваш_секрет';
$response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secret&response=$recaptcha");
$responseKeys = json_decode($response, true);
if (intval($responseKeys["score"]) >= 0.5) {
echo 'Капча пройдена, имя: ' . htmlspecialchars($_POST['name']);
} else {
echo 'Вы бот';
}
}
?>
При успешной проверке: Капча пройдена, имя: Иван
2. Сохранение данных формы в базу данных через PDO
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
$stmt->execute([
':name' => htmlspecialchars($_POST['name']),
':email' => filter_var($_POST['email'], FILTER_SANITIZE_EMAIL)
]);
echo 'Пользователь добавлен с ID: ' . $pdo->lastInsertId();
}
?>
<form method="post">
<input type="text" name="name" required>
<input type="email" name="email" required>
<button>Сохранить</button>
</form>
Пользователь добавлен с ID: 5
3. Обработка JSON-данных с множественными полями
// JSON отправляется из клиента:
// fetch('api.php', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({user:{name:'Петр', skills:['PHP','JS']}})})
<?php
$input = json_decode(file_get_contents('php://input'), true);
if (isset($input['user']['name'])) {
$name = htmlspecialchars($input['user']['name']);
$skills = implode(', ', array_map('htmlspecialchars', $input['user']['skills'] ?? []));
echo "Имя: $name, навыки: $skills";
}
?>
Имя: Петр, навыки: PHP, JS
4. Отправка формы с загрузкой нескольких файлов
<form method="post" enctype="multipart/form-data">
<input type="file" name="files[]" multiple>
<button>Загрузить</button>
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['files'])) {
foreach ($_FILES['files']['tmp_name'] as $index => $tmp) {
if ($_FILES['files']['error'][$index] === UPLOAD_ERR_OK) {
$ext = pathinfo($_FILES['files']['name'][$index], PATHINFO_EXTENSION);
if (in_array(strtolower($ext), ['jpg','png','gif'])) {
move_uploaded_file($tmp, 'uploads/' . uniqid() . '.' . $ext);
echo 'Файл ' . $_FILES['files']['name'][$index] . ' загружен. ';
} else {
echo 'Недопустимый формат: ' . $_FILES['files']['name'][$index] . ' ';
}
}
}
}
?>
Файл photo1.jpg загружен. Файл photo2.png загружен. Недопустимый формат: script.php
5. AJAX-отправка с валидацией на стороне сервера и возвратом JSON
// JavaScript
const formData = new FormData(document.querySelector('form'));
fetch('ajax_handler.php', {
method: 'POST',
body: formData
}).then(r => r.json()).then(data => {
if (data.success) alert('OK'); else alert(data.error);
});
// ajax_handler.php
<?php
$errors = [];
if (empty($_POST['name'])) $errors[] = 'Имя обязательно';
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if (!$email) $errors[] = 'Некорректный email';
if (empty($errors)) {
echo json_encode(['success' => true, 'message' => 'Все хорошо']);
} else {
echo json_encode(['success' => false, 'error' => implode(', ', $errors)]);
}
?>
При пустом имени и неверном email: {"success":false,"error":"Имя обязательно, Некорректный email"}
6. Обработка формы с проверкой уникальности email в БД
<?php
$pdo = new PDO('sqlite:users.db');
$pdo->exec('CREATE TABLE IF NOT EXISTS users (email TEXT PRIMARY KEY, name TEXT)');
if ($_POST) {
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if (!$email) die('Неверный email');
$stmt = $pdo->prepare('SELECT 1 FROM users WHERE email = ?');
$stmt->execute([$email]);
if ($stmt->fetch()) {
echo 'Email уже зарегистрирован';
} else {
$stmt = $pdo->prepare('INSERT INTO users (email, name) VALUES (?, ?)');
$stmt->execute([$email, htmlspecialchars($_POST['name'])]);
echo 'Регистрация успешна';
}
}
?>
Если email уже существует: Email уже зарегистрирован