Как избежать повторной отправки формы в php при нажатии f5 - PullRequest
14 голосов
/ 06 апреля 2009

У меня на сайте есть следующий код (с использованием 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 ]

40 голосов
/ 06 апреля 2009

Ваш метод может работать теоретически, но есть гораздо более простой способ.

После успешной отправки формы выполните перенаправление. Неважно, куда, но он очистит $ _POST.

header('Location: http://www.example.com/form.php');

В вашем случае кажется, что вы хотите перенаправить на страницу, на которой вы уже находитесь. Добавьте параметр $ _GET к URL-адресу, если вы хотите отобразить подтверждающее сообщение.

Надеюсь, это поможет,

Tom

9 голосов
/ 06 апреля 2009

Решение - шаблон, обычно известный как Post / Redirect / Get

6 голосов
/ 06 апреля 2009

Лучший способ обработки форм - это использовать самопредставление и перенаправление. Примерно так:

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 Framework :

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');
}
2 голосов
/ 17 октября 2014

Вы можете переписать форму-заявку в AJAX-способ. Если вам нужно показать HTML-контент, верните его в JSON-формате и вставьте с помощью JavaScript (например, jQuery.)

1 голос
/ 23 июня 2017

Лучший метод, который я нашел, - это использование javascript и css. Общий метод перенаправления php header ('Location: 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;

Тег стиля важен, иначе пользователь может почувствовать, что страница загружена дважды. Если мы используем тег style с отсутствующим отображением тела, а затем обновляем страницу, пользовательский интерфейс будет аналогичен заголовку php ('Location: ....);

Надеюсь, это поможет:)

1 голос
/ 13 сентября 2015

Это работает для меня, если я использую header () или exit () в конце моего кода, например, после сохранения некоторых данных.

1 голос
/ 23 мая 2013

Использовать местоположение заголовка после успешного пост-действия

header('Location: '.$_SERVER['HTTP_REFERER']);
1 голос
/ 19 декабря 2011

Я решил это (в php):

  1. в форме добавить уникальный идентификатор (id + counter), не основанный на времени () (!!!)

  2. отправить в отдельный файл (postform.php), который проверил сеанс с этим уникальным идентификатором

  3. a) если сеанс с уникальным идентификатором НЕ был найден: отправить в базу данных и заполнить сеанс с уникальным идентификатором

    b) если был найден сеанс с уникальным идентификатором: ничего не делать

  4. после перенаправления 3a / 3b на страницу результатов с заголовком ('Location: http://mydomain.com/mypage')

Результат:
нет повторных действий при обновлении / нажатии кнопки и только повторное предупреждение при двойном щелчке по кнопке (но без повторного действия)

0 голосов
/ 03 февраля 2018

Попробуйте свой собственный, возможно, это не лучшее решение (сделано быстро), но я протестировал его, и оно работает. Проверено на 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>
0 голосов
/ 27 ноября 2011

Перенаправление заголовка после публикации необходимо, но недостаточно.

На стороне PHP после успешной отправки формы выполните перенаправление. Например. заголовок ('Местоположение: http://www.example.com/form.php');

Но этого недостаточно. Некоторые пользователи нажимают на ссылки дважды (двойной щелчок). Требуется JavaScript, который отключит кнопку отправки после первого клика.

...