Gestionar formularios y enlaces
Información general
1. Introducción
En los sitios web dinámicos, muy a menudo es necesario interactuar con el usuario.
En HTML, existen principalmente dos métodos para interactuar con un usuario:
-
los enlaces (etiqueta <a>);
-
los formularios (etiqueta <form>).
Se pueden usar scripts PHP para procesar el clic del usuario en un enlace o la introducción de datos por parte del usuario en un formulario.
2. Los enlaces
El enlace o vínculo es la técnica básica que permite a un usuario navegar entre las diferentes páginas de un sitio.
Un enlace HTML se define entre las etiquetas <a> y </a>.
Sintaxis simplificada
<a
[ href="url" ]
[ id="identificador_enlace" ]
[ target="destino" ]
>
...
</a>
Los atributos de la etiqueta <a> son los siguientes:
href |
URL (Uniform Resource Locator) relativa o absoluta a la que llama el enlace. |
id |
Identificador del enlace. Si la página HTML contiene varios enlaces, el identificador permite diferenciarlos. En nuestro caso, este identificador no tiene ningún valor porque no se recupera en el script de procesamiento del enlace. En contraposición, se puede utilizar del lado del cliente, en JavaScript, por ejemplo. |
target |
Destino (por ejemplo, otra ventana) en el que se abrirá la dirección URL de destino. Por defecto, la URL de destino se muestra en la misma ventana. |
La URL puede contener parámetros que permitan pasar información de una página a otra.
Sintaxis
url_clasica?nombre=valor[&...]
El signo de interrogación (?) introduce la lista de parámetros de URL separados por el carácter «&»; cada parámetro se compone de un nombre/valor en la forma nombre=valor:
www.misitio.com/info/inicio.php?nombre=Olivier
buscar.php?nombre=Olivier&apellido=HEURTEL
Ejemplo
-
Script pagina1.php
<?php
// Inicialización de una variable.
$nombre='Olivier';
?>
<!DOCTYPE html>
<html xmlns=“http://www.w3.org/1999/xhtml” lang=“es”>
<head><meta charset="utf-8" /><title>Página 1</title></head>
<body> ...
Recuperar los datos pasados por la URL
1. Consideraciones
a. ¿Qué sucede si dos parámetros comparten el mismo nombre?
Simplemente, el último parámetro encontrado en la URL es el que determina el valor.
Ejemplo
<a href="pagina2.php?nombre=Olivier&nombre=Xavier">Página 2</a>
Esta URL da una sola variable nombre igual a Xavier en la matriz $_GET.
b. Utilizar una matriz para pasar datos en la URL
Es posible utilizar una notación del tipo matriz en el nombre del parámetro que se pasa en la URL.
Ejemplo
<a href="pagina2.php?data[]=HEURTEL&data[]=Olivier">Página 2</a>
Esta URL da una variable data, de tipo matriz, que contiene las siguientes líneas:
Clave |
Valor |
0 |
HEURTEL |
1 |
Olivier |
PHP completa la matriz añadiendo una línea para cada parámetro con un índice entero consecutivo que comienza en 0 (como para la notación [] estudiada en el capítulo Introducción a PHP - Las bases del lenguaje PHP - Matrices).
Esta técnica es interesante, pero debe saber que en el código, el índice 0 corresponde al apellido y el índice 1 al nombre. Por otra parte, puede surgir un problema si el orden de los parámetros cambia.
Para mejorar esta técnica, es posible establecer la clave, bien con un número o con una cadena de caracteres.
Ejemplo
<a href="pagina2.php?data[apellido]=HEURTEL&data[nombre]=Olivier">
Página 2</a>
Esta URL da el resultado siguiente en la matriz data:
Clave |
Valor |
apellido |
HEURTEL |
nombre |
Olivier |
2. Transferir caracteres especiales
Si el valor que se transmite no contiene caracteres especiales (espacio, signo &, signo de interrogación (?), etc.), puede colocarse directamente en la URL como se ha indicado anteriormente. De lo contrario, es necesario codificarla para evitar la interpretación incorrecta de estos caracteres especiales.
Por ejemplo, si el dato pasado en la URL contiene «Olivier & Xavier», solo «Olivier» se recuperará a su llegada, ya que el & se interpreta como el separador de parámetros.
La codificación necesaria se puede realizar muy fácilmente con las funciones urlencode o rawurlencode.
Sintaxis
cadena urlencode(cadena valor)
cadena rawurlencode(cadena valor)
valor |
Cadena que se va a codificar. |
Estas dos funciones devuelven...
Recuperar los datos introducidos en el formulario
1. Consideraciones
a. ¿Qué sucede si dos campos comparten el mismo nombre?
Simplemente, el último campo encontrado en el formulario es el que determina el valor.
Ejemplo
<form action="entrada.php" method="POST"><div>
Apellido: <input type="text" name="nombre"><br />
Nombre: <input type="text" name="nombre"><br />
<input type="submit" name="ok" value="OK">
</div></form>
El texto HEURTEL en la primera zona y Olivier en la segunda dan un solo valor igual a Olivier en la matriz $_POST.
b. ¿Qué ocurre si hay dos formularios en la página HTML?
Las variables solo se crean y se rellenan en el formulario que ha sido validado.
Ejemplo
<form action="entrada.php" method="POST"><div>
Nombre 1: <input type="text" name="nombre1"><br />
<input type="submit" name="ok1" value="OK1">
</div></form>
<form action="entrada.php" method="POST"><div>
Nombre 2: <input type="text" name="nombre2"><br />
<input type="submit" name="ok2" value="OK2">
</div></form>
Si el usuario valida el primer formulario, el valor nombre1 estará disponible. Si el usuario valida el segundo formulario, el valor nombre2 es el que estará disponible.
c. Usar una matriz para recuperar los datos introducidos
Es posible utilizar una notación de tipo matriz en el atributo name de las etiquetas <input>, <select> y <textarea>.
Ejemplo
<form action="entrada.php" method="POST"><div>
Apellido: <input type="text" name="entrada[]"><br />
Nombre: <input type="text" name="entrada[]"><br />
<input type="submit" name="ok" value="OK">
</div></form>
El texto HEURTEL en el primer campo y Olivier en el segundo dan una sola variable $entrada, de tipo de matriz, que contiene las siguientes líneas:
Clave |
Valor... |
Controlar los datos recuperados
1. Información general
En la primera parte de este capítulo, vimos cómo recuperar los datos pasados en una URL o introducidos en un formulario.
A continuación, es necesario comprobar que los datos recuperados son correctos, es decir, que respetan las normas de gestión definidas para la aplicación.
Para la seguridad del sitio, es necesario no fiarse de los datos procedentes del exterior (formulario, URL, pero esto también lo veremos más adelante: cookie, etc.). Estos datos se deben controlar, filtrar, para evitar posibles ataques de un usuario malintencionado.
El objetivo de este apartado es proporcionar una orientación sobre las técnicas más utilizadas en PHP para realizar esta comprobación. Otro posible enfoque consiste en realizar un control en JavaScript en el navegador; se trata de evitar un viaje de ida y vuelta al servidor.
Los diferentes ejemplos que se presentan en esta parte utilizan formularios. Deben realizarse las mismas verificaciones para los datos pasados en una URL.
2. Comprobaciones clásicas
a. Limpieza de los espacios no deseados
La función trim (véase el capítulo Utilizar las funciones PHP - sección Manipular las cadenas de caracteres) se puede utilizar para eliminar los espacios en blanco no deseados al principio o al final de la cadena. En el caso de un formulario, este procesamiento se aplica especialmente a los campos de entrada libre (<input> de tipo text o password, <textarea>).
Ejemplo
// Recuperar el valor introducido en el campo «apellido» y limpiar
// los espacios en blanco (al principio y al final)
$apellido = trim($_POST['apellido']);
b. Datos obligatorios
Comprobar si un dato obligatorio está presente resulta muy simple: basta con comprobar si la variable asociada contiene un valor.
Ejemplo
$apellido = trim($_POST['apellido']);
if ($apellido == '') {
// $apellido vacío = campo "apellido" no rellenado => hacer algo
}
c. Longitud máxima de una cadena
La longitud de los datos recuperados se puede controlar con la función strlen (véase el capítulo Utilizar las funciones PHP - sección Manipular las cadenas de caracteres). En el caso de un formulario, este procesamiento se aplica especialmente a los campos...
Problemas con los datos recuperados
Puede producirse un problema de presentación en un campo de formulario si el texto que se muestra contiene un signo de comillas (").
Ejemplo
![images/07ri20.png](https://www.eni-training.com/download/74e1440d-6b0e-4af9-a157-0d3a7851889f/images/07ri20.png?id=AAEAAAD%2f%2f%2f%2f%2fAQAAAAAAAAAMAgAAAE1FbmkuRWRpdGlvbnMuTWVkaWFwbHVzLCBWZXJzaW9uPTEuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49bnVsbAUBAAAAJ0VuaS5FZGl0aW9ucy5NZWRpYXBsdXMuQ29tbW9uLldhdGVybWFyawIAAAAHcGlzVGV4dAlwaWR0ZURhdGUBAA0CAAAABgMAAAAwdGVzdCB2Ml84IC0gZmZhNjQzOWQtZDZjYi00NzYxLWJhYTMtZWZkZDNiZDcwMWM25rSq0F7p2IgL)
![images/07ri21.png](https://www.eni-training.com/download/74e1440d-6b0e-4af9-a157-0d3a7851889f/images/07ri21.png?id=AAEAAAD%2f%2f%2f%2f%2fAQAAAAAAAAAMAgAAAE1FbmkuRWRpdGlvbnMuTWVkaWFwbHVzLCBWZXJzaW9uPTEuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49bnVsbAUBAAAAJ0VuaS5FZGl0aW9ucy5NZWRpYXBsdXMuQ29tbW9uLldhdGVybWFyawIAAAAHcGlzVGV4dAlwaWR0ZURhdGUBAA0CAAAABgMAAAAwdGVzdCB2Ml84IC0gZmZhNjQzOWQtZDZjYi00NzYxLWJhYTMtZWZkZDNiZDcwMWM25rSq0F7p2IgL)
Código fuente de la página en el navegador (extracto)
<form action="entrada.php" method="post">
<div>
Entrada: <input type="text" name="entrada"
value="dijo: "¡Hola!"" />
<input type="submit" name="ok" value="OK" />
<br />dijo: "¡Hola!" </div>
</form>
En HTML, en los atributos de las etiquetas (value, name...), el delimitador de cadena es el signo de comillas. En el atributo value, la secuencia "dijo:" se considera como el valor del atributo y el resto de la cadena se pasa por alto. El problema se produce incluso si las comillas se escapan por medio del carácter \ porque este último no es un carácter de escape en HTML.
Otro problema de presentación se produce en la página si los datos mostrados contienen etiquetas HTML.
Ejemplo
![images/07ri22.png](https://www.eni-training.com/download/74e1440d-6b0e-4af9-a157-0d3a7851889f/images/07ri22.png?id=AAEAAAD%2f%2f%2f%2f%2fAQAAAAAAAAAMAgAAAE1FbmkuRWRpdGlvbnMuTWVkaWFwbHVzLCBWZXJzaW9uPTEuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49bnVsbAUBAAAAJ0VuaS5FZGl0aW9ucy5NZWRpYXBsdXMuQ29tbW9uLldhdGVybWFyawIAAAAHcGlzVGV4dAlwaWR0ZURhdGUBAA0CAAAABgMAAAAwdGVzdCB2Ml84IC0gZmZhNjQzOWQtZDZjYi00NzYxLWJhYTMtZWZkZDNiZDcwMWM25rSq0F7p2IgL)
El fragmento Olivier <b>Heurtel da la palabra Heurtel en negrita cuando se visualiza en la página HTML. La secuencia <b> introducida por el usuario se encuentra tal cual en el código fuente de la página y, por lo tanto, se interpreta por el navegador como la etiqueta de la negrita.
Por último, podemos encontrarnos con un tercer problema al escribir en un campo de comentario.
Ejemplo
![images/07ri23.png](https://www.eni-training.com/download/74e1440d-6b0e-4af9-a157-0d3a7851889f/images/07ri23.png?id=AAEAAAD%2f%2f%2f%2f%2fAQAAAAAAAAAMAgAAAE1FbmkuRWRpdGlvbnMuTWVkaWFwbHVzLCBWZXJzaW9uPTEuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49bnVsbAUBAAAAJ0VuaS5FZGl0aW9ucy5NZWRpYXBsdXMuQ29tbW9uLldhdGVybWFyawIAAAAHcGlzVGV4dAlwaWR0ZURhdGUBAA0CAAAABgMAAAAwdGVzdCB2Ml84IC0gZmZhNjQzOWQtZDZjYi00NzYxLWJhYTMtZWZkZDNiZDcwMWM25rSq0F7p2IgL)
Un texto de varias líneas en el campo <textarea> se vuelve a mostrar tal cual en el campo, pero aparece sin los saltos de línea en la página HTML. El texto está presente con saltos de línea en el código fuente de la página, pero el salto de línea fuera de un campo <textarea> no es interpretado por el navegador: es necesario incorporar una etiqueta <br />.
Por tanto, vemos que aparecen tres problemas relativos a la presentación en la página HTML de los datos introducidos por el usuario:
-
La presencia del carácter de comillas, que puede suponer un problema cuando se usan los datos en un formulario...
Utilizar filtros
1. Principios
Esta extensión permite filtrar y validar los datos, incluidos los introducidos por los usuarios.
Cada filtro está definido por un número (identificador), un nombre y posibles opciones y los indicadores que definen el comportamiento del filtro. Cada opción está definida por un nombre que se utiliza como clave en una matriz asociativa. Cada indicador se define por una constante; para especificar varios indicadores, basta con sumar las constantes correspondientes.
Algunos ejemplos de ellos filtros (véase la documentación para la descripción de todos):
Identificador (constante predefinida) |
Descripción |
FILTER_VALIDATE_INT |
Valida un valor como entero. Las opciones min_range y max_range permiten definir un intervalo de validez. |
FILTER_VALIDATE_FLOAT |
Valida un valor como número de punto flotante. La opción decimal permite especificar el carácter que se utiliza como separador decimal y la opción thousand el carácter que se utiliza como separador de miles. Las opciones min_range y max_range permiten definir un intervalo válido. Para autorizar la presencia de los separadores de miles, es necesario, además, utilizar el indicador FIL-TER_FLAG_ ALLOW_THOUSAND. |
FILTER_VALIDATE_REGEXP |
Valida un valor utilizando una expresión regular compatible con PERL. La expresión regular que se va a utilizar se especifica con la opción regexp. |
FILTER_VALIDATE_EMAIL |
Valida un valor como dirección de correo electrónico. |
FILTER_SANITIZE_STRING |
Elimina las etiquetas contenidas en una cadena y codifica los caracteres ’ y ". Hay disponibles varios indicadores para eliminar o codificar caracteres adicionales (más adelante). Obsoleto a partir de la versión 8.1 (en su lugar, utilice la función htmlspecialchars descrita anteriormente). |
FILTER_SANITIZE_SPECIAL_CHARS |
Codifica en HTML los caracteres ’, ", <, > y &, así como todos los caracteres de código ASCII inferior a 32. Hay disponibles varios indicadores para eliminar o codificar caracteres adicionales (véase más adelante). |
FILTER_SANITIZE_ADD_SLASHES |
Añade un carácter de barra invertida (\) delante de los caracteres apóstrofo (’), comillas ("), barra invertida (\) y NUL. |
Los siguientes indicadores se pueden...
Ir a otra página
En el procesamiento efectuado por un script PHP, puede ser necesario mostrar otra página.
El caso puede producirse, por ejemplo, al final del procesamiento de un formulario; la situación puede variar en función de si el formulario se procesa por el script que lo muestra o por un script independiente.
Variantes posibles
![images/07ri32a.png](https://www.eni-training.com/download/74e1440d-6b0e-4af9-a157-0d3a7851889f/images/07ri32a.png?id=AAEAAAD%2f%2f%2f%2f%2fAQAAAAAAAAAMAgAAAE1FbmkuRWRpdGlvbnMuTWVkaWFwbHVzLCBWZXJzaW9uPTEuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49bnVsbAUBAAAAJ0VuaS5FZGl0aW9ucy5NZWRpYXBsdXMuQ29tbW9uLldhdGVybWFyawIAAAAHcGlzVGV4dAlwaWR0ZURhdGUBAA0CAAAABgMAAAAwdGVzdCB2Ml84IC0gZmZhNjQzOWQtZDZjYi00NzYxLWJhYTMtZWZkZDNiZDcwMWM25rSq0F7p2IgL)
Es posible redirigir al usuario a otra página desde el script utilizando la función header, que permite enviar encabezados http con la página HTML (véase el capítulo Utilizar las funciones PHP - Manipular los encabezados HTTP).
Vamos a utilizar el encabezado location, que redirige la solicitud a otra dirección.
Sintaxis de la directiva location
location: URL absoluta o relativa
Sintaxis con la función header
header('location: URL absoluta o relativa')
Ejemplos
// Redirección a un script PHP situado al mismo nivel.
header('location: error.php');
// Redirección hacia una página HTML situada en un subnivel.
header('location: ./error/entrada.htm');
// Redirección hacia otro sitio.
header('location: http://www.olivier-heurtel.es');
El protocolo HTTP 1.1 requiere una URL absoluta en la directiva location. Para ello, puede utilizar las variables globales $_SERVER[’HTTP_HOST’] y $_SERVER[’PHP_SELF’] (véase el capítulo Anexo - sección Variables PHP predefinidas).
Ejemplo
<?php
$url_relativa = 'error.php';
echo '$url_relativa = ',$url_relativa,'<br />';
echo '$_SERVER[\'HTTP_HOST\'] = ',
$_SERVER['HTTP_HOST'],'<br />';
echo '$_SERVER[\'PHP_SELF\'] = ',
$_SERVER['PHP_SELF'],'<br />';
echo 'dirname($_SERVER[\'PHP_SELF\']) = ',
dirname($_SERVER['PHP_SELF']),'<br />';
$url_absoluta = 'http://' . $_SERVER['HTTP_HOST'] .
rtrim(dirname($_SERVER['PHP_SELF']), '/\\') .
'/' . $url_relativa;
echo '$url_absoluta = ',$url_absoluta,'<br...
Intercambiar un archivo entre el cliente y el servidor
1. Resumen general
Algunos sitios pueden ofrecer a los usuarios cargar documentos desde su equipo al servidor web: enviar un currículum vitae en un sitio (sitio de búsqueda de empleo), adjuntar un archivo en un mensaje (sitio de mensajería) o, simplemente, guardar el documento en el servidor (sitio de almacenamiento).
En la terminología anglosajona, esta característica se llama «file upload».
Por el contrario, muchos sitios permiten a los usuarios descargar («download») documentos desde el servidor web a su equipo.
Estas dos características son aplicaciones específicas de las técnicas que se presentan en este capítulo.
2. Enviar un archivo desde el cliente (upload)
Esta característica es muy fácil de implementar en PHP y necesita dos operaciones:
-
En un formulario, proporcionar un campo en el que el usuario pueda especificar la ubicación del archivo en su equipo.
-
En el script de procesamiento del formulario, recuperar el archivo enviado por el usuario y hacer algo.
En la primera parte de este capítulo hemos visto la posibilidad de disponer en un formulario un campo que permita indicar la ubicación de un archivo en su equipo (type="file").
Pero colocar una zona de este tipo no es suficiente. Para provocar la transferencia del archivo, basta con añadir el atributo enctype="multipart/form-data" en la etiqueta <form>:
<form action="entrada.php" method="post"
enctype="multipart/form-data">
Esta técnica funciona solo con los formularios que utilizan el método POST.
Además, es posible añadir un campo oculto en el formulario para limitar el tamaño de los archivos que se pueden enviar al servidor. Este campo oculto, obligatoriamente situado antes del campo de tipo file, debe llamarse MAX_FILE_SIZE (atributo name) y especificar el tamaño máximo en bytes en el atributo value.
Ejemplo de zona oculta para limitar el tamaño de los archivos a 10 KB
<input type="hidden" name="MAX_FILE_SIZE" value="10240">
El valor especificado en esta zona no puede superar el valor de la directiva de configuración upload_max_filesize (por defecto, 2 MB). Si la zona oculta no está presente, se aplica...