按回按钮后阻止表单重新提交

时间:2013-03-05 14:47:48

标签: php forms get refresh back

我在这里和其他地方搜索过很多帖子,但似乎找不到解决我问题的方法。 我有一个显示数据库条目的页面: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 = whatever”。在该页面上,我只是从URL获取ID以显示该单个条目:

view.php:

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

?>

如果我现在点击后退按钮,database.php上的表单(用于过滤数据库结果的表单)需要确认重新提交。这不仅非常烦人,而且对我来说也毫无用处。

我该如何解决这个问题?我希望代码示例和我的问题的解释是充分的。如果不让我知道,我会尽力指定。

8 个答案:

答案 0 :(得分:23)

我知道这个问题已经过时了,但是我自己也有这个问题,我发现有两条线是有效的:

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

答案 1 :(得分:8)

我知道有两种方法可以做到这一点。简单的方法和艰难的方式。

无论如何,当您处理基于状态的页面(使用$_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");
?>

困难的方法是生成一个id并将其作为隐藏输入或&_SESSION cookie存储在页面的某个位置。然后在服务器上将相同的ID存储为$_SESSION。如果它们不匹配,一系列预编程的if else类型语句会导致重新提交页面时发生任何事情(这是您在单击后再尝试执行的操作)。

简单的方法是,如果表单已成功提交,只需将用户重定向回表单提交页面,如下所示:

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

我希望这有帮助!

答案 2 :(得分:3)

可能有用的一件事是使您的过滤器表单使用GET方法而不是POST

浏览器通常会阻止POST输入被自动重新提交,这是使用GET输入时不会执行的操作。此外,这将允许用户使用过滤器链接到您的页面。

答案 3 :(得分:0)

如果/当重新加载页面时也可以使用的替代解决方案涉及使用$ _SESSION检查帖子的原创性。简而言之,检查一个唯一或随机的字符串。

在表单中,使用rand()或microtime()添加一个带有值集的input元素:

<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 */
}

答案 4 :(得分:0)

我使用How do I detect if a user has got to a page using the back button?的答案来检测访问是否是由浏览器的后退按钮触发的,如果是这种情况,我就使用JavaScript重新加载了页面。重新加载页面后,我的代码已经处理了相应的验证,以确保该表单永远不会提交两次。对于我而言,重要的部分是在单击浏览器的后退按钮后重新访问表单时,强制重新加载页面。这是我在URL中要应用此验证的代码:

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

答案 5 :(得分:0)

header(“ Cache-Control:no cache”);

session_cache_limiter(“ private_no_expire”);

注意:在使用您从表单提交的帖子数据之后,应在函数末尾使用这两行。因此,当我们返回重定向页面时,它不会要求您重新提交页面。这将起作用。

答案 6 :(得分:0)

对我来说可行的解决方案是

$(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 );
}

答案 7 :(得分:-2)

您需要从浏览器历史记录

中删除POST数据的请求
history.replaceState("", "", "/the/result/page")

请参阅this回答

您也可以遵循Post/Redirect/Get模式。