Как правильно предотвратить повторную отправку формы?

Например, написание сообщения пользователем: после заполнения формы и нажатия кнопки Отправить, появляется страница, где написано сообщение Отправлено, а ниже список всех сообщений. Если обновить страницу в Опере, то сообщение еще раз отправится, если в Хроме, то спросит Отправить ли форму еще раз, а нужно обновить страницу с сообщениями не спрашивая не о чем.

- Если делать со скрытым полем со случайным значением, и проверять это значение, то повторная отправка всё равно будет спрашиваться, хоть и не добавится уже.

- Если после добавления сообщения в базу делать перенаправление на страницу вида index.php?message=Сообщение%20успешно%20добавлено! , то это сообщение после обновления страницы так и будет появляться.

+ Поэтому я хочу сделать так: на сайте используются свои сессии в базе MySQL, но чтобы не напрягать базу, я хочу использовать встроенные в php сессии как раз для этого дела, а именно: в месте вывода сообщения об успешной отправке, то есть после физического добавления информации в базу, стартовать сессию, в нее добавить переменную с сообщением "Сообщение успешно добавлено!", затем сделать перенаправление на эту же страницу, где выводятся все сообщения. А в коде самой страницы, стартовать сессию, и если есть в ней переменная с сообщением, то вывести его и удалить переменную.

+ А еще лучше, сделать массив сообщений и выводить их все, но если вдруг открыто несколько вкладок, то есть очень малая вероятность, что будет что-то одновременно и отобразится сообщение не в той вкладке, поэтому наверно стоит сделать какое-то случайное имя переменной, и передавать это имя GET параметром в url перенаправления, и уже по нему выводить и удалять переменную. Тогда вроде всё нормально.

Как Вам такой вариант, и как вообще это правильно делать, может, всё-таки отдельную страницу, как на многих форумах "Сообщение добавлено, сейчас Вы будете перенаправлены"?

Заранее всем спасибо за ответы!
  • Вопрос задан
  • 22259 просмотров
Решения вопроса 2
akubintsev
@akubintsev
Опытный backend разработчик
Я бы не стал хранить массив сообщений в сессии, это вообще дурная практика что-либо складировать в неё, кроме пары-тройки идентификаторов.
Для гарантии от дублирования есть приём:
- на сервере генерируется идентификатор нового сообщения
- сервер передает этот идентификатор клиенту
- клиент заполняет сообщение и отсылает его серверу с тем же самым идентификатором
- сервер при получении ставит в соответствие идентификатору сообщение (т.е. заполняет соответствующее поле в БД, если оно было пустым)

Рассмотрим теперь сценарии при попытке отправки с клиента сообщения:
- идентификатор сообщения задан:
-- на сервере уже есть сообщение с таким id => отказ
-- на сервере нет такого id => отказ (возможно попытка поиска уязвимости)
- идентификатор не задан => отказ
Ответ написан
maxaon
@maxaon
Да, вы вполне корректно описали решение проблемы с повторной отправкой формы.
Однако лучше остановится на чем-то одном.
Перенаправлять пользователя и хранить массив сообщений в сессии. Выводить сообщения, потом удалять. Беспокоится о том, что пользователь заполнит форму, откроет другую вкладку с вашим сайтом, потом перейдет обратно, где была форма и это за 50-200 мс, думаю не стоит. Так сделано в ZF1 и ZF2 и много наверное где.
Второй вариант - перенаправлять пользователя по другому адресу, тоже можно, но это не так элегантно как в первом варианте.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
Весь текст вопроса не читал, лень :)
Вот так делаю я, после чтения и обработки полей (полученных данных)
$_POST = NULL;
header("Location: " . Url::$url);
exit();

данные передаются POST-ом
Url::$url - содержит ссылку на текущую страницу.
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Отправлять данные ajax'ом и пусть обновляют страницу, если надо.
Ответ написан
@coderxOne
Короче все просто..
после обработки данных сохраняете массив в сессии и делаете редирект на другую функцию, в другой функции проверяете на наличие сессии и выводите массив. Вот и все теперь при переходе на другую страницу не будет запроса на перезагрузку)).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
19 апр. 2024, в 03:01
1000 руб./за проект
18 апр. 2024, в 21:56
2000 руб./за проект
18 апр. 2024, в 21:00
150 руб./за проект