La Página de DriverOp

Recuperar datos de un formulario.

Aquí desarrollaré un método para recuperar datos de un formulario que el usuario ya ha enviado al servidor y este lo rechaza.

Introducción.

El problema es simple y bastante común. El usuario llena un formulario. Introduce datos erróneos, faltantes o inconsistentes y el servidor los rechaza devolviéndolo al formulario de ingreso, pero el usuario ahora tiene que comenzar todo de nuevo. Esto puede ser frustrante para el usuario si se trata de un formulario con datos delicados o con muchos campos para rellenar.

Entonces es mejor que el servidor le ayude recuperando los datos que el usuario ya ha enviado poniéndoselos en su lugar para que el usuario solo tenga que modificar y/o completar lo que está mal o faltante.

La solución que implementaré aquí utiliza HTML y PHP únicamente concentrándome solo en el problema planteado dejando para el lector la tarea de determinar cuándo y por qué un dato es erróneo. Aunque es verdad que los datos de un formulario hoy en día se pueden verificar usando algo de JavaScript, no todo tipo de dato puede ser validado usando JS, por ejemplo, saber si un número de cliente existe en la base de datos remota exige que el cliente haga una petición al servidor, algo que JavaScript por sí mismo no podría hacer (incluso con AJAX!).

Mi solución divide el problema en dos partes. La primera parte es la recogida de datos, esto se traduce en un formulario HTML (tag form). La segunda parte es la validación de datos luego de que el usuario ha enviado esos datos al servidor para ser validados. Esto se traduce en dos archivos diferentes. Al primero lo llamaré formulario.php y al segundo validador.php.

Provisiones del sistema.

Ambos componentes del sistema, formulario y validador, trabajan en conjunto. Mientras que el primero espera que el segundo se encargue de la validación, el segundo espera que el primero recoja los datos. El problema aparece porque el modelo HTTP es unidireccional. Esto quiere decir que el servidor no hace nada a menos que el cliente se lo pida, mientras que en un sistema de validación de datos exigie que el servidor le ordene al cliente que corrija los datos cuando encuentra que estos son, de alguna manera, erróneos.

Para subsanar esto recurriré a algunos mecanismos previstos por el protocolo HTTP, como ser la redirección automática, y del lenguaje PHP, que tiene la capacidad para administrar sesiones en el sevidor.

Esto de las sesiones implementadas por PHP es una gran ventaja que nos ayudará a resolver el problema en cuestión. Es importante que el lector entienda el concepto detrás de las sesiones en PHP. Básicamente una sesión es un espacio de almacenamiento de información en forma de variables que son persistentes al cambio entre la ejecución de un script y otro; y a su vez, permiten que cada espacio de almacenamiento sea único para cada visitante del sitio web, de forma tal que dos usuarios distintos accediendo a las mismas páginas no se interfieran entre sí. En otras palabras, a cada usuario le corresponde una sesión y el estado de una, no afecta el estado de la otra.

Esto quiere decir que los datos persisten para un usuario durante toda su estadía en el sitio permitiéndole al servidor trasladar datos de una ejecución a otra para ese usuario.

Este mecanismo es sencillo de manejar en PHP y bastante transparente en cuanto a su implementación para nosotros los programadores. Solo hay que tener una precaución importante: Si durante la ejecución de un script PHP se necesita acceder a una variable de sesión, la sesión debe ser iniciada o reiniciada antes de enviar ningún dato al cliente. No puede ejecutarse un "echo" o un fragmento de código HTML o tan siquiera un espacio vacío o retorno de carro hacia el navegador. Esto se debe a que las sesiones hacen uso de cookies que se almacenan en el cliente y el protocolo HTTP dispone que las cookies se envian como cabeceras (headers) de una página. Y las cabeceras siempre se envian ANTES que cualquier otra cosa cuando un navegador intenta cargar una página web.

PHP tiene una función estandar para indicar que se usará una sesión, la cual es session_start(). Esta función es la que envia las cabeceras requeridas al cliente y por tanto es la que primero debe ejecutarse antes de enviar cualquier otra cosa al navegador. Una vez que se ha ejecutado esa función ya podemos acceder a cualquier variable de sesión.

Las variables de sesión en PHP están contenidas en un array superglobal cuyo identificador es $_SESSION[]. Esta variable es un array asociativo donde cada posición de ese array puede contener cualquier dato, incluso otros arrays.

En orden a implementar una solución para el problema planteado haré uso de sesiones en PHP. Con lo explicado hasta aquí es fácil darse cuenta que este mecanismo es bastante obvio como solución.

El formulario.

Pasemos entonces a implementar el formulario con su script PHP asociado. He aquí el código fuente del archivo que llamaré "formulario.php".

<?php 
session_start();
$nombre = "";
$apellido = "";
if (isset($_SESSION["datos"])) {
$nombre = $_SESSION["datos"]["nombre"];
$apellido = $_SESSION["datos"]["apellido"];
}
?>
<html>
<body>
<form name="form1" action="validar.php" method="post">
<input type="text" name="nombre" value="<?=$nombre?>">
<input type="text" name="apellido" value="<?=$apellido?>">
<input type="submit" name="submit" value="enviar">
</body>
</html>

En primer lugar y antes que nada se abre una sesión. Luego se inicializan un par de variables que se corresponden con los datos que se piden en el formulario. A continuación se pregunta si existe el array $_SESSION["datos"], si es así, entonces se procede a extraer los datos del array. La parte de PHP explicada aquí la explicaré más profundamente más adelante.

Finalmente, ya en el código HTML se muestran los valores de ese par de variables donde va el parámetro "value" de los inputs los cuales son cajas de textos.

Aquí el mecanismo descanza sobre la asunción de que si existe el array $_SESSION["datos"] implica que el usuario ya pasó por este formulario y ese array debería contener los datos ingresados por el usuario la vez anterior. Sin embargo el amable lector se estará preguntando dónde se han asignado esos valores para el array $_SESSION["datos"]. Esa tarea es del siguiente script, el que recibe los datos que el usuario ha ingresado.

El validador.

En el código anterior vemos que el parámetro "action" del "form" apunta al script validar.php, este script es el encargado de hacer algo con los datos que el usuario ha escrito. He aquí el código fuente del script.

<?php
session_start();
$_SESSION["datos"] = Array();
$nombre = @$_POST["nombre"]; $_SESSION["datos"]["nombre"] = $nombre;
$apellido = @$_POST["apellido"];
$_SESSION["datos"]["apellido"] = $apellido;
$err = false;
if (validar_nombre($nombre) == false) { $err = true; }
if (validar_apellido($apellido) == false) { $err = true; }
if ($err == true) { header("Location: formulario.php"); exit; }
// resto del código aquí...
unset($_SESSION["datos"]);
?>

Se comienza (re)iniciando la sesión. Luego se inicializa el array $_SESSION["datos"]. Esto se hace porque se asume que si ese array ya existía debido a un rechazo anterior de los datos, esos datos ya no son válidos, los que contarían como nuevos son los datos que ahora mismo el usuario ha ingresado. Pero si es la primera vez que el usuario ha enviado los datos desde el formulario, entonces se crea ese array como tal, como un array. A continuación se extraen los datos que el usuario envió desde el array superglobal $_POST puesto que ese es el tipo de petición especificado en el "method" del "form". El "@" delante de $_POST hace que si esa posición en el array no existe, la variable que está a la izquierda del signo igual quede definida pero vacía, es una pequeña medida de seguridad.

Al mismo tiempo se pasa el valor extraído así hacia el array de sesión, este paso es muy importante y es el núcleo de la solución implementada.

Luego se establece una variable tipo bandera que indicará al final del proceso de validación, si hubo un error en los datos o no. Por omisión se asume que no habrá errores.

Las funciones "validar_nombre" y "validar_apellido" implementarán los códigos necesarios para determinar si las variables $nombre y $apellido contienen valores válidos, se espera en este ejemplo que esas funciones devuelvan un valor booleano. Las implementaciones de estas dos funciones serán a gusto del lector, aquí solo se mencionan a modo de ejemplo. En caso de que alguna variable resulte tener un dato inválido, la variable de bandera $err tomará valor "verdadero".

Lo que resta por hacer es determinar el valor de esa variable bandera. En caso de haber error, se redirecciona al cliente a que vuelva a cargar la página "formulario.php" mediante el uso de la función estandar de PHP header() y se fuerza a que termine el script ahí mismo. Caso contrario se puede proceder a poner el resto del código que el lector crea conveniente (por ejemplo aquí se puede hacer una inserción o modificación de una base de datos).

Finalmente se destruye el array $_SESSION["datos"]. Esto se hace porque si éste script llegó al final, significa que los datos que aportó el cliente fueron usandos adecuadamente y ya no es necesario volver a mostrárselos al usuario en caso de que visite de nuevo el formulario.

¿Por qué funciona?.

La primera vez que el usuario visita "formulario.php" el if que determina si $_SESSION["datos"] existe resultará falso. Por lo tanto los dos inputs tipo texto se mostrarán vacíos, listos para que el usuario los rellene.

Pero si ese if resulta verdadero implica que el usuario fue forzado a recargar el formulario debido a la ejecución de la función header() que está en validar.php y por lo tanto $_SESSION["datos"] contiene los mismos datos que ya había ingresado. Y así los inputs mostrarán los datos que el usuario ingresó la vez anterior.

Consideraciones finales.

Lo explicado hasta aquí y el ejemplo implementado es nada más que para mostrar la funcionalidad básica de la solución propuesta. Hay muchos detalles en el camino que habría que controlar pero que escapan al propósito de este artículo. Un ejemplo de ello es que debido a la forma en que PHP y el servidor web trata ciertos caracteres en el array $_POST, el usuario podría no tener exactamente la misma cadena de texto que él ingresó. Esto es cierto en el caso de las comillas simples o dobles.

Una forma de controlar esto sería así:

if (get_magic_quotes_gpc()) {
$nombre = stripslashes($nombre); }

Este código iría en el script validar.php.

En el ejemplo se asume que los datos que se le piden al usuario son nuevos datos y no modificación de datos que ya están contenidos en otra parte. Por ejemplo si el formulario sirve para modificar datos que están en una base de datos. En ese caso este ejemplo ya no funciona sin una extensa revisión de la lógica del mismo.

Otro detalle que no está en el ejemplo es que si bien funciona como solución, el usuario no es informado de ninguna manera de por qué sus datos fueron rechazados. El lector tendrá también la tarea de modificar adecuadamente el código presentado aquí para suplir esta falencia.

Si tienes preguntas o comentarios sírvete usar mi formulario de contacto.

Por Diego Romero,