我有一个向SQL表提交文本的简单表单。问题在于,在用户提交文本之后,他们可以刷新页面并再次提交数据,而无需再次填写表单。我可以在文本提交后将用户重定向到另一个页面,但我希望用户停留在同一页面上。

我记得我读过一些关于给每个用户一个唯一的会话id,并将其与另一个值进行比较,这解决了我所遇到的问题,但我忘记了它在哪里。


当前回答

基本上,你需要重定向出该页面,但它仍然可以使一个问题,而你的互联网缓慢(重定向头从服务器端)

基本场景示例:

点击提交按钮两次

解决方法

客户端 一旦客户端点击它,禁用提交按钮 如果你使用Jquery: Jquery.one PRG模式 服务器端 使用基于差分的哈希时间戳/发送请求时的时间戳。 Userequest令牌。当主进程加载完成时,分配一个临时请求标记,如果重复则忽略该标记。

其他回答

你真的应该使用Post Redirect Get模式来处理这个问题,但如果你在某种程度上陷入了PRG不可行的境地(例如,表单本身在一个include中,防止重定向),你可以散列一些请求参数,根据内容生成一个字符串,然后检查你是否已经发送了它。

//create digest of the form submission:

    $messageIdent = md5($_POST['name'] . $_POST['email'] . $_POST['phone'] . $_POST['comment']);

//and check it against the stored value:

    $sessionMessageIdent = isset($_SESSION['messageIdent'])?$_SESSION['messageIdent']:'';

    if($messageIdent!=$sessionMessageIdent){//if its different:          
        //save the session var:
            $_SESSION['messageIdent'] = $messageIdent;
        //and...
            do_your_thang();
    } else {
        //you've sent this already!
    }

一个非常可靠的方法是在post中实现一个唯一的ID,并将其缓存到

<input type='hidden' name='post_id' value='".createPassword(64)."'>

然后在你的代码中这样做:

if( ($_SESSION['post_id'] != $_POST['post_id']) )
{
    $_SESSION['post_id'] = $_POST['post_id'];
    //do post stuff
} else {
    //normal display
}

function createPassword($length)
{
    $chars = "abcdefghijkmnopqrstuvwxyz023456789";
    srand((double)microtime()*1000000);
    $i = 0;
    $pass = '' ;

    while ($i <= ($length - 1)) {
        $num = rand() % 33;
        $tmp = substr($chars, $num, 1);
        $pass = $pass . $tmp;
        $i++;
    }
    return $pass;
}

如何防止php表单重新提交没有重定向。如果你正在使用$_SESSION(在session_start之后)和$_POST表单,你可以这样做:

if ( !empty($_SESSION['act']) && !empty($_POST['act']) && $_POST['act'] == $_SESSION['act'] ) {
  // do your stuff, save data into database, etc
}

在你的html表单中放这个:

<input type="hidden" id="act" name="act" value="<?php echo ( empty($_POST['act']) || $_POST['act']==2 )? 1 : 2; ?>">
<?php
if ( $_POST['act'] == $_SESSION['act'] ){
    if ( empty( $_SESSION['act'] ) || $_SESSION['act'] == 2 ){
        $_SESSION['act'] = 1;
    } else {
        $_SESSION['act'] = 2;
    }
}
?>

因此,每当表单提交时,都会生成一个新的行为,存储在会话中并与后行为进行比较。

Ps:如果你正在使用一个Get表单,你可以很容易地用Get更改所有POST,它也可以工作。

正如其他人所说,不可能不使用post/redirect/get。但与此同时,在服务器端做你想做的事情也很容易。

在POST页面中,只需验证用户输入,但不对其进行操作,而是将其复制到SESSION数组中。然后再次重定向到主提交页面。您的主提交页面首先检查您正在使用的SESSION数组是否存在,如果存在,则将其复制到本地数组中并取消设置。从那里你可以采取行动。

这样你只需要做一次主要的工作,就能完成你想做的事情。

对我有用的是:

if ( !refreshed()) {
   //Your Submit Here
        if (isset( $_GET['refresh'])) {
            setcookie("refresh",$_GET['refresh'], time() + (86400 * 5), "/");
        }

    }    
}


function refreshed()
{
    if (isset($_GET['refresh'])) {
        $token = $_GET['refresh'];
        if (isset($_COOKIE['refresh'])) {
            if ($_COOKIE['refresh'] != $token) {
                return false;
            } else {
                return true;
            }
        } else {
            return false;
        }
    } else {
        return false;
    }
}  


function createToken($length) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

?>

在你的表格中

 <form  action="?refresh=<?php echo createToken(3)?>">



 </form>