23

我在这里和其他地方搜索了很多帖子,但似乎找不到解决我问题的方法。我有一个显示数据库条目的页面:database.php。可以使用表单过滤这些条目。当我过滤它们并只显示我感兴趣的那些时,我可以单击一个条目(作为链接),将我带到该条目页面(通过 php GET)。当我在该条目页面(即“view.php?id=1”)并点击返回按钮(返回到 database.php)时,过滤器表单需要确认表单重新提交。有什么办法可以防止这种情况发生吗?

以下是一些(简化的)代码示例:

数据库.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 以显示该单个条目:

视图.php:

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

?>

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

我怎样才能解决这个问题?我希望我的问题的代码示例和解释是足够的。如果不让我知道,我会尝试指定。

4

9 回答 9

32

我知道这个问题很老,但是我自己也有这个问题,我发现有两行有效:

header("Cache-Control: no cache");
session_cache_limiter("private_no_expire");
于 2016-10-21T14:29:06.627 回答
9

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

无论如何,当您处理基于状态的页面(使用$_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 并将其作为隐藏输入或&_SESSIONcookie 存储在页面上的某个位置。然后你在服务器上存储相同的 id 作为$_SESSION. 如果它们不匹配,则一系列预编程的if else类型语句会导致重新提交页面时不会发生任何事情(当您单击返回时,它会尝试执行此操作)。

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

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

我希望这有帮助!

于 2013-03-05T15:05:09.473 回答
3

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

浏览器通常会阻止POST自动重新提交输入,这是在使用输入时它们不会做的事情GET。此外,这将允许用户使用过滤器链接到您的页面。

于 2013-11-30T00:57:14.437 回答
2
header("Cache-Control: no cache");

session_cache_limiter("private_no_expire");

注意:在使用你从表单提交的post数据之后,这两行应该在function的末尾使用。所以,当我们回到重定向页面时,它不会要求你重新提交页面。这将起作用。

于 2019-07-18T05:55:57.393 回答
1

我使用了如何检测用户是否使用后退按钮进入页面?检测访问是否是由浏览器的后退按钮单击触发的,如果是这种情况,我使用 JavaScript 重新加载页面。当页面重新加载时,我的代码已经处理了相应的验证,以确保表单永远不会提交两次。在我的案例中,重要的部分是在单击浏览器的后退按钮后重新访问表单时强制页面重新加载。这是我想要应用此验证的 URL 中的代码:

<script type="text/javascript">
    if (window.performance && window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD) {
        location.reload();
    }
</script>
于 2019-01-29T00:26:23.537 回答
0

如果/当重新加载页面时,另一种解决方案也可以使用 $_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 */
}
于 2018-01-25T16:00:09.963 回答
0

上面已经提到过,但我再说一遍,如果您在代码中使用了 session_start() ,那么您只需要在头文件中添加这一行,如:-

<?php
header("Cache-Control: no cache");
?>

但是如果你还没有使用 session_start() 那么你可以在你的头文件中添加下面的行,比如:-

<?php
header("Cache-Control: no cache");
session_cache_limiter("private_no_expire");
?>
于 2022-01-27T05:59:39.407 回答
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 );
}
于 2020-08-17T09:58:31.543 回答
-2

您需要POST从浏览器历史记录中删除请求哪些数据

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

看到这个答案

你也可以按照Post/Redirect/Get 模式。

于 2017-11-12T11:48:08.360 回答