使用PHP表单提交导航返回

19

这里的问题是,我正在使用HTML表单来传递变量从一个页面到另一个页面,并使用PHP脚本根据提交的值创建页面。通常情况下如下所示:从产品目录中选择您想要的内容,下一页将显示此特定项目的详细信息。一切工作得很好,除了一个问题:

每当我使用浏览器的后退按钮时,我总是会收到错误:ERR_CACHE_MISS,然后我需要刷新页面并确认我确实要重新提交数据。

有没有办法修复这个问题,使我的客户能够像他们应该做的那样只使用后退按钮。

这里是浏览器提供给我的完整文本:

为了正确显示此网页,需要之前输入的数据。您可以再次发送此数据,但这样做将重复此页面之前执行的任何操作。重新加载此网页。按下重新加载按钮以重新提交加载页面所需的数据。错误代码:ERR_CACHE_MISS


2
你是否愿意使用服务器端数据存储?MySQL,Redis?最好的方法是在用户浏览时将数据存储在服务器上。 - Matt R. Wilson
你的意思是我需要在用户会话期间存储所有提交表单的值吗?我可以使用会话存储来实现吗? - Maxim Ershov
你可以使用会话存储,但它并不是非常可扩展的,如果数据量从一点变成了更多,那么这将是错误的选择。我认为对于作业来说,会话存储是可以的,但对于生产环境来说,这是不够的。 - Matt R. Wilson
我有一个非常小的项目,只有两个导航级别(目录和项目详情),所以我只需要存储2-3个链接以返回目录,所以我想这对我来说应该可行。那么我如何连接“返回”按钮和sessionStorage呢? - Maxim Ershov
他为什么不能使用会话?当未登录时(同样适用于Cookie),会话被广泛用于购物车、存储搜索查询等。因此,在我看来,会话是捕获这个的好方法。1)提交表单,2)将表单数据存储在会话中,3)基于会话重定向到执行操作的页面,4)享受。如果用户按返回键,则会转到使用会话而不是发布数据的页面。 - Joshua - Pendo
@MaximErshov。兄弟,你打算标记一个答案吗?人们应该得到他们为你提供的免费代码的一些认可。 - RayLoveless
6个回答

31
当您使用php或其他数据提交表单时,可能会在浏览器中看到消息,如“文档已过期”或“使用Chrome确认表单重新提交”。这些消息是浏览器对于像post变量这样的敏感数据使用的安全预防措施。浏览器将不会自动为您提供新鲜的页面,您必须通过点击“重试”或刷新页面来重新加载页面。然后,它将按照您的期望操作。
但是,php编码人员可以通过在脚本中添加一些代码来解决浏览器烦人的消息。示例显示了几行代码,可以添加到session_start()之前,以便能够在提交表单时来回访问页面而没有任何问题。'private_no_expire'模式意味着客户端将首先不会收到已过期的标头。
header('Cache-Control: no cache'); //no cache
session_cache_limiter('private_no_expire'); // works
//session_cache_limiter('public'); // works too
session_start();

这对我不起作用,而且我的情况完全相同,这个问题有解决吗? - Kapytanhook

9

**背景信息:感谢bruce(sqlwork.com)提供的出色解释。

此网页需要您先前输入的数据才能正确显示。您可以再次发送这些数据,但这样将重复此页面以前执行的任何操作。单击“重新加载”以重新发送该数据并显示此页面。

由于网络开发人员的代码实践不规范,浏览器不得不添加此消息。场景如下:

1)用户填写表单并提交(发布表单) 2)服务器处理帖子数据并响应一个新页面(确认),标记为不可缓存 3)用户导航到新页面。 4)用户按回退:

对于浏览器来说,在步骤2中显示页面,因为其标记为无缓存,它必须从服务器请求它,换句话说,重新发布数据(执行步骤1)。在这里,编码不规范,如果这是信用卡收费,并且服务器上没有重新发布检测,则会收取两次费用。这是一个(仍然存在)非常普遍的问题,以至于浏览器不得不检测它并警告用户。

最佳修复方法在第二步,服务器向确认页面发送重定向。然后,当用户通��历史记录或后退访问确认页面时,它是一个获取请求,而不是一个发布请求,将不显示警告。

注意:Web表单的后台模型容易出现此问题。还要避免服务器传输。

我的解决方案

$_SESSION ['home']用于存储主页上的任何错误。

$_SESSION ['tempEmail']用于在php表单上回显值。

注意:为了进行错误处理,每个具有HTML表单的页面使用一个唯一的会话变量,并且用于在HTML表单上回显任何值的每个会话变量。

<?php
session_start(); 

//Initialize variables not initialized without overwriting previously set variables.
if(!isset($_SESSION['home'])) {
$_SESSION['home']="";
$_SESSION['tempEmail']="";
}

可选 - 如果已登录,则将电子邮件地址分配给 $_SESSION['tempEmail'] 变量(如果以前未完成)以预填充 HTML 表单。

if(isset($_POST['Submit'])){

---your code---


    //Error message(s) examples
    $_SESSION['home'] = "Email and Password do not match, please try again.";
    header("Location: " . $_SERVER['REQUEST_URI']);

    $_SESSION['home'] = "Email address format is invalid.  Please recheck.";
    header("Location: " . $_SERVER['REQUEST_URI']);

    //success
    unset ($_SESSION['home']); //optional, unset to clear form values.
    header ("location: nextpage.php"); 
             ---or---
    header("Location: " . $_SERVER['REQUEST_URI']);  //re-post to same page with the $_SESSION['home'] success message.   
}
?>



<body>

错误提示框
<span><strong class="error"><?php echo $_SESSION['home'] ?></strong></span>

HTML表单

<form action="#" name="loginform" method="post" >
    <input type="text" name="userEmail" maxlength="50" title="Enter Your email" autocomplete="off" value="<?php echo htmlspecialchars($_SESSION['tempEmail']); ?>" placeholder="enter email" required/>
    <input type="submit" name="Submit" value="Submit">
</form>

</body>

不建议在支付页面使用,详情请参见上面的讨论。已在Firefox、Chrome、Safari和IE9中进行了测试。使用返回按钮时,烦人的消息已经消失。确保在您的php脚本或php.ini中打开输出缓冲以避免头部警告。您可以检查您的php.ini文件是否包含以下内容;

output_buffering=On

8
我发现只使用以下代码:

我发现只使用以下代码:

header('Cache-Control: no cache'); //disable validation of form by the browser

解决问题。

6

其他的答案对我没用。

  • 我不想重定向
  • 设置不同的标头不起作用
  • 我已经在我的帖子中使用令牌来确保不能重新提交
  • 我将帖子发布到显示表单的相同网址上

这个简单的 JavaScript 解决了后退按钮引发 "ERR_CACHE_MISS" 的问题。

if ( window.history.replaceState ) {
  window.history.replaceState( null, null, window.location.href );
}

1
这真的很棒,我正在寻找一些基于JS的答案来摆脱烦人的“确认表单重新提交”提示。对于那些可能不理解的人来说,这会在浏览器上添加一个历史状态,这样当用户点击“返回”按钮时,它会回到没有附加表单提交数据的页面。 - Juanma Guerrero

5

我尝试了这个答案,它是可以的。 在session_start()之前,您必须放置此代码:

session_cache_limiter('private, must-revalidate');
session_cache_expire(60);

祝你好运


0
<?php
if(isset($_POST['submit']))
{
 //submission goes here
}
?>

这是你想要的吗?

编辑 - SQL 真的是一个非常好用的工具,我看到有人在评论中推荐使用它,我也同意如果可以的话使用 SQL,它快速、直观且高效。


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