Как избежать повторной отправки формы в 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 ответов

Решение

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

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

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

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

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

Том

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

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

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

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

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

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

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

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

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

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

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

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

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

header('Location: '.$_SERVER['HTTP_REFERER']);

Ответ , который вы ищете, - это волшебный лайнер: header('Location: '.$_SERVER['HTTP_REFERER']);

например

if(isset['submit']){
    //insert database
    header('Location: '.$_SERVER['HTTP_REFERER']);
}

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

На стороне PHP после успешной отправки формы выполните перенаправление. Например. заголовок ('Location: 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>
Другие вопросы по тегам