Избегая повторной отправки формы на php при нажатии клавиши f5
У меня на сайте есть следующий код (с использованием php и smarty), чтобы попытаться избежать повторной отправки формы при нажатии клавиши f5:
if ($this->bln_added == false) {
if (isset($_POST['submit'])) {
$this->obj_site->obj_smarty->assign('title', $_POST['tas_heading']);
$this->obj_site->obj_smarty->assign('desc', $_POST['tas_description']);
}
} else {
$this->obj_site->obj_smarty->assign('title', '');
$this->obj_site->obj_smarty->assign('desc', '');
unset($_POST);
}
Значение Bln_added по умолчанию равно false, но меняется на true после успешной отправки формы. Переменные smarty title и desc используются в шаблоне для сохранения содержимого формы на случай ошибки пользователя и необходимости изменить то, что они ввели.
Если форма отправлена успешно, она устанавливает bln_added = true, поэтому второй бит код должен не только очищать поля формы, но и очищать $_POST. Но если я нажму f5, данные записи все еще будут там.
Есть идеи?
10 answers
Ваш метод мог бы работать теоретически, но есть гораздо более простой способ.
После успешной отправки формы выполните перенаправление. Неважно, куда, но это очистит $_POST.
header('Location: http://www.example.com/form.php');
В вашем случае это звучит так, как будто вы хотите перенаправить на страницу, на которой вы уже находитесь. Добавьте параметр $_GET к URL-адресу, если вы хотите отобразить сообщение с подтверждением.
Надеюсь, это поможет,
Том
Решением является шаблон, обычно известный как Сообщение/Перенаправление/Получение
Лучший способ обработки форм - использовать самостоятельную отправку и перенаправление. Что-то вроде этого:
if (isset($_POST)) {
// Perform your validation and whatever it is you wanted to do
// Perform your redirect
}
// If we get here they didn't submit the form - display it to them.
С использованием фреймворка CodeIgniter:
function index() {
$this->load->library('validation');
// Your validation rules
if ($this->form_validation->run()) {
// Perform your database changes via your model
redirect('');
return;
}
// The form didn't validate (or the user hasn't submitted)
$this->load->view('yourview');
}
Вы можете переписать свою форму-отправить в AJAX-способ. Если вам нужно показать HTML-контент, верните его в формате JSON и вставьте с помощью JavaScript (например, jQuery.)
Я решил эту проблему (на php) с помощью:
В форме добавьте уникальный идентификатор (идентификатор+счетчик), не основанный на времени() (!!!)
Опубликовать в отдельном файле (postform.php), который проверил наличие сеанса с этим уникальным идентификатором
-
A) если сеанс с уникальным идентификатором НЕ найден: отправьте сообщение в базу данных и заполните сеанс уникальным идентификатором
Б) если был найден сеанс с уникальным идентификатором: ничего не делать
После любого из 3a/3b перенаправление на страницу результатов с заголовком ('Местоположение: http://mydomain.com/mypage')
Результат:
никаких действий по повторной отправке для кнопки обновления/возврата и только предупреждение о повторной отправке при двойном нажатии кнопки возврата (но без повторной отправки)
Используйте расположение заголовка после успешного действия после публикации
header('Location: '.$_SERVER['HTTP_REFERER']);
Это работает для меня, если я использую либо заголовок(), либо выход() в конце своего кода, например, после сохранения некоторых данных.
Лучший метод, который я нашел, - это использование javascript и css. Заголовок обычного метода перенаправления php ('Местоположение: http://www.yourdomain.com/url ); будет работать, но это вызовет предупреждение "Предупреждение: Невозможно изменить информацию заголовка - заголовки уже отправлены" в разных фреймворках и cms, таких как wordpress, drupal и т.д. Поэтому я предлагаю следовать приведенному ниже коду
echo '<style>body{display:none;}</style>';
echo '<script>window.location.href = "http://www.siteurl.com/mysuccesspage";</script>';
exit;
Тег стиля важен, иначе пользователю может показаться, что страница загружена дважды. Если мы используем тег стиля с отображением тела нет, а затем обновите страницу, тогда пользовательский интерфейс будет таким же, как заголовок php ('Местоположение: ....);
Надеюсь, это поможет:)
Перенаправление заголовка после публикации необходимо, но недостаточно.
На стороне PHP после успешной отправки формы выполните перенаправление. Например, заголовок ('Местоположение: http://www.example.com/form.php');
Но этого недостаточно. Некоторые пользователи нажимают ссылки дважды (двойной клик). Требуется JavaScript, который отключил бы кнопку отправки после первого нажатия.
Попробуйте мой собственный, возможно, это не лучшее решение (сделано быстро), но я протестировал его, и он работает. Протестировано на Chrome. Нажмите, чтобы посмотреть, как это выглядит BR
<?php
session_start(); // Start session
?>
<html>
<head>
<title>
Test
</title>
</head>
<body>
<form name="test" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>" method="post">
<input type="text" name="name"><br>
<input type="submit" name="submit" value="Submit Form"><br>
</form>
<?php
if(isset($_POST['submit']))
{
$_SESSION['name'] = $_POST['name']; // Assign $_POST value to $_SESSION variable
header('Location: refresh.php'); // Address of this - reloaded page - in this case similar to PHP_SELF
} else session_destroy(); // kill session, depends on what you want to do / maybe unset() function will be enough
if(isset($_SESSION['name']))
{
$name = $_SESSION['name'];
echo "User Has submitted the form and entered this name : <b> $name </b>";
echo "<br>You can use the following form again to enter a new name.";
}
?>
</body>
</html>