Comments 30
Просто не делайте переадресацию если форма оказалась невалидной.
+19
А я уже и забыл как это отправлять не ассинхронные запросы :)
+5
Или можно сделать отправку данных формы через ajax, сразу проверить валидность, выдать комментарии по ошибкам, если таковые нашлись, а в случае успешной отправки убрать саму форму, оставив сообщение о том, что данные отправлены. При необходимости, можно после этого устроить редирект на нужную страницу. Обязательно на время отправки данных и получения отклика заблокировать возможность повторной отправки.
Как альтернатива — блокировать повторную отправку формы одним пользователем на определенное время. Например, на минуту-две. Чаще всего истории с повторными отправками случаются, когда человек сразу или почти сразу пытается вернуться назад, а через пару минут эта проблема уже не так часто случается… хотя, это вариант не особо надежный — для ленивых.
Как альтернатива — блокировать повторную отправку формы одним пользователем на определенное время. Например, на минуту-две. Чаще всего истории с повторными отправками случаются, когда человек сразу или почти сразу пытается вернуться назад, а через пару минут эта проблема уже не так часто случается… хотя, это вариант не особо надежный — для ленивых.
+1
Если данные были некорректны — то зачем редирект на самого себя, они ничем не угрожают?
Проблема ведь именно в непреднамеренном повторении запрошенного действия и делать редирект надо только если форма успешно прошла валидацию и выполнено запрошенное действие.
Проблема ведь именно в непреднамеренном повторении запрошенного действия и делать редирект надо только если форма успешно прошла валидацию и выполнено запрошенное действие.
+2
Удивительно! Я пока писал эту статью, меня как раз посетила эта мысль: а какого фига я вообще редиректю если форма заполнена не правильно? Ведь можно редиректить только после успешной отправки. Выдать сообщение «ваши данные отправлены, все гуд».
Видимо, пока писал, невольно все прокрутил в башке и дошел до такой вот мысли.
Спасибо за то что подкрепили ее!
Видимо, пока писал, невольно все прокрутил в башке и дошел до такой вот мысли.
Спасибо за то что подкрепили ее!
+1
Тогда вопрос вот в чем: как узнать что произошла успешная отправка и нужно делать переадресацию? Ведь header нужно вызывать раньше любого вывода на экран, иначе не работает. Поэтому header в моих кодах всегда стоит «выше» всего остального. И функция, которая его вызывает, ориентируется на $_POST, в котором содержится идентификатор нажатой кнопки. Т.е. функция проверяет $_POST['send_message'] и если есть такое, то вызывает редирект.
Теперь же, после того как мы решили, что редирект не нужно вызывать все время когда нажата send_message, а только в момент когда она нажата и произошла УСПЕШНАЯ отправка. Как отследить этот момент? Нужно тогда чтобы функция, вызывающая редирект, «видела» признак успешной отправки, возвращенный функцией отправки. А в моей структуре это невозмножно. Распределение зон видимости не позволяет.
Теперь же, после того как мы решили, что редирект не нужно вызывать все время когда нажата send_message, а только в момент когда она нажата и произошла УСПЕШНАЯ отправка. Как отследить этот момент? Нужно тогда чтобы функция, вызывающая редирект, «видела» признак успешной отправки, возвращенный функцией отправки. А в моей структуре это невозмножно. Распределение зон видимости не позволяет.
-2
Это проблема вашей структуры, в нормальной ситуации вся логика отрабатывает до начала любого вывода.
Поройте на досуге исходники популярных фреймворков.
Тем не менее, в качестве решения можно применять буферизацию вывода.
Поройте на досуге исходники популярных фреймворков.
Тем не менее, в качестве решения можно применять буферизацию вывода.
+3
Вам точно нужно изменить структуру вашего web приложения. С таким подходом, как у вас, вы закопаетесь в коде и вскоре его поддержка выльется в мысль, а возьму-ка я и перепишу весь сайт нафиг. Гуглите в сторону MVC подхода, а по проблеме, что вы обозначили — делайте все проверки ДО ТОГО как будете выводить HTML.
+3
есть более простое: ru.wikipedia.org/wiki/Post/Redirect/Get
Редирект надо делать только после успешной обработки формы. А при ошибках это делать не обязательно.
И — да, это тянет на вопрос, а совсем не на статью.
Редирект надо делать только после успешной обработки формы. А при ошибках это делать не обязательно.
И — да, это тянет на вопрос, а совсем не на статью.
0
Да, пардон, ошибся! А теперь никак не могу поменять пост на вопрос. Это вообще возможно? Выбираю «вопрос» обновляется страница и предлагается создать новый.
0
А разве ru.wikipedia.org/wiki/Post/Redirect/Get — это примерно не то о чем я говорил?
0
Да, как раз об этом пишу.
Я почему-то полагал, что в описание паттерна входит и обработка ошибок. А сейчас посмотрел — там просто про редирект.
Так что мой комментарий оказался лишним, стоило просто плюсануть самый первый.
Напишу тогда про сессии.
С ними тоже не всё слава богу: если удалять данные поста сразу после редиректа, то перезагрузка страницы позволит-таки юзеру очистить форму от введённых в нее данных (понятно, что он будет сам дурак, но ведь юзабилити — это и есть забота о как раз таких вот пользователях...).
А если удалять после успешной обработки, то надо предусматривать наличие в сессии зоопарка из заполненных форм — пользователи часто заполняют по две сразу.
Я почему-то полагал, что в описание паттерна входит и обработка ошибок. А сейчас посмотрел — там просто про редирект.
Так что мой комментарий оказался лишним, стоило просто плюсануть самый первый.
Напишу тогда про сессии.
С ними тоже не всё слава богу: если удалять данные поста сразу после редиректа, то перезагрузка страницы позволит-таки юзеру очистить форму от введённых в нее данных (понятно, что он будет сам дурак, но ведь юзабилити — это и есть забота о как раз таких вот пользователях...).
А если удалять после успешной обработки, то надо предусматривать наличие в сессии зоопарка из заполненных форм — пользователи часто заполняют по две сразу.
0
Если ты сделал какую-то ошибку в кодах (которая проявляется именно в момент отправки), то она даже не высветится, т.к. произойдет переадресация и ты даже не увидишь сообщение об ошибке.
В дев-окружении появится две ошибки (если первая не фатальная) — основная и headers already sent или как там её. В продакшене — основная зафиксируется в логах (а пользователю её показывать всё равно незачем). Если же так сильно боитесь её пропустить, то можно сделать два ридиректа в случае ошибки валидации, что-то вроде:
— form.php — вывод формы с полями по умолчанию из $_SESSION и ошибками оттуда же.
— form_prehandler — тупое заполнение $_SESSION из формы с очисткой ошибок и редиректом на form_handler.php (вероятность допустить ошибку минимальна)
— form_handler — валидация и основная обработка, с редиректом в случае ошибок на form.php
В дев-окружении появится две ошибки (если первая не фатальная) — основная и headers already sent или как там её. В продакшене — основная зафиксируется в логах (а пользователю её показывать всё равно незачем). Если же так сильно боитесь её пропустить, то можно сделать два ридиректа в случае ошибки валидации, что-то вроде:
— form.php — вывод формы с полями по умолчанию из $_SESSION и ошибками оттуда же.
— form_prehandler — тупое заполнение $_SESSION из формы с очисткой ошибок и редиректом на form_handler.php (вероятность допустить ошибку минимальна)
— form_handler — валидация и основная обработка, с редиректом в случае ошибок на form.php
-1
Use the AJAX, Luke!
-3
>И продолжаю задаваться вопросом: а есть ли другие, более элегантные решения?
Допустим форма и ее обработчик находятся в form.php (это только для простоты):
Допустим форма и ее обработчик находятся в form.php (это только для простоты):
<?
...
if (isset($_POST["secret"]) && $_POST["secret"] != $_SESSION["secret"] )
{
// Произошла повторная отправка, принимаем меры
}
else
{
// Все отлично, можем обрабатывать данные
}
...
$_SESSION["secret"] = mt_random();
...
// Вывод формы
?>
...
<input type="hidden" value="<?=$_SESSION["secret"]?>" />
...
-1
Вы, я уверен, такое решение никогда на практике не использовали.
0
Такой эффект получался от использования псевдокапчи.
Какие у этого решения недостатки?
Какие у этого решения недостатки?
0
Пользователи имеют склонность открывать больше одной страницы сайта.
Как минимум, нужно иметь пул этих «секретов».
Но я сейчас не о недостатках конкретно этого метода, а о недостатках сайтов типа хабрахабр. На которых можно увидеть миллион полезных советов… которые никто из советчиков никогда не применял на практике. А все только лишь переписывают друг у друга.
Как минимум, нужно иметь пул этих «секретов».
Но я сейчас не о недостатках конкретно этого метода, а о недостатках сайтов типа хабрахабр. На которых можно увидеть миллион полезных советов… которые никто из советчиков никогда не применял на практике. А все только лишь переписывают друг у друга.
0
> Как минимум, нужно иметь пул этих «секретов»
Не вижу в этом проблемы.
>На которых можно увидеть миллион полезных советов… которые никто из советчиков никогда не применял на практике. А все только лишь переписывают друг у друга.
Пожалуй, это не про меня.
Не вижу в этом проблемы.
>На которых можно увидеть миллион полезных советов… которые никто из советчиков никогда не применял на практике. А все только лишь переписывают друг у друга.
Пожалуй, это не про меня.
0
Почему же, я, например такой подход применял и могу сказать, что это лучше, чем ничего. Такой подход вполне жизнеспособен, в случае если мы в любом случае каждому посетителю стартуем сессию.
0
Блин, случайно плюсанул, извините.
-1
Раз уж вы так заморочились, и раз не подходит аякс, постите в iframe. Старо как интернет
1. Указываем в target атрибуте формы имя iframe (скрытого или сгенеренного на onsubmit)
2. В качестве ответа на POST в iframe выводится JS, который совершает в top или parent необходимые действия (вывод ошибки, очистка полей и т.д.) либо устанавливает новый document.location
3. Profit
Плюс: не надо заморачиваться с повторной подстановкой данных формы из POST
Минус: iframe, ну и не очень элегантно
1. Указываем в target атрибуте формы имя iframe (скрытого или сгенеренного на onsubmit)
2. В качестве ответа на POST в iframe выводится JS, который совершает в top или parent необходимые действия (вывод ошибки, очистка полей и т.д.) либо устанавливает новый document.location
3. Profit
Плюс: не надо заморачиваться с повторной подстановкой данных формы из POST
Минус: iframe, ну и не очень элегантно
-2
Вот уже 5 лет я использую следующий простой принцип:
1. Тэг form ничего никуда отправляет, он служит скорее для группировки полей, но в принципе можно обойтись и без него. Очень часто я использую div — это не имеет большого значения.
2. По событию нажатия на submit (или какому-то другому — для сложных форм) js собирает данные из контролов и отправляет их на адрес обработчика с помощью ajax.
3. Обработчик на PHP (каждая форма считается объектом и у него есть просто метод onFormSubmit()) анализирует данные и через JSON возвращает последовательность простых команд по дальнейшей работе клиента. Это могут быть: подсветить поле(-я), вывести alert, сделать редирект, выполнить js-код или обновить кусок DOM. Редирект не делается только в том случае, если есть ошибки в форме и надо повторить отправку после их исправления.
Куда делать редирект — решает сам контроллер, и это, я считаю, правильно. Сам клиент ничего не валидирует и не принимает никаких решений (валидация на клиенте бессмысленна), а просто следует командам сервера.
1. Тэг form ничего никуда отправляет, он служит скорее для группировки полей, но в принципе можно обойтись и без него. Очень часто я использую div — это не имеет большого значения.
2. По событию нажатия на submit (или какому-то другому — для сложных форм) js собирает данные из контролов и отправляет их на адрес обработчика с помощью ajax.
3. Обработчик на PHP (каждая форма считается объектом и у него есть просто метод onFormSubmit()) анализирует данные и через JSON возвращает последовательность простых команд по дальнейшей работе клиента. Это могут быть: подсветить поле(-я), вывести alert, сделать редирект, выполнить js-код или обновить кусок DOM. Редирект не делается только в том случае, если есть ошибки в форме и надо повторить отправку после их исправления.
Куда делать редирект — решает сам контроллер, и это, я считаю, правильно. Сам клиент ничего не валидирует и не принимает никаких решений (валидация на клиенте бессмысленна), а просто следует командам сервера.
0
Sign up to leave a comment.
Повторная отправка данных формы при обновлении страницы