Страничка, форма. Заполенная данными. Нажат "субмит", данные ушли и обработались. Человек зачем-то делает "релоад", у него спрашивают "повторить данные?" Он жмёт йес и я имею проблему. Как с ней бороться? Как обнулить "пост" после передачи?
>Страничка, форма. Заполенная данными. Нажат "субмит", данные ушли и обработались. Человек зачем-то
>делает "релоад", у него спрашивают "повторить данные?" Он жмёт йес и
>я имею проблему. Как с ней бороться? Как обнулить "пост" после
>передачи?
Боролся с этим же и буду признателен, если кто-нибудь подскажет стандартное решение. Однако, как я понимаю от скрипта тут уже мало что зависит - данные с формы ушли и тут уже апач и броузер общаются.Браузер: повторить
Апачь: ты засылал посты мне их же принять?
Браузер: да
Апачь: пожалуйстапо-моему так...
>>Страничка, форма. Заполенная данными. Нажат "субмит", данные ушли и обработались. Человек зачем-то
>>делает "релоад", у него спрашивают "повторить данные?" Он жмёт йес и
>>я имею проблему. Как с ней бороться? Как обнулить "пост" после
>>передачи?
>Боролся с этим же и буду признателен, если кто-нибудь подскажет стандартное решение.
>Однако, как я понимаю от скрипта тут уже мало что зависит
>- данные с формы ушли и тут уже апач и броузер
>общаются.
>
>Браузер: повторить
>Апачь: ты засылал посты мне их же принять?
>Браузер: да
>Апачь: пожалуйста
>
>по-моему так...Более логичным кажется проверка самим броузером, что он уже эти данные отправлял. Это проще, и главное - быстрее: предотвращается лишнее обращение к серверу. Учитывая, что запрос на повторную отправку возникает практически мгновенно - похоже, так оно и есть. ;-)
Кстати, не во всех броузерах и не всегда запрос вообще возникает. В той же Опере...
Но это все теория.Как бороться? Не знаю, можно ли вообще как-то обнулить пост...
Я, например, делаю так.Если данные формы ДОБАВЛЯЮТСЯ в таблицу, то перед их сохранением специальный кусок кода проверяет по таблице, не были ли они уже сохранены. Проверка может быть либо по уникальному полю (например, в таблице юзеров не может быть два одинаковых логина), либо, если такового нет - по всему набору данных. Если данные уже есть, об этом сообщается пользователю.
Под уникальностью поля я в данном случае подразумевал просто логическую уникальность, хотя можно это зафиксировать и в описании структуры таблицы.Если данные ОБНОВЛЯЮТ какую-то запись, то можно, в принципе, никаких проверок и не делать. Ну, обновит юзер запись одними и теми же данными дважды. Можно все-таки рассчитывать, что далеко не каждый юзер будет жать F5, и слишком много лишних бессмысленных запросов к базе не будет :-)
У вышеописанного подхода есть свои минусы: подразумевается лишний запрос к базе. Но у меня, как правило, возникает потребность не просто исключить повторную отправку формы, а исключить вообще вторичный ввод данных, дублирование. Скажем, на условном примере с таблицей юзеров: я могу не посылать форму повторно, но попытаться завтра зарегистрировать пользователя с таким же логином. Что тогда? Поэтому меня такой подход устраивает. Думаю, что и Вы "имеете проблему" именно в таком ключе.
Если все же для Вас запрет повторной обработки формы достаточен (т.е. "завтра" пусть вводят то же самое заново), то приходит в голову такой вариант: при выдаче формы пользователю сгенерировать уникальный идентификатор формы, который поместить в скрытый элемент ввода. При передаче данных формы сначала проверять, не зарегистрирован ли в сессии идентификатор формы. Если нет - обработать данные и зарегистрировать. Если да - ничего не делать.
Еще вариант. После обработки данных формы пользователю что-то выводится-сообщается. Сделать чтобы это "что-то" выводилось не непосредственно сразу, в том же куске кода, что обрабатывал форму, а в результате редиректа. Скажем, редирект на страничку, которая сообщает: Ваши данные сохранены. Или на страничку, которая показывает резутьтаты обработки данных. После редиректа, сколько ни жми F5 - будет запрашиваться именно эта страничка без повторной отправки формы.
Удачи!
>Более логичным кажется проверка самим броузером, что он уже эти данные отправлял.
^^^^^^^^^^^
Это как ???
Броузер не МОЖЕТ САМ ДЕЛАТЬ запрос к удаленной базе данных!!!!!!
Это делают скрипты на WEB-сервере!!!!>Это проще, и главное - быстрее: предотвращается лишнее обращение к серверу.
>Учитывая, что запрос на повторную отправку возникает практически мгновенно - похоже,
>так оно и есть. ;-)
>Кстати, не во всех броузерах и не всегда запрос вообще возникает. В
>той же Опере...
>Но это все теория.
>
>Как бороться? Не знаю, можно ли вообще как-то обнулить пост...
>Я, например, делаю так.
>
>Если данные формы ДОБАВЛЯЮТСЯ в таблицу, то перед их сохранением специальный кусок
>кода проверяет по таблице, не были ли они уже сохранены. Проверка
>может быть либо по уникальному полю (например, в таблице юзеров не
>может быть два одинаковых логина), либо, если такового нет - по
>всему набору данных. Если данные уже есть, об этом сообщается пользователю.
^^^^^^^^^^^^^^
А ВЫ САМИ ПРОБОВАЛИ ЭТО ДЕЛАТЬ????>Под уникальностью поля я в данном случае подразумевал просто логическую уникальность, хотя
>можно это зафиксировать и в описании структуры таблицы.
>
>Если данные ОБНОВЛЯЮТ какую-то запись, то можно, в принципе, никаких проверок и
>не делать. Ну, обновит юзер запись одними и теми же данными
>дважды. Можно все-таки рассчитывать, что далеко не каждый юзер будет жать
>F5, и слишком много лишних бессмысленных запросов к базе не будет
>:-)
>
>У вышеописанного подхода есть свои минусы: подразумевается лишний запрос к базе. Но
>у меня, как правило, возникает потребность не просто исключить повторную отправку
>формы, а исключить вообще вторичный ввод данных, дублирование. Скажем, на условном
>примере с таблицей юзеров: я могу не посылать форму повторно, но
>попытаться завтра зарегистрировать пользователя с таким же логином. Что тогда? Поэтому
>меня такой подход устраивает. Думаю, что и Вы "имеете проблему" именно
>в таком ключе.
>
>Если все же для Вас запрет повторной обработки формы достаточен (т.е. "завтра"
>пусть вводят то же самое заново), то приходит в голову такой
>вариант: при выдаче формы пользователю сгенерировать уникальный идентификатор формы, который поместить
>в скрытый элемент ввода. При передаче данных формы сначала проверять, не
>зарегистрирован ли в сессии идентификатор формы. Если нет - обработать данные
>и зарегистрировать. Если да - ничего не делать.
>
>Еще вариант. После обработки данных формы пользователю что-то выводится-сообщается. Сделать чтобы это
>"что-то" выводилось не непосредственно сразу, в том же куске кода, что
>обрабатывал форму, а в результате редиректа. Скажем, редирект на страничку, которая
>сообщает: Ваши данные сохранены. Или на страничку, которая показывает резутьтаты обработки
>данных. После редиректа, сколько ни жми F5 - будет запрашиваться именно
>эта страничка без повторной отправки формы.
Самый простой вариант - после отправки формы использовать JAVA-SCRIPT<script language="JavaScript"><!-- window.location.href = "your_page.html" // --></script>
>>Более логичным кажется проверка самим броузером, что он уже эти данные отправлял.
>^^^^^^^^^^^
>Это как ???
>Броузер не МОЖЕТ САМ ДЕЛАТЬ запрос к удаленной базе данных!!!!!!
>Это делают скрипты на WEB-сервере!!!!
>
Да что Вы говорите? Никогда бы не подумал! ;-)))
Уважаемый, Вы "слышали звон..."
Почитайте внимательней этот тред. Я не предлагал каким-то образом заставлять броузер лезть в базу. Речь шла о том, как сам броузер определяет, что данные уже были отправлены. Он же Вам выдает запрос на повторную отправку формы, не так ли? Почитайте пост ╧1. Там человек предположил, кто это контролирует (Апач). А я предположил (поставив себя на место разработчиков), что это логичнее реализовать в броузере. Да, я считаю, что броузер сам контролирует, что вы пытаетесь отправить форму повторно. А Апач сколько раз получит одну и ту же форму, столько раз ее и обработает. Вы не согласны? Возразите по существу!>>Если данные формы ДОБАВЛЯЮТСЯ в таблицу, то перед их сохранением специальный кусок
>>кода проверяет по таблице, не были ли они уже сохранены. Проверка
>>может быть либо по уникальному полю (например, в таблице юзеров не
>>может быть два одинаковых логина), либо, если такового нет - по
>>всему набору данных. Если данные уже есть, об этом сообщается пользователю.
>^^^^^^^^^^^^^^
>А ВЫ САМИ ПРОБОВАЛИ ЭТО ДЕЛАТЬ????
Да, я пробовал. И не надо так шуметь! ;-) Что Вас смущает?
У меня по такому принципу не один проект работает. Я не советую автору гостевой делать так, поскольку оговаривал, что все еще зависит от поставленных задач. Хотя в начале дискуссии я и не знал, что речь идет о гостевой. Да, в гостевой не очень хорошо делать проверку по тексту, был уже такой или нет. Но я поделился СВОИМ опытом. Т.к. вопрос задал один человек, а возникать он мог еще у кого-то, читающих рассылку. И не все пишут гостевую.
Проверять по всему набору данных (имелось ввиду по всему набору полей или какой-то его части, обеспечивающей уникальность) - это, конечно, крайний случай, если нет уникальных полей. В моих проектах эти поля есть. Поэтому проверяю по ним. И другого выхода не вижу, исходя из своих задач. Я приводил пример, почитайте посты: если вести таблицу юзеров, то мне не только надо отфутболить повторную форму в течение ближайших 10 минут, но и завтра, послезавтра и т.д. отфутболить любую попытку завести юзера с тем же логином еще раз. Как Вы предлагаете это делать? Java-скриптом?!>>Еще вариант. После обработки данных формы пользователю что-то выводится-сообщается. Сделать чтобы это
>>"что-то" выводилось не непосредственно сразу, в том же куске кода, что
>>обрабатывал форму, а в результате редиректа. Скажем, редирект на страничку, которая
>>сообщает: Ваши данные сохранены. Или на страничку, которая показывает резутьтаты обработки
>>данных. После редиректа, сколько ни жми F5 - будет запрашиваться именно
>>эта страничка без повторной отправки формы.
>
>
>Самый простой вариант - после отправки формы использовать JAVA-SCRIPT
>
><script language="JavaScript"><!-- window.location.href = "your_page.html" // --></script>
>
Вы сказали то же самое другими словами. Плюс сообщили нам выше прописные истины о том, кто может делать запрос к базе. В итоге, ничего нового, зато на 2 Ваших строчки пол-страницы квотинга. Поэкономнее надо бы...
И еще. Да, это самый простой вариант в случае для гостевой. И я его даже повторно предлагал (см. пост ╧8, 2 абзац). Хотя вариант со скрытым полем В СЛУЧАЕ ГОСТЕВОЙ вполне приемлем и даже экономит время, т.к. не надо сначала получать Java-скрипт, а потом уже по нему переходить.
А вот для примера с таблицей юзеров редирект - это не выход. Так что проверка наличия записи в базе - вполне обоснованный подход ДЛЯ СВОЕГО КРУГА ЗАДАЧ. Напомню еще раз, что в начале дискуссии не было ясно, какие задачи решает автор вопроса.
http://xpoint.ru/archive/threads/50/10087.html
Почитайте здесь- все уже давно открыто и изобретено. Осталось только пользовать =)
Ирония судьбы! По техническим причинам мое сообщение задвоилось, и именно в дискуссии о повторной отправке формы :-) Прошу у всех прощения.
Бороться можно легко, если саму страничку с формой тоже генерировать скриптом :формируешь на ней поле hidden с уникальным ключом (например функцией time)
и, при получении поста скрипт обрабатывающий отосланную форму должен проверить, приходила-ли уже форма с таким ключом.
>Бороться можно легко, если саму страничку с формой тоже генерировать скриптом :
>
>
>формируешь на ней поле hidden с уникальным ключом (например функцией time)
>и, при получении поста скрипт обрабатывающий отосланную форму должен проверить, приходила-ли уже
>форма с таким ключом.да, это выход. Кстати, применительно к гостевухе (а у меня эта проблема именно там) можно не делать лишнюю проверку-запрос к мускулу а просто смотреть - пришёл unix-time, смотрим скока времени щаз. Если разность больше там скажем 10 (20,30) сек - не кладём в базу.
>Кстати, применительно к гостевухе (а у меня эта проблема
>именно там) можно не делать лишнюю проверку-запрос к мускулу а просто
>смотреть - пришёл unix-time, смотрим скока времени щаз. Если разность больше
>там скажем 10 (20,30) сек - не кладём в базу.А если повторный запрос придет через 9 (19, 29) сек? ;-)))
При таком подходе никогда не будешь уверен, что он всегда срабатывает верно. С одной стороны, чтобы юзер уж точно не успел послать форму повторно, надо поставить время как можно меньше. С другой стороны, чтобы сервер не отбивал ошибочно тех, у кого слабый коннект, надо время поставить больше. М-да... Где здесь золотая середина?
>>Кстати, применительно к гостевухе (а у меня эта проблема
>>именно там) можно не делать лишнюю проверку-запрос к мускулу а просто
>>смотреть - пришёл unix-time, смотрим скока времени щаз. Если разность больше
>>там скажем 10 (20,30) сек - не кладём в базу.
>
>А если повторный запрос придет через 9 (19, 29) сек? ;-)))
>При таком подходе никогда не будешь уверен, что он всегда срабатывает верно.
>С одной стороны, чтобы юзер уж точно не успел послать форму
>повторно, надо поставить время как можно меньше. С другой стороны, чтобы
>сервер не отбивал ошибочно тех, у кого слабый коннект, надо время
>поставить больше. М-да... Где здесь золотая середина?
Согласен, это надо экспериментальным путём посчитать... :)
Например, ставим 10 и смотрим появляются ли повторные сообщения или жалобы пользователей. Плохо, если появятся и те и те :)
Ну, а вообще, тут надо подумать и понаблюдать за средним юзверем - ведь любой интерфейс пользователя он точится под людей в первую очередь.
Написал человек, заслал... Пробежался ещё раз глазами своё творение... Нажал Ф5... Короче, надо посадить 50 испытуемых разного возраста, обтыкать датчиками и собрать статистику... :))
>Согласен, это надо экспериментальным путём посчитать... :)
>Например, ставим 10 и смотрим появляются ли повторные сообщения или жалобы пользователей.
>Плохо, если появятся и те и те :)
>Ну, а вообще, тут надо подумать и понаблюдать за средним юзверем -
>ведь любой интерфейс пользователя он точится под людей в первую очередь.
>
>Написал человек, заслал... Пробежался ещё раз глазами своё творение... Нажал Ф5... Короче,
>надо посадить 50 испытуемых разного возраста, обтыкать датчиками и собрать статистику...
>:))посмотрел сейчас в базе все случаи повторной заысылки сообщений и вывел что в основном все начинают жмакать рефрешь - через секунд 30-45
однако было 2 случая, где пауза была 2 сек. 1 из них был умышленным.
вообщем, как я и сказал - начну пока с десяточки.
>посмотрел сейчас в базе все случаи повторной заысылки сообщений и вывел что
>в основном все начинают жмакать рефрешь - через секунд 30-45
Ну, народ-то эф-пятит, как правило, чтоб увидеть новые сообщения. :-)
И быстрее жмакать - нет смысла. Разве, из злого умысла - досадить автору гостевухи ;-)>вообщем, как я и сказал - начну пока с десяточки.
Да, видимо, в твоем случае это самое подходящее решение. Если кто и задвоит данные - это не критично. Многие гостевухи этим грешат - и ничего.
А вот я отказаться от более надежного метода подзапроса не могу. У меня задвоение - критично. Так что решение зависит от задач.
>>>Кстати, применительно к гостевухе (а у меня эта проблема
>>>именно там)
Кстати, раз это гостевуха, то тогда понятно, почему "человек ЗАЧЕМ-ТО делает релоад". После отправки сообщения он наверняка попадает на страничку сообщений, где показаны последние N сообщений, в том числе и его. Верно? Если да, то он обновляет страничку, чтоб увидеть, не ответил ли кто. Это естественно и удивляться нечему.
Сделай, чтобы скрипт после обработки формы не сразу выдавал эту страничку, а посылал редирект на нее. Можешь даже выдать сообщение типа "Все Ок, Ваши данные сохранены, через 5 сек. вы будете перемещены _туда_куда_надо_. Не хотите ждать - нажмите _ЗДЕСЬ_".
И все, никакой статистики.
Кое-где я такое видел, и теперь понимаю, для чего это сделано ;-)>Например, ставим 10 и смотрим появляются ли повторные сообщения или жалобы пользователей.
>Плохо, если появятся и те и те :)
Ага, особенно если появятся сообщения типа:
"Почему мои сообщения то не доходят, то задваиваются?"
"Почему мои сообщения то не доходят, то задваиваются?"
:-))))))))>Ну, а вообще, тут надо подумать и понаблюдать за средним юзверем -
>ведь любой интерфейс пользователя он точится под людей в первую очередь.
Тогда какая-то часть юзеров, _совпадающая_ по параметрам со "средним", будет иметь счастье. А остальные, у которых плюс-минус - одну из двух проблем.>Написал человек, заслал... Пробежался ещё раз глазами своё творение... Нажал Ф5... Короче,
>надо посадить 50 испытуемых разного возраста, обтыкать датчиками и собрать статистику...
>:))
Не только разного возраста, но и разного пола. Интересно ведь, кто чаще жмет Ф5 ;-)))
А зачем изобретать велосипед? Алгоритм прост как 3 копейки.1 страница:
форма, неважно какой метод, главное в action прописать страницу 2.2 страница:
обрабатываем данные пришедшие с первой страници (впихиваем в БД например)
после чего сразу редирект на любую другую страницу, или на первуюЕще от двойного сабмита можно защититься используя сессии...
согласен, но это можно уместить в один скрипт
например так:
#!/usr/bin/perluse CGI qw/:cgi/;
$do = param("Submit");
if ( $do =~ "Add")
{
AddNews();
print redirect("/cgi-bin/addnews.pl")
}elsif ( $do =~ 'Delete' )
{
DelNews();
print redirect("/cgi-bin/addnews.pl")
}elsif ( $do =~ 'Update' )
{
UpNews();
print redirect("/cgi-bin/addnews.pl")
}else { ShowNews(); }
... ( далее проезано )
>согласен, но это можно уместить в один скрипт
>например так:
>#!/usr/bin/perl
>
>use CGI qw/:cgi/;
>
>$do = param("Submit");
>if ( $do =~ "Add")
>{
> AddNews();
> print redirect("/cgi-bin/addnews.pl")
>}
>
>elsif ( $do =~ 'Delete' )
>{
> DelNews();
> print redirect("/cgi-bin/addnews.pl")
>}
>
>elsif ( $do =~ 'Update' )
>{
> UpNews();
> print redirect("/cgi-bin/addnews.pl")
>}
>
>else { ShowNews(); }
>... ( далее проезано )
Браво!Дельная мысль!!!!!!!
Все ТАК и должно быть и работает всегда как надо!!!!!