Очистить форму после передачи данных. Повторная отправка данных формы при обновлении страницы. Предотвращение повторной отправки формы с помощью клиентского редиректа

Помощь 03.03.2020

В свое время озадачился вопросом - как защитить страницы сайта от повторной отправки данных формы во время обновления страницы (если перед этим была отправка, естественно).
Каждый веб-мастер и разработчик наверное знает, что если на сайте вы нажали кнопку «отправить», заполнив какую-либо форму, то после отправки, если попытаться обновить страницу браузер выдаст сообщение с подтверждением повторной отправки.
В некоторых моментах это бывает недопустимо. Например, в случае элементарной формы обратной связи. Когда пользователь заполнил форму и отправил сообщение, а потом по какой-то ему одному известной причине обновил страницу, письмо ушло снова. Это может, конечно, и не такой фатальный случай, просто как пример. Все гораздо болезненнее, например, при отправке заказа в интернет-магазине.
Так вот задался вопросом поиска решения этой проблемы и понял, что решение только одно: использование перенаправления после отправки формы header (‘location: адрес’). Т.е. все просто – после отправки вызываем перенаправление (можно даже на ту же страницу) и все! Обновление страницы будет чистым, без всяких заполненных POST-ов и GET-ов.

Все бы хорошо, но лично я испытал с этим некоторые проблемы. Они заключаются в следующем. Раньше, без использования переадресации механизм отправки данных на моих сайтах работал следующим образом:
Пользователь заполняет форму, жмет «отправить», скрипт принимает отправленные данные, проверяет их на корректность (валидность, заполненность обязательных данных и т.д.) и выдает ответ – либо операция прошла успешно, либо произошла ошибка и список ошибок (например: ошибка - поле «имя» не заполнено. А на странице отправки уже в свою очередь выдается соответствующее сообщение: отправка успешна или не успешна.
В случае если отправка не успешна, то форма остается на экране и поля ее заполнены теми данными, которые пользователь ввел. Т.е. данные берутся из переменной $_POST (если метод POST) и встают в соответствующие поля (т.е. возвращаются из поста в свои поля, чтобы заново их не вводить). Ведь всех же бесит когда ты заполнил форму, и не дай бог что-то указал неправильно и при попытке отправить тебе выдается сообщение, что что-то заполнено неправильно, а форма обновляется и снова пуста. И приходится из-за одного неправильно заполненного поля заново ее заполнять.
Так вот, как уже сказал, в случае неуспешного заполнения, форма остается заполненной данными, взятыми из $_POST, и пользователь может исправить неправильные данные и снова отправить форму.
Все было хорошо и все работало.
Но потом я сделал отправку с использованием переадресации и получилось так, что после нажатия кнопки «отправить», в случае неуспешного заполнения, форма обновлялась и в ней уже не могли остаться заполненные поля, т.к. раньше они автоматом заполнялись из массива $_POST, а теперь после того как произошла переадресация $_POST подчистился как будто и не было никакой отправки.
Но и на этот случай нашелся выход. Использовать сессии. Т.е. до вызова header передавать в переменные сессии данные из POST и уже потом после переадресации ими оперировать.
В итоге код усложнился значительно. Отладка усложнилась, т.к. вообще трудно определить что происходит с функциями в тот момент когда случается переадресация. Если ты сделал какую-то ошибку в кодах (которая проявляется именно в момент отправки), то она даже не высветится, т.к. произойдет переадресация и ты даже не увидишь сообщение об ошибке.
В общем, мне после внедрения в свои коды header стало сложнее работать с моими приложениями. Разработка/доработка/поиск ошибок усложнился. Но и отказаться я от этого не могу.
И продолжаю задаваться вопросом: а есть ли другие, более элегантные решения?

В свое время озадачился вопросом - как защитить страницы сайта от повторной отправки данных формы во время обновления страницы (если перед этим была отправка, естественно).
Каждый веб-мастер и разработчик наверное знает, что если на сайте вы нажали кнопку «отправить», заполнив какую-либо форму, то после отправки, если попытаться обновить страницу браузер выдаст сообщение с подтверждением повторной отправки.
В некоторых моментах это бывает недопустимо. Например, в случае элементарной формы обратной связи. Когда пользователь заполнил форму и отправил сообщение, а потом по какой-то ему одному известной причине обновил страницу, письмо ушло снова. Это может, конечно, и не такой фатальный случай, просто как пример. Все гораздо болезненнее, например, при отправке заказа в интернет-магазине.
Так вот задался вопросом поиска решения этой проблемы и понял, что решение только одно: использование перенаправления после отправки формы header (‘location: адрес’). Т.е. все просто – после отправки вызываем перенаправление (можно даже на ту же страницу) и все! Обновление страницы будет чистым, без всяких заполненных POST-ов и GET-ов.

Все бы хорошо, но лично я испытал с этим некоторые проблемы. Они заключаются в следующем. Раньше, без использования переадресации механизм отправки данных на моих сайтах работал следующим образом:
Пользователь заполняет форму, жмет «отправить», скрипт принимает отправленные данные, проверяет их на корректность (валидность, заполненность обязательных данных и т.д.) и выдает ответ – либо операция прошла успешно, либо произошла ошибка и список ошибок (например: ошибка - поле «имя» не заполнено. А на странице отправки уже в свою очередь выдается соответствующее сообщение: отправка успешна или не успешна.
В случае если отправка не успешна, то форма остается на экране и поля ее заполнены теми данными, которые пользователь ввел. Т.е. данные берутся из переменной $_POST (если метод POST) и встают в соответствующие поля (т.е. возвращаются из поста в свои поля, чтобы заново их не вводить). Ведь всех же бесит когда ты заполнил форму, и не дай бог что-то указал неправильно и при попытке отправить тебе выдается сообщение, что что-то заполнено неправильно, а форма обновляется и снова пуста. И приходится из-за одного неправильно заполненного поля заново ее заполнять.
Так вот, как уже сказал, в случае неуспешного заполнения, форма остается заполненной данными, взятыми из $_POST, и пользователь может исправить неправильные данные и снова отправить форму.
Все было хорошо и все работало.
Но потом я сделал отправку с использованием переадресации и получилось так, что после нажатия кнопки «отправить», в случае неуспешного заполнения, форма обновлялась и в ней уже не могли остаться заполненные поля, т.к. раньше они автоматом заполнялись из массива $_POST, а теперь после того как произошла переадресация $_POST подчистился как будто и не было никакой отправки.
Но и на этот случай нашелся выход. Использовать сессии. Т.е. до вызова header передавать в переменные сессии данные из POST и уже потом после переадресации ими оперировать.
В итоге код усложнился значительно. Отладка усложнилась, т.к. вообще трудно определить что происходит с функциями в тот момент когда случается переадресация. Если ты сделал какую-то ошибку в кодах (которая проявляется именно в момент отправки), то она даже не высветится, т.к. произойдет переадресация и ты даже не увидишь сообщение об ошибке.
В общем, мне после внедрения в свои коды header стало сложнее работать с моими приложениями. Разработка/доработка/поиск ошибок усложнился. Но и отказаться я от этого не могу.
И продолжаю задаваться вопросом: а есть ли другие, более элегантные решения?

Мне часто задают вопросы относительно отмены повторной отправки формы . Например, Вы сделали форму добавления комментария, добавили обработчик на эту же страницу. Затем при добавлении комментария он успешно добавляется, но стоит пользователю нажать F5 , как форма будет отправлена ещё раз . А F5 пользователь может легко нажать, если страница будет долго грузиться. В итоге, вместо 1-го комментария будет целых 2 , а то и больше. В этой статье я покажу, как этого можно избежать.

Для начала разберём более подробно проблему на примере этого кода:


echo "Квадрат числа ".$_POST["x"]." равен ".pow($_POST["x"], 2);
}
?>








Нажав на кнопку "Возвести в квадрат ", Вы увидите результат работы скрипта. Но стоит после этого пользователю нажать F5 , как скрипт снова будет выполняться. В данном случае, это не так критично, как с добавлением комментарием, однако, зачем нужна лишняя нагрузка на сервер?

Теперь поговорим о способах решения данной проблемы. Первый способ - выделить скрипт обработки в отдельный файл . Тогда в атрибуте action у тега form надо добавить путь к этому скрипту. А сам скрипт должен сохранять куда-нибудь результат своих действий, либо переменные пришедшие на скрипт, а после делать редирект обратно. В общем, смотрите код скрипта:

session_start();

header("Location: ".$_SERVER["HTTP_REFERER"]);
exit;
?>

А код страницы с формой теперь будет выглядеть так:

session_start();

}
?>








Недостаток этого подхода очевиден - приходится создавать ещё один файл для такого простого скрипта. Поэтому рассказываю и про второй способ , как можно избежать повторной отправки формы :

session_start();
if (!empty($_POST["sqr"])) {
$_SESSION["x"] = $_POST["x"];
header("Location: ".$_SERVER["REQUEST_URI"]);
exit;
}
if (isset($_SESSION["x"])) echo "Квадрат числа ".$_SESSION["x"]." равен ".pow($_SESSION["x"], 2);
?>








Здесь обработка снова происходит в этом же файле, но ключевое отличие - это наличие редиректа на эту же страницу в конце . В результате, страница перегрузится после отправки формы и браузер при нажатии F5 не будет предлагать пользователю отправить форму ещё раз.

Подведу итог того, как отменить повторную отправку формы :

  • Либо делать обработку в отдельном файле , а затем оттуда делать редирект назад.
  • Либо делать обработку в том же файле, что и форма, но при этом после обработки делать редирект на ту же страницу .

Вот так это делается в простых скриптах. Да и, в сложных, в конечном счёте делается то же самое.



Рекомендуем почитать

Наверх