Запретить повторную отправку формы после нажатия кнопки "Назад"

Я просмотрел много сообщений здесь и в других местах, но, похоже, не нашел решения своей проблемы. У меня есть страница, на которой отображаются записи базы данных: database.php. Эти записи можно фильтровать с помощью формы. Когда я фильтрую их и отображаю только те, которые мне интересны, я могу щелкнуть запись (как ссылку), которая приведет меня на эту страницу записей (через php GET). Когда я нахожусь на этой странице записей (т.е. "view.php? Id = 1") и нажимаю кнопку "Назад" (назад к database.php), форма фильтра требует подтверждения повторной отправки формы. Есть ли способ предотвратить это?

вот несколько (упрощенных) примеров кода:

Database.php:

<form>
    <select>
        <option>1</option>
        <option>2
        <option>
    </select>
    <input type="submit" name="apply_filter" />
</form>
<?php
if ( isset( $_POST[ "apply_filter" ] ) ) { // display filtered entries
    $filter = $_POST[ "filter" ];
    $q = "Select * from table where col = '" . $filter . "'";
    $r = mysql_query( $q );
} else { // display all entries
    $q = "Select * from table";
    $r = mysql_query( $q );
}
while ( $rec = mysql_fetch_assoc( $r ) ) {
    echo "<a href='view.php?id=" . $rec[ "id" ] . "'>" . $rec[ "name" ] . "</a><br />"; // this is where the link to the view.php page is...
}
?>

Как уже упоминалось, если я нажму на ссылку, я перейду на «view.php? Id = something». На этой странице я просто получаю идентификатор из URL-адреса для отображения этой единственной записи:

view.php:

<?php
$id = $_GET[ "id" ];
$q = "Select * from table where id = '" . $id . "'";
$r = mysql_query( $q );
while (  ) {
    // display entry
}

?>

Если я сейчас нажму кнопку «Назад», форма на database.php (та, которая используется для фильтрации результатов БД) потребует подтверждения для повторной отправки. Это не только очень раздражает, но и бесполезно для меня.

Как я могу это исправить? Надеюсь, примеров кода и объяснения моей проблемы достаточно. Если нет, дайте мне знать, и я постараюсь уточнить.


person user1889382    schedule 05.03.2013    source источник
comment
POST - ›ServerSide 302 Redirect -› GET   -  person scunliffe    schedule 05.03.2013
comment
Я знаю, что на эту тему есть масса сообщений. Просматривая их, я не мог понять свою проблему, поэтому решил задать ее как новый вопрос.   -  person user1889382    schedule 05.03.2013
comment
Вероятно, вы захотите использовать шаблон Post-Redirect-Get, см. en.wikipedia.org/wiki/Post/ Перенаправить / получить, а также stackoverflow.com/questions/15288229/   -  person Adrien Be    schedule 29.07.2014
comment
Возможный дубликат Запретить кнопку «Назад» отображать предупреждение о подтверждении POST   -  person Eugen Konkov    schedule 12.11.2017


Ответы (8)


Я знаю, что этот вопрос старый, но, столкнувшись с этой проблемой, я обнаружил, что работают две строки:

header("Cache-Control: no cache");
session_cache_limiter("private_no_expire");
person Ryan Konkolewski    schedule 21.10.2016
comment
где мы должны добавить эти строчки? - person ; 25.09.2017
comment
@ user3663 Я использовал его на всех страницах, но могу работать только на страницах интерфейса, например view.php в отношении вопроса OP. - person Ryan Konkolewski; 25.09.2017
comment
У меня ошибка при использовании session_cach_limiter. Я также использую session_start. Казалось, что это сработало, когда я не использовал session_cache_limiter (private_no_expire); и использовал session_start и header (Cache-Control: без кеша); Использовал его на странице с кнопкой отправки. - person Glen; 21.04.2020

Я знаю два способа сделать это. Простой и трудный путь.

Независимо от способа, когда вы имеете дело со страницей, основанной на состоянии (используя $_SESSION), что вы должны делать, чтобы ваши страницы оставались «живыми» и находились под вашим контролем, это предотвращает кеширование всех страниц следующим образом:

<?php
//Set no caching
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); 
header("Cache-Control: no-store, no-cache, must-revalidate"); 
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
?>

Сложный способ предполагает создание идентификатора и сохранение его где-нибудь на странице в виде скрытого ввода или &_SESSION cookie. Затем вы сохраняете тот же идентификатор на сервере, что и $_SESSION. Если они не совпадают, серия заранее запрограммированных операторов типа if else не приведет к тому, что страница будет повторно отправлена ​​(это то, что она пытается сделать, когда вы нажимаете кнопку "Назад").

Самый простой способ - просто перенаправить пользователя обратно на страницу отправки формы, если форма была отправлена ​​успешно, например:

header('Location: http://www.mydomain.com/redirect.php');

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

person Phillip Berger    schedule 05.03.2013
comment
Я не понимаю простого способа ... если пользователь находится на странице просмотра, нет возможности перенаправить его, так как я не знаю, как долго он хочет просматривать информацию на этой странице. Я включил кнопку перенаправления, которая возвращает пользователя на страницу формы; это не проблема. Проблема возникает только в том случае, если пользователь нажимает кнопку «Назад», чтобы вернуться ко всей БД. - person user1889382; 05.03.2013
comment
Вы должны отправить из своей формы Database.php, затем собрать всю информацию и перенаправить пользователя в конце этого сценария, используя URL-адрес стиля $_GET в вашем header('Location: http://www.mydomain.com/view.php?databse=this&somethingelse=that'); - person Phillip Berger; 05.03.2013

Одна вещь, которая может помочь, - это заставить вашу форму фильтра использовать метод GET вместо POST.

Браузеры обычно предотвращают POST автоматическую повторную отправку ввода, чего они не делают, когда используется GET ввод. Кроме того, это позволит пользователям ссылаться на вашу страницу с помощью фильтра.

person tanios    schedule 30.11.2013
comment
Это решение лучше всего подходит для форм поиска / фильтрации. Для создания / обновления формы лучше всего подходит перенаправление. - person Michał Maluga; 02.09.2015

Я использовал ответ на Как определить, перешел ли пользователь на страницу с помощью кнопки" Назад "?, чтобы определить, было ли посещение вызвано нажатием кнопки" Назад "в браузере, а затем, если это В таком случае я использовал JavaScript для перезагрузки страницы. Когда страница перезагружается, мой код уже обрабатывает соответствующие проверки, чтобы форма никогда не отправлялась дважды. Важной частью в моем случае была принудительная перезагрузка страницы при повторном посещении формы после нажатия кнопки возврата в браузере. Это мой код в URL-адресе, к которому я хотел применить эту проверку:

<script type="text/javascript">
    if (window.performance && window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD) {
        location.reload();
    }
</script>
person Jaime Montoya    schedule 29.01.2019

header("Cache-Control: no cache");

session_cache_limiter("private_no_expire");

ПРИМЕЧАНИЕ. После использования данных публикации, которые вы отправили из формы, эти две строки следует использовать в конце функции. Поэтому, когда мы вернемся на перенаправленную страницу, она не попросит вас повторно отправить страницу. Это сработает.

person Hemanth Paidiparthi    schedule 18.07.2019

Альтернативное решение, которое также работает, если / когда страница перезагружается, включает проверку оригинальности сообщения с помощью $ _SESSION. Короче говоря, проверьте уникальную или случайную строку.

В форме добавьте элемент ввода со значением, установленным с помощью rand () или microtime ():

<input type="hidden" name="formToken" value="<?php echo microtime();?>"/>

А затем оберните функцию PHP для проверки и анализа данных формы в блоке if:

if(!isset($_SESSION['formToken']) || $_POST['formToken'] !== $_SESSION['formToken'])){
       $_SESSION['formToken'] = $_POST['formToken'];
      /*continue form processing */
}
person SilentStone    schedule 25.01.2018

Решение, которое работает для меня, это

$(document).ready( function() {
//prevent form submit on refresh or resubmit with back button
if ( window.history.replaceState ) window.history.replaceState( null, null, window.location.href );
}
person tsig    schedule 17.08.2020

Вам необходимо удалить запрос, который POST данные из истории браузера

history.replaceState("", "", "/the/result/page")

См. этот ответ

Также вы можете следовать шаблону Post/Redirect/Get.

person Eugen Konkov    schedule 12.11.2017