You are on page 1of 37

Curso programacin en PHP y MySQL

Bloque III: El Lenguaje PHP Formularios


Ponentes: Vicente Martnez Martnez y Juan Jos Guarinos Huesca

CEFIRE

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License.

ndice de contenidos
1 - Presentacin de la Sesin.......................................................................................4 2 - Breve Repaso A Los Formularios............................................................................5 3 - Envo Y Recepcin De Datos en Formularios.........................................................6 4 - Acceso Desde PHP A Los Diferentes Tipos De Elementos De Entrada.................8 4.1 - Elemento INPUT TEXT.....................................................................................8 4.2 - Elemento INPUT RADIO...................................................................................8 4.3 - Elemento INPUT CHECKBOX..........................................................................9 4.4 - Elemento INPUT BUTTON................................................................................9 4.5 - Elemento INPUT HIDDEN...............................................................................10 4.6 - Elemento INPUT PASSWORD........................................................................10 4.7 - Elemento INPUT SUBMIT...............................................................................11 4.8 - Elemento SELECT SIMPLE............................................................................11 4.9 - Elemento SELECT MLTIPLE........................................................................12 4.10 - Elemento TEXTAREA...................................................................................12 4.11 - Elemento INPUT IMAGE...............................................................................13 4.12 - Paso de Matrices A PHP...............................................................................14 4.13 - Paso De Datos Por QUERY_STRING..........................................................15 4.14 - Elemento INPUT FILE...................................................................................16 4.14.1 - Gestin De Subida de Ficheros Desde HTML......................................16 4.14.2 - Tratamiento De Subida de Ficheros Desde PHP..................................17 4.14.3 - Problemas ms habituales en la configuracin.....................................17 4.14.4 - Ejemplo de subida de ficheros comentado...........................................18 5 - Procesamiento De Formularios En PHP................................................................21 5.1 - Procesamiento En Un Solo Script...................................................................21 5.2 - Validacin De Formularios Desde El Servidor................................................22 5.2.1 - Expresiones Regulares...........................................................................22 5.2.2 - Esquemas de validacin..........................................................................24 6 - Aendice I................................................................................................................30 7 - Bibliografa.............................................................................................................37

CEFIRE

Programacin en PHP y MySQL

1 - PRESENTACIN DE LA SESIN
En esta parte del bloque vamos a ver como enviar datos desde formularios en el cliente al script de PHP que los procesar en el servidor. Tambin se abordarn algn esquema de validacin de datos, para que estos lleguen de forma correcta al servidor. No se abordar, dejndose para ms adelante la gestin de cookies y sesiones.

-4-

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

2 - BREVE REPASO A LOS FORMULARIOS


Los formularios se crean mediante el elemento form. Dentro de este elemento se colocan los distintos tipos de controles que permiten recoger la informacin del usuario. Dos controles especiales realizan las acciones de enviar los datos al servidor o borrar los datos introducidos y restablecer los valores por defecto si los hubiera. En el lado del servidor debe existir un programa encargado de procesar los datos recogidos por el formulario, en nuestro caso ser un script en PHP. Los atributos de la etiqueta <form> sern los siguientes: action: URL del programa encargado de procesar la informacin recogida con el formulario, en nuestro caso el nombre del fuente con el script en PHP. enctype: tipo de codificacin empleada para enviar la informacin. method: mtodo utilizado para enviar los datos. Existen dos mtodos: get y post. target: nombre del marco donde se va a visualizar la informacin devuelta por el servidor. Funciona igual que en el elemento ancla de hipertexto A.

Aunque los elementos los describiremos ms adelante, podemos destacar las etiquetas fieldset y legend para agrupar elementos de un formulario y aplicarles estilos comunes.
<html> <body> <form action="procesa_formulario.php" method="post"> <fieldset> <legend>datos personales</legend> <div> nombre: <input type="text" name="nombre" value="" size="20"> </div> <div> correo: <input type="text" name="correo" value="" size="20"> </div> <div> <input type="submit" name="enviar" value="enviar"> <input type="reset" name="borrar" value="borrar formulario"> </div> </fieldset> </form> </body> </html>

-5-

CEFIRE

Programacin en PHP y MySQL

3 - ENVO Y RECEPCIN DE DATOS EN FORMULARIOS


Cuando el usuario pulsa el botn de envo de un formulario (SUBMIT) se manda al servidor una cadena de la forma: nombre=valor&nombre=valor&nombre=valor... La forma de recibirlos depender de atributo METHOD que hayamos puesto en el FORM: GET: Los datos se envan en un mensaje HTTP-GET el cual anexa la cadena con los pares nombre-valor precedidos del carcter '?' a la direccin URL con el la solicitud del script que va a tratar los datos. Esta cadena es denominada QUERY_STRING y si usamos un CGI se almacenar en una variable de ambiente con ese nombre en el servidor. PHP almacenar estos valores en la matriz superglobal $_GET utilizando como ndice de bsqueda del valor el nombre $_GET[nombre]. Recordemos del bloque 2.1 que desde PHP 4.2 el estilo corto esta desactivado, a travs de la opcin register_globals, por motivos de seguridad y el estilo largo para referenciar la matriz $HTTP_GET_VARS se ha desactivado en PHP 5. Tambin podremos usar la matriz $_REQUEST para acceder a un valor recibido mediante HTTP-GET. POST: Los datos se envan en un mensaje HTTP-POST donde se pasan los pares nombre-valor en el propio cuerpo del mensaje de solicitud http y no en la URL. Si usamos un CGI el servidor los almacena estos valores en diferentes variables de ambiente para cada par nombre-valor. PHP almacenar estos valores en la matriz superglobal $_POST utilizando como ndice de bsqueda del valor el nombre $_POST[nombre]. Deberemos usar este estilo intermedio de referencia y no es estilo corto y largo, tal y como comentbamos en el GET. As mismo tambin podremos usar la matriz $_REQUEST para acceder a un valor recibido mediante HTTPPOST.

Supongamos el siguiente formulario de la pgina formulario.html:


<html> <body> <form action="procesa_formulario.php" method="get/post"> nombre:<input type="text" name="nombre" value="" size="20"> <input type="submit" name="enviar" value="enviar"> </form> </body> </html>

-6-

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

Si enviamos los datos mediante GET, se procesarn por el siguiente script procesa_formulario.php: y podemos observar que los pares nombre-valor van en la url:

http://localhost:8084/pruebas/procesa_formulario.php? nombre=Juan&enviar=Enviar
<html> <body> <?php if (isset($_GET['enviar']) === true) // tambin seria vlido $_REQUEST['nombre'] echo 'hola '.$_GET['nombre']; else echo 'no hay datos para visualizar'; ?> </body> </html>

Si enviamos los datos mediante POST, tambin se procesarn por procesa_formulario_php pero en la URL no veremos los pares nombre valor, irn ocultos en el mensaje HTTP-POST.
<html> <body> <?php if (isset($_POST['enviar']) === true) // tambin seria vlido $_REQUEST['nombre'] echo 'hola '.$_POST['nombre']; else echo 'no hay datos para visualizar'; ?> </body> </html>

-7-

CEFIRE

Programacin en PHP y MySQL

4 - ACCESO DESDE PHP A LOS DIFERENTES TIPOS DE ELEMENTOS DE ENTRADA.


4.1 - Elemento INPUT TEXT
html: nombre: <input type="text" name="cadena" value="valor por defecto" size="20"> php: <?php $cadena = $_REQUEST['cadena']; echo $cadena; ?>

4.2 - Elemento INPUT RADIO


html: matricula: <input type="radio" name="matricula" value="o" checked>ordinaria <input type="radio" name="matricula" value="l">libre php: <?php $matricula = $_REQUEST['matricula']; echo $matricula; // visualizar o o l ?>

-8-

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

4.3 - Elemento INPUT CHECKBOX


html: <input type="checkbox" name="optativas[]" value="log" checked>lgica <input type="checkbox" name="optativas[]" value="fra">francs <input type="checkbox" name="optativas[]" value="inf">informtica php: <?php $optativas = $_REQUEST['optativas']; // devolver una matriz. foreach ($optativas as $optativa) echo $optativa.'<br>'; ?>

4.4 - Elemento INPUT BUTTON


html: <input type="button" name="actualizar" value="actualizar datos"> php: <?php $actualizar = $_REQUEST['actualizar']; if (isset($actualizar) === true) echo 'se han actualizado los datos'; ?>

-9-

CEFIRE

Programacin en PHP y MySQL

4.5 - Elemento INPUT HIDDEN


html: <input type="hidden" name="username" value="<?php $usuario ?>"> php: <?php $username = $_REQUEST['username']; echo $username; ?>

No se visualizar nada.

4.6 - Elemento INPUT PASSWORD


html: contrasea: <input type="password" name="clave"> php: <?php $clave = $_REQUEST['clave']; echo $clave; ?>

- 10 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

4.7 - Elemento INPUT SUBMIT


html: <input type="submit" name="enviar" value="enviar datos"> php: <?php $enviar = $_REQUEST['enviar']; if (isset($enviar === true) echo 'se ha pulsado el botn de enviar'; ?>

Si en lugar de submit ponemos reset se borrarn los datos del formulario.

4.8 - Elemento SELECT SIMPLE


html: calificacin: <select name="calificacion"> <option value="nopresentado" selected>no presentado <option value="noapto">no apto <option value="apto">apto </select> php: <?php $calificacion = $_REQUEST['calificacion']; echo $calificacion; ?>

- 11 -

CEFIRE

Programacin en PHP y MySQL

4.9 - Elemento SELECT MLTIPLE


html: <select multiple size="4" name="idiomas[]"> <option value="valenciano" selected>valenciano <option value="frances">francs <option value="ingles">ingles </select> php: <?php $idiomas = $_REQUEST['idiomas']; foreach ($idiomas as $idioma) echo '$idioma<br>'; ?>

4.10 - Elemento TEXTAREA


html: comentario: <textarea cols="30" rows="3" name="comentario"> este libro me parece ... </textarea> php: <?php $comentario = $_REQUEST['comentario']; echo $comentario; ?>

- 12 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

4.11 - Elemento INPUT IMAGE


Si queremos enviar datos de un formulario conuna imagen tendremos en cuenta que se envan como dato las coordenadas en dos variables Nombre.x y Nombre.y que PHP trasforma a Nombre_x y Nombre_y para que sean nombre de variable vlidos.
html: <form action="procesa_formulario.php" method="get"> <p><input type="text" name="texto" value="juan" size="20"></p> <p><input type="image" width="75" src="http://images.jupiterimages.com/common/detail/50/17/22851750.jpg" name="envio" /></p> </form> php: <?php if (isset($_GET['envio_x']) === true) echo 'hola '. $_GET['text']; ?>

En el QUERY_STRING se envia: http://localhost:8084/pruebas/procesa_formulario.php ? cadena=Juan&envio.x=58&envio.y=46

- 13 -

CEFIRE

Programacin en PHP y MySQL

4.12 - Paso de Matrices A PHP


Ya hemos visto en los casos de seleccin mltiple como enviar los datos en una matriz. Pero nos puede interesar enviar varios datos de diferentes campos de un formulario metidos en una matriz indexada. Por ejemplo si tenemos secciones diferentes de un formulario con campos del mismo nombre.
html: <form action="procesa_formulario.php" method="post"> <fieldset> <legend>datos propios</legend> <div>nombre: <input type="text" name="propio[nombre]" value="" size="20"></div> <div>correo: <input type="text" name="propio[correo]" value="" size="20"></div> </fieldset> <fieldset> <legend>datos conyuge</legend> <div>nombre: <input type="text" name="conyuge[nombre]" value="" size="20"></div> <div>correo: <input type="text" name="conyuge[correo]" value="" size="20"></div> </fieldset> <div> <input type="submit" name="enviar" value="enviar"> <input type="reset" name="borrar" value="borrar formulario"> </div> php: <?php extract($_POST['propio'] , extr_prefix_all, 'propio'); extract($_POST['conyuge'] , extr_prefix_all, 'conyuge'); echo '<table>'; echo '<tr>'; echo '<td></td><td>nombre</td><td>correo</td>'; echo '</tr>'; echo '<tr>'; echo '<td>propio</td>'; echo '<td>'.$propio_nombre.'</td>'; echo '<td>'.$propio_correo.'</td>'; echo '</tr>'; echo '<tr>'; echo '<td>conyuge</td>'; echo '<td>'.$conyuge_nombre.'</td>'; echo '<td>'.$conyuge_correo.'</td>'; echo '</tr>'; ?>

- 14 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

4.13 - Paso De Datos Por QUERY_STRING


En ocasiones me interesar pasar datos a travs de un enlace en lugar de un formulario, por ejemplo para pasar variables de Javascript a PHP o para pasar un identificador de sesin. En esos casos seremos nosotros quienes compondremos un QUERY_STRING con las variables Javascript o el id de sesin para pasarlos a travs de un mensaje HTTP-GET.
<?php echo '<a class="enlace" href="pagina_de_sesion.php?id='.$idSesion.'">'. $texto_enlace. '</a>'; ?>

El siguiente script se enva a si mismo las variables screen.widht y screen.height de Javascript para saber que resolucin de pantalla se esra usando en el cliente.
<?php // Como hemos pasado los datos en el QUERY_STRING usamos $_GET if (isset($_GET['ancho'])===true && isset($_GET['altura'])===true) { echo "El ancho de la pantalla es: ". $_GET['ancho'] ."<br />\n"; echo "La altura de la pantalla es: ". $_GET['altura'] ."<br />\n"; } else { echo "<script language='javascript'>\n"; // Pasamos las variables al propio script. echo " location.href=\"${_SERVER['SCRIPT_NAME']}?"; // Concatenamos el QUERY_STRING que ya tuviera la pagina. echo "${_SERVER['QUERY_STRING']}"; // Concatenamos las variables de Javascript de alto y ancho de la // resolucin que esta usando el usurio. echo "ancho=\" + screen.width + \"&"; echo "altura=\" + screen.height;\n"; echo "</script>\n"; exit(); } ?>

- 15 -

CEFIRE

Programacin en PHP y MySQL

4.14 - Elemento INPUT FILE


html: <form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post" enctype="multipart/form-data"> <input type="file" name="fichero"> </form>

4.14.1 - Gestin De Subida de Ficheros Desde HTML


Para subir un fichero al servidor se utiliza el elemento de entrada FILE para formularios HTML. Deberemos tener en cuenta lo siguiente: El elemento FORM debe tener el atributo enctype="multipart/form-data El elemento FORM debe tener el atributo method="post, no se puede usar HTTP-GET para enviar ficheros. El fichero tiene un lmite en cuanto a su tamao, el cual podremos fijar de dos formas diferentes. En el fichero de configuracin php.ini
;;;;;;;;;;;;;;;; ; File Uploads ; ;;;;;;;;;;;;;;;; ; Whether to allow HTTP file uploads. file_uploads = On ; Temporary directory for HTTP uploaded files (will use ; system default if not specified). upload_tmp_dir = "ruta" ; Maximum allowed size for uploaded files. upload_max_filesize = 2M

- 16 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

En el propio formulario A travs de un campo oculto en el propio formulario denominado MAX_FILE_SIZE cuyo valor indicar el tamao mximo en bytes y que no puede ser mayor al especificado en upload_max_filesize.
<h1>Subida de ficheros</h1> <form enctype="multipart/form-data" action="subida.php" method="post"> <input type="hidden" name="MAX_FILE_SIZE" value="1000000"> Seleccione el fichero .GIF a subir: <input name="imagen" type="file"> <input type="submit" value="Enviar"> </form>

4.14.2 - Tratamiento De Subida de Ficheros Desde PHP


Al cargar un archivo, se guardar en una ubicacin temporal indicada por la opcin upload_tmp_dir en el php.ini. Si no se mueve o cambia el nombre del archivo antes de que termine la ejecucin de la secuencia de comandos, se eliminar. Los datos que procesar la secuencia de comandos se almacenarn en la matriz superglobal $_FILES. Esta ser bidimensional, siendo la primera clave el nombre que asignamos en el atributo name <input name="imagen" type="file">. Esto me permitir subir ms de un fichero desde el mismo formulario. Las otras claves que tendr para un mismo fichero son: $_FILES[imagen]['tmp_name'] Es el lugar y nombre con que el archivo se ha almacenado temporalmente en el servidor. $_FILES[imagen]['name'] Nombre original del fichero en la mquina cliente $_FILES[imagen]['size'] Tamao en bytes del fichero subido. $_FILES[imagen]['type'] Tipo MIME asociado al fichero. Por ejemplo, "image/gif" o text/plain $_FILES[imagen]['error'] Cdigo de error asociado al fichero subido.

4.14.3 - Problemas ms habituales en la configuracin


Especificar en upload_tmp_dir un directorio al cual no se tiene acceso. La directiva memory_limit tiene un valor muy bajo o inferior a upload_max_filesize. La directiva max_execution_time tiene un valor bajo y el nuestro script lo excede durante la subida del fichero. La directiva post_max_size tiene un valor bajo y el nuestro fichero lo excede, su valor debe ser mayor a upload_max_filesize.

- 17 -

CEFIRE

Programacin en PHP y MySQL

4.14.4 - Ejemplo de subida de ficheros comentado


Veamos a continuacin el cdigo para subida.php donde tenemos un esquema bsico de gestin de archivos subidos al servidor, donde suponemos que esta definido el ndice $_FILES[imagen]:
<?php // Comprobamos si hay un error al subirlo. if ($_FILES['imagen']['error'] != UPLOAD_ERR_OK) { echo 'Error: '; switch ($_FILES['imagen']['error']) { case UPLOAD_ERR_INI_SIZE: case UPLOAD_ERR_FORM_SIZE: echo 'El fichero es demasiado grande'; break; case UPLOAD_ERR_PARTIAL: echo 'El fichero no se ha podido subir entero'; break; case UPLOAD_ERR_NO_FILE: echo 'No se ha podido subir el fichero'; break; default: echo 'Error indeterminado.'; } exit; } // Comprobamos que el fichero es del tipo que esperamos. if ($_FILES['imagen']['type'] != 'image/gif') { echo 'Error: No se trata de un fichero .GIF.'; exit; } // Si se ha podido subir el fichero lo guardamos if (is_uploaded_file($_FILES['imagen']['tmp_name']) === true) { // En primer lugar establecemos un nombre no repetido. $nombre = './subidas/'.$_FILES['imagen']['name']; if (is_file($nombre) === true) { $idUnico = time(); $nombre = $idUnico.'_'.$nombre; } // Movemos el fichero a su nueva ubicacin if (move_uploaded_file($_FILES['imagen']['tmp_name'], $nombre)) { // Muestro la imagen. header("Content-type: image/gif"); $fp = fopen($nombre, 'rb'); $contenido = fread ($fp, filesize ($nombre)); fclose ($fp); echo $contenido; } else echo 'Error: No se puede mover el fichero a su destino'; } else echo 'Error: Posible ataque. Nombre: '.$_FILES['imagen']['name']; ?>

Si nos fijamos la mayor parte del cdigo esta dirigido a la comprobacin de errores, puesto que la carga de archivos implica riesgos potenciales en la seguridad que deberemos tener controlados.

- 18 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

A continuacin comentaremos las diferentes partes de cdigo de ejemplo. En primer lugar comprobamos el cdigo de error en $_FILES[imagen]['error'] cuyos defines para los valores que puede contener son: UPLOAD_ERR_OK Valor: 0; El fichero se ha subido con xito. UPLOAD_ERR_INI_SIZE Valor: 1; El tamao del fichero excede el establecido en la directiva upload_max_filesize. UPLOAD_ERR_FORM_SIZE Valor: 2; El tamao del fichero excede el establecido en MAX_FILE_SIZE que se especifico en el Form de HTML. UPLOAD_ERR_PARTIAL Valor: 3; El fichero se ha subido pracialmente. UPLOAD_ERR_NO_FILE Valor: 4; no se ha subido ningn fichero. UPLOAD_ERR_NO_TMP_DIR Valor: 6; No se encuentra el directorio temporal de descarga. UPLOAD_ERR_CANT_WRITE Valor: 7; fallo de escritura en disco. Introducido en UPLOAD_ERR_EXTENSION Valor: 8; Subida parada debido a la extensin.

Una segunda comprobacin de seguridad puede ser que el contenido del fichero sea del tipo que esperamos examinando su tipo MIME en $_FILES[imagen][' type'] A finales del 2000 exista un tipo de ataque el cual consista en engaar al script para que tomara como archivo subido algn archivo local, de tal manera que si su contenido se mostraba o se copiaba en otra ubicacin donde quedara accesible poda producir fallos de seguridad.(http://seclists.org/bugtraq/2000/Sep/0055.html) Para evitar este tipo de ataques se incluy la funcin: bool is_uploaded_file ( string nombre_archivo ) Devuelve TRUE si el archivo dado por nombre_archivo fue cargado a travs de HTTP POST, lo cual nos permite verificar que un usuario malicioso no ha intentado engaar al script hacindole trabajar sobre algn archivo local como por ejemplo, /etc/passwd en Linux. Para que trabaje adecuadamente, la funcin is_uploaded_file() necesita un argumento como $_FILES[imagen][' tmp_name'] Existe otra funcin que cumple un cometido similar. Si utilizramos copy para copiar el archivo temporal a otra ubicacin con otro nombre para que no se pierda o para acceder a el posteriormente a la finalizacin del script. Nadie nos asegura que no estamos copiando un archivo local de nuestro sistema a una ubicacin accesible. Para ello se introdujo la funcin:

- 19 -

CEFIRE

Programacin en PHP y MySQL

bool move_uploaded_file ( string nombre_archivo, string destino ) Esta funcin realiza un chequeo para asegurar que el archivo indicado por nombre_archivo sea un archivo cargado vlido.

Si existe un archivo destino con el mismo nombre, este ser sobrescrito.

Por este motivo fijmonos que antes de mover el archivo subido, comprobamos con bool is_file ( string nombre_archivo ) que no existe en destino un archivo con el nombre $_FILES[imagen]['name'] y si as sucede aadimos como prefijo al nombre una marca de tiempo para que no sea sobrescrito.

- 20 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

5 - PROCESAMIENTO DE FORMULARIOS EN PHP


5.1 - Procesamiento En Un Solo Script
La forma habitual de trabajar con formularios en PHP es utilizar un nico script programa que procese el formulario o lo muestre segn haya sido o no enviado, respectivamente. Esto nos proporcionar las siguientes ventajas: Disminuye el nmero de ficheros. Permite validar los datos del formulario en el propio formulario. Esquema de funcionamiento: La 1 vez que se carga la pgina se muestra el formulario La 2 vez se procesa el formulario
SI Se ha enviado el formulario Procesar formulario SINO Mostrar formulario FINSI

Si aplicamos este esquema al ejemplo sencillo que vimos al principio, nos quedar el siguiente cdigo:
<html> <body> <?php if (isset($_GET['enviar']) === true) echo 'hola '.$_GET['nombre']; else { ?> <form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="get"> nombre: <input type="text" name="nombre" value="" size="20"> <input type="submit" name="enviar" value="enviar"> </form> <?php } ?> </body> </html>

Primero comprobamos si existe la variable del submit y si es as, suponemos que el resto de variables del formulario estn tambin establecidas. En caso contrario mostramos el formulario y en ACTION usamos la variable supreglobal $_SERVER['PHP_SELF'] para enviar los datos al mismo script que esta mostrando el formulario.

- 21 -

CEFIRE

Programacin en PHP y MySQL

5.2 - Validacin De Formularios Desde El Servidor


5.2.1 - Expresiones Regulares
Una expresin regular (ER), a menudo llamada tambin patrn, es una expresin representada por caracteres y metacaracteres que describe un conjunto de cadenas sin enumerar sus elementos. A travs de la ER es posible interpretar rpidamente vastas cantidades de un texto (o cadena de consumo). Uno de sus usos ms comunes es el de filtrar entradas de usuario, aunque lo ms lgico es hacerlo en el lado del cliente, usando por ejemplo el motor de ER de JavaScript, para no sobrecargar al servidor de trabajo evitando as envos de informacin innecesarios. No obstante, aunque comprobemos en el lado del cliente, antes de dar de alta la informacin en la BD conviene comprobar para evitar posibles ataques ala integridad de la informacin. Aunque no hay un estndar para ER. En casi todos los lenguajes la base de metacaracteres para definirlas es muy similar. PHP acepta ER estilo Perl a travs de la librera PCRE presente tambin en otros lenguajes como C y C++ y expresiones estilo POSIX-extendido ms sencillas y rpidas pero no tan seguras para datos binarios. Adems pasar de una expresin POSIX a una PCRE en muy sencillo porque POSIX es un subconjunto de los metacaracteres utilizados en PCRE. Para ver ER en general puede encontrar informacin en: http://es.wikipedia.org/wiki/Expresi%C3%B3n_regular Para expresiones PRCE puede encontrar informacin en: http://docs.php.net/manual/es/ref.pcre.php Para expresiones POSIX-extendido puede encontrar informacin en: http://docs.php.net/manual/es/ref.regex.php
A partir de la versin 5.3 de PHP, la librera de POSIX ha quedado obsoleta recomendndose en su lugar el uso de PCRE.

Aunque no se va a entrar en la construccin de ER, si que vamos a ver algunas de las funciones de PHP para utilizar ER usando PCRE. (Posiblemente si ya las hemos utilizado en otros lenguajes nos suenen las ER de los ejemplos).
Para aprender a construir expresiones regulares o patrones en la librera PCRE podemos consultar la siguiente pgina http://www.php.net/manual/es/reference.pcre.pattern.syntax.php

Buscar subcadenas con expresiones regulares.

- 22 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags [, int $offset ]]] ) Busca en el string subject las coincidencias con la expresin regular pattern. Si se proporciona array de entrada/salida matches, entonces ste se llena con los resultados de la bsqueda. $matches[0] contendr el texto que coincidi con el patrn completo, $matches[1] tendr el texto que coincidi con el primer sub-patrn entre parntesis capturado, y as sucesivamente. Normalmente, la bsqueda comienza por el principio de la cadena objetivo. Devuelve el nmero de veces que pattern coincide. Esto pordr ser 0 veces (sin coincidencias) o 1 vez ya que preg_match() detendr la bsqueda despus de la primera coincidencia. FALSE en caso de error en la expresin regular.
function EsNumeroReal($texto) { $patron = "/^[-+]?\d*[,.]?\d+([eE][-+]?\d+)?$/"; return (preg_match($patron, $texto) > 0)?true:false; } $stdin = fopen('php://stdin', 'r'); for(;;) { echo 'Numero real (escribe "s" para terminar): '; if (($nuemro = trim(fgets($stdin,1000))) == "s") exit; echo $nuemro; echo (EsNumeroreal($nuemro) === true)?' es ':' no es '; echo "un numero real \n"; } fclose($stdin);

Como hemos comentado en la descripcin del parmetros, a travs del array $matches podemos obtener el valor de sub-patrones. Algo muy til si queremos extraer datos de un texto,
$fecha = '2007-09-17'; $patron = /^(\d{4})-(\d{2})-(\d{2})$/; if (preg_match($patron, $matches) > 0) // Mostrar 1007-09-17 -> 17-09-2007 echo $matches[0].' -> '.$matches[3].'-'.$matches[2].'-'. $matches[1]; else echo 'Formato de fecha no vlido: '.$fecha;

Como en otras libreras, tambin podemos etiquetar los sub-patrones para aclarar el cdigo y evitar errores de la siguiente manera.
$fecha = '2007-09-17'; $patron = "/^(?<ao>\d{4})-(?<mes>\d{2})-(?<dia>\d{2})$/"; if (preg_match($patron, $matches) > 0) echo $matches['dia'].'-'.$matches['mes'].'-'.$matches['ao']; else echo 'Formato de fecha no vlido: '.$fecha;

- 23 -

CEFIRE

Programacin en PHP y MySQL

5.2.2 - Esquemas de validacin.


Como ya mencionamos, podremos validar los datos en el lado del cliente con algn tipo de script o desde el servidor en un proceso de ida y vuelta. Para validar los datos desde el servidor seguiremos un esquema de este tipo:
SI Se ha enviado el formulario SI Hay Errores Mostrar formulario con errores SINO Procesar formulario FINSI SINO Mostrar formulario FINSI

Aunque tambin podemos aplicar un esquema en el que se muestre el formulario slo una vez de la siguiente forma:
SI Se ha enviado el formulario Validar datos FINSI SI Se ha enviado el formulario y no hay errores Procesar formulario SINO Mostrar formulario con valores por defecto o ya enviados Mostrar algn aviso de error. FINSI

Vamos a poner un ejemplo de implementacin del segundo esquema o patrn de validacin, donde se muestra solo una vez el formulario....

- 24 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

Supongamos la siguiente biblioteca de funciones de validacin en valida.inc.


<?php function valida_EsTexto($texto) { $patron = "/^[A-Za-z][A-Za-z ]*$/"; return (preg_match($patron, $texto) > 0)?true:false; } function valida_EsEntero($texto) { $patron = "/^[0-9]+$/"; return (preg_match($patron, $texto) > 0)?true:false; } // Aqu podemos aadir otras funciones de validacin. function valida_CamposCorrectos($datos, $tipos, &$errores, &$txterrores) { $numDatos = count($datos); assert($numDatos == count($tipos)); $correctos = true; reset($datos); while (list($clave, $valor) = each($datos)) { switch($tipos[$clave]) { case 'texto': $errores[$clave] =!valida_EsTexto($valor); $txterrores[$clave] = $clave." debes introducir un texto."; break; case 'entero': $errores[$clave] =!valida_EsEntero($valor); $txterrores[$clave] = $clave." debes introducir un nmero entero."; break; // Aqu podemos aadir otros casos de validacin. case 'nada': $errores[$clave] = false; break; default: // La opcin por defecto no se puede dar // y finalizara la ejecucin. assert(false); } if ($errores[$clave] === true) $correctos = false; } return $correctos; } ?>

valida.inc

- 25 -

CEFIRE

Programacin en PHP y MySQL

Definicin de los estilos para el formulario y los errores:


div.Form { float: left; width: 450px; padding-right: 50px; padding-left: 20px; } div.Resultado { float: left; width: 450px; padding-right: 50px; padding-left: 20px; } div.EtiControl { clear: both; padding-top: 3%; } div.EtiControl span.Etiqueta { float: left; width: 100px; text-align: right; } div.EtiControl span.EtiquetaError { float: left; width: 100px; text-align: right; color: red; } .Error { color: red; } div.EtiControl span.Control { float: right; width: 335px; text-align: left; }

formulario.css

- 26 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

Cdigo PHP con el esquema de validacin del formulario:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>ejemplo validacion</title> <link href="formulario.css" rel="stylesheet" /> </head> <body> <?php include_once('valida.inc'); $enviadoFormulario = isset($_POST['datosenviados']); if ($enviadoFormulario === true) { // Obtenemos los datos recibidos. $datos = array(); $datos['Nombre'] = trim($_POST['Nombre'], " \t"); $datos['Nota'] = $_POST['Nota']; // Definimos la comprobacin para los datos recibidos. $tipos = array(); $tipos['Nombre'] = 'texto'; $tipos['Nota'] = 'entero'; // Validamos el formulario, obteniendo los errores si los hay. if (valida_CamposCorrectos($datos, $tipos, $errores, $txterrores)) $hayErroresEnFormulario = false; else $hayErroresEnFormulario = true; } else { // Inicializamos los datos a vaco, para la primera visualizacin // del formulario. $datos = array(); $datos['Nombre'] = ""; $datos['Nota'] = ""; $hayErroresEnFormulario = false; $errores = false; $txterrores = false; } // Funcin encargada de mostrarme los errores en un determinado campo. function AvisoError($errores, $txterrores, $campo) { if ($errores != false && $errores[$campo]) echo '<br /><span class="Error">'. $txterrores[$campo].'</span>'; } if ($enviadoFormulario === true && $hayErroresEnFormulario === false) { // Si todo ha ido correctamente procesamos los datos. echo '<div class = "Resultado">'; while (list($clave, $valor) = each($datos)) { echo '<div class = "EtiControl">'; echo '<span class="Etiqueta">'.$clave.':</span>'; echo '<span class="Control">'.$valor.'</span><br />'; echo '</div>'; } echo '</div>'; } else

- 27 -

CEFIRE
{ ?>

Programacin en PHP y MySQL

<div class="Form"> <form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post" name="Form_ejemplo"> <?php // Mostramos la etiqueta Nombre con o sin error. echo '<div class = "EtiControl">'; echo '<span class="'; echo $errores['Nombre']?'EtiquetaError">*':'Etiqueta">'; echo 'Nombre</span>'; // Mostramos el campo de texto para Nombre acompaado del // aviso de error si procede. echo '<span class="Control">'; echo '<input name="Nombre" id="Nombre" size="30" type="text" value="'.$datos['Nombre'].'">'; AvisoError($errores, $txterrores, 'Nombre'); echo '</span>'; echo '</div>'; // Mostramos la etiqueta Nota con o sin error. echo '<div class = "EtiControl">'; echo '<span class="'; echo $errores['Nota']?'EtiquetaError">*':'Etiqueta">'; echo 'Nota</span>'; // Mostramos el campo de texto para Nota acompaado del // aviso de error si procede. echo '<span class="Control">'; echo '<input name="Nota" id="Nota" size="3" type="text" value="'.$datos['Nota'].'">'; AvisoError($errores, $txterrores, 'Nota'); echo '</span>'; echo '</div>';?> <!-- Botones de enviar y reestablecer --> <div class = "EtiControl"> <span class="Control"> <input type="submit" name="datosenviados" value="Enviar"> <input name="Reestablecer" type="reset" id="Reestablecer" value="Restablecer"> </span> </div> </form> <?php // Aviso de revisin de errores. if ($hayErroresEnFormulario === true) echo '<br /><div class="Error">* Vuelva a introducir los campos no vlidos.</div>'; ?> </div> <!-- del Form --> <?php } ?> </body> </html>

ejemplo.php

- 28 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

El siguiente cdigo nos proporcionara una salida como esta al introducir un campo con uno o ms valores no vlidos:

La siguiente salida ser el resultado de procesar los datos de forma correcta:

Si queremos ver una explicacin ms detellada de este ejemplo podemos consultar el Apndice I de este documento.

- 29 -

CEFIRE

Programacin en PHP y MySQL

6 - AENDICE I
En el ejemplo del punto 5.2.2, intentamos implementar el modelo en que se validan los errores mostrando una sola vez el formularo. El mostarlo una vez evita que el cdigo se repita y as evitar posibles errores adems de simplificar su actualizacin. Su seudocdigo un poco ampliado sera:
SI Se ha enviado el formulario Obtener los datos Validar datos SINO Inicializar los datos por defecto a mostrar la primera vez. FINSI SI Se ha enviado el formulario y no hay errores Procesar formulario SINO Mostrar formulario con los datos por defecto o ya enviados Mostrar algn aviso de error FINSI

Vamos a intentar explicar de forma detallada como hemos implementado este esquema en el ejemplo.

- 30 -

El Lenguaje PHP Formularios. Primer SI-SINO del esquema:

Vicente Martnez Martnez Juan Jos Guarinos Huesca

SI Se ha enviado el formulario Obtener los datos Validar datos SINO Inicializar los datos por defecto a mostrar la primera vez. FINSI

Los datos del formulario se introducen en la matriz asociativa $datos y as ya podemos tener 2 o 400 datos en el formulario, que ni la interfaz, ni la implementacin de la funcin valida_CamposCorrectos cambiar. Adems definimos otra matriz asociativa $tipos, que ser un mapeo de tipos de datos a comprobar de la matriz $datos. Por ejemplo si en el formulario vamos a tener un campo llamado Nombre tendremos: $datos['Nombre'] $tipos['Nombre'] Siendo $datos['Nombre'] donde tendremos el valor del nombre Siendo $tipos['Nombre'] donde tendremos el tipo del campo a validar ('texto').
$enviadoFormulario = isset($_POST['datosenviados']); if ($enviadoFormulario === true) { // Obtenemos los datos recibidos. $datos = array(); $datos['Nombre'] = trim($_POST['Nombre'], " \t"); $datos['Nota'] = $_POST['Nota']; // Definimos la comprobacin para los datos recibidos. $tipos = array(); $tipos['Nombre'] = 'texto'; $tipos['Nota'] = 'entero'; // Validamos el formulario, obteniendo los errores si los hay. if (valida_CamposCorrectos($datos, $tipos, $errores, $txterrores)) $hayErroresEnFormulario = false; else $hayErroresEnFormulario = true; } else { // Inicializamos los datos a vaco, para la primera visualizacin // del formulario. $datos = array(); $datos['Nombre'] = ""; $datos['Nota'] = ""; $hayErroresEnFormulario = false; $errores = false; $txterrores = false; }

- 31 -

CEFIRE Validacin:

Programacin en PHP y MySQL

Definimos las comprobaciones para cada tipo, lo ms sencillo es utilizar expresiones regulares y por eso en el material comentamos algunas funciones de la librera preg. Como el objetivo de este curso no es explicar ER por tanto no pediremos que creis ninguna. Las que podis necesitar las proporcionamos. Aquellos que las hayan utilizado en otros lenguajes como Java, C#, Perl, etc.. podreis utilizarlas sin problemas. Como indicamos en el punto 5.2.1, si tnis tiempo podis profundizar en su sitaxis en la siguente URL_ http://www.php.net/manual/es/reference.pcre.pattern.syntax.php
<?php function valida_EsTexto($texto) { $patron = "/^[A-Za-z][A-Za-z ]*$/"; return (preg_match($patron, $texto) > 0)?true:false; } function valida_EsEntero($texto) { $patron = "/^[0-9]+$/"; return (preg_match($patron, $texto) > 0)?true:false; } // Aqu podemos aadir otras funciones de validacin.

- 32 -

El Lenguaje PHP Formularios. La funcin valida_CamposCorrectos

Vicente Martnez Martnez Juan Jos Guarinos Huesca

Recibe como parmetros de entrada: $datos: Matriz asociativa con Nombre campo (Clave) Dato campo (Valor) $tipos: Matriz asociativa mapeada con $datos con Nombre campo (Clave) Tipo (Valor) Devuelve como parmetros de salida: $errores: Matriz asociativa con Nombre campo (Clave) bool (Valor) el valor ser true en caso de que haya un error en el tipo del campo y false en caso sontrrio. $txterrores: Matriz asociativa mapeada con $errores con Nombre campo (Clave) texto (Valor) el texto del valor ser una descripcin del error en caso de que $errores['nombre_campo'] = true; Adems si ha habido algn error la funcin se evaluar a true y false en caso contrrio.
function valida_CamposCorrectos($datos, $tipos, &$errores, &$txterrores) { $numDatos = count($datos); assert($numDatos == count($tipos)); // Validacin mapeo. $correctos = true; reset($datos); while (list($clave, $valor) = each($datos)) { switch($tipos[$clave]) { case 'texto': $errores[$clave] =!valida_EsTexto($valor); $txterrores[$clave] = $clave." debes introducir un texto."; break; case 'entero': $errores[$clave] =!valida_EsEntero($valor); $txterrores[$clave] = $clave." debes introducir un nmero entero."; break; // Aqu podemos aadir otros casos de validacin. case 'nada': // Si no hay tipo, no hay error.. $errores[$clave] = false; break; default: // La opcin por defecto no se puede dar. assert(false); } if ($errores[$clave] === true) $correctos = false; } return $correctos; } ?>

- 33 -

CEFIRE Segundo SI-SINO del esquema:

Programacin en PHP y MySQL

SI Se ha enviado el formulario y no hay errores Procesar formulario SINO Mostrar formulario con los datos por defecto o ya enviados Mostrar algn aviso de error FINSI

if ($enviadoFormulario === true && $hayErroresEnFormulario === false) { // Si todo ha ido correctamente procesamos los datos. echo '<div class = "Resultado">'; while (list($clave, $valor) = each($datos)) { echo '<div class = "EtiControl">'; echo '<span class="Etiqueta">'.$clave.':</span>'; echo '<span class="Control">'.$valor.'</span><br />'; echo '</div>'; } echo '</div>'; } else { ?> // Este cdigo podra ir en una funcin para aclarar el esquema. <div class="Form"> <form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post" name="Form_ejemplo"> <?php

El modelo de visualizacin de la etiqueta y control con el error asociado ser igual para todos los campos y se explica a continuacin: 1 Mostramos la etiqueta con un estilo diferente dependiendo de si hay error o no: Sabremos que el campo tiene un error por que $errores['<nombre_campo>'] se evaluar a true.
// Mostramos la etiqueta Nombre con o sin error. echo '<div class = "EtiControl">'; echo '<span class="'; echo $errores['Nombre']?'EtiquetaError">*':'Etiqueta">'; echo 'Nombre</span>';

2 Mostramos el control con el valor del dato asociado : $datos['<nombre_campo>'] contendr el valor a visualizar en el control, ya sea el dato por defecto si ejecutamos la primera vez o el dato errneo si volvemos a pedir los datos.
// Mostramos el campo de texto para Nombre acompaado del // aviso de error si procede. echo '<span class="Control">'; echo '<input name="Nombre" id="Nombre" size="30" type="text" value="'.$datos['Nombre'].'">';

- 34 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

3 Tras mostrar la etiqueta y el dato mostramos el error asociado al campo SI LO HAY: Para ello utilizaremos la siguiente la funcin AvisoError
// Funcin encargada de mostrarme los errores en un determinado campo. function AvisoError($errores, $txterrores, $campo) { if ($errores != false && $errores[$campo]) echo '<br /><span class="Error">'. $txterrores[$campo].'</span>'; }

En este caso le indicamos que el campo (clave de las matrices asocitivas $errores y $txterrores) es 'Nombre' y dentro de la funcin AvisoError comprobar si hay error en $errores[$campo] y si lo hay, mostrar el texto del error obtenindolo de $txterrores.
AvisoError($errores, $txterrores, 'Nombre'); echo '</span>'; echo '</div>';

El resto de etiquetas seguirn un formato parecido, de echo quiz podramos generalizarlo para todos los imput text metiendolo en una funcin y as no repetir cdigo.
// Mostramos la etiqueta Nota con o sin error. echo '<div class = "EtiControl">'; echo '<span class="'; echo $errores['Nota']?'EtiquetaError">*':'Etiqueta">'; echo 'Nota</span>'; // Mostramos el campo de texto para Nota acompaado del // aviso de error si procede. echo '<span class="Control">'; echo '<input name="Nota" id="Nota" size="3" type="text" value="'.$datos['Nota'].'">'; AvisoError($errores, $txterrores, 'Nota'); echo '</span>'; echo '</div>';?> <!-- Botones de enviar y reestablecer --> <div class = "EtiControl"> <span class="Control"> <input type="submit" name="datosenviados" value="Enviar"> <input name="Reestablecer" type="reset" id="Reestablecer" value="Restablecer"> </span> </div> </form>

- 35 -

CEFIRE

Programacin en PHP y MySQL

4 Por ltimo, si ha habido errores en el formulario se generar un aviso.


<?php // Aviso de revisin de errores. if ($hayErroresEnFormulario === true) echo '<br /><div class="Error">* Vuelva a introducir los campos no vlidos.</div>'; ?> </div> <!-- del Form --> <?php } ?> </body> </html>

- 36 -

El Lenguaje PHP Formularios.

Vicente Martnez Martnez Juan Jos Guarinos Huesca

7 - BIBLIOGRAFA
DIVERSOS AUTORES Manual PHP Oficial Versin web 17/08/2010 desde RedIris http://docs.php.net/manual/es/ Editor principal Philip Olson. Copyright 1997-2010 por el Grupo de documentacin de PHP Bajo Licencia http://creativecommons.org/licenses/by/3.0/

- 37 -

You might also like