有没有办法做到以上几点?基本上,如果有人在已经提交过一次表单后按下刷新,我不希望再次提交表单。在这种情况下,浏览器会询问您是否要再次提交表单。unset($_POST['username'])
这种情况会有什么帮助吗?
11 回答
正如一些海报已经提到的那样,post/redirect/get 是一个不错的选择。
我能想到的另一种方法是在 dostuff.php 页面中设置一个会话以指示发布已经完成。每次检查此会话变量以查看是否由于页面刷新而再次加载页面。
<?php
session_start();
if(isset($_SESSION['indicator']))
{
/*
dont do anything because session indicator says
that the processing was already done..
you might want to redirect to a new url here..
*/
}
else
{
/*
first set session indicator so that subsequent
process requests will be ignored
*/
$_SESSION['indicator'] = "processed";
//process the request here..
}
?>
在您重定向到的页面中,取消设置会话变量,以便可以重新重新提交表单,使其成为新的发布操作。这将允许新表单发布,但会因页面刷新而阻止发布操作
使用中间页面进行操作,然后重定向。
例如:
mypage.php --> 带有表单的页面
dostuff.php --> 接收表单数据并进行操作,然后重定向到任何其他页面。
要进行重定向:
将此行放在“dostuff.php”的顶部:header("Location: mypage.php");
您在上面特别面临的问题可以(并且应该)通过Post/Redirect/Get来解决。在php_POST
端取消设置是无效的,因为问题是它是一个单独的请求。
您还必须处理双击提交按钮。您可以在客户端解决此问题,方法是在单击按钮后禁用表单提交,或者在表单中放置一个随机令牌并将该令牌存储在会话中。令牌只会被接受一次(会话会跟踪令牌是否已发布)。
这是我用来防止用户两次提交相同数据的好方法,这也将防止页面在重新加载时将相同的记录添加到数据库中。
// First IF
if ($_SESSION['dup_comment_body'] == $_POST['comment_body']) {
echo 'You already entered that.';
} else {
// Second IF
if ($_POST['comment_body']) {
// Run your query here
$_SESSION['dup_comment_body'] = $_POST['comment_body'];
header('location:'.$_SERVER['REQUEST_URI'].'');
}
}
第一个IF
检查$_POST
是否等于他们键入的最后一个内容 ( $_SESSION
)。如果不一样,它会运行下一个IF
以测试$_POST
变量是否不为空。在最后一个IF
朝向底部的内部,它设置$_SESSION['dup_comment_body']
为等于$_POST
. 所以下一次第一次IF
运行时$_POST
,它们是相同的,他们将收到消息“你已经输入了。”。希望这可以帮助!
使用此代码
if(isset($_POST)){
header('location:'.$_SERVER['PHP_SELF']);
die();
}
为此,您需要使用POST/REDIRECT/GET 模式。
Post/Redirect/Get (PRG) 是一种 Web 开发设计模式,可以防止一些重复的表单提交,为用户代理(用户)创建更直观的界面。PRG 以可预测的方式支持书签和刷新按钮,不会创建重复的表单提交。
当通过 HTTP POST 请求将 Web 表单提交到服务器时,Web 用户尝试在某些用户代理中刷新服务器响应可能会导致重新提交原始 POST 请求的内容,可能会导致不希望的结果,例如重复的网络购买。
为了避免这个问题,许多 Web 开发人员使用 PRG 模式——而不是直接返回网页,POST 操作返回一个重定向命令。HTTP 1.1 规范引入了 HTTP 303(“查看其他”)响应代码,以确保在这种情况下,Web 用户的浏览器可以安全地刷新服务器响应,而不会导致重新提交初始 POST 请求。然而,当今使用的大多数常见商业应用程序(新旧都一样)在这些情况下仍会继续发出 HTTP 302(“找到”)响应。
这是 PHP 中的一个示例:
header('Location: /yourpage.php', true, 303);
exit;
如果您将此表单的内容插入数据库,只需使用 php/sql SELECT 语句检查“用户名”是否已提交。如果是,则抛出错误。像这样:
//Database Values: servername, dbname, username and password;
//Also set ($_POST['username']) = $username or anything you like;
$usererror = ""; //Will be filled later.
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt1 = $conn->prepare("SELECT * FROM yourdb WHERE username=:username");
$stmt1->bindParam(':email', $email);
$stmt1->execute();
$stmt1->fetch();
$querycheck = $stmt1->rowCount();
if ($querycheck >= 1) {
$usererror = "User already exists.";
}
}
catch(PDOException $e) {
// roll back the transaction if something failed
$conn->rollback();
echo "Critical Error. Contact admin immediately.";
error_log("Error: " . $e->getMessage(), 0); //logs connection errors instead of echoing the errors (for security reasons.)
}
$conn = null;
然后你现在可以只插入没有错误的表单:
If (empty($usererror)) {
//insert command
}
注意我使用了prepared statements,因为在很多文章中,它被认为是使用php+sql操作数据库最安全的方法。如果您真的不担心安全问题,您也可以使用普通方法,它也会为您节省更多代码行。
还要注意$querycheck >= 1,即使用户刷新 2,000 次、单击返回按钮并再次提交等,确保 1 次插入并且永远不会超过 1 是非常重要的。这个错误让我陷入困境并让我发疯了好几天正在使用$querycheck > 1而不是$querycheck >= 1,这样,我的表单在抛出“已经存在”错误之前不断提交两次。最后,我已经能够修复它。希望这对稍后将访问此问题的人有所帮助。
您可以在处理表单数据后重置 $_POST 数组,例如下面的代码
<?php
if( isset($_POST['submit']))
{
//do some processing related to form;
//after done.....
$_POST = array(); //this declares post as empty array
//which is global variable anyways.
}
?>
或者第二种方法是使用隐藏形式的东西......
<?php
if( isset($_POST['submit']))
{
//do some processing related to form;
//create a form with hidden field
?>
<form method="post" name="myform" action="actionpage">
<input type="hidden" name="somename" value="">
</form>
<?php
echo "<script> document.forms['myform'].submit();</script>";
}
?>
这将基本上提交带有 1 个空值字段的表单,我不知道这是否是最佳的,但它满足了这里的需要。
如果您的表单要更新数据库,那么只有在记录不存在时才可以更新或插入。只需先执行一个 select 语句。这将防止由于刷新导致重复记录。
我的解决方案是如果设置了 post 变量,则进行元刷新,刷新后不要遵循它。
<head>
<?php
if (isset($_POST['Task'])){
echo' <meta http-equiv="refresh" content="0; url=./ThisFile.php">';
}
?>
</head>
相反,您可以使用诸如 Recaptcha 之类的验证码,它不允许在不进行验证码的情况下提交后提交。这就是我使用的,并且效果很好。