Как предотвратить повторное заполнение формы при обновлении страницы (F5 / CTRL + R)

У меня есть простая форма, которая отправляет текст в мою таблицу SQL. Проблема в том, что после того, как пользователь отправит текст, они могут обновить страницу, и данные будут отправлены снова, не заполнив форму снова. Я мог перенаправить пользователя на другую страницу после отправки текста, но я хочу, чтобы пользователи оставались на одной странице.

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

Используйте шаблон Post / Redirect / Get. http://en.wikipedia.org/wiki/Post/Redirect/Get

На моем веб-сайте я буду хранить сообщение в cookie или сеансе, перенаправить после публикации, прочитать cookie / session, а затем очистить значение этой сессии или переменной cookie.

Вы действительно должны использовать шаблон Post Redirect Get для обработки этого, но если вы каким-то образом оказались в позиции, где PRG не является жизнеспособным (например, сама форма включена, предотвращая переадресацию), вы можете изменить некоторые параметры запроса создать строку на основе содержимого, а затем проверить, что вы ее еще не отправили.

 //create digest of the form submission: $messageIdent = md5($_POST['name'] . $_POST['email'] . $_POST['phone'] . $_POST['comment']); //and check it against the stored value: $sessionMessageIdent = isset($_SESSION['messageIdent'])?$_SESSION['messageIdent']:''; if($messageIdent!=$sessionMessageIdent){//if its different: //save the session var: $_SESSION['messageIdent'] = $messageIdent; //and... do_your_thang(); } else { //you've sent this already! } 
  1. Используйте заголовок и перенаправляйте страницу.

    header("Location:your_page.php"); Вы можете перенаправить на ту же страницу или на другую страницу.

  2. Unset $ _POST после вставки его в базу данных.

    unset($_POST);

Когда форма обрабатывается, вы перенаправляетесь на другую страницу:

 ... process complete.... header('Location: thankyou.php'); 

вы также можете перенаправить на ту же страницу.

если вы делаете что-то вроде комментариев и хотите, чтобы пользователь оставался на одной странице, вы можете использовать Ajax для обработки формы

Довольно верный способ – реализовать уникальный идентификатор в сообщении и кэшировать его в

 <input type='hidden' name='post_id' value='".createPassword(64)."'> 

Затем в коде выполните следующее:

 if( ($_SESSION['post_id'] != $_POST['post_id']) ) { $_SESSION['post_id'] = $_POST['post_id']; //do post stuff } else { //normal display } function createPassword($length) { $chars = "abcdefghijkmnopqrstuvwxyz023456789"; srand((double)microtime()*1000000); $i = 0; $pass = '' ; while ($i <= ($length - 1)) { $num = rand() % 33; $tmp = substr($chars, $num, 1); $pass = $pass . $tmp; $i++; } return $pass; } 

вы можете использовать форму повторной отправки через переменную сеанса.

сначала вам нужно установить rand () в текстовое поле и $ _SESSION ['rand'] на странице формы

 <form action="" method="post"> <?php $rand=rand(); $_SESSION['rand']=$rand; ?> <input type="hidden" value="<?php echo $rand; ?>" name="randcheck" /> Your Form's Other Field <input type="submit" name="submitbtn" value="submit" /> </form> 

После проверки $ _SESSION ['rand'] с текстовым полем $ _POST ['randcheck'] value Like

  if(isset($_POST['submitbtn']) && $_POST['randcheck']==$_SESSION['rand']) { //Your Code here } 

Просто переадресовывайте его на ту же страницу после использования данных формы, и он работает. Я попробовал.

 header('location:yourpage.php'); 

Утонченная версия сообщения Моба. Создайте хэш POST, сохраните его как файл cookie сеанса и сравните хеши с каждой сессии.

 // Optionally Disable browser caching on "Back" header( 'Cache-Control: no-store, no-cache, must-revalidate' ); header( 'Expires: Sun, 1 Jan 2000 12:00:00 GMT' ); header( 'Last-Modified: ' . gmdate('D, d MYH:i:s') . 'GMT' ); $post_hash = md5( json_encode( $_POST ) ); if( session_start() ) { $post_resubmitted = isset( $_SESSION[ 'post_hash' ] ) && $_SESSION[ 'post_hash' ] == $post_hash; $_SESSION[ 'post_hash' ] = $post_hash; session_write_close(); } else { $post_resubmitted = false; } if ( $post_resubmitted ) { // POST was resubmitted } else { // POST was submitted normally } 

Вставив его в базу данных, вызовите метод unset (), чтобы очистить данные.

снята с охраны ($ _ POST);

Чтобы предотвратить обновление данных обновления, выполните перенаправление страницы на ту же страницу или на другую страницу после вставки записи.

Заголовок ( 'Location:'. $ _ SERVER [ 'PHP_SELF']);

Я нашел следующее обходное решение. Вы можете избежать перенаправления после обработки запроса POST , манипулируя объектом history .

Итак, у вас есть HTML-форма:

 <form method=POST action='/process.php'> <input type=submit value=OK> </form> 

Когда вы обрабатываете эту форму на своем сервере, вы вместо перенаправления пользователя на /the/result/page настраиваете заголовок Location следующим образом:

 $cat process.php <?php process POST data here ... header('Location: /the/result/page'); exit(); ?> 

введите описание изображения здесь

После обработки POST данных вы выполняете небольшие <script> и результат /the/result/page

 <?php process POST data here render the <script> // see below render `/the/result/page` // OK ?> 

<script> вы должны сделать:

 <script> window.onload = function() { history.replaceState("", "", "/the/result/page"); } </script> 

Результат:

введите описание изображения здесь

так как вы можете видеть, что данные формы POST ed для скрипта process.php .
Этот скрипт обрабатывает POST данные и рендеринг /the/result/page сразу :

  1. перенаправление
  2. без повторных POST данных при обновлении страницы (F5)
  3. no re POST при переходе на предыдущую / следующую страницу через историю браузера

UPD

В качестве другого решения я попрошу функцию запросить команду Mozilla FireFox, чтобы разрешить пользователям настраивать заголовок NextPage который будет работать как заголовок Location и сделать post/redirect/get шаблон устаревшим.

Вкратце. Когда серверный процесс успешно формирует данные POST он:

  1. Настройка заголовка NextPage вместо Location
  2. Отобразить результат обработки данных формы POST который будет отображать для запроса GET в post/redirect/get pattern

Браузер, в свою очередь, видит заголовок NextPage :

  1. Отрегулируйте window.location со значением NextPage
  2. Когда пользователь обновляет страницу, браузер будет согласовывать GET с NextPage вместо данных формы POST

Я думаю, что это было бы превосходно, если бы реализовано, не так ли? =)

Я также хотел бы указать, что вы можете использовать подход javascript, window.history.replaceState чтобы предотвратить повторную window.history.replaceState на кнопку обновления и возврата.

 <script> if ( window.history.replaceState ) { window.history.replaceState( null, null, window.location.href ); } </script> 

Доказательство концепции здесь: https://dtbaker.net/files/prevent-post-resubmit.php

Я бы по-прежнему рекомендовал подход Post / Redirect / Get, но это новое решение JS.

Использование шаблона Post / Redirect / Get из ответа Keverw – хорошая идея. Тем не менее, вы не можете оставаться на своей странице (и я думаю, что это было то, о чем вы просили?) Кроме того, это может иногда терпеть неудачу :

Если веб-пользователь обновляется до того, как первоначальная подача завершилась из-за задержки сервера, в результате возникает дублированный запрос HTTP POST в определенных пользовательских агентах.

Другой вариант – сохранить в сеансе, если текст должен быть записан в вашу базу данных SQL следующим образом:

 if($_SERVER['REQUEST_METHOD'] != 'POST') { $_SESSION['writeSQL'] = true; } else { if(isset($_SESSION['writeSQL']) && $_SESSION['writeSQL']) { $_SESSION['writeSQL'] = false; /* save $_POST values into SQL */ } } 

Как предотвратить повторную отправку php-формы без перенаправления. Если вы используете $ _SESSION (после session_start) и форму $ _POST, вы можете сделать что-то вроде этого:

 if ( !empty($_SESSION['act']) && !empty($_POST['act']) && $_POST['act'] == $_SESSION['act'] ) { // do your stuff, save data into database, etc } 

В вашей html-форме поставьте это:

 <input type="hidden" id="act" name="act" value="<?php echo ( empty($_POST['act']) || $_POST['act']==2 )? 1 : 2; ?>"> <?php if ( $_POST['act'] == $_SESSION['act'] ){ if ( empty( $_SESSION['act'] ) || $_SESSION['act'] == 2 ){ $_SESSION['act'] = 1; } else { $_SESSION['act'] = 2; } } ?> 

Таким образом, каждый раз при отправке формы создается новый акт, хранящийся в сеансе и сравниваемый с постулированием.

Ps: если вы используете форму Get, вы можете легко изменить все POST с помощью GET, и он тоже работает.

Как говорили другие, невозможно использовать post / redirect / get. Но в то же время довольно легко сделать то, что вы хотите сделать на стороне сервера.

На странице POST вы просто проверяете ввод пользователя, но не действуете на нем, вместо этого вы копируете его в массив SESSION. Затем вы снова перенаправляетесь на главную страницу представления. Ваша основная страница отправки начинается с проверки, существует ли массив SESSION, который вы используете, и если это необходимо скопировать в локальный массив и отключить его. Оттуда вы можете действовать на нем.

Таким образом, вы выполняете всю свою основную работу один раз, достигая того, что хотите.

Почему бы просто не использовать переменную $_POST['submit'] как логическую инструкцию, чтобы сохранить все, что есть в форме. Вы всегда можете перенаправить на ту же страницу (в случае их обновления, а когда они удастся go back в браузере, переменная post post больше не будет установлена. Просто убедитесь, что ваша кнопка отправки имеет name и id submit .