#7 php форма и обработчик в разных файлах: header Location и редирект после POST
Primary tabs
До сих пор форма и код её обработки жили в одном файле — с пустым action="" мы работали в уроках про форму с GET, форму с POST и проверку отправки формы.
Теперь разнесём их по разным файлам: страница с формой останется «витриной», а приём данных займётся отдельный обработчик. И сразу научимся главному приёму такого разделения: после обработки отправлять посетителя обратно — перенаправлением (редиректом).
Немного теории
Перенаправление — это обычный ответ сервера, только со специальным статусом (3xx) и заголовком Location: браузер, получив такой ответ, сам тут же запрашивает адрес из заголовка. Как отправлять заголовки из PHP — читайте в учебнике: перенаправление.
Файл первый: страница с формой
Пример сменим: пусть будет форма «оставить сообщение» с полем для имени и большим текстовым полем (многострочное поле — textarea):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Форма и обработчик</title>
</head>
<body>
<h1>Оставить сообщение</h1>
<?php if (isset($_GET['sent'])) { ?>
<p><strong>Спасибо! Сообщение получено.</strong></p>
<?php } ?>
<form action="handler.php" method="post">
<p>Имя:
<input type="text" name="name">
</p>
<p>Сообщение:<br>
<textarea name="text" rows="5" cols="40"></textarea>
</p>
<p><button type="submit">Отправить</button></p>
</form>
</body>
</html>
Обратите внимание: в action теперь адрес другого файла — handler.php. А блок «Спасибо» наверху показывается только если в адресе есть параметр sent — откуда он возьмётся, увидите через минуту.
Файл второй: обработчик
handler.php — это чистый PHP-файл без единой строки HTML:
<?php
// handler.php - принимает форму и возвращает на страницу
$isPosted = $_SERVER['REQUEST_METHOD'] === 'POST';
$name = '';
$text = '';
if (isset($_POST['name'])) {
$name = $_POST['name'];
}
if (isset($_POST['text'])) {
$text = $_POST['text'];
}
if (!$isPosted || $name === '' || $text === '') {
// данных нет или они пустые - просто возвращаемся к форме
header('Location: index.php');
exit;
}
// здесь данные валидны: в реальном приложении их
// сохранили бы в базу или отправили на почту
header('Location: index.php?sent=1');
exit;
Как это работает
- браузер отправляет данные формы POST-запросом на
handler.php; - обработчик проверяет данные (метод запроса и заполненность полей — всё это мы разбирали в прошлом уроке);
- если всё хорошо — «делает работу» (у нас это место с комментарием) и отвечает редиректом:
header('Location: index.php?sent=1'); - браузер автоматически запрашивает
index.php?sent=1уже обычным GET-запросом; - страница с формой видит параметр
sentи печатает «Спасибо».
Посмотрите на адресную строку после отправки: там index.php?sent=1 — данные уехали на сервер POST-ом, а «квитанция» вернулась GET-параметром.
Почему редирект, а не просто «Спасибо» в обработчике
Можно было бы напечатать «Спасибо» прямо в handler.php — но тогда посетитель останется на странице обработчика, и: во-первых, её обновление (F5) снова отправит форму — с тем самым предупреждением браузера из урока про POST; во-вторых, адрес обработчика останется в истории. После редиректа обновляется уже обычная GET-страница, и ничего не отправляется повторно. Этот приём называют POST-Redirect-GET.
И два обязательных правила работы с header() (документация): заголовки отправляются до любого вывода в браузер — поэтому в handler.php нет ни HTML, ни echo; и сразу после header() вызывайте exit, иначе скрипт продолжит выполняться дальше.
Попробуйте сами
- отправьте сообщение и нажмите F5 — переспроса о повторной отправке не будет;
- откройте
handler.phpнапрямую, без формы, — вас просто вернёт на страницу с формой (подумайте, почему); - в DevTools (F12, Network) отправьте форму и найдите три запроса подряд: POST на handler.php, ответ 302, затем GET на index.php;
- доработка: при пустых полях показывайте на странице формы сообщение «заполните оба поля» — подсказка: передавайте ещё один GET-параметр при редиректе, а показ сообщения делайте по образцу урока 6.
Итоги
- форму и обработчик можно (и часто удобно) держать в разных файлах:
action="handler.php"; - после обработки POST-данных правильно возвращать посетителя редиректом:
header('Location: ...')+exit; header()работает только до любого вывода — обработчик не должен ничего печатать;- паттерн POST-Redirect-GET избавляет от повторной отправки формы при обновлении страницы.
В следующем уроке начинается новая тема: научим сервер «узнавать» посетителя при повторном заходе — куки.
- Log in to post comments
- 12 reads