3. Páginas Dinámicas con PHP

El objetivo de este tema es:

  1. Entender cómo enviar información a un servidor (web/aplicaciones)

  2. Entender cómo recibe y procesa la información el servidor

  3. Desarrollar aplicaciones sencillas que devuelvan contenido web

Las referencias son al manual oficial de PHP. Está en inglés, pero hay traducción a diferentes idiomas (arriba a la derecha en Change language).

Requisitos

Necesitas tener conocimientos básicos del lenguaje PHP (El Lenguaje PHP (básico)) o de cualquier lenguaje que vayas a utilizar en tu entorno de desarrollo en el servidor de aplicaciones.

Está organizado en 8 talleres de unas 3 sesiones de clase. En total unas 24 sesiones de clase más tu trabajo en casa.

La dedicación depende del conocimiento previo, motivación y capacidad de aprendizaje del estudiante para esa sesión en concreto.

3.1. Páginas Dinámicas

  1. Páginas Dinámicas

    1. El HTML (o lo que sea) es generado por un lenguaje externo que …

    2. … es ejecutado por un servidor de aplicación que usa un intérprete concreto.

    https://aitor-medrano.github.io/dwes2122/imagenes/01/paginadinamica.png
  2. Ejecución usando una interfaz CGI (RFC 3875)

    1. Permite usar un programa externo (en cualquier lenguaje) usando un estándar de intercambio de datos ( Common Gateway Interface )

    2. La entrada estándar al script (variables de entorno) y la salida estandar la devuelve a la conexión

    3. Puede llegar a ser muy potente.

      https://www.ionos.es/digitalguide/fileadmin/DigitalGuide/Schaubilder/funcionamiento-de-common-gateway-interface.png

      Esquema general de la creación de un HTML dinámico usando CGI

    4. Plantea ciertos inconvenientes

      1. Concurrencia. Abre un proceso por cada petición HTTP y puede plantear problemas de concurrencia

      2. Seguridad. Abre la posibilidad a que se ejecuten programas en tu servidor (sin tu permiso)

    5. Un ejemplo (muy avanzado pero interesante) por si quieres profundizar en el uso de CGI

  3. Ejecución usando un módulo integrado

    1. Hoy en día lo más habitual

    2. Se ejecuta en módulos integrados (que necesitan ser instalados). Así se evita lanzar un nuevo proceso por cada petición

    3. Se incluyen en el lenguaje etiquetas específicas dentro del HTML o se ejecuta el script directamente (al estilo CGI)

  4. Hay un montón de posibilidades de creación de páginas dinámicas. Ojo a la diferencia en la generación de las páginas dinámicas:

    1. en Cliente (Front End). Se modifica la que es recibida (se modifica por el cliente HTTP).

    2. en Servidor (Back End). Se modifica en el momento de crearse en el servidor.

    3. Sistema Híbrido (lo habitual). Hay modificaciones en cliente y servidor

Actividad T03-A01. Página Hola Mundo

Prepara tu entorno de desarrollo para hacer tu página Hola Mundo ( en php ).

Si quieres probar la interfaz CGI puedes probar a hacer tu página hola mundo con cualquier lenguaje que se te ocurra (tienes que configurar el servidor adecuadamente).


3.2. Página Dinámica Sencilla

  1. Repasando Arrays:

    1. Númericos (php-indexed-array índice númerico -> valor). P.ej mi_variable[0] = “Hola”;

    2. Asociativos (php-associative-array clave -> valor). P.ej mi_variable[«Saludo»] = “Hola”;

    3. Y tienes varias funciones para usarlos -> php-array-functions

  2. Arrays superglobales: ya predefinidos y con valores de la conexión y/o datos enviados

    1. $_SERVER -> reserved.variables.server. Parámetros de la conexión

    2. $_GET[] -> reserved.variables.get. Parámetros en el URL (query string)

    3. $_POST[] -> reserved.variables.post. Parámetros en cuerpo mensaje (no se ve en el URL)

    4. $_FILES[] -> Lo vemos para subir archivos

    5. $_COOKIE[], $_SESSION[], $_ENV[]. Lo vemos al ver el estado de la conexión HTTP

Actividad T03-A02. Diseña una página dinámica que muestre:

  1. La IP del servidor

  2. El nombre del host enviado en la cabecera Host

  3. El método de la petición HTTP

  4. La hora de la solicitud

  5. La página que envía a esta página (referer)

  6. La dirección IP mía (la que consulta la página, no la del servidor)

  7. La cadena de consulta (query_string), si la hubiere

  8. El día de la solicitud y el mes (solo)

  9. ¿Y un bucle para imprimir todas las variables y valores del array $SERVER ?

  10. ¿Y una función a la que le pases el nombre de la variable y te devuelva el valor? Me refiero a las variables de $_SERVER

3.3. Formularios HTML

  1. Formulario: Elemento form

    1. action -> form#action

    2. method -> form#method

    3. y algunos atributos más

  2. Elementos (campos y controles) del Formulario -> Elementos input

    1. Muchos tipos y muy potentes

    2. Atributo input#attributes :

      1. Los 10 habituales y más antiguos: text, password, checkbox, radio, submit, reset, file, hidden, image, button

      2. HTML5 añade 12 tipos más

    3. Usamos el atributo name para obtener el valor (value) del campo. El atributo id lo identifica (de forma única).

    4. Cada elemento tiene sus atributos (y seudo elementos) para personalizarlos

  3. Algunos campos (no input) muy utilizados):

    1. Usar una lista desplegable para seleccionar -> select

    2. Usar un elemento especial para una entrada de tipo párrafo -> textarea

Actividad T03-A03. Diseña un formulario sencillo en HTML

Hacer Ejercicio 14 (Curso AG) y Ejercicio 15 (Curso AG)

3.4. Formularios Avanzados

  1. Mejorar la interfaz del formulario:

    1. Agrupar campos -> fieldset

    2. Con títulos -> legend

    3. Definir elemento de control -> label (amplía el control del elemento input)

  2. Mejoras en HTML5:

    1. Nuevos 12 tipos de input añadidos en HTML5 : email, url, date, time, datetime, month, week, number, range, tel, search, color

      1. Facilitan la validación

      2. Facilitan la accesibilidad

      3. Mejoran el rendimiento

    2. Nuevos atributos

    3. Nuevos elementos

    4. Hay que comprobar la compatibilidad en tus usuarios: html5test

Actividad T03-A04. Diseña un formulario más complejo

Hacer Ejercicio 16 (Curso AG). También puedes probar con los elementos de HTML5 en este otro ejercicio

3.5. Enviar datos al servidor

  1. Es un proceso secuencial ( Sending and Retrieving … )

  2. Formulario listo para enviar (validado en el lado del cliente)

    1. Se define a quien se le va a enviar la información -> form#action

    2. Se define una forma de enviar la información -> form#method

      1. Método GET. Los campos van en la cadena de búsqueda (query_string) codificados de una forma concreta ( codificación de URL )

      2. Método POST. Los campos van en el cuerpo del mensaje ( form#enctype)

    3. Se define un conjunto de campos (con name) y valores (value o del usuario), que se envían al servidor

  1. Según tu plataforma de desarrollo web.

    1. Los campos irán en algún tipo de estructura de datos. P.ej. en PHP la información va en el array $_GET y/o $_POST

    2. El lenguaje usa esa información:

      1. para generar su lógica de procesamiento

      2. y (opcional) generar el resultado HTML

  2. ¿Cuando usamos GET y cuando POST?

    1. Casi siempre POST (más limpio, más capacidad, codifica los datos, con contraseñas, etc)

    2. A veces GET cuando queremos que se vean los parámetros y para el mismo URL siempre se dan las mismas respuestas ( concepto de idempotencia , no modifica el estado de los datos)

Actividad T03-A05. Formulario básico (con GET y POST)

  1. Crear un servicio que me devuelva el nombre enviado, vía GET, en un campo «nombre». Es decir, que me responda «Hola $nombre», siendo nombre un campo que envío vía GET (fíjate que para esto no necesito ningún formulario).

  2. Igual que el anterior pero usando un formulario y enviando la información con el método POST

3.6. Recibiendo formularios

  1. Creas el formulario ( Form Handling ) con todos los campos que necesites

    <!-- Una sugerencia en HTML es poner los atributos, p.ej name y type, en orden alfabético -->
    Nombre: <input name="nombre" type="text" ><br>
    Nombre: <input name="edad" type="number"><br>
    Nombre: <input name="email" type="text"><br>
    
  2. Con cada uno de los campos que llegan al script:

    1. Lo verificas porque no debes fiarte de lo que te envían ( Form Validation )

    2. Decides si es obligario o no ( Form Required )

  3. Piensas qué necesitas:

    1. ¿Debe tener valor el campo? -> function.isset

    2. ¿Debe existir y sino tener un valor prederterminado? Muy útil el operador de comparación null coalescing -> language.operators

    3. Evitar entrada de caracteres no deseados -> function.htmlspecialchars.php

    4. Filtrar (o sanear) Datos -> function.filter-var.php

  1. Y si usas patrones específicos, nada como usar regex (Taller de Expresiones Regulares)

   <?php

$_POST['nombre'] = "Javier";
$_POST['edad'] = 12;

if (!isset($_POST['nombre'])) {
   echo "nombre debe tener un valor";
   die(); // Sale del script
} else {
   $n = htmlspecialchars($_POST['nombre']);
}
$e = $_POST['edad'] ?? '' ;

if (!preg_match("/[0-9]{1,2}/", $e)) {
   echo "edad tiene que tener uno o dos dígitos";
   die();
}

echo "Pasó la validación (al menos esta)"

?>

Actividad T03-A06. Crea una aplicacion web sencilla

Crea el formulario del Ejercicio 16 (Curso AG) Diseña una aplicación web que recoja esa información y la presente en el navegador de forma legible (para humanos).

Puedes añadirle un control extra sobre el contenido de los valores y que muestre qué errores existen en el formulario de entrada (o lo que le está llegando a la aplicación)

3.7. Enviar archivos

  1. Los archivos son un caso especial de envío de información

  2. Añade el tipo de contenido a la solicitud (request) en la cabecera HTTP Content-Type

  3. Lo habitual en un formulario (POST) es Content-Type: application/x-www-form-urlencoded

  4. Pero, para enviar archivos (siempre con POST) Content-Type: multipart/form-data -> form#enctype

  5. Cada plataforma de desarrollo recibirá esos archivos en una variable. En PHP:

    1. Se usa el array $_FILES (reserved.variables.files.php)

    2. Hay diferentes métodos (features.file-upload.post-method.php)

      1. $_FILES es un array bidimensional (hay un array para cada archivo)

      2. El archivo lo dejará en un directorio de tu servidor (necesitas control sobre el servidor)

  6. Aspectos de seguridad:

    1. Subir archivos (puede) ser un riesgo importante de seguridad

    2. Además de la entrada de valores en los campos, un archivo queda en el sistema de almacenamiento (y podría ejecutarse)

    3. Pero no hay mayor problema si lo supervisas (p.ej comprobar function.is-uploaded-file.php o definir el directorio de subida)

    4. Y, como siempre, en estos casos revisa bien los logs del servidor

  7. Para guardar el archivo, lo mueves del campo recibido al sistema de almacenamiento con function.move-uploaded-file.php

  8. Un ejemplo de código resumen:

    <?php
    
    // Recibiendo un formulario con campo file y name archivo
    // Uso de null coalescing (devuelve el primer valor no nulo
    $form_file = $_FILES['archivo']['name']??'';
    
    
    if ($form_file == '') {
        $html = "<p>¡Uy! Algo pasa con el archivo!</p>";
    } else {
    
        // Preparar el servidor (directorio y nombre de archivo)
        $dir_servidor= '/var/www/descargas/';
        $nombre_archivo = $dir_servidor . basename($_FILES['archivo']['name']);
    
        // Suponemos (es mucho suponer) que no habrá
        // problemas en el servidor (permisos, espacio, etc)
        move_uploaded_file($form_file, $nombre_archivo);
        $html = "<p>Archivo guardado como $nombre_archivo</p>";
    }
    
    
    // Con la cadena $html puedo o crear un documento HTML o
    //incrustar el valor
    print($html)
    
    ?>
    

Actividad T03-A07. Añade la subida de un archivo en un formulario

Añadele al formulario anterior (Ejercicio 16 (Curso AG)) el envío una imagen, que luego visualizarás al recibirla.

Puedes añadirle que se envíen 3 imágenes.

3.8. Aspectos de Seguridad

  1. No te fíes porque:

    1. Los datos no siempre te llegarán de donde esperas (de tu formulario)

    2. Los valores no siempre serán los que crees (se pueden cambiar)

    3. Revisa la puerta. Está en el script que procesa datos de entrada. Es decir, en el PHP (no en el HTML)

    4. Y, en producción, revisa los logs

  2. Las puertas de entrada, en este contexto son:

    1. Los campos de los formularios (si todos son obligatorios o no)

    2. Los valores en los campos de los formularios

    3. Los archivos, tanto su contenido como tipo

  3. Es más complejo (Web Security) de lo que parece, pero no hay que volverse paranoico. Simplemente prestar la atención necesaria.

  4. Lo ideal es tener tu propia librería de validación y saneamiento de datos, porque así podrás utilizarla en todo el código

  5. Y, si ya es algo serio, alguien experto puede probarla

Actividad T03-A08. Revisa la seguridad de tu aplicación web

  1. Usa una librería con las funciones para revisar la entrada de datos

  2. Prueba a usar directamente tu aplicación SIN formulario (vía GET o POST)

  3. Prueba a usar datos que no corresponden a los que te esperas