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

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


当前回答

if (($_SERVER['REQUEST_METHOD'] == 'POST') and (isset($_SESSION['uniq']))){
    if($everything_fine){
        unset($_SESSION['uniq']);
    }
}
else{
    $_SESSION['uniq'] = uniqid();
}

$everything_fine是表单验证的布尔结果。如果表单没有验证,那么通常会再次显示,并提示需要更正的内容,以便用户可以再次发送。因此,如果需要更正的形式,也会再次创建$_SESSION['uniq']

其他回答

你真的应该使用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!
    }
if (($_SERVER['REQUEST_METHOD'] == 'POST') and (isset($_SESSION['uniq']))){
    if($everything_fine){
        unset($_SESSION['uniq']);
    }
}
else{
    $_SESSION['uniq'] = uniqid();
}

$everything_fine是表单验证的布尔结果。如果表单没有验证,那么通常会再次显示,并提示需要更正的内容,以便用户可以再次发送。因此,如果需要更正的形式,也会再次创建$_SESSION['uniq']

我还想指出,您可以使用javascript方法window.history.replaceState来防止在刷新和返回按钮时重新提交。

<script>
    if ( window.history.replaceState ) {
        window.history.replaceState( null, null, window.location.href );
    }
</script>

这里的概念证明:https://dtbaker.net/files/prevent-post-resubmit.php(链接不再工作)

我仍然推荐Post/Redirect/Get方法,但这是一个新颖的JS解决方案。

我使用这个javascript行来阻止弹出窗口要求表单重新提交刷新一旦表单提交。

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

只需将这一行放在文件的页脚,就能看到神奇的效果

我寻找解决方案,以防止在一个巨大的项目之后再次提交。 代码高度工作与$_GET和$_POST和我不能改变表单元素的行为没有不可预见的错误的风险。 这是我的代码:

<!-- language: lang-php -->
<?php

// Very top of your code:

// Start session:
session_start();

// If Post Form Data send and no File Upload
if ( empty( $_FILES ) && ! empty( $_POST ) ) {
    // Store Post Form Data in Session Variable
    $_SESSION["POST"] = $_POST;
    // Reload Page if there were no outputs
    if ( ! headers_sent() ) {
        // Build URL to reload with GET Parameters
        // Change https to http if your site has no ssl
        $location = "https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
        // Reload Page
        header( "location: " . $location, true, 303 );
        // Stop any further progress
        die();
    }
}

// Rebuilt POST Form Data from Session Variable
if ( isset( $_SESSION["POST"] ) ) {
    $_POST = $_SESSION["POST"];
    // Tell PHP that POST is sent
    $_SERVER['REQUEST_METHOD'] = 'POST';
}

// Your code:
?><html>
    <head>
        <title>GET/POST Resubmit</title>
    </head>
    <body>

    <h1>Forms:</h1>
    <h2>GET Form:</h2>
    <form action="index.php" method="get">
        <input type="text" id="text_get" value="test text get" name="text_get"/>
        <input type="submit" value="submit">
    </form>
    <h2>POST Form:</h2>
    <form action="index.php" method="post">
        <input type="text" id="text_post" value="test text post" name="text_post"/>
        <input type="submit" value="submit">
    </form>
    <h2>POST Form with GET action:</h2>
    <form action="index.php?text_get2=getwithpost" method="post">
        <input type="text" id="text_post2" value="test text get post" name="text_post2"/>
        <input type="submit" value="submit">
    </form>
    <h2>File Upload Form:</h2>
    <form action="index.php" method="post" enctype="multipart/form-data">
        <input type="file" id="file" name="file">
        <input type="submit" value="submit">
    </form>

    <h1>Results:</h1>
    <h2>GET Form Result:</h2>
    <p>text_get: <?php echo $_GET["text_get"]; ?></p>
    <h2>POST Form Result:</h2>
    <p>text_post: <?php echo $_POST["text_post"]; ?></p>
    <h2>POST Form with GET Result:</h2>
    <p>text_get2: <?php echo $_GET["text_get2"]; ?></p>
    <p>text_post2: <?php echo $_POST["text_post2"]; ?></p>
    <h2>File Upload:</h2>
    <p>file:
    <pre><?php if ( ! empty( $_FILES ) ) {
            echo print_r( $_FILES, true );
        } ?></pre>
    </p>
    <p></p>
    </body>
    </html><?php
// Very Bottom of your code:
// Kill Post Form Data Session Variable, so User can reload the Page without sending post data twice
unset( $_SESSION["POST"] );

它只能避免$_POST的重新提交,而不是$_GET的重新提交。但这是我需要的行为。 重新提交的问题不工作的文件上传!