Como evitar a reapresentação do formulário quando a página é atualizada (F5 / CTRL+R)

Tenho um formulário simples que submete texto à minha tabela SQL. O problema é que depois que o usuário submete o texto, eles podem atualizar a página e os dados são enviados novamente sem preencher o formulário novamente. Eu poderia redirecionar o Usuário para outra página depois que o texto é submetido, mas eu quero que os usuários fiquem na mesma página.

Lembro-me de ler algo sobre dar a cada utilizador um id de sessão único e compará-lo com outro valor que resolveu o problema que estou a ter, mas Esqueci-me. onde está.

Author: Eugen Konkov, 2011-06-12

18 answers

Usa o padrão Post/Redirect / Get. http://en.wikipedia.org/wiki/Post/Redirect/Get

Com o meu site, vou armazenar uma mensagem em um cookie ou sessão, redirecionar após o post, ler o cookie/sessão, e, em seguida, limpar o valor dessa sessão ou variável cookie.

 66
Author: Keverw, 2017-07-24 04:58:07

Eu também gostaria de salientar que você pode usar uma abordagem javascript, window.history.replaceState para evitar uma reapresentação no botão Actualizar e voltar.

<script>
    if ( window.history.replaceState ) {
        window.history.replaceState( null, null, window.location.href );
    }
</script>
Prova do conceito aqui: https://dtbaker.net/files/prevent-post-resubmit.php Eu ainda recomendaria uma abordagem Post / Redirect / Get, mas esta é uma nova solução JS.
 17
Author: dtbaker, 2017-08-13 02:46:07

Você deve realmente usar um padrão de redirecionamento de Post para lidar com isso, mas se você de alguma forma acabou em uma posição onde o PRG não é viável (por exemplo, o formulário em si está em uma inclusão, impedindo redirecionamentos) você pode ajustar alguns dos parâmetros de pedido para fazer uma string com base no conteúdo e, em seguida, verificar que você não Enviou já.

//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!
    }
 16
Author: Moob, 2016-04-29 11:02:21

Você pode perventar a apresentação do formulário através de uma variável de sessão como

Primeiro você tem que definir rand() na caixa de texto e $_SESSION ['rand'] na página do formulário

<form action="" method="post">
  <?php
   $rand=rand();
   $_SESSION['rand']=$rand;
  ?>
 <input type="hidden" value="<?php echo $rand; ?>" name="randcheck" />
   Your Form's Other Field 
 <input type="submit" name="submitbtn" value="submit" />
</form>

Depois de verificar $_SESSION ['rand'] com o valor da caixa de texto $_POST['randcheck'] Tipo

         if(isset($_POST['submitbtn']) && $_POST['randcheck']==$_SESSION['rand'])
          {
         //Your Code here
         }
 12
Author: Savoo, 2016-08-04 13:03:14
  1. Use o cabeçalho e redireccione a página.

    header("Location:your_page.php"); você pode redirecionar para a mesma página ou página diferente.

  2. Desligue $_POST depois de O inserir na Base de dados.

    unset($_POST);

 11
Author: Prasanth Bendra, 2013-03-08 06:21:17

Quando o formulário é processado, você redireciona para outra página:

... process complete....
header('Location: thankyou.php');

Você também pode redirecionar para a mesma página.

Se estiver a fazer algo como comentários e quiser que o utilizador fique na mesma página, pode usar o Ajax para lidar com o envio do formulário

 10
Author: Ibu, 2011-06-12 04:26:13

Uma maneira bastante segura é implementar um ID único no post e guardá-lo no

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

Então no seu código faça isto:

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;
}
 7
Author: Absolut, 2014-08-21 06:49:41
Encontrei o próximo trabalho. Você pode escapar do redirecionamento após o processamento POST pedido manipulando history protesto.

Então você tem o formulário HTML:

<form method=POST action='/process.php'>
 <input type=submit value=OK>
</form>

Quando processa este formulário no seu servidor, em vez de redireccionar o utilizador para /the/result/page, Configurando o cabeçalho Location assim:

$cat process.php
<?php 
     process POST data here
     ... 
     header('Location: /the/result/page');
     exit();
?>

enter image description here

Após o tratamento POST os dados são pequenos <script> e o resultado /the/result/page

<?php 
     process POST data here
     render the <script>         // see below
     render `/the/result/page`   // OK
?>

O <script> Você deve Desenho:

<script>
    window.onload = function() {
        history.replaceState("", "", "/the/result/page");
    }
</script>

O resultado é:

enter image description here

Como você pode ver, os dados do formulário são POST ed para process.php script.
Este programa processa POST Dados ed e renderização /the/result/page de uma vez com:

  1. sem redireccionamento
  2. não existem dados relativos aPOST quando actualizar a página (F5)
  3. não há re POST Quando você navega para a Página Anterior / Seguinte através do histórico do navegador

UPD

Como outra solução, pergunto: pedido de funcionalidades a equipa Mozilla FireFox para permitir aos utilizadores configurar NextPage o cabeçalho que irá funcionar como Location o cabeçalho e tornar post/redirect/get o padrão obsoleto. Resumindo. Quando o formulário de processo do servidor POST os dados são obtidos com sucesso:
  1. configuração NextPage cabeçalho em vez de Location
  2. renderize o resultado do processamento POST de dados de forma como iria renderizar para GET pedido em post/redirect/get padrão

O navegador por sua vez quando vê o NextPage cabeçalho:

  1. Ajustar window.location com NextPage valor
  2. quando o utilizador actualizar a página, o navegador irá negociar GET o pedido para NextPage em vez de re POST os dados do formulário
Acho que isto seria excelente se fosse implementado, não seria? =)
 7
Author: Eugen Konkov, 2017-11-15 09:41:11
Basta redirecioná-lo para a mesma página depois de fazer o uso de dados do formulário, e ele funciona. Já tentei.
header('location:yourpage.php');
 4
Author: krsoni, 2014-06-10 16:37:57
Uma versão refinada do post do Moob. Crie um hash do POST, salve-o como um cookie de sessão, e compare hashs a cada sessão.
// Optionally Disable browser caching on "Back"
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Expires: Sun, 1 Jan 2000 12:00:00 GMT' );
header( 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT' );

$post_hash = md5( json_encode( $_POST ) );

if( session_start() )
{
    $post_resubmitted = isset( $_SESSION[ 'post_hash' ] ) && $_SESSION[ 'post_hash' ] == $post_hash;
    $_SESSION[ 'post_hash' ] = $post_hash;
    session_write_close();
}
else
{
    $post_resubmitted = false;
}

if ( $post_resubmitted ) {
  // POST was resubmitted
}
else
{
  // POST was submitted normally
}
 3
Author: skibulk, 2016-06-29 11:45:58

Depois de inseri-lo na base de dados, chame o método unset() para limpar os dados.

Desactivado ($_POST);

Para evitar a inserção de dados de atualização, faça um redirecionamento de página para a mesma página ou página diferente após a inserção de registro.

Cabeçalho ('Localização:'.$_SERVER ['PHP_ SELF']);

 2
Author: Thinesh, 2016-06-01 16:16:19

Basicamente, você precisa redirecionar para fora dessa página, mas ele ainda pode fazer um problema enquanto a sua internet lenta (redirecionar o cabeçalho do serverside)

Exemplo de cenário básico:

Carregue no botão enviar duas vezes

Maneira de resolver

  • Lado do cliente

    • desactivar o botão Enviar assim que o cliente carregar nele
    • Se estiver a utilizar Jquery : Jquery.um
    • padrão PRG
  • Servidor lado

    • usando um intervalo de variação baseado na hashing quando o pedido foi enviado.
    • Userequest tokens. Quando a carga principal para cima atribuir um pedido temporário tocken que, se repetido é ignorado.
 2
Author: ZenithS, 2016-06-08 01:28:31

Como prevenir a re-submissão do formulário php sem redireccionar. Se você estiver usando $_SESSION (após session_ start) e um formulário $_POST, você pode fazer algo assim:

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

No seu formulário html coloque isto:

<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;
    }
}
?>
Assim, cada vez que o formulário é submetido, um novo ato é gerado, armazenado em sessão e comparado com o post act.

Ps: Se você está usando um formulário Get, você pode facilmente mudar todo o POST com o GET e ele funciona também.

 1
Author: Rômulo Z. C. Cunha, 2017-09-22 14:26:02

Uso Esta linha de javascript para bloquear o pop up a pedir uma nova apresentação do formulário quando o formulário for enviado.

if ( window.history.replaceState ) {
  window.history.replaceState( null, null, window.location.href );
}
Coloca esta linha no rodapé do teu ficheiro e vê a magia.
 1
Author: Mo'men Mohamed, 2018-09-23 08:33:34

Usar o padrão Post/Redirect / Get a partir da resposta Keverw é uma boa ideia. No entanto, você não é capaz de ficar em sua página (e eu acho que era isso que você estava pedindo?) Além disso, pode por vezes falhar:

Se um Utilizador da web actualizar antes de a submissão inicial ter terminado devido ao atraso do servidor, resultando em uma solicitação de POST HTTP duplicado em alguns agentes utilizadores.

Outra opção seria armazenar numa sessão se o texto fosse escrito para a sua base de dados SQL como esta:

if($_SERVER['REQUEST_METHOD'] != 'POST')
{
  $_SESSION['writeSQL'] = true;
}
else
{
  if(isset($_SESSION['writeSQL']) && $_SESSION['writeSQL'])
  {
    $_SESSION['writeSQL'] = false;

    /* save $_POST values into SQL */
  }
}
 0
Author: Adam, 2016-06-22 14:58:34

Como outros já disseram, não é possível deixar de usar post/redirect/get. Mas, ao mesmo tempo, é muito fácil fazer o que você quer fazer do lado do servidor.

Na sua página de publicação, você simplesmente valida a entrada do utilizador, mas não aja nela, em vez disso copia-a para uma lista de sessões. Você então redireciona de volta para a página principal de Submissão novamente. A sua página de envio principal começa por verificar se a lista de sessões que está a usar existe e, se for o caso, copiá - la para uma lista local e desactivá-la ele. A partir daí podes agir.

Assim só fazes o teu trabalho principal uma vez, alcançando o que queres fazer.
 0
Author: Stu, 2017-11-20 21:42:46
Procurei uma solução para evitar a reabertura de um grande projecto. O código altamente funciona com $_GET e $_POST e eu não posso mudar o comportamento dos elementos do formulário sem o risco de bugs imprevistos. Então, aqui está o meu código:
<!-- 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"] );

Só funciona para evitar a apresentação de $ _POST, não $_GET. Mas este é o comportamento de que preciso. A questão do reenvio não funciona com uploads de ficheiros!

 0
Author: Andreas Rex, 2018-08-24 08:20:18

Porque não usar apenas a variável $_POST['submit'] como uma declaração lógica, a fim de salvar o que quer que esteja na forma. Você pode sempre redirecionar para a mesma página (caso eles refresquem, e quando eles carregam go back no navegador, a variável enviar post não seria mais definida. Certifique-se apenas de que o botão enviar tem um name e id de submit.

 -2
Author: Brant, 2011-11-30 06:20:20