Ha pasado mucho tiempo (os pido sincero perdón) desde que hice la última publicación, por desgracia no siempre se tiene posibilidad de continuar un proyecto que comenzó con ilusión. Ahora voy a intentar publicar algunas entradas más para tratar de ayudaros en la construcción de formularios y gestión de datos vía php. Veréis que he introducido también alguna actualización en los posts anteriores pero solamente para incluir la descarga de ficheros de los ejemplos (error por mi parte no habéroslo facilitado desde el comienzo).
En la entrada anterior, fijamos conceptos básicos del diseño
de formularios y os comenté la filosofía Todo en Uno a la hora de crear estos
formularios. Continuando esta “línea argumental”, la filosofía Todo en uno es
muy cómoda porque nos permite conservar los valores del formulario remitidos en
los mismos campos desde los que fueron enviados (si pusimos un campo “nombre”,
podremos rellenarlo con el valor enviado por el usuario sin utilizar ningún
campo adicional).
Pero no todo es “bonito”. La filosofía Todo en uno se nos
vuelve un auténtico monstruo cuando:
- El formulario tiene mucho procesamiento y/o validación.
- Se realizan múltiples acciones condicionales (por ejemplo, si introducen un DNI y se detecta el tipo NIF, redirigir a la web X; en otro caso, si se detecta el tipo NIE, comprobar tal cosa y redirigir a la web Y; ...).
- En definitiva, cuando, hablando “en bruto”, las líneas del PHP son suficientes como para no entenderlo de un vistazo.
- Los cambios adaptativos (introducir nuevas funcionalidades) nos obligan a revisar todo el PHP completo. Como tiende a crecer, al final aumenta la probabilidad de que nos “saltemos” algo y aparezcan más errores de los deseados.
En el desarrollo de webs “importantes”, al principio me
encontré con que el Todo en uno me venía muy bien, pero poco a poco fue
complicándose:
- Tenía un “gran” formulario con los datos del solicitante (dni, nombre y apellidos, domicilio, provincia, etc etc) visibles.
- Tenía algunos campos de control, ocultos al usuario (más adelante os pondré un pequeño ejemplo de cómo utilizarlos) para manejar el flujo de la información (estoy grabando datos, estoy borrando, actualizando...) y el estado de validación (los datos introducidos son correctos / tienen error).
- Una vez rellenado el formulario, cuando el usuario hacía clic en Enviar ocurría lo siguiente:
- Comprobaba si venían los campos rellenos y ponía una variable de control a “Grabando” y la validación a “No comprobado”.
- Re-rellenaba el formulario con los datos que me vinieran por $_POST (generalmente lo usaba siempre en detrimento de $_GET).
- Según me indicase la variable de control y la de validación, ahora hacía operaciones:
- Si control no está rellenado ==>es la primera vez que muestro el formulario y, por tanto, no hago nada más (el usuario acaba de entrar)
- Si control = “Grabando” y validación = “No comprobado” ==> comprobar los datos recibidos (puede que no sean “aceptables” para lo que esperamos encontrar)
- Si control = “Grabando” y validación = “Erróneo” ==> redirigir el tráfico a una pantalla de Error.
- Si control = “Grabando” y validación = “Correcto” ==> proceder a su grabación y notificar al usuario.
- Podrían añadirse muchas más operaciones condicionadas, pero ¿veis que ya empieza a enrevesarse el procesamiento?
Os dejo un ejemplo en el que
podréis ver algo así. Se trata de recibir 3 campos del usuario: Nombre, Tipo de
Usuario (1 = Normal, 2 = Administrador) y correo electrónico. Supondremos que
para admitir los datos, el usuario ha de introducir bien el tipo de usuario y,
además, el correo electrónico debe contener el carácter “@”.
Para la resolución del ejemplo
sólo necesitáis conocer (aparte de lo visto en posts anteriores) la función
strpos de PHP, que opera de la siguiente forma: strpos(cadena,
búsqueda,desplazamiento) donde:
-
cadena es el texto donde buscamos (por ejemplo, pepe@pepito.com)
-
búsqueda es el texto que queremos encontrar (en nuestro
caso, “@” aunque no tiene por qué ser sólo un carácter).
-
desplazamiento es un parámetro opcional que viene a
decir: busca la cadena “búsqueda” en el texto A PARTIR de la posición que te
indique. Esto nos es útil en búsquedas anidadas (cuando queremos buscar un
texto VARIAS veces dentro de una misma cadena, por ejemplo si quisiéramos
encontrar cuántas veces está la letra “e” en pepe@pepito.com
o cuántas veces encontramos la sílaba “pe” en el mismo texto).
Strpos nos devolverá la posición
(un número comenzando por cero) donde se encuentra la cadena buscada o FALSE si
no la ha encontrado. MUCHO OJO con este FALSE. Fijaos en este código:
if (strpos(“hola”, “x”) == false)
Echo
“No lo encuentro”;
Y ahora en este otro código:
if (strpos(“hola”, “h”) == false)
Echo
“No lo encuentro”;
En el primer caso es evidente que
debe acabar mostrando “No lo encuentro”. Pero ¿a que no parece que en el
segundo caso deba mostrar también ese texto? Pues lo hace. ¿Por qué? Porque la
posición de la letra H en el texto HOLA es la primera, interpretada como cero.
Pero es que el valor cero, cuando PHP lo interpreta como valor verdadero/falso,
¡es el único valor que interpreta como FALSO!
¿Hay solución? Sí, claro que la
hay. Utilizar el operador === (tres signos igual seguidos)
if (strpos(“hola”, “x”) === false)
Echo
“No lo encuentro”;
if (strpos(“hola”, “h”) === false)
Echo
“No lo encuentro”;
Ahora, en el primer caso dirá “No
lo encuentro” pero no así en el segundo, ya que el operador triple igual fuerza
la igualdad booleana Y NO hace la conversión de numérico a booleano.
Podéis ver el ejemplo funcionando
en Capitulo 5, ejemplo 1
y también descargarlo en el enlace al final del capítulo con el resto de
ejemplos.
Volviendo al tema que nos ocupa
en el post (perdonad la divagación con strpos pero es que son de las cosas más
extrañas que me encontré al empezar con PHP viniendo de saber C/C++), parece
que la opción “Todo en uno” no es útil cuando los formularios son grandes o
tienen muchas condiciones de verificación.
¿Qué opciones tenemos entonces?
Hay varias que podemos ir explorando en sucesivos posts. No tienen por qué ser
excluyentes, se pueden usar varias a la vez:
1) Utilizar
páginas php intermedias cuya función es validar los datos y redirigir a páginas
de éxito / error.
2) Utilizar
páginas php intermedias que se encarguen de toda la gestión de base de datos,
de forma que cuando tengamos que escribir a base de datos, el código esté en
otros php auxiliares.
3) Utilizar
validaciones que no se realicen en el servidor (php) sino en el cliente. Para
ello nos apoyaríamos en el lenguaje JavaScript (existen otras opciones como
Visual Basic Script pero la más utilizada y donde más recursos vas a encontrar
es en JavaScript).
Si estás leyendo este post por
“entretenimiento” más que por aprendizaje, verás que estas 3 opciones nos
llevan al modelo de desarrollo más extendido que hay actualmente: MVC = Modelo
– Vista – Controlador. Pero no te asustes, no voy a escribir sobre frameworks
de desarrollo, vamos a seguir trabajando poco a poco cada uno de los puntos
para que veas que se puede con un poquito de esfuerzo por tu parte.
Más de uno diréis, ¡eh, eh,
espera! ¿MVC? ¿Esto no era un blog para aprender paso a paso? Sí, tranquilos
que no voy a dar un salto enorme ni mucho menos. Aún no hemos hablado siquiera
de bases de datos o de nociones básicas de javascript como para “saltar” a MVC,
pero me gustaría que adoptemos una visión global de a qué queremos llegar (ojo,
yo aún estoy en ese camino y llevo 12 años programando en php).
Por el momento vamos a obviar el
tema “base de datos” (si alguien está muy interesado y le urge, le recomiendo
empezar a mirar php.net y las funciones de MySQL) y nos vamos a centrar en
hacer avances en validación php y validación JavaScript. Para no cargar mucho
este post, vamos a intentar dividir el ejemplo 1 de forma que tengamos:
-
Una pantalla cuya función sea mostrar el formulario y,
a lo sumo, recuperar los valores previos (del array $_POST). La llamaremos c5-e2-principal.php.
-
Una pantalla que informa que los datos son correctos y
se ha tenido éxito, llamada c5-e2-exito.php
-
Una pantalla que informa de errores, llamada
c5-e2-error.php
-
Un PHP cuya función sea validar los datos y, en función
de la calidad de los mismos, redirija el tráfico a una u otra página,
denominada c5-e2-validador.php.
La pantalla inicial, con el
formulario y recepción de datos, creo que no hace falta que la pongamos aquí
completa. A fin de cuentas es un formulario con campos básicos en el que la
única diferencia será cómo definimos la etiqueta FORM
Observad esa etiqueta action
porque ahora estamos redirigiendo a un php distinto. Este php, como es lógico,
recibirá en $_POST los valores del formulario que se hayan consignado.
¿Qué haremos en este PHP?
Construirlo tal que así:
<?
if (strlen($_POST[‘nombre’]) ==
0)
{
header(“location:c5-e2-error.php”);
exit():
}
if ($_POST['tipo'] != "1"
&& $_POST['tipo'] != "2")
{
header (“location:c5-e2-error.php”);
exit():
}
if (strpos($_POST['email'],"@") ===
false)
{
header (“location:c5-e2-error.php”);
exit():
}
header(“location:c5-e2-exito.php”);
?>
Venga, vamos a trabajarlo un poco
porque esto se parece muy poco a lo visto hasta ahora. Para empezar, ¿dónde
están las etiquetas HTML, HEAD, BODY, etc? La respuesta es obvia: no están.
Recuerda que esas etiquetas pertenecen al estándar HTML y en la tercera lección
dijimos: “nuestro PHP debe generar un
HTML cuando queramos visualizar algo en pantalla” pero ¿necesita el
validador MOSTRAR algo en pantalla? Si miras unas líneas más arriba, verás que
dijimos que la función del validador era analizar los datos y redirigir el
tráfico a una página u otra. Al no necesitar de interacción con el usuario, no
necesitamos incluir etiquetas de HTML ya que no mostramos información.
Como es lógico, sí que
necesitamos las marcas <? y ?> ya que las comprobaciones las
vamos a hacer a través de PHP.
Las siguientes líneas de código
(ignorad la sentencia header aunque ahora mismo os la explico) son las mismas
que utilizamos para hacer comprobaciones en el ejercicio 1 (salvo el primer
strlen que, simplemente, es para comprobar que se nos ha enviado algo en la
variable nombre).
Sólo nos queda explicar qué hacen
las sentencias header y exit. header nos permite enviar encabezados http sin
formato según la especificación http/1.1. En “cristiano”, lo que nos permite
header es mandar cabeceras que le sirven al navegador para interpretar el
contenido de la página o realizar ciertas operaciones especiales reservadas. Si
tienes interés en verlas todas, aquí te dejo el enlace al RFC 2616 – Hypertext Transfer Protocol – HTTP/1.1
La cabecera que nos interesa es
Location, que nos permite redirigir el tráfico a la dirección de Internet que
indiquemos. Algunos ejemplos más de qué sería válido como
header(“location......”) son:
header(“location:www.google.es”);
header(“location:https://www.gmail.com”);
header(“location:http://servidor.com/miphp.php”);
header(“location:miphp.php?variable1=valor1&variable2=valor2”);
Fíjate que podemos redirigir el
tráfico a un servidor (Google.es) con lo que abriría la página “por defecto”
que tenga configurada (normalmente es index.html, index.php, index.jsp, ...); o
bien redirigir a una página dentro de un servidor concreto
(servidor.com/miphp.php) o, incluso, enviar parámetros por GET como se ve en el
último enlace.
Por ahora y para no complicarnos
más la cosa, nuestros location han sido simples: a un php dentro de nuestro
servidor sin más.
La sentencia exit, por su parte,
lo único que hace es detener el procesamiento en el punto en que se encuentra.
Es decir, todo el código que haya por debajo de exit es ignorado y no se
ejecuta nada más.
Los php c5-e2-exito.php y
c5-e2-error.php van a ser un simple mostrado de una frase orientativa, así que
no creo que necesitemos comentar su estructura aquí (no obstante, en el link
más abajo os podéis descargar el ejemplo completo).
Podéis ver funcionar este ejemplo
en Capitulo 5 - Ejemplo 2
3 comentarios:
Me alegro que sigas! Un saludo
A ti por volver! ;-)
exelente pagina me agrado mucho seria de gran ayuda si me pasas un tutorial completo basado en el desarrollo web empezando desde conocimiento html, si esta ejemplificado y con algunas tareas mucho mejor,, gracias.
Publicar un comentario