Как избежать повторной отправки данных при обновлении в php - PullRequest
10 голосов
/ 19 апреля 2010

У меня есть страница «index.php», где у меня есть ссылка под названием «add_users.php». В «add_users.php» я принимаю информацию о пользователе и возвращаюсь на ту же страницу «index.php», где информация поступает после действия и вставляется в базу данных.

Когда я обновляю страницу или нажимаю кнопку "Назад", появляется окно повторной отправки. Я прошел через множество решений, где меня попросили создать третью страницу. Я попытался сделать это следующим образом: после вставки значений в базу данных я перенаправил страницу как заголовок ('Location: http://thisisawebsite.com/thankyou.php, и в thankyou.php я снова перенаправил страницу в index.php. Но это привело к получению предупреждение «Не удается изменить информацию заголовка - заголовки уже отправлены [....]»

Какое решение лучше?

Ответы [ 6 ]

19 голосов
/ 19 апреля 2010

Приянка,

Вы на правильном пути. То, что вы пытаетесь реализовать, - это на самом деле хорошо известный шаблон, используемый в веб-разработке, который называется POST / Redirect / GET pattern . (В наши дни шаблон - это немного модное слово, так что, возможно, парадигма - лучшее слово для этого).

Обычная реализация этого паттерна / парадигмы состоит в том, чтобы просто иметь только одну точку входа.

Делая это, add_user.php теперь может выглядеть следующим образом (это все еще не самое элегантное, но, надеюсь, это даст вам представление о том, как его реализовать):

<?php

// is this a post request?
if( !empty( $_POST ) )
{
   /*
     process the form submission
     and on success (a boolean value which you would put in $success), do a redirect
   */
   if( $success )
   {
       header( 'HTTP/1.1 303 See Other' );
       header( 'Location: http://www.example.com/add_user.php?message=success' );
       exit();
   }
   /* 
      if not successful, simply fall through here
   */
}

// has the form submission succeeded? then only show the thank you message
if( isset( $_GET[ 'message' ] ) && $_GET[ 'message' ] == 'success' )
{
?>

<h2>Thank you</h2>
<p>
You details have been submitted succesfully.
</p>

<?php
}
// else show the form, either a clean one or with possible error messages
else
{
?>

<!-- here you would put the html of the form, either a clean one or with possible error messages -->

<?php
}
?>

Итак, как это в основном работает, так это:

  • Если запрос к сценарию НЕ является запросом POST (то есть форма не была отправлена), и к URL-адресу не добавлено ?message=success, просто отобразите чистую форму.
  • Если запрос к сценарию является запросом POST, обработайте форму.
    • Если обработка формы прошла успешно, снова перенаправьте на тот же скрипт и добавьте ?message=success
      • Если запрос к сценарию является запросом с добавлением ?message=success, к которому отображается только сообщение с благодарностью, не показывайте форму.
    • Если обработка формы завершилась неудачно, то пусть она «провалится» и снова покажет форму, но на этот раз с некоторыми описательными сообщениями об ошибках и с элементами формы, заполненными тем, что пользователь уже заполнил.

Надеюсь, это, наряду с примером, который я привел, имеет достаточно смысла.

Теперь, причина, по которой вы получили печально известное Warning: headers already sent сообщение, объясняется в этом ответе, который я дал на другой вопрос о том, почему определенные вызовы php лучше ставить вверху скрипта он не обязательно должен быть сверху, но он должен вызываться до того, как ЛЮБОЙ вывод (даже (случайный) пробел) будет выводиться).

3 голосов
/ 19 апреля 2010

Но появляется предупреждение, поскольку невозможно изменить информацию заголовка - заголовки уже отправлены

Что-то не так с использованием буферизации вывода? Почему ваша страница отправляет заголовки, даже если она работает только в базе данных? У вас есть пробел или перевод строки перед первым?

У вас есть решение, вы должны просто заставить его работать.

2 голосов
/ 25 января 2012

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

session_start();
if(!isset($_SESSION['s'])){
  $_SESSION['s'] = true;
};

if( !empty( $_POST ) && ($_SESSION['s']) )
{
  //your code
 $_SESSION['s'] = false;
}

После этого вы можете использовать unset($_SESSION['s']) или destroy_session(), если хотите, чтобы пользователи могли что-то публиковать снова.

1 голос
/ 01 октября 2014

С той же проблемой, с которой я столкнулся, используя окно комментария, я перенаправил страницу на ту же страницу и на определенный «якорь». Пример:

<form id="myForm" action="<?php echo $_SERVER['PHP_SELF'];?>#myForm" method="post">
<!--Stuff for form in here -->
</form>

Тогда для кода PHP у меня есть:

<?php

//Do your stuff and when finished...

$reloadpage = $_SERVER['PHP_SELF']."#myForm";
header("Location:$reloadpage");
exit();

?>

Это позволяет избежать повторной отправки данных F5 из формы

1 голос
/ 19 апреля 2010

Пожалуйста, используйте ob_start (); оператор в первой строке.

0 голосов
/ 21 мая 2010

Использовать метаобновление

<% meta http-equ = "refresh" content = "5; url = <a href="http://example.com/" rel="nofollow noreferrer">http://example.com/" />" во время сообщения об успешном завершении после добавления данных в БД.

может быть хитростью, чтобы избежать перезагрузки.

Thanxs, Гоби.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...