Формы в PHP: короткая инструкция по обработке данных
За полчаса сделаете рабочую форму на PHP: покажем разметку, приём данных на сервере, проверку полей и защиту от подделки запросов. Код можно скопировать и запустить.

К концу этой инструкции у вас будет форма обратной связи на PHP: HTML-разметка, серверный скрипт, который принимает данные, проверяет их и возвращает результат пользователю. Плюс защита от CSRF и базовая фильтрация. Времени займёт минут тридцать, если PHP уже установлен. Пишу под PHP 8.1 и выше — синтаксис проверки полей местами отличается от PHP 7.
Что нужно иметь до начала
Прежде чем писать код, убедитесь, что окружение готово. Иначе на середине выяснится, что скрипт просто отдаётся браузеру как текст.
- PHP 8.1+ — проверьте командой
php -vв терминале. Если версия ниже, часть кода проfilter_varи типизацию сработает, но примеры я тестировал на 8.1. - Веб-сервер, который выполняет PHP. Для локального запуска хватит встроенного:
php -S localhost:8000в папке проекта. Открывать файл черезfile://нельзя — PHP не выполнится. - Текстовый редактор и папка для двух файлов:
form.phpс разметкой иhandler.phpс обработкой. Здесь объединим их в один файл — так проще для старта.
Шаг 1. Разметка формы
Форма отправляет данные методом POST на тот же файл. Обратите внимание на атрибут action: пустая строка означает «отправить сюда же».
<!-- form.php -->
<form method="post" action="">
<label>Имя:
<input type="text" name="name">
</label>
<label>Email:
<input type="email" name="email">
</label>
<label>Сообщение:
<textarea name="message"></textarea>
</label>
<button type="submit">Отправить</button>
</form>
Проверка: откройте файл через php -S localhost:8000 и зайдите на http://localhost:8000/form.php. Должна появиться форма с тремя полями и кнопкой. Пока при отправке ничего не происходит — обработчик добавим дальше.
Шаг 2. Принимаем данные на сервере
Данные из формы, отправленной методом POST, лежат в суперглобальном массиве $_POST. Ключи массива — это значения атрибута name у полей. Проверяем, что запрос пришёл именно методом POST, иначе при первом открытии страницы код полезет в пустой массив.
<?php
// В самом верху form.php, до HTML
$errors = [];
$sent = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// trim убирает пробелы по краям, ?? '' страхует от отсутствия ключа
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');
}
?>
Проверка: добавьте после присваивания строку var_dump($name, $email, $message);, отправьте форму — в браузере увидите введённые значения. После проверки эту строку уберите.
Шаг 3. Валидация полей
Никогда не доверяйте тому, что пришло от пользователя. Атрибут type="email" в HTML — подсказка браузеру, а не защита: запрос можно отправить в обход формы. Проверяйте на сервере.
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');
if ($name === '') {
$errors[] = 'Укажите имя.';
}
// filter_var с FILTER_VALIDATE_EMAIL вернёт false для некорректного адреса
if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
$errors[] = 'Email введён неверно.';
}
if (mb_strlen($message) < 10) {
$errors[] = 'Сообщение слишком короткое, минимум 10 символов.';
}
if (empty($errors)) {
$sent = true;
// здесь отправка письма или запись в базу
}
}
Для длины строки берём mb_strlen, а не strlen: обычный strlen считает байты, и кириллица в UTF-8 даст в два раза большее число. Проверка: отправьте форму с пустым именем — под ней должна появиться ошибка (вывод добавим на шаге 5).
Шаг 4. Защита от CSRF
CSRF1 — атака, при которой сторонний сайт заставляет браузер пользователя отправить запрос на ваш сервер от его имени. Защита стандартная: кладём в сессию случайный токен, дублируем его скрытым полем формы и при приёме сверяем.
<?php
session_start(); // самой первой строкой, до любого вывода
// Генерируем токен один раз на сессию
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// hash_equals сравнивает строки без утечки времени сравнения
$tokenValid = isset($_POST['csrf_token'])
&& hash_equals($_SESSION['csrf_token'], $_POST['csrf_token']);
if (!$tokenValid) {
$errors[] = 'Форма устарела, обновите страницу.';
}
// ... остальные проверки из шага 3
}
?>
В разметку формы добавьте скрытое поле:
<input type="hidden" name="csrf_token"
value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
Проверка: отправьте форму нормально — ошибки про устаревание быть не должно. Если очистите куки сессии между открытием и отправкой, увидите сообщение об устаревшей форме.
Шаг 5. Вывод результата и защита от XSS
Когда возвращаете введённые значения обратно в HTML (например, чтобы пользователь не перезаполнял форму), пропускайте их через htmlspecialchars. Иначе введённый в поле <script> выполнится в браузере — это XSS2.
<?php if ($sent): ?>
<p>Спасибо, сообщение отправлено.</p>
<?php else: ?>
<?php if (!empty($errors)): ?>
<ul>
<?php foreach ($errors as $error): ?>
<li><?= htmlspecialchars($error) ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<form method="post" action="">
<input type="hidden" name="csrf_token"
value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
<input type="text" name="name"
value="<?= htmlspecialchars($name ?? '') ?>">
<input type="email" name="email"
value="<?= htmlspecialchars($email ?? '') ?>">
<textarea name="message"><?= htmlspecialchars($message ?? '') ?></textarea>
<button type="submit">Отправить</button>
</form>
<?php endif; ?>
Проверка: отправьте форму с корректными данными — увидите «Спасибо, сообщение отправлено». С ошибочными — список ошибок и заполненная форма с сохранёнными значениями.
Данные из $_POST — это всегда ввод недоверенного пользователя. Валидация при приёме и экранирование при выводе — не «на всякий случай», а базовая гигиена, без которой форма превращается в дыру.
Если не получилось
- Браузер показывает код PHP как текст вместо выполнения. Файл открыт через
file://или сервер не обрабатывает.php. Запускайте черезphp -S localhost:8000и открывайте поhttp://. - Warning: session_start(): Cannot start session, headers already sent. До
session_start()уже был вывод — пробел, HTML или BOM в начале файла. Уберите всё, что печатается до вызова. - Undefined array key "name". Поле формы называется иначе, чем ключ в
$_POST, либо код читает массив при GET-запросе. Сверьтеnameв разметке и используйте$_POST['name'] ?? ''. - Форма всегда пишет «устарела, обновите страницу». Токен не совпадает: чаще всего
session_start()не вызван или скрытое полеcsrf_tokenне попало в форму. Проверьте оба места. - Кириллица в проверке длины ведёт себя странно. Использован
strlenвместоmb_strlen. Меняйте наmb_strlen.
Что делать дальше
Форма работает и защищена от базовых атак. Следующие шаги, когда понадобятся:
- Отправка письма — функция
mail()подойдёт для простого случая, но для надёжной доставки берут библиотеку вроде PHPMailer. - Запись в базу — используйте PDO с подготовленными выражениями, чтобы закрыть SQL-инъекции; конкатенация строк в запрос недопустима.
- Ограничение частоты отправок и капча против спам-ботов — отдельная тема, здесь её не разворачиваем.
1. CSRF (Cross-Site Request Forgery) — межсайтовая подделка запроса: вредоносная страница отправляет запрос на ваш сайт, используя активную сессию пользователя.
2. XSS (Cross-Site Scripting) — внедрение стороннего скрипта в страницу через непроверенный ввод, который затем выполняется в браузере других пользователей.
Проверка рекламы на риски: Что в макете вызовет вопросы ФАС: превосходные степени, сравнения, обещания результата, маркировка.
Спросить за 40 ₽Источники: PHP Manual: Dealing with Forms, PHP Manual: filter_var
Частые вопросы
У меня PHP 7.4, примеры сработают?
Чем POST лучше GET для формы?
Отправил форму, а сервер выдал ошибку 500 — что делать?
Нужно ли экранировать данные перед записью в базу?
CSRF-токен обязателен для простой формы обратной связи?
Значения полей после ошибки не сохраняются, пропадают. Почему?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.