Обработка форм в PHP: полное руководство
PHP — мощный язык для веб-разработки. Узнайте, как обрабатывать формы, проверять данные и защищаться от XSS и SQL-инъекций.
Обработка форм — одна из самых распространённых задач в любом веб-приложении: страница регистрации, контактная форма, строка поиска или оформление заказа — всё это отправляет пользовательский ввод на сервер, где PHP считывает его, проверяет и работает с ним. Это руководство описывает полный цикл — от HTML-формы в браузере до PHP-скрипта, который получает, валидирует и безопасно использует отправленные данные.
По окончании вы поймёте, как работают $_POST и $_GET, как выполнять валидацию на сервере, как сохранять значения формы после ошибки («sticky»-форма) и как избежать двух классических уязвимостей (XSS и SQL-инъекции).
Как работает отправка формы
Отправка формы — это единственный HTTP-запрос от браузера к серверу:
- Пользователь заполняет поля и нажимает Отправить.
- Браузер упаковывает значения полей согласно атрибуту
methodформы и отправляет их на URL, указанный в атрибутеaction. - PHP на сервере получает значения в суперглобальном массиве —
$_POSTили$_GET— и ваш скрипт обрабатывает их.
Поскольку данные поступают из браузера пользователя, никогда нельзя им доверять. Любой может изменить значения полей, убрать поля или отправить запрос, минуя вашу форму. Поэтому серверная валидация обязательна — клиентские атрибуты required и type="email" служат лишь для удобства.
Создание HTML-формы
Любая форма начинается с HTML. Форма содержит поля ввода — текстовые поля, поля email, переключатели, флажки — и кнопку отправки. Всё определяют два атрибута:
action— URL, на который отправляются данные (можно опустить для отправки на ту же страницу).method—postилиget(см. сравнение ниже).
<form action="form_processing.php" method="post">
<p>
<label for="name">Name:</label>
<input type="text" id="name" name="name" />
</p>
<p>
<label for="email">Email:</label>
<input type="email" id="email" name="email" />
</p>
<input type="submit" value="Submit" />
</form>Атрибут name каждого поля — это ключ, который вы читаете на сервере: name="email" становится $_POST['email']. Поле без атрибута name никогда не отправляется. Всегда связывайте каждое поле с тегом <label> для доступности.
POST и GET
Атрибут method определяет, как передаются данные и в какой массив они попадают.
method="post" | method="get" | |
|---|---|---|
| Расположение данных | Тело HTTP-запроса | Добавляется к URL как строка запроса |
| Массив PHP | $_POST | $_GET |
| Виден в URL | Нет | Да (?name=Ann&email=...) |
| Можно добавить в закладки | Нет | Да |
| Подходит для | Паролей, всего, что изменяет данные | Фильтров поиска, пагинации — запросов только на чтение |
Используйте POST для всего, что создаёт, обновляет или удаляет данные, либо содержит конфиденциальные значения. Используйте GET для поиска и фильтров, которые пользователи хотят сохранить в закладках. Данные попадают в соответствующий суперглобальный массив; в этом руководстве используется POST.
Чтение отправленных данных
После отправки формы PHP заполняет $_POST именами полей в качестве ключей и отправленным текстом в качестве значений. Считывайте каждое поле, но защититесь от отсутствующих ключей с помощью оператора объединения с null ??, чтобы отсутствующее поле давало пустую строку, а не предупреждение:
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';Проверяйте $_SERVER['REQUEST_METHOD'], чтобы код обработки выполнялся только при реальной отправке, а не при первом открытии страницы:
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
// ...validate and use the values
}Валидация ввода
Валидация отвечает на один вопрос: является ли это значение допустимым? Собирайте все проблемы в массив $errors, чтобы показать пользователю все ошибки сразу, а не останавливаться на первой. Используйте filter_var() с флагом FILTER_VALIDATE_EMAIL для корректной проверки формата email:
$errors = [];
if (trim($name) === '') {
$errors[] = "Name is required";
}
if (trim($email) === '') {
$errors[] = "Email is required";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Invalid email format";
}
if (!empty($errors)) {
foreach ($errors as $error) {
echo htmlspecialchars($error) . "<br>";
}
}Мы используем trim(), чтобы поле, содержащее только пробелы, считалось пустым, а затем filter_var() для проверки, что email выглядит как [email protected]. Если $errors не пуст, сообщения выводятся; иначе данные чистые и готовы к использованию. Подробнее о валидации обязательных полей и правилах проверки email/URL читайте в разделах валидация форм PHP и валидация обязательных полей.
Экранирование вывода: защита от XSS
Обратите внимание на вызов htmlspecialchars() выше. Всякий раз, когда вы выводите значение, пришедшее от пользователя, вы обязаны его экранировать — иначе злоумышленник может отправить теги <script>, которые выполнятся в браузерах других посетителей — это атака межсайтового скриптинга (XSS). htmlspecialchars() преобразует <, >, & и кавычки в безвредные HTML-сущности:
$dangerous = '<script>alert("xss")</script>';
echo htmlspecialchars($dangerous);
// <script>alert("xss")</script>Теперь браузер отобразит текст буквально, а не выполнит его. Всегда экранируйте при выводе.
Сохранение значений формы («sticky»-форма)
Если валидация не прошла, повторно отобразите форму с уже введёнными пользователем значениями — повторный ввод всего раздражает. Выводите каждое значение обратно в атрибут value, экранируя его:
<input
type="text"
name="name"
value="<?php echo htmlspecialchars($name ?? ''); ?>"
/>Поскольку одна и та же страница и отображает форму, и обрабатывает её, установите action="" (отправка на себя) — поле заполнится автоматически после неудачной отправки.
Сводим всё вместе
Вот одна самообрабатывающая страница, которая отображает форму, выполняет валидацию при POST, показывает ошибки, сохраняет значения и подтверждает успех — шаблон, которому следует большинство реальных контактных форм:
<?php
$name = $email = '';
$errors = [];
$success = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
if ($name === '') {
$errors[] = 'Name is required';
}
if ($email === '') {
$errors[] = 'Email is required';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Invalid email format';
}
if (!$errors) {
$success = true; // here you would save to a database or send an email
}
}
?>
<?php if ($success): ?>
<p>Thanks, <?php echo htmlspecialchars($name); ?>!</p>
<?php else: ?>
<?php foreach ($errors as $e): ?>
<p style="color:red"><?php echo htmlspecialchars($e); ?></p>
<?php endforeach; ?>
<form action="" method="post">
Name:
<input type="text" name="name"
value="<?php echo htmlspecialchars($name); ?>"><br>
Email:
<input type="email" name="email"
value="<?php echo htmlspecialchars($email); ?>"><br>
<input type="submit" value="Submit">
</form>
<?php endif; ?>Безопасное хранение данных: защита от SQL-инъекций
Когда данные прошли валидацию, их часто сохраняют в базу данных. Никогда не вставляйте пользовательский ввод напрямую в SQL-строку — это открывает дверь для SQL-инъекций. Используйте подготовленные выражения, чтобы база данных воспринимала значения как данные, а не как команды:
$mysqli = new mysqli('localhost', 'user', 'pass', 'app');
$stmt = $mysqli->prepare(
'INSERT INTO contacts (name, email) VALUES (?, ?)'
);
$stmt->bind_param('ss', $name, $email);
$stmt->execute();Заполнители ? и bind_param() отделяют значения от запроса, поэтому ввод вроде '; DROP TABLE contacts; -- сохраняется как безвредный текст, а не выполняется.
Контрольный список безопасности
Безопасный скрипт обработки формы следует короткой повторяемой процедуре:
- Валидируйте каждое поле на сервере — никогда не полагайтесь только на проверки в браузере.
- Экранируйте при выводе с помощью
htmlspecialchars()для защиты от XSS. - Используйте подготовленные выражения для каждого запроса к базе данных, чтобы предотвратить SQL-инъекции.
- Хешируйте пароли с помощью
password_hash()перед сохранением — никогда не храните открытый текст. - Добавьте CSRF-токен в формы, изменяющие состояние, чтобы запросы нельзя было подделать с других сайтов.
- Добавьте CAPTCHA в публичные формы для снижения числа автоматических спам-отправок.
Связанные разделы
- Обработка форм PHP — основы получения данных формы.
- PHP $_POST — суперглобальная переменная в деталях.
- Валидация форм PHP — полные шаблоны валидации.
- Суперглобальные переменные PHP —
$_POST,$_GET,$_SERVERи другие.