我的php应用程序的用户有时会意外地提交消息或其他操作两次而不想这样做。这似乎是(移动)客户端在响应时间过长时自动重试请求所导致的问题,例如由于网络连接不良。我的服务器虽然处理这两个请求并将它们作为单独的动作处理。
如何在不禁用发送故意双重发布请求的可能性的情况下处理此类重试发布请求?因此,我如何区分这些重试和用户发送同一请求的重新发送?
一些上下文,可以帮助理解问题:我正在运行一个基于html的oldschool浏览器游戏。用户可能希望通过页面刷新delibaretly多次重新发送完全相同的操作,如“攻击”,我不想删除此选项,因为它非常方便。但我希望通过客户端自动发送邮件请求两次而不首先询问用户来防止意外的双重操作。我不完全确定它是否是特定于移动浏览器的问题。
答案 0 :(得分:1)
你正在关注问题的错误结局。如果用户发送了两次帖子,那可能是因为他们没有在他们的结尾看到回复。是的,您仍然需要规划和处理问题服务器端,但在客户端上解决它不仅会减少返回服务器的次数,还会改善用户体验。
前端的实时更新意味着JavaScript。此外,当您使用触控设备时,默认情况下,延迟时间约为三分之一秒,除非您明确禁用某些触控功能。
答案 1 :(得分:0)
我相信这应该做你想要的,它至少应该给你一个想法 - 它最初是关于防止实际双重提交的更大的帖子Stop multiple submits for a html from的一部分。
再次看一遍,期待你自己可能会提出太多问题,所以这里有一个底层版本。您可能希望重新实现禁用提交按钮,但似乎您实际上希望它能够连续启用,所以为了清楚起见,我在此处删除了该代码。
您可能需要调整计数 - 不确定可能会发生多少次自动提交 - 因为它会占用一个,但之后它将不接受任何内容,直到下一次“真实”提交。
此时,PHP代码可以请求用户干预“你真的提交了两次吗?”或者它可以简单地忽略提交。根据@ symcbean的建议,在重新提交之前可以要求确认的JavaScript也是如此 - 腰带和括号总是一个好主意!如果您仍在提交时单击,则应选择故意提交两次,或取消。
据我所知,在此版本中,如果您注释掉按键F4键的keyPress事件submit_this();
,则不会接受F5提交进行刷新。 - 当keyPress功能运行时,按F5 提交,而没有通常的确认警告,您将获得刷新。
我有测试运行,但只能等待您的确认,看看它是否也能应对自动重新提交。如果单击浏览器刷新按钮,则PHP中不接受提交。由Ctrl+R
刷新产生的提交也不被接受。希望这反映了重新提交的情况。由于无法判断确认/取消是否正常,因此我提交的提醒点击的速度比提交的页面快。你可以尝试一下!
<?php
session_start();
if (!isset($_POST['hidden_input'])) $hidden_input = 1;
if (!isset($_SESSION['submit_count_input'])) $_SESSION['submit_count_input'] = -1;
if (isset($_POST['hidden_input'])) $hidden_input = intval($_POST['hidden_input']);
// detect difference between JavaScript submitted value and possible automatic ones
if (($hidden_input - $_SESSION['submit_count_input']) == 1){
// do your processing here
//$submit_count_input should always be 1 behind
echo "Thank you. Form processed";
}else{
// correct the balance between $hidden_input and $submit_count_input
$_SESSION['submit_count_input'] = ($hidden_input - 1); // will be incremented so will be -1 effectively
echo "Form not processed.";
}
// remove this echo section - just for testing
echo " Control Token: " . $hidden_input . " ";
echo " Submit Count: " . $_SESSION['submit_count_input']; // to show it submits but does not process form
$_SESSION['submit_count_input']++;
?>
<!DOCTYPE html>
<html>
<head>
<script language="javascript">
document.onkeydown=function(e) {
var event = window.event || e;
if (event.keyCode == 116) {
event.keyCode = 0;
submit_this();
return false;
}
}
function submit_this(){
if(document.getElementById('submit_count_input').value - document.getElementById('hidden_input').value == -1) {
// Warning when submit clicked before previous submission finished confirm/cancel option as per link below could be used
alert("Easy Tiger - please slow down a bit!");
}else{
document.getElementById('hidden_input').value = 1+parseInt(document.getElementById('hidden_input').value);
document.form.submit();
}
}
</script>
</head>
<body>
<form name="form" id="form" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="post">
<input type="hidden" name="hidden_input" id="hidden_input" value="<?php echo $hidden_input ?>" />
<input type="hidden" name="submit_count_input" id="submit_count_input" value="<?php echo intval($_SESSION['submit_count_input']) ?>" />
<input type="button" name="sbutton" id="sbutton" value="Submit" onclick="submit_this();" />
</form>
<a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI']); ?>">Click to start a new submission</a>
</body>
</html>
确认/取消JavaScript对话框JavaScript confirm cancel button not stopping JavaScript
关于在提交的表单中保留值的次要问题,如果没有会话,那么即使对于很多表单,如果在每个表单文本框元素的值中使用value="<?php echo htmlspecialchars($_POST['form_element_name_value'] ?>"
,这应该相当简单。确保每个文本框都有一个name="something"
,以便php选择$_POST
- 抱歉,如果这太明显了。
为了满足用户能够使用F5提交页面的愿望,您可以捕获功能并将其破坏为实际提交,但这可能是一个令人讨厌的想法,虽然它确实有效...而且它会保持PHP端提供的数据可能仍然可以与失败连接的自动重新提交区分开来。
document.onkeydown=function(e) {
var event = window.event || e;
if (event.keyCode == 116) {
event.keyCode = 0;
submit_this();
return false; }
}
要捕获浏览器上的实际刷新按钮,您可以查看此How to know whether refresh button or browser back button is clicked in firefox,但颠覆浏览器行为以强制给定用户体验是一种通常不受欢迎的事情。