Php – Formularios

En este capítulo vamos a explicar diversos tipos de formularios que podemos usar en nuestras aplicaciones en PHP.

Autenticación de usuarios

En determinados momentos, nos interesará ofrecer mecanismos de seguridad para poder controlar que se puedan acceder a diferentes zonas de nuestras páginas web.

Una forma sencilla de conseguirlo es a través de la validación de usuarios mediante el mecanismo de autenticación básica del protocolo HTTP.

El protocolo http tiene una función denominada “header()” que enviará un mensaje en una ventana emergente “Authentication Required” al navegador del usuario, de tal forma que le estaremos obligando a introducir un usuario y un password.

Cuando el usuario haya introducido estos datos, el script se encargará de volver a cargar la página habiendo introducido estos valores en las variables “PHP_AUTH_USER” y “PHP_AUTH_PW”, además de la variable “AUTH_TYPE” que es utilizada para indicar el tipo de autenticación.

Estas variables se encuentran localizadas en la variable superglobal que vimos en anteriores unidades “$_SERVER”.

En la unidad 3 ya utilizamos la función “header()” para enviar una cabecera “Location”, que en ese caso nos servía para redirigirnos hacia una página web que especificamos junto con el comando. Como podremos ver en el ejemplo que explicamos a continuación, en esta ocasión incluimos en la función una cabecera “WWW- Authenticate” que utilizaremos como medio de autenticación básico y para restringir el acceso a la página si fuera necesario.

Una cuestión muy importante que debemos tener en cuenta es que el código que va a comprobar la identidad de los usuarios deberá ser ejecutado antes de que cualquier salida sea enviada al navegador, es decir, antes de enviar las cabeceras. En nuestro ejemplo, primero ejecutamos la función “validar()” antes de enviar la cabecera mediante la función “header()”.

Veamos el ejemplo:

En nuestro sencillo ejemplo, primero definimos una función donde vamos a tener a nuestros usuarios almacenados en un array. Más adelante, cuando expliquemos cómo conectar con bases de datos, lo habitual será comprobar si los usuarios se encuentran almacenados en una tabla.

Mediante la función “isset()” comprobaremos si dichos valores existen en nuestro array, de tal forma que si existen, devolvemos el valor TRUE y si no existen, devolvemos un valor FALSE.

En el código principal del programa, utilizamos los valores TRUE o FALSE que devuelve la función para tener claro si el usuario existe, y en tal caso le damos la bienvenida, o no existe, para lo cual primero enviamos una cabecera de autenticación, y a continuación, otra cabecera de no autorizado, junto con el mensaje de aviso para indicar que el usuario no es válido.

Es importante conocer que primero siempre habrá que enviar la cabecera WWW-Authenticate, antes de la cabecera http/1.0 401.

<?php
function validar($user,$pass){
$users = array('silvia'=>'silvia','pedro'=>'perico');
if(isset($users[$user])&& ($users[$user] == $pass)){
return true;
}else{
return false;
}
}
//codigo principal de la validación
if(!validar($_SERVER['PHP_AUTH_USER'],
$_SERVER['PHP_AUTH_PW'])){
header('WWW-Authenticate:Basic realm = "Mi zona web"');
header('HTTP/1.0 401 Unauthorized');
echo "Usuario y contraseña incorrectos";
exit;
}else{
echo "Bienvenido/a ".$_SERVER['PHP_AUTH_USER'];
}
?>

Subida de ficheros

Con PHP también podremos realizar cargas de archivos mediante la utilización del navegador con la presentación de un formulario, donde el usuario elegirá el archivo que quiere subir al servidor.

Esta tarea tendrá dos fases.

En primer lugar, tendremos que realizar la presentación del formulario por pantalla para indicarle al usuario que tiene que subir un archivo.

A continuación, habrá que escribir el código en PHP para gestionar la subida de ese archivo.

Podríamos presentar un formulario sencillo HTML de la siguiente forma:

Vamos a explicar las características de este formulario:

■ Con la etiqueta <form> para comenzar a crear el formulario, establecemos el atributo enctype=”multipart/form-data” para de esta forma poder permitir que el servidor pueda conocer que vamos a enviar un archivo con la información habitual de un formulario.

■ Incluimos un campo de formularios para establecer el archivo con su tamaño máximo que podrá ser subido. Lo definimos como un campo oculto y lo hemos especificado en la línea: <input type=”hidden” name”MAX_FILE_SIZE” value = “1000000”>.

■ Por último, será necesaria la introducción de una entrada de tipo “file” para poder seleccionar el archivo: <input type=”file” name=”fichero”>.

En la siguiente fase de recogido del archivo, vamos a diseñar un script en PHP para controlar determinados parámetros.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Subida de Archivos</title>
</head>
<body>
<h1>Subida de Archivos</h1>
<form action="2.php" method="post" enctype="multipart/form-data">
Introduce el fichero: <input type="file" name="fichero"><br>
<input type="hidden" name="MAX_FILE_SIZE" value="1000000">
<input type="submit" value="Enviar fichero">
</form>
</body>
</html>

Al subir el archivo, se almacenará en un lugar temporal en el servidor, concretamente, su directorio predeterminado, de tal forma que si no lo movemos o cambiamos el nombre del archivo antes de terminar la ejecución de la secuencia de comandos, el archivo será eliminado.

Podremos controlar algunos parámetros relacionados con la subida del archivo mediante la variable superglobal $_FILES. Todas las entradas en $_FILES serán guardadas con el nombre de la etiqueta “<file>” que hayamos creado en el formulario HTML. En nuestro ejemplo, el elemento del formulario recibirá el nombre de “fichero”, y por lo tanto, la variable $_FILES tendrá los siguientes contenidos:

$_FILES[‘fichero][‘tmp_name’]. Lugar donde se almacena temporalmente el archivo en el servidor.

$_FILES[‘fichero][‘name’]. Nombre del archivo en el sistema de ficheros.

$_FILES[‘fichero][‘size’]. Tamaño del archivo en bytes.

$_FILES[‘fichero][‘type’]. Tipo MIME del archivo. Por ejemplo si es text/plain o image/gif.

$_FILES[‘userfile’][‘error’]. Errores que se puedan producir en la carga de archivos. En el ejemplo podremos ver hasta 4 tipos de errores que se pueden producir.

Además, existen otras funciones que pueden ser muy útiles en determinados contextos.

Por ejemplo, mediante la función “is_upload_file()”, podremos comprobar si el archivo ha sido subido con éxito.

Con la última función “move_uploaded_file()”, podremos mover el archivo subido de la zona temporal a una localización definitiva.

Veamos cómo sería el archivo “2.php”, que recibiría los datos del formulario diseñado anteriormente en otro fichero:

En este ejemplo se ha utilizado como ruta definitiva una ruta de Linux. Si el equipo servidor fuera Windows, tendríamos que especificar con \\ en lugar de solo una \.

<?php
if (is_uploaded_file($_FILES['fichero']['tmp_name'])) {
echo "Archivo " . $_FILES['fichero']['name'] . "subido conéxito.\n";
} else {
echo "Posible ataque del archivo subido: ";
echo "nombre del archivo " . $_FILES['fichero']
['nombre_tmp'] . "’.";
}
if ($_FILES['fichero']['error']) {
switch ($_FILES['fichero']['error']) {
case 1: // UPLOAD_ERR_INI_SIZE
echo "El archivo sobrepasa el limite autorizado por el servidor(archivo php.ini)!";
break;
case 2: //UPLOAD_ERR_FORM_SIZE
echo "El archivo sobrepasa el limite autorizado por el formulario!";
break;
case 3: // UPLOAD_ERR_PARTIAL
echo "El envio del archivo ha sido suspendido durante la transferencia";
break;
case 4: // UPLOAD_ERR_NO_FILE
echo "El archivo que ha enviado tiene un tamaño nulo!";
break;
}
}
if ((isset($_FILES['fichero']['archivo'])) && ($_FILES['fichero']['error'] == UPLOAD_ERR_OK)) {
$ruta_destino = '//UPLOAD_FILES//';
move_uploaded_file($_FILES['fichero']['tmp_name'],
$ruta_destino . $_FILES['fichero']['name']);
}

Validación de campos

Una tarea muy importante en la recogida de datos de un formulario, es validar que los datos introducidos son correctos en cuanto a su formato. Nos estamos refiriendo a tareas de comprobación como que un usuario ha entrado una dirección de email de forma correcta, o una dirección http con sintaxis perfecta o que no ha entrado un dato de tipo cadena de texto cuando se solicitaba un dato de tipo entero.

Antiguamente se escribían cientos de líneas de código para poder realizar estas verificaciones, pero por suerte, a día de hoy ya no es necesario gracias a la extensión de PHP filter_var.

Esta extensión nos va a suministrar un conjunto de funciones que nos van a posibilitar la validación de los datos de una manera relativamente sencilla. Incluye numerosos filtros a elegir en función del tipo de dato que queramos filtrar. La función filter_var utiliza los siguientes parámetros:

$var. Variable que queremos filtrar.

$filter. El filtro que queremos aplicar.

$options. Algunos de los filtros pueden utilizar un array de opciones que modificarán su comportamiento.

A continuación, vamos a mostrar los filtros que están disponibles:

FILTER_VALIDATE_BOOLEAN. Comprueba si la variable es un booleano.

FILTER_VALIDATE_EMAIL. Comprueba si la variable es una dirección de correo electrónico correcta.

FILTER_VALIDATE_FLOAT. Comprueba si la variable es del tipo float.

FILTER_VALIDATE_INT. Comprueba si la variable es un número entero.

FILTER_VALIDATE_IP. Comprueba si la variable es una dirección IP.

FILTER_VALIDATE_REGEXP. Valida la variable contra una expresión regular enviada en la variable de opciones.

FILTER_VALIDATE_URL. Comprueba si la variable es una URL de acuerdo con la RFC 2396. Implementa también una serie de filtros que pueden ser utilizados para depurar las variables que le pasemos como argumentos:

FILTER_SANITIZE_EMAIL. Elimina todos los caracteres excepto letras, números y !#$%&’*+-/=?^_`{|}~@.[].

FILTER_SANITIZE_ENCODED. Codifica la cadena como una URL válida.

FILTER_SANITIZE_MAGIC_QUOTES. Aplica la función addslashes.

FILTER_SANITIZE_NUMBER_FLOAT. Elimina todos los caracteres excepto números, +- y opcionalmente ,.eE.

FILTER_SANITIZE_NUMBER_INT. Elimina todos los caracteres excepto números y los signos + -.

FILTER_SANITIZE_SPECIAL_CHARS. Escapa caracteres HTML y caracteres con ASCII menor a 32.

FILTER_SANITIZE_STRING. Elimina etiquetas, opcionalmente elimina o codifica caracteres especiales.

FILTER_SANITIZE_STRIPPED. Alias del filtro anterior.

FILTER_SANITIZE_URL. Elimina todos los caracteres excepto números, letras y $-_.+!*’(),{}|\\^~[]`<>#%”;/?:@&=.

Veamos unos cuantos ejemplos para comprobar la potencia de esta función.

Para comprobar si la variable que pasamos como argumento es un dato entero:

En el siguiente ejemplo, solo serán válidas aquellas variables que sean de tipo entero, y además, se encuentre su valor entre un rango proporcionado:

<?PHP
$var = '2.3';
if (filter_var($var, FILTER_VALIDATE_INT) === false) {
echo 'Valor incorrecto';
} else {
echo 'Valor correcto';
}
?>

En el siguiente ejemplo vamos a comprobar si las direcciones de email que hay almacenadas en variables tienen un formato correcto:

<?php
$email_a = 'cristian@midominio.com';
$email_b = 'cristian';
if (filter_var($email_a, FILTER_VALIDATE_EMAIL)) {
echo "Esta dirección de email (email_a) esconsiderada válida.<br>";
}
if (filter_var($email_b, FILTER_VALIDATE_EMAIL)) {
echo "Esta dirección de email (email_b) es considerada válida.<br>";
}
?>
<?php
$a = '1';
$b = '-1';
$c = '3';
$options = array('options' => array(
'min_range' => 0,
'max_range' => 3,
)
);
if (filter_var($a, FILTER_VALIDATE_INT, $options) !== FALSE) {
echo "La variable a es correcta(valor entre 0 y 3).<br>";
}
if (filter_var($b, FILTER_VALIDATE_INT, $options) !== FALSE) {
echo "La variable b es correcta(valor entre 0 y 3).<br>";
}
if (filter_var($c, FILTER_VALIDATE_INT, $options) !== FALSE) {
echo "La variable c es correcta(valor entre 0 y 3).<br>";
}
?>

Podemos también comprobar si determinadas direcciones IP tienen un formato correcto:

En cuanto al saneamiento de datos, veamos un sencillo ejemplo donde eliminamos lo que no nos interesa de una cadena de texto:

Paso de variables (Métodos GET y POST)

Hasta este momento, en los ejercicios previos, nuestros principales objetivos han sido realizar tareas con los datos introducidos por un usuario: hemos visto cómo autenticar un usuario, cómo se puede subir archivos al servidor o cómo podemos validar y sanear los datos introducidos.

Pero aún no hemos visto la forma en la que un formulario envía esos datos para que posteriormente puedan ser procesados.

Un formulario en HTML, siempre comienza y termina con la etiqueta <FORM>, pero será a través de su etiqueta <METHOD> donde se especifique los dos métodos posibles de envío de valores: GET y POST:

■ GET. Mediante el método GET, los datos serán enviados a través de la URL y unidos por el símbolo “&” que genera el formulario, después pulsar el botón SUBMIT (Enviar). De hecho, en realidad no sería necesario realizar un formulario

para enviar estos datos. Simplemente tendremos que crear una URL con los datos como la de nuestro ejemplo, para que pudieran ser enviados mediante sencillos links. Sería un formato como el siguiente:

<?php
$text = '<b>"Hola mundo!"</b>';
echo $text."<br>";
echo filter_var($text, FILTER_SANITIZE_STRING);
?>
<?php
$ip_a = '192.168.1.25';
$ip_b = '23.34.36.36';
if (filter_var($ip_a, FILTER_VALIDATE_IP)) {
echo "La dirección IP " . $ip_a . " es válida.<br>";
}
if (filter_var($ip_b, FILTER_VALIDATE_IP)) {
echo "La dirección IP " . $ip_b . " es válida.<br>";
}
?>

y serán recogidos de esta forma:

POST. Este método solo puede ser utilizado mediante un formulario, y la información no será enviada por una URL, sino que será enviada de forma transparente al usuario. Es preferible usarlo si vamos a pasar grandes campos de texto, vamos a subir imágenes, o si simplemente no queremos crear una URL tan larga y favorecer las denominadas URL’s amigables, que tanto gustan a los motores de búsqueda como Google. Las variables enviadas mediante este método podrán ser recogidas con el siguiente formato:

De esta forma, tendremos que decidir qué método queremos usar para definirlo en el formulario en primer lugar, y posteriormente en el script que recoge los datos, utilizar $_POST o $_GET. Veamos un ejemplo para cada caso.

$nombre_de_variable=$_POST[‘nombre_de_objeto’] ;
$nombre_de_variable=$_GET[‘nombre_de_objeto’] ;

http://www.mipagina.com/index.php?page=mia&variable2&variable3=valor3

Envío de variables mediante método POST.

En este primer archivo, crearíamos el formulario para recoger los datos del usuario y enviarlos al segundo script en PHP que recogerá y mostrará los datos:

En el script “2.php” recogemos los datos enviados y para comprobar que se han enviado de forma correcta, los mostramos en pantalla:

<!DOCTYPE html>
<html lang="en">
<HEAD>
<TITLE>Uso de POST</title>
<BODY>
<h1>Métodos POST</h1>
<?php
echo "El nombre que ha introducido es ".$_POST['nombre'];
echo "<br>";
echo "El email introducido es: ".$_POST['email'];
echo "<br>";
echo "El comentario introducido es: ".$_POST['comentario'];
?>
<br>
</BODY>
</HTML>
<!DOCTYPE html>
<html lang="en">
<HEAD>
<TITLE>USO DE POST</title>
<BODY>
<h1>FORMULARIO POST</h1>
<form action="08.POST_2.php" method="post">
Nombre:<br/>
<input type="text" name="nombre"/><br/>
E-mail:<br/>
<input type="text" name="email"/><br/>
Comentario:<br/>
<textarea type="text" rows="5" cols="50"name="comentario"></textarea><br/>
<input type="submit" name="boton"/>
</form>
</BODY>
</HTML>

Envío de variables mediante método GET.

En este primer archivo, crearíamos el formulario para recoger los datos del usuario.

Observamos que solo cambia el método de envío.

En el script “2.php” recogemos los datos enviados y para comprobar que se han enviado de forma correcta, los mostramos en pantalla. Comprobaremos, que solo cambia la variable superglobal $_POST por $_GET:

<!DOCTYPE html>
<html lang="en">
<HEAD>
<TITLE>Uso de GET</title>
<BODY>
<h1>Métodos GET</h1>
<?php
echo "El nombre que ha introducido es ".$_GET['nombre'];
echo "<br>";
echo "El email introducido es: ".$_GET['email'];
echo "<br>";
echo "El comentario introducido es: ".$_GET['comentario'];
?>
<br>
</BODY>
</HTML>