El procesamiento de formularios es una actividad diaria en cualquier sitio de internet. Registros, pedidos, compras, accesos, busquedas, etc. requieren de procesar un formulario para iniciar la serie de acciones que le darán al usuario la respuesta deseada.
Precisamente por ser tan común el modo de procesar un formulario tiene tantas soluciones como programadores. Sin embargo, muchas de estas maneras tienen omisiones, descuidos o errores que pueden afectar a un sitio.
Por ello decidí hacer este tutorial en 4 partes, para ofrecer distintas alterntivas para procesar un formulario, destacando en todas ellas lo bueno, lo malo y lo feo con el fìn de que el lector adquiera el conocimiento necesario para elegir el mejor modo para procesar un formulario en sus circunstancias particulares.
Parto del ejemplo mas burdo (que algunas personas aún utilizan) hasta procesamiento ajax.
El problema de ejemplo:
Para ilustrar el tema del procesamiento de formularios, elegí un problema de lo mas común: la recepción del comenario de un visitante en nuestro sitio.
Basicamente el visitante nos dará nombre, correo electrónico, su comentario y nos indicará si desea recibir el boletin de nuestro sitio.
Requisitos:
Conocer lo basico de PHP y MySQL. Si se desea se pueden bajar los archivos de ejemplo aqui.
Antecedentes:
Básicamente, un formulario realiza una petición a un servidor enviando una serie de datos, que corresponden a los campos del formulario y el servidor devuelve una respuesta indicando si la peticion se efectuó correctamente.
Generalmente, la página indica al usuario el resultado de la peticion y, generalmente, queda a la espera de una nueva acción por parte del usuario.
Estas peticiones tienen dos métodos para realizarse: GET y POST.
El método get envía la información al servidor como parte de una URI, en una estructura de pares nombre:valor, por ejemplo:
www.lapagina.com/prueba.php?nombre=juan&apellido=perez
Este método tiene la limitacion de la cantidad de información que puede enviar.
El método POST envía los datos como parte de la propia petición y tambien esta estructurado como pares nombre:valor.
No tiene la limitacion del tamaño del metodo GET.
Mas informacion...
Paso 1: el formulario
Primero crearemos el formulario que utilizará nuestro usuario para dejar su comentario. Intencionalmente no manejé ningún estilo, para centrarnos totalmente en la funcionalidad.
En la linea uno, en el tag form, determinamos un nombre y un id para nuestro formulario. Estos 2 atributos permiten identificar a este elemento dentro del DOM de la página y serán utilizados mucho, más adelante.
Enseguida definimos el atributo action. Este atributo indica la pagina .php que recibirá y procesará nuestra petición. En este caso se denomina procesa_formulario.php.
A continuacion se especifica el tipo de "enconding" o codificación que se utilizará para este formulario (enctype). Generalmente podemos omitir este atributo, que por default toma application/x-www-form-urlencoded, que basta para cualquiera de los usos comunes, con excepcion de la subida de archivos, que entonces tendría que ser multipart/form-data.
Finalmente, indicamos en que ventana se mostrá procesa_formulario.php. En este caso puse _self, para que se muestre dentro de la misma ventana.
De esta forma hemos definido el comportamiento de nuestro formulario.
Posteriormente se presentan los campos que se procesarán como nombre, mail, comentario y boletín. Cada input representa una variable que se enviará a procesa_formulario.php.
Incluso el botón es enviado como variable, cuyo valor en este caso es "Enviar" (sin las comillas).
Paso 2: el servidor
Para procesar nuestra petición es necesario crear un archivo php que reciba y procese los datos enviados.
Para este ejemplo he creado el archivo procesa_formulario.php. Lo único que realiza este servidor es recibir los datos, crear y ejecutar el query para guardar el comentario en la base de datos:
$conex=new mysqli('localhost', 'usuario', 'password', 'testdata');
if (mysqli_connect_error()) {
die('Error de conexión (' . mysqli_connect_errno() . ') '
. mysqli_connect_error());
}
if(isset($_GET["boletin"])){
$boletin=1;
}else{
$boletin=0;
}
$qry_comentario="INSERT INTO comentario SET nombre='$_GET[nombre]', email='$_GET[email]', comentario='$_GET[comentario]', boletin=$boletin";
$res_comentario=$conex->query($qry_comentario);
if($res_comentario){
$resultado="Se ha guardado el comentario exitosamente";
}else{
$resultado="Ha ocurrido un error en el proceso de alta.".$qry_comentario." - ".$conex->error;
}
echo $resultado;
Lo primero que realiza este archivo es conectarse a la base de datos mediante el objeto mysqli. No hay que olvidar sustituir los datos de conexión por los de nuestro servidor MySQL.
En segundo lugar se presenta una estructura if..else.. para la variable boletín.
Esto se debe a una particularidad de los checkboxes: cuando estan seleccionados o "checked" sí envían el nombre de variable. Caso contrario no.
Dado que necesitamos saber si el usuario desea que se le envíe el boletin, validamos con la funcion isset() si existe o esta "seteada" la variable boletín.
Si la variable existe significa que el usuario la ha seleccionado o "checkeado", por ello asignamos como 1 el valor a la variable $boletin.
En caso contrario asignamos el valor 0.
Solucionado el escollo de la variable boletín, se construye y ejecuta el query para insertar la información recibida en nuestra base de datos.
$res_comentario=$conex->query($qry_comentario);
if($res_comentario){
La variable $res_comentario recibe el resultado de nuestro query. Si es verdadero o "true" nos muestra un mensaje de éxito, caso contrario, nos informa del error.
Generalmente, cuando ocurre un error en etapas de desarrollo es una buena idea mostrar el query que se ejecuto y el mensaje de error recibido. Por ello se utilizan las instrucciones:
$resultado="Ha ocurrido un error en el proceso de alta.".$qry_comentario." - ".$conex->error;
Como se puede apreciar en la linea 16 del procesa_formulario, $query_comentario contiene la cadena de texto que se esta ejecutando. $conex->error contiene la descripción del error recibido.
Una vez que el archivo ya haya sido probado y validado, se deberían quitar estas líneas ya que pueden dar información sensible que puede ser utilizada por un atacante.
Paso 3: La base de datos
En los archivos de este tutorial viene un archivo SQL para la creación de la base de datos. Sin embargo a continuacion se muestra igualmente la sentencia:
CREATE TABLE IF NOT EXISTS `comentario` (
`id_comentario` int(11) NOT NULL AUTO_INCREMENT,
`nombre` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL,
`comentario` text NOT NULL,
`boletin` tinyint(1) NOT NULL,
PRIMARY KEY (`id_comentario`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
Ya con estos tres elementos: formulario.php, procesa_formulario.php y la base de datos podemos probar nuestra aplicación.
Conclusiones:
Lo bueno:
- Es una aplicación sencilla.
- Rápida y fácilmente se puede adecuar a cualquier caso.
Lo malo:
- ¿Que sucede cuando el usuario no captura algún dato, por ejemplo el nombre?
- ¿Si el usuario pone una direccion erronea de correo electrónico o incluso, captura el email en nombre y el nombre en el email que hacemos?
Por otro lado, al ser recibidos los datos por el metodo GET, un usuario malicioso puede ingresar los datos para el formulario escribiendolos directamente en la barra de navegación:
http://localhost/pruebas2/procesa_formulario.php?nombre=&email=wakawaka&comentario=&enviar=Enviar
En este caso no es relevante, pero en casos de una compra o pago, esto podría generar operaciones no validadas por el usuario.
Lo feo:
Si interceptamos los errores y se los mostramos al usuario desde procesa_formulario.php, para que los corrija es necesario que se regrese a formulario.php para que haga la corrección. En este caso es más que posible que tenga que capturar todo de nuevo.
¿Tu volverías a capturar un formulario grande?
Evidentemente este ejemplo es meramente educacional y con fines de prueba. Pero nos ha mostrado los fundamentos y problemas asociados con el procesamiento de formularios.
En el la siguiente parte mostraremos un paso adelante para mejorar el procesamiento de nuestros formularios.
To Do's:
Trata de agregar reglas de validación para asegurarte que no lleguen datos vacíos. Puedes usar la función empty().
¿Como te aseguras que un correo electrónico es correcto?.
¿Te parece correcto que la conexión a la base de datos se encuentre dentro del archivo procesa_formulario.php o sería mejor que estuviese en un archivo aparte y agregarla con un include()?.
