在按下F5时避免PHP表单重新提交

14

我在网站上使用了以下代码(使用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,则post数据仍然存在。

有什么想法吗?

11个回答

41

你的方法在理论上是可行的,但有更简单的方法。

成功提交表单后,执行重定向。重定向的位置并不重要,但它会清除 $_POST。

header('Location: http://www.example.com/form.php');
在您的情况下,似乎您想要重定向到当前所在页面。如果您想要显示确认消息,请将$_GET参数附加到URL中。
希望这能有所帮助,
Tom

3
非常好的答案,PRG绝对是可行的方法:http://zh.wikipedia.org/wiki/Post/Redirect/Get - Neil Williams
1
我认为不需要提供完整的URL,当您提供相对URL时,PHP或Apache将解析它为绝对URL并发送给客户端(不确定这个过程在链中的哪个阶段发生)。 - Ciaran McNulty
设置 $_POST = ''; 不是更容易吗?只是好奇,不确定它是否有帮助。 - santa
@TomWright 这在理论上是一个不错的想法,但在现实世界中,这是一种可怕的模式,因为没有清晰的方式来传递反馈。 - Sliq
@Panique,我和其他23个赞同者不得不在这件事上与您持不同意见。PRG被广泛使用,并且只要使用了get参数(PRG中的G),它就足以“传输”反馈信息。 - Tom Wright
显示剩余4条评论

10

6
最好的处理表单的方式是使用自我提交和重定向。可以像这样实现:

处理表单的最佳方法是使用自我提交和重定向。类似以下代码:

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');
}

2
您可以将表单提交改写成AJAX方式。如果需要显示HTML内容,请以JSON格式返回并使用JavaScript(例如jQuery)插入。

1
在成功的提交操作后使用“Header location”。
header('Location: '.$_SERVER['HTTP_REFERER']);

1

如果我在代码末尾使用header()或exit(),例如在保存数据后,它对我有效。


1

我用php解决了这个问题:

  1. 在表单中添加一个唯一标识符(id+计数器),不要基于time()(重要!!!)

  2. 提交到一个单独的文件(postform.php),该文件检查是否存在具有该唯一标识符的会话

  3. a)如果未找到具有唯一标识符的会话:将其提交到数据库并填充会话以获取唯一标识符

    b)如果找到具有唯一标识符的会话:什么也不做

  4. 在3a/3b之后,使用header('Location: http://mydomain.com/mypage')重定向到结果页面

结果是:
在刷新/返回按钮上没有重新提交操作,在双击返回按钮时只有重新提交警告(但没有重新提交操作)


谢谢Paul,我已经有了一个基本的想法,为什么我们不应该在同一页中使用表单提交。之前我一直在使用表单提交到同一页。在处理完表单后,我将其重定向回自身,并附带一些GET参数。 - Dinesh Patra

1
我发现最好的方法是使用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;

我希望这可以帮到你 :)


1
您正在寻找的答案是这个神奇的一行代码: header('Location: '.$_SERVER['HTTP_REFERER']);

e.g

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

0

试试我的方法,也许不是最好的解决方案(匆忙完成),但我已经测试过了,它可以运行。在Chrome上进行了测试。点击查看效果。敬礼

 <?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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接