Evitar doble POST en PHP

En la mayor parte de desarrollos de aplicaciones hechas en web, nos encontramos con el problema de que el usuarios puede enviar dos veces la información, estos por ejemplo hay un formulario de registro el usuario ingresa sus datos y completa el registro, pero si el usuarios actualiza la página el browser preguntará si desea enviar la información nuevamente con lo cual nos arriesgamos a que el usuario se registre dos veces.

post.gif

Entre las muchas lecturas que tengo me encontré con una solución en Big Trapezze la cual comparto con ustedes. Se trata de una clase que verificará que no se envíen dos veces los datos del formulario. Para ello debes crear un archivo llamado postClass.php.

php
  1. <?php
  2. class Post_Block {
  3.     function startPost() {
  4.         echo "<input type='hidden' name='postID' ";
  5.         echo "value='".md5(uniqid(rand(), true))."'>";
  6.     }
  7.  
  8.     function postBlock($postID) {
  9.         session_start();
  10.         if(isset($_SESSION['postID'])) {
  11.             if ($postID == $_SESSION['postID']) {
  12.                 return false;
  13.             } else {
  14.                 $_SESSION['postID'] = $postID;
  15.                 return true;
  16.             }
  17.         } else {
  18.             $_SESSION['postID'] = $postID;
  19.             return true;
  20.         }
  21.     }
  22. ;}
  23. ?>

Esta clase tiene dos funciones la primera startPost creara un campo oculto en el formulario con un número identificador único que servirá para verificar si se envió el formulario. La segunda función llamada postBlock verifica que el identificador no exista y si no detiene la ejecución del script.

Uso de la Clase

Primero debemos insertar el código de verificación en nuestro formulario y esto lo hacemos con la función startPost.

php
  1. <?php
  2. require("postClass.php");
  3. $thisPost = new Post_Block;
  4. ?>
  5. <form name="foo" action="action.php" method="post">
  6.     <input type="text" name="generica" size="25">
  7.     <?php $thisPost->startPost(); ?>
  8. </form>

El siguiente paso es verificar el número identificador en nuestra pagina que procesa el formulario, en nuestro ejemplo action.php.

php
  1. <?php
  2. require("postClass.php");
  3. $thisPost = new Post_Block;
  4. if ($thisPost->postBlock($_POST['postID'])) {
  5.     // No existe doble post
  6.     // Procesamos la información
  7. } else {
  8.     // Doble post, no procesamos el form.
  9.     echo "Oops!! Doble Post!";
  10. }
  11. ?>

Como verá con una sentencia if podemos verificar que no se esten enviando dos veces el formulario. Como comentario adicional debo decirles que hay otra forma de evitar este problema y es que luego de procesar los datos redireccionemos a otra página de confirmación de procesamiento de datos, con esto se evita que se envíen los datos, el único problema es que tenemos que crear un tercera página solo para confirmación de resultados.

Comentarios Total 16 comentarios


HERNAN CONTRERAS
Publicado: 13/12/2006 6:20 pm

Excelente aporte, a mí me pasaba que un formulario se estaba enviando dos veces, pero era por un error de hacer submit en el javascript. Pero gracias a esta clase encontré que el formulario se enviaba dos veces. Saludos.

eduardo
Publicado: 03/01/2008 11:04 pm

Excelente articulo, muchas gracias! Con esto solucioné mi problema :)

Oz
Publicado: 06/02/2008 8:31 pm

excelente tip¡ muy util¡ para evitar tipos de mail bombers¡

Leonardo
Publicado: 13/05/2010 1:33 am

SOS UN MAESTRO!!!

Muchisimas gracias!! Me solucionaste un problema muy grande.

Ahora tengo que hacerlo en todos los forms. ¿Alguna ayudita para buscarlos? jeje

Saludos

Juanma
Publicado: 18/09/2010 4:04 pm

Buenísimo, muchas gracias, realmente el único método que me solucionó el problema del doble post.

Gracias!

Carlos
Publicado: 06/10/2011 8:56 am

Gracias! Funciona perfectamente y es muy útil. No solo evita el doble post, sino el triple-post, cuadruple-post… y aquellos emails repetidos enviados tantas veces como veces clicado el F5!!

Fernando Sánchez
Publicado: 16/12/2011 2:54 pm

Como siempre, fantástico.

Pedro Urday
Publicado: 06/03/2012 2:20 pm

Esa manera esta muy bien. Tambien se puede evitar que aparesca ese cartel. Se trata simplemente de usar redireccion absoluta con php. Tu codigo se puede convinar de alguna manera con este:

//archivo 'formulario.php'
'', 'campo2' => '', 'campo3' => '');
}
?>

Campo 1:
<input type="text" name="campo1" value="">

Campo 2:
<input type="text" name="campo2" value="">

Campo 3:
<input type="text" name="campo3" value="">

Con esto el browser no volvera a preguntar si desea enviar la información nuevamente. Que les parece? A mi me funciona. Diganme si les funciona.

Pedro Urday
Publicado: 06/03/2012 3:04 pm

Perdon. El codigo se me chispoteo. Es este:


//archivo 'formulario.php'
<?php
if (isset($_POST)){
//recibo los campos del formulario
$msg_error = ''; //mensaje de validacion erronea
//valido los campos del formulario
$id; //id del resultado del post
if ($msg_error == '') {
require_once 'include/conectar.php'; //archivo de coneccion
$sql = "INSERT INTO blablabla"//el 'blablabla' no va, lo remplazan
if (mysql_query($sql)){
header("HTTP/1.1 301 Moved Permanently");
header("Location: resultados.php?id=$id");
exit();
}else
$msg_error .= 'Error en el servidor: no se pudo enviar.';
}
$campo = $_POST;
}else{
//Les seteo algunos valores por defecto a los campos del formulario
$campo = array('campo1' => '', 'campo2' => '', 'campo3' => '');
}
?>

<!-- Envio las variables al mismo formulario por el metodo post-->
<form class="mi-formulario" action="formulario.php" method="post">

<label>Campo 1:<br>
<input type="text" name="campo1" value="<?=$campo['campo1']?>"><br></label>

<label>Campo 2:<br>
<input type="text" name="campo2" value="<?=$campo['campo2']?>"><br></label>

<label>Campo 3:<br>
<input type="text" name="campo3" value="<?=$campo['campo3']?>"><br></label>

</form>

Con esto el browser no volvera a preguntar si desea enviar la información nuevamente. Que les parece? A mi me funciona. Diganme si les funciona.

jander
Publicado: 20/03/2012 11:52 am

Pedro Urday, lo que dices es la mejor manera de evitar este tipo de problemas Está documentado aquí: http://en.wikipedia.org/wiki/Post/Redirect/Get

SaludoS!

Gustalh
Publicado: 29/06/2012 6:47 pm

Definitivamente eres el cool!!!, me salvaste de morir por fin pude ver la luz =$

chuchhin
Publicado: 27/12/2012 2:32 am

Muy buenas entradas, me han ayudado mucho con mi trabajo de tesis.
Ojalá sigas escribiendo información que nos ayuda a todos.
Un sauldo y gracias.

Fernando
Publicado: 17/02/2013 8:39 pm

Me fue de utilidad.Muy claro y bien explicado.Pude arreglar el tema que los reenvios que durante mucho tiempo lo venia portergando.Gracias

Francisco
Publicado: 09/03/2013 1:16 pm

Funciona bien con el retroceder del navegador, no puede enviar dos veces el formulario. Pero no funciona con que el idiota de mi cliente presione dos veces el boton submit, lo bloqueare con javascript a ver si no me sigue jodiendo

 

Comentar

En este blog los comentarios están moderados, serán mostrados cuando el administrador los apruebe. Por favor, evita comentarios ofensivos u obscenos por que no serán aprobados.
Si deseas publicar código fuente debes hacerlo entre las etiquedas <code> y </code>, además debes reemplazar los carácteres < por &lt; y > por &gt;.

(Requerido)

(Requerido, no será publicado)

(Requerido)

(Tags aceptados: <a> <em> <strong> <code> <ul> <li>)