php - recargue - Cómo prevenir el reenvío de formularios cuando la página se actualiza(F5/CTRL+R)
php evitar recargar pagina (16)
Tengo un formulario simple que envía texto a mi tabla SQL. El problema es que una vez que el usuario envía el texto, puede actualizar la página y los datos se vuelven a enviar sin llenar el formulario nuevamente. Podría redirigir al usuario a otra página después de enviar el texto, pero quiero que los usuarios permanezcan en la misma página.
Recuerdo haber leído algo acerca de darle a cada usuario una ID de sesión única y compararla con otro valor que resolvió el problema que tengo pero olvidé dónde está.
Usa el encabezado y redirige la página.
header("Location:your_page.php");
Puede redirigir a la misma página o página diferente.Desactivar $ _POST después de insertarlo en la base de datos.
unset($_POST);
¿Por qué no usar simplemente la variable $_POST[''submit'']
como una declaración lógica para guardar lo que esté en el formulario? Siempre se puede redirigir a la misma página (en caso de que se actualicen, y cuando go back
a activarse, go back
a aparecer en el navegador, la variable de envío de envío ya no se establecerá. Solo asegúrese de que su botón de envío tenga un name
y una id
de submit
.
Básicamente, debe redirigir fuera de esa página, pero aún así puede generar un problema mientras su Internet se ralentiza (Redirigir encabezado desde el servidor)
Ejemplo de escenario básico:
Haga clic en el botón enviar dos veces
Manera de resolver
Lado del cliente
- Desactiva el botón de enviar una vez que el cliente hace clic en él
- Si usas Jquery: Jquery.one
- Patrón de PRG
Lado del servidor
- Utilizar la marca de tiempo / indicación de fecha y hora de hashing basada en diferenciación cuando se envió la solicitud.
- Use tokens de solicitud. Cuando las cargas principales asignen una solicitud temporal, se bloqueará y, si se repite, se ignorará.
Cómo prevenir la reenvío del formulario php sin redireccionar. Si está usando $ _SESSION (después de session_start) y un formulario $ _POST, puede hacer algo como esto:
if ( !empty($_SESSION[''act'']) && !empty($_POST[''act'']) && $_POST[''act''] == $_SESSION[''act''] ) {
// do your stuff, save data into database, etc
}
En su formulario html, ponga esto:
<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;
}
}
?>
Entonces, cada vez que se envía el formulario, se genera un nuevo acto, se almacena en sesión y se compara con el acto de publicación.
Ps: si está usando un formulario Get, puede cambiar fácilmente todo el POST con GET y también funciona.
Como otros han dicho, no es posible dejar de usar post / redirect / get. Pero al mismo tiempo, es bastante fácil hacer lo que quiere hacer en el lado del servidor.
En su página POST simplemente valida la entrada del usuario pero no actúa sobre ella, en su lugar, la copia en una matriz SESSION. Luego redirige nuevamente a la página principal de envío. Su página principal de presentación comienza por verificar si existe la matriz SESSION que está utilizando y, de ser así, cópiela en una matriz local y desactívela. Desde allí puedes actuar sobre eso.
De esta manera solo haces todo tu trabajo principal una vez, logrando lo que quieres hacer.
Cuando se procesa el formulario, se lo redirecciona a otra página:
... process complete....
header(''Location: thankyou.php'');
también puedes redirigir a la misma página.
Si está haciendo algo así como los comentarios y desea que el usuario permanezca en la misma página, puede usar Ajax para manejar el envío del formulario.
Deberías usar un patrón de Post Redirect Get para manejar esto, pero si de alguna manera terminaste en una posición donde PRG no es viable (por ejemplo, el formulario en sí está en una inclusión, impidiendo redirecciones) puedes usar hash algunos de los parámetros de solicitud para hacer una cadena basada en el contenido y luego verifique que no la haya enviado ya.
//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!
}
Después de insertarlo en la base de datos, llame al método unset () para borrar los datos.
unset ($ _ POST);
Para evitar la inserción de datos de actualización, realice una redirección de página a la misma página o página diferente después de insertar el registro.
encabezado (''Ubicación:''. $ _ SERVER [''PHP_SELF'']);
Encontré la siguiente solución. Puede escapar de la redirección después de procesar la solicitud POST
manipulando el objeto del history
.
Entonces tienes el formulario HTML:
<form method=POST action=''/process.php''>
<input type=submit value=OK>
</form>
Cuando procesa este formulario en su servidor, en lugar de redirigir al usuario a /the/result/page
configurando el encabezado Location
esta manera:
$cat process.php
<?php
process POST data here
...
header(''Location: /the/result/page'');
exit();
?>
Después de procesar datos POST
ed, renderiza <script>
pequeño y el resultado /the/result/page
<?php
process POST data here
render the <script> // see below
render `/the/result/page` // OK
?>
El <script>
que debe representar:
<script>
window.onload = function() {
history.replaceState("", "", "/the/result/page");
}
</script>
El resultado es:
como puede ver, los datos del formulario se POST
a la secuencia de comandos process.php
.
Este proceso de secuencia de comandos POST
ed datos y la representación /the/result/page
de una vez con:
- sin redirección
- no hay datos
POST
cuando actualiza la página (F5) - no vuelva a
POST
cuando navegue a la página anterior / siguiente a través del historial del navegador
UPD
Como otra solución que solicito , solicite al equipo de Mozilla FireFox que permita a los usuarios configurar el encabezado de NextPage
que funcionará como un encabezado de Location
y hará post/redirect/get
patrón de post/redirect/get
obsoleto.
En breve. Cuando el proceso del servidor forma datos POST
éxito:
- Configurar el encabezado de
NextPage
lugar de laLocation
- Renderice el resultado del procesamiento de datos de formulario
POST
, ya que se procesaría para la solicitudGET
en el patrón depost/redirect/get
El navegador a su vez cuando vea el encabezado NextPage
:
- Ajustar
window.location
con el valor deNextPage
- Cuando el usuario actualice la página, el navegador negociará la solicitud
GET
aNextPage
lugar de volver a los datos del formularioPOST
Creo que esto sería excelente si se implementara, ¿no? =)
Simplemente redirija a la misma página después de hacer uso de los datos del formulario, y funciona. Lo intenté
header(''location:yourpage.php'');
También me gustaría señalar que puede usar un enfoque de javascript, window.history.replaceState
para evitar que se window.history.replaceState
a enviar en la actualización y el botón Atrás.
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
Prueba de concepto aquí: https://dtbaker.net/files/prevent-post-resubmit.php
Todavía recomendaría un enfoque Publicar / Redirigir / Obtener, pero esta es una nueva solución JS.
Una forma bastante segura es implementar una identificación única en la publicación y almacenarla en caché en el
<input type=''hidden'' name=''post_id'' value=''".createPassword(64)."''>
Luego en tu código haz esto:
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;
}
Una versión refinada de la publicación de Moob. Cree un hash del POST, guárdelo como una cookie de sesión y compare hashes en cada sesión.
// 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
}
Usar el patrón Publicar / Redirigir / Obtener de la respuesta de Keverw es una buena idea. Sin embargo, no puede permanecer en su página (¿y creo que esto era lo que estaba pidiendo?) Además, a veces puede fail :
Si un usuario web se actualiza antes de que la presentación inicial se haya completado debido al retraso del servidor, se produce una solicitud HTTP POST duplicada en ciertos agentes de usuario.
Otra opción sería almacenar en una sesión si el texto se debe escribir en su base de datos SQL de esta manera:
if($_SERVER[''REQUEST_METHOD''] != ''POST'')
{
$_SESSION[''writeSQL''] = true;
}
else
{
if(isset($_SESSION[''writeSQL'']) && $_SESSION[''writeSQL''])
{
$_SESSION[''writeSQL''] = false;
/* save $_POST values into SQL */
}
}
Use el patrón Publicar / Redirigir / Obtener. Post/Redirect/Get
Con mi sitio web, almacenaré un mensaje en una cookie o sesión, redireccionaré después de la publicación, leeré la cookie / sesión y luego borraré el valor de esa sesión o variable de cookie.
puedes pervertir el reenvío de formularios a través de la variable de sesión Me gusta
primero tiene que configurar rand () en el cuadro de texto y $ _SESSION [''rand''] en la página del formulario
<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>
Después de marcar $ _SESSION [''rand''] con textbox $ _POST [''randcheck''] value Like
if(isset($_POST[''submitbtn'']) && $_POST[''randcheck'']==$_SESSION[''rand''])
{
//Your Code here
}