Cancelar el reenvío después de actualizar la página. PHP: Cómo evitar que se vuelva a enviar un formulario

04.08.2021

Hubo un tiempo en que me desconcertaba la cuestión de cómo proteger las páginas del sitio contra el envío repetido de datos del formulario durante la actualización de la página (si hubo un envío antes de eso, por supuesto).
Todo webmaster y desarrollador probablemente sepa que si hace clic en el botón "enviar" en un sitio web al completar algún formulario, luego de enviarlo, si intenta actualizar la página, el navegador mostrará un mensaje confirmando el reenvío.
En algunos casos esto puede resultar inaceptable. Por ejemplo, en el caso de un formulario de retroalimentación elemental. Cuando el usuario completó el formulario y envió un mensaje, y luego, por alguna razón que sólo él conocía, actualizó la página, la carta se envió nuevamente. Por supuesto, este puede no ser un caso tan fatal, sólo como ejemplo. Todo es mucho más doloroso, por ejemplo, a la hora de enviar un pedido en una tienda online.
Entonces me pregunté cómo encontrar una solución a este problema y me di cuenta de que solo había una solución: usar una redirección después de enviar el formulario de encabezado ('ubicación: dirección'). Aquellos. Es simple: después del envío, llamamos a una redirección (incluso puedes ir a la misma página) ¡y listo! La actualización de la página será limpia, sin POST ni GET completos.

Todo estaría bien, pero personalmente tuve algunos problemas con esto. Son los siguientes. Anteriormente, sin utilizar redirecciones, el mecanismo para enviar datos en mis sitios funcionaba de la siguiente manera:
El usuario completa el formulario, hace clic en "enviar", el script acepta los datos enviados, verifica su exactitud (validez, finalización de los datos requeridos, etc.) y da una respuesta: o la operación fue exitosa o se produjo un error y una lista de errores (por ejemplo: error - El campo "nombre" no está completado. Y en la página de envío, se muestra el mensaje correspondiente: el envío se realizó correctamente o no.
Si el envío no tiene éxito, el formulario permanece en pantalla y sus campos se completan con los datos que ingresó el usuario. Aquellos. los datos se toman de la variable $_POST (si el método es POST) y se colocan en los campos correspondientes (es decir, se devuelven desde la publicación a sus campos para no volver a ingresarlos). Después de todo, todos se molestan cuando usted completa un formulario, y Dios no permita que ingrese algo incorrecto, y cuando intenta enviárselo, aparece un mensaje de que algo se completó incorrectamente y el formulario se actualiza y está vacío. de nuevo. Y debido a que un campo se completó incorrectamente, debe completarlo nuevamente.
Entonces, como ya dije, en caso de que no se complete correctamente, el formulario permanece lleno con los datos tomados de $_POST y el usuario puede corregir los datos incorrectos y enviar el formulario nuevamente.
Todo estuvo bien y todo funcionó.
Pero luego lo envié usando la redirección y resultó que después de hacer clic en el botón "enviar", si el llenado no era exitoso, el formulario se actualizaba y los campos completados ya no podían permanecer en él, porque Anteriormente, se completaban automáticamente desde la matriz $_POST, pero ahora, después de que se produjo la redirección, $_POST se borró como si nunca hubiera habido ningún envío.
Pero también en este caso había una salida. Utilice sesiones. Aquellos. Antes de llamar al encabezado, transfiera datos de POST a las variables de sesión y solo entonces opere con ellos después de la redirección.
Como resultado, el código se volvió mucho más complicado. La depuración se ha vuelto más complicada porque En general, es difícil determinar qué sucede con las funciones en el momento en que se produce la redirección. Si cometiste algún tipo de error en los códigos (que aparece precisamente en el momento del envío), entonces ni siquiera se mostrará, porque Se producirá una redirección y ni siquiera verás el mensaje de error.
En general, después de implementar el encabezado en mis códigos, me resultó más difícil trabajar con mis aplicaciones. El desarrollo/refinamiento/búsqueda de errores se ha vuelto más complicado. Pero tampoco puedo rechazar esto.
Y sigo preguntándome: ¿existen otras soluciones más elegantes?

Hubo un tiempo en que me desconcertaba la cuestión de cómo proteger las páginas del sitio contra el envío repetido de datos del formulario durante la actualización de la página (si hubo un envío antes de eso, por supuesto).
Todo webmaster y desarrollador probablemente sepa que si hace clic en el botón "enviar" en un sitio web al completar algún formulario, luego de enviarlo, si intenta actualizar la página, el navegador mostrará un mensaje confirmando el reenvío.
En algunos casos esto puede resultar inaceptable. Por ejemplo, en el caso de un formulario de retroalimentación elemental. Cuando el usuario completó el formulario y envió un mensaje, y luego, por alguna razón que sólo él conocía, actualizó la página, la carta se envió nuevamente. Por supuesto, este puede no ser un caso tan fatal, sólo como ejemplo. Todo es mucho más doloroso, por ejemplo, a la hora de enviar un pedido en una tienda online.
Entonces me pregunté cómo encontrar una solución a este problema y me di cuenta de que solo había una solución: usar una redirección después de enviar el formulario de encabezado ('ubicación: dirección'). Aquellos. Es simple: después del envío, llamamos a una redirección (incluso puedes ir a la misma página) ¡y listo! La actualización de la página será limpia, sin POST ni GET completos.

Todo estaría bien, pero personalmente tuve algunos problemas con esto. Son los siguientes. Anteriormente, sin utilizar redirecciones, el mecanismo para enviar datos en mis sitios funcionaba de la siguiente manera:
El usuario completa el formulario, hace clic en "enviar", el script acepta los datos enviados, verifica su exactitud (validez, finalización de los datos requeridos, etc.) y da una respuesta: o la operación fue exitosa o se produjo un error y una lista de errores (por ejemplo: error - El campo "nombre" no está completado. Y en la página de envío, se muestra el mensaje correspondiente: el envío se realizó correctamente o no.
Si el envío no tiene éxito, el formulario permanece en pantalla y sus campos se completan con los datos que ingresó el usuario. Aquellos. los datos se toman de la variable $_POST (si el método es POST) y se colocan en los campos correspondientes (es decir, se devuelven desde la publicación a sus campos para no volver a ingresarlos). Después de todo, todos se molestan cuando usted completa un formulario, y Dios no permita que ingrese algo incorrecto, y cuando intenta enviárselo, aparece un mensaje de que algo se completó incorrectamente y el formulario se actualiza y está vacío. de nuevo. Y debido a que un campo se completó incorrectamente, debe completarlo nuevamente.
Entonces, como ya dije, en caso de que no se complete correctamente, el formulario permanece lleno con los datos tomados de $_POST y el usuario puede corregir los datos incorrectos y enviar el formulario nuevamente.
Todo estuvo bien y todo funcionó.
Pero luego lo envié usando la redirección y resultó que después de hacer clic en el botón "enviar", si el llenado no era exitoso, el formulario se actualizaba y los campos completados ya no podían permanecer en él, porque Anteriormente, se completaban automáticamente desde la matriz $_POST, pero ahora, después de que se produjo la redirección, $_POST se borró como si nunca hubiera habido ningún envío.
Pero también en este caso había una salida. Utilice sesiones. Aquellos. Antes de llamar al encabezado, transfiera datos de POST a las variables de sesión y solo entonces opere con ellos después de la redirección.
Como resultado, el código se volvió mucho más complicado. La depuración se ha vuelto más complicada porque En general, es difícil determinar qué sucede con las funciones en el momento en que se produce la redirección. Si cometiste algún tipo de error en los códigos (que aparece precisamente en el momento del envío), entonces ni siquiera se mostrará, porque Se producirá una redirección y ni siquiera verás el mensaje de error.
En general, después de implementar el encabezado en mis códigos, me resultó más difícil trabajar con mis aplicaciones. El desarrollo/refinamiento/búsqueda de errores se ha vuelto más complicado. Pero tampoco puedo rechazar esto.
Y sigo preguntándome: ¿existen otras soluciones más elegantes?

El proceso de envío del formulario HTML puede tardar varios segundos antes de que el formulario se envíe correctamente y se muestre la página de respuesta. Los usuarios que no sean lo suficientemente pacientes pueden hacer clic en el botón Enviar varias veces, lo que provocará que se vuelva a enviar el formulario. Por lo general, esto no es un problema, pero en algunos casos puedes hacer algo para evitar que suceda.
A continuación encontrará dos trucos sencillos para evitar la doble mensajería. Puede utilizar cualquiera de ellos o una combinación de ellos.

Evitar envíos múltiples con Javascript

Probablemente, usar Javascript para evitar que se vuelva a enviar el formulario sea la forma más sencilla. Cuando el usuario envía el formulario, puede desactivar el botón "Enviar" y cambiar su nombre por algo más claro: "Enviando, espere..."

El primer paso es establecer una identificación única, por ejemplo id="myButton":

El segundo (y último) paso es especificar dos comandos de Javascript en el archivo . El primer comando desactivará el botón Enviar después de enviar el formulario y el segundo cambiará el texto del botón para darle al usuario una idea de lo que está sucediendo. Es necesario agregar el siguiente código a la etiqueta:

La etiqueta del formulario se verá así:

En este caso, el servidor recibirá los datos, los procesará y, en lugar de mostrar el resultado, enviará al cliente a una página donde se mostrará este resultado.

La desventaja de este método es que el usuario puede hacer clic en el botón Atrás y regresar a la página redirigida. Lo arrojará hacia adelante nuevamente y, por lo tanto, el usuario difícilmente podrá regresar dos páginas al formulario que completó originalmente.

Evitar reenvíos de formularios mediante una redirección del lado del cliente

Una redirección de cliente se llama redirección de cliente porque ocurre en el lado del cliente. Es decir, en el navegador. La redirección del cliente puede ocurrir usando JavaScript y metaetiquetas.

JavaScript tiene la ventaja de sobrescribir el historial del navegador, de modo que incluso si el usuario presiona el botón Atrás del navegador, no volverá a la página que devolvió el controlador del formulario. Es decir, la ventana desaparecerá por completo. Pero algunas personas tienen JS deshabilitado.

Las etiquetas META, por otro lado, tienen la ventaja de ser universales. Redirigen a todos, siempre.

Lo óptimo sería combinar estos dos métodos. Cómo: Alexander Shurkayev describió la redirección óptima en su nota.

Usamos su método de la siguiente manera.

¡Intentemos! Ahora, como puede ver, no aparece ninguna ventana. ¿Qué hemos hecho? Lo revisamos. Si se han recibido los datos, mostramos todo lo necesario para la redirección. En principio, después de esto puedes incluso salir, para no cargar el navegador con datos innecesarios que de todos modos nadie verá.

A menudo recibo preguntas sobre la cancelación de reenvíos de formularios. Por ejemplo, creó un formulario para agregar un comentario y agregó un controlador a la misma página. Luego, al agregar un comentario, se agrega exitosamente, pero tan pronto como el usuario presiona F5, el formulario se enviará nuevamente. Y el usuario puede presionar fácilmente F5 si la página tarda mucho en cargarse. Como resultado, en lugar de 1 comentario habrá hasta 2 o incluso más. En este artículo mostraré cómo se puede evitar esto.

Primero, veamos el problema con más detalle usando este código como ejemplo:









Al hacer clic en el botón "Cuadrado", verá el resultado del script. Pero tan pronto como el usuario presione F5 después de esto, el script se ejecutará nuevamente. En este caso, esto no es tan crítico como agregar un comentario; sin embargo, ¿por qué necesita una carga adicional en el servidor?

Ahora hablemos de formas de resolver este problema. La primera forma es separar el script de procesamiento en un archivo separado. Luego, en el atributo de acción de la etiqueta del formulario, debe agregar la ruta a este script. Y el script en sí debe guardar en algún lugar el resultado de sus acciones, o las variables que llegaron al script, y luego redirigirlo de regreso. En general, mire el código del script:

Y el código de la página con el formulario ahora se verá así:









La desventaja de este enfoque es obvia: es necesario crear otro archivo para un script tan simple. Por eso, te hablo de la segunda forma de evitar volver a enviar el formulario:









Aquí el procesamiento vuelve a tener lugar en el mismo archivo, pero la diferencia clave es la presencia de una redirección a la misma página al final. Como resultado, la página se recargará después de enviar el formulario y el navegador no solicitará al usuario que envíe el formulario nuevamente al presionar F5.

Permítanme resumir cómo cancelar el reenvío de un formulario:

  • O realice el procesamiento en un archivo separado y luego redirija desde allí.
  • O realice el procesamiento en el mismo archivo que el formulario, pero después del procesamiento realice una redirección a la misma página.

Así es como se hace en scripts simples. Y, en los complejos, al final se hace lo mismo.