Урок 6. Формы: $_GET, $_POST и htmlspecialchars
Форма — главный способ, которым посетитель передаёт сайту данные: поиск, вход, заказ, отзыв. Браузер отправляет заполненные поля на сервер, а PHP получает их в готовых массивах $_GET и $_POST. Файлы урока открывайте через встроенный сервер: php -S localhost:8000.
GET и POST
У формы есть атрибут method:
- GET — данные идут в адресе страницы:
search.php?q=кот. Такой адрес можно сохранить в закладки и отправить другу. Подходит для поиска и фильтров. - POST — данные идут в теле запроса и в адресе не видны. Подходит для всего, что меняет данные на сайте: регистрация, заказ, сообщение.
Ключи в массивах — это значения атрибутов name у полей формы: поле <input name="q"> попадёт в $_GET['q'] или $_POST['q'].
Поиск: форма GET
Файл search.php:
<?php
$q = trim($_GET['q'] ?? '');
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Поиск</title>
</head>
<body>
<form method="get">
<input type="text" name="q" value="<?= htmlspecialchars($q) ?>">
<button>Найти</button>
</form>
<?php if ($q !== ''): ?>
<p>Вы искали: <?= htmlspecialchars($q) ?></p>
<?php endif; ?>
</body>
</html>Откройте http://localhost:8000/search.php, введите слово и нажмите «Найти»: адрес станет search.php?q=…, а на странице появится введённый текст.
Что здесь важно:
$_GET['q'] ?? ''— при первом открытии поляqв адресе нет, и??подставляет пустую строку вместо предупрежденияUndefined array key.trimубирает пробелы по краям — иначе запрос из одних пробелов выглядел бы непустым.- У формы нет атрибута
action, поэтому она отправляется на тот же адрес. - Всё введённое выводится только через
htmlspecialchars.
Зачем htmlspecialchars
Посетитель может ввести не слово, а кусок HTML или JavaScript. Если вывести его как есть, браузер выполнит этот код. Такой взлом называется XSS (межсайтовый скриптинг): чужой скрипт на вашей странице может украсть вход посетителя или подменить содержимое.
htmlspecialchars заменяет опасные знаки (<, >, &, кавычки) на безопасные HTML-записи — браузер покажет их как текст:
<?php
$input = '<script>alert("Взлом")</script>';
echo htmlspecialchars($input) . "\n";<script>alert("Взлом")</script>Любые данные от посетителя — поля формы, адрес, cookie, даже имя загруженного файла — выводите на страницу только через htmlspecialchars. Одно забытое место — и сайт уязвим для XSS.
Чтобы не писать длинное имя каждый раз, заведите короткую функцию и подключайте её на всех страницах:
<?php
function e(string $value): string
{
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}Флаг ENT_QUOTES заменяет и двойные, и одинарные кавычки — тогда значение безопасно и внутри атрибута value='…'. С PHP 8.1 так и задано по умолчанию, но явная запись не повредит.
Обратная связь: форма POST с проверкой
Файл feedback.php показывает форму, проверяет поля и при ошибках показывает форму снова, с уже введёнными значениями:
<?php
$errors = [];
$name = '';
$email = '';
$sent = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
if ($name === '') {
$errors[] = 'Введите имя';
} elseif (mb_strlen($name) > 50) {
$errors[] = 'Имя длиннее 50 знаков';
}
if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
$errors[] = 'Почта указана неверно';
}
if (!$errors) {
// Здесь данные сохраняют в базу или отправляют письмом.
$sent = true;
}
}
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Обратная связь</title>
</head>
<body>
<?php if ($sent): ?>
<p>Спасибо, <?= htmlspecialchars($name) ?>! Сообщение принято.</p>
<?php else: ?>
<?php foreach ($errors as $error): ?>
<p style="color: red"><?= htmlspecialchars($error) ?></p>
<?php endforeach; ?>
<form method="post">
<p><label>Имя: <input type="text" name="name" value="<?= htmlspecialchars($name) ?>"></label></p>
<p><label>Почта: <input type="email" name="email" value="<?= htmlspecialchars($email) ?>"></label></p>
<button>Отправить</button>
</form>
<?php endif; ?>
</body>
</html>Как это работает:
- При первом открытии страницы запрос — GET, блок
ifпропускается, и показывается пустая форма. - После нажатия «Отправить» тот же файл получает запрос POST.
$_SERVER['REQUEST_METHOD']— способ запроса. - Поля проверяются, ошибки собираются в массив
$errors. Пустой массив в условии —false, поэтому!$errorsозначает «ошибок нет». filter_varсFILTER_VALIDATE_EMAILвозвращает адрес, если он похож на почту, иfalse, если нет.
Атрибуты required и type="email" в HTML помогают посетителю, но не защищают: запрос можно отправить в обход браузера. Поэтому проверка на сервере обязательна всегда.
Повторная отправка
Если после отправки POST обновить страницу (F5), браузер предложит отправить форму ещё раз — и сообщение придёт дважды. Поэтому после успешной обработки обычно делают перенаправление на страницу «Спасибо». Как это устроено — в справках Как отправить форму на ту же страницу и Как сделать редирект.
Флажки, списки и несколько значений
- Флажок (
checkbox) отправляется, только если отмечен. Проверяйте его так:$agree = isset($_POST['agree']);. - Если у полей имя с квадратными скобками, например
name="colors[]", в$_POST['colors']придёт массив. - Значение из списка (
select) проверяйте по списку допустимых:in_array($city, ['Минск', 'Брест'], true)— посетитель может прислать любое значение, а не только те, что были в списке.
Массив $_REQUEST объединяет GET, POST и cookie. Им лучше не пользоваться: непонятно, откуда пришло значение.
Частые ошибки
Undefined array key "name"при первом открытии страницы — поле читается без??: формы ещё не отправляли, и ключа в массиве нет. Пишите$_POST['name'] ?? ''.- Поле не приходит совсем — у него нет атрибута
name(одногоidмало): браузер отправляет только поля сname. - В
$_GETпусто, хотя форма отправлена, — у формыmethod="post", и данные лежат в$_POST. - Введённый текст выведен без
htmlspecialchars— страница открыта для XSS.
Коротко
- Данные формы приходят в
$_GET(данные в адресе) и$_POST(данные в теле запроса); ключ — атрибутnameполя. - Значение по умолчанию для отсутствующего поля —
$_POST['x'] ?? ''. - Способ запроса —
$_SERVER['REQUEST_METHOD']. - Проверка на сервере обязательна, даже если в HTML стоит
required. - Всё, что пришло от посетителя, выводится только через
htmlspecialchars— защита от XSS.