[go: up one dir, main page]

0% encontró este documento útil (0 votos)
427 vistas290 páginas

MySQL y PHP

Este documento trata sobre tecnologías web como AJAX y PHP. Explica conceptos básicos sobre servidores web como Apache, bases de datos como MySQL, y lenguajes de programación del lado servidor como PHP. También cubre temas como la instalación y configuración de estos componentes, y el diseño y desarrollo de aplicaciones web dinámicas.

Cargado por

josemo27
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
427 vistas290 páginas

MySQL y PHP

Este documento trata sobre tecnologías web como AJAX y PHP. Explica conceptos básicos sobre servidores web como Apache, bases de datos como MySQL, y lenguajes de programación del lado servidor como PHP. También cubre temas como la instalación y configuración de estos componentes, y el diseño y desarrollo de aplicaciones web dinámicas.

Cargado por

josemo27
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 290

Módulo III

AJAX y PHP

U.N.E.D.
Indice general

Módulo 3

Volumen 4

10 Tecnologías Web 10.1


10.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10.1
10.2 Procesamiento de páginas web estáticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10.1
10.3 Procesamiento de páginas web dinámicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10.3
10.4 Acceso a una base de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10.3
10.5 Creacción de páginas web dinámicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10.4
10.6 Elección de una tecnología de servidor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10.6

11 Servidores WEB. APACHE 11.1


11.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11.1
11.2 Características de Apache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11.4
11.3 Instalación de Apache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11.5
11.4 Iniciar Apache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11.6
11.5 Creación de directorios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11.7
11.6 Opciones principales de configuración . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11.8
11.7 Hosts virtuales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11.11
11.8 Configuración de Apache en modo gráfico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11.13
11.9 Mas recursos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11.14

12 Conceptos básicos sobre bases de datos 12.1


12.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12.1
12.2 definiciones básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12.1
12.3 Objetivos de los sistemas de bases de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12.3
12.4 Abstracción de la información . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12.5
2.2 INDICE GENERAL

12.5 Modelos de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12.6


12.6 Estructura general del sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12.6

13 Diseño de bases de datos relacionales 13.1


13.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13.1
13.2 Proceso de diseño . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13.1
13.3 Modelo Entidad-Relación (E-R) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13.2
13.4 Modelo relacional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13.8
13.5 Normalización . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13.21

14 Instalación y primeros pasos con MySQL 14.1


14.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14.1
14.2 Instalación y configuración . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14.1
14.3 Entrar y salir de la ventana de comandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14.4
14.4 Manual de referencia y ayuda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14.5
14.5 Usuarios y privilegios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14.8
14.6 Husos horarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14.11
14.7 Palabras reservadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14.13

15 Creación de bases de datos y tablas e inserción de datos 15.1


15.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15.1
15.2 Reglas para asignar nombres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15.1
15.3 Crear y eliminar bases de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15.3
15.4 Tipos de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15.4
15.5 Crear y eliminar tablas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15.8
15.6 Insertar y modificar datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15.16
15.7 Importar y exportar datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15.18

16 Consultas 16.1
16.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16.1
16.2 Selección de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16.1
16.3 Expresiones regulares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16.8
16.4 Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16.10
16.5 Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16.17

17 Tecnología PHP 17.1


17.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17.1
17.2 Un poco de historia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17.2
17.3 Comparativa entre ASP y PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17.3

18 Instalación 18.1
18.1 Instalación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .18.1
18.2 Instalación en Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .18.2
18.3 Instalación de MySQL en Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .18.7
18.4 Instalación en Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .18.7

Desarrollo de Aplicaciones Web Dinámicas


2.3

19 Fundamentos del lenguaje -I 19.1


19.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .19.1
19.2 Formato del código PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .19.1
19.3 Sintaxis básica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .19.4

20 Fundamentos del lenguaje - II 20.1


20.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .20.1
20.2 Sentencias condicionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .20.1
20.3 sentencias de bucle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .20.7
20.4 Inclusión de ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .20.15

21 Cadenas 21.1
21.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21.1
21.2 Delimitación de cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21.1
21.3 Visualización de cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21.2
21.4 Acceso al contenido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21.4
21.5 Búsqueda en cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21.5
21.6 Comparación de cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21.7
21.7 Operar con subcadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21.7
21.8 Modificación del contenido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21.10
21.9 Relación con html . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21.15
21.10 Otras funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21.15

22 Arrays 22.1
22.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22.1
22.2 Arrays escalares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22.1
22.3 Arrays asociativos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22.5
22.4 Arrays multidimensionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22.6
22.5 Recorrer un array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22.9
22.6 Ordenar un array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22.14
22.7 Otras operaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22.18

23 Funciones 23.1
23.1 Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .23.1
23.2 Funciones con número indeterminado de parámetros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .23.7
23.3 Funciones variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .23.9
23.4 Funciones recursivas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .23.9

24 Funciones de fecha y hora 24.1


24.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24.1
24.2 Funciones de fecha y hora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24.1
24.3 Ejemplo de uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24.5

25 Formularios, Cookies y Sesiones 25.1


25.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .25.1
25.2 El protocolo HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .25.1

Desarrollo de Aplicaciones Web Dinámicas


2.4 INDICE GENERAL

25.3 Formularios en HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .25.9


25.4 Formularios en PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .25.10
25.5 Cookies en PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .25.14
25.6 Sesiones en PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .25.17

26 Ficheros y directorios 26.1


26.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26.1
26.2 Operaciones con ficheros (Nivel interno) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26.1
26.3 Operaciones con ficheros (Nivel externo) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26.5
26.4 Manejo de directorios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26.5
26.5 Operaciones con directorios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26.6
26.6 Otras funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26.7
26.7 Transferencia de ficheros entre el cliente y el servidor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26.7
26.8 Control de la salida estándar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26.10

27 Bases de datos 27.1


27.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .27.1
27.2 Guia de estudio del tema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .27.2

28 PHP Avanzado 28.1


28.1 Pogramación orientada a objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .28.2
28.2 Plantillas de diseño SMARTY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .28.10
28.3 XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .28.27

Desarrollo de Aplicaciones Web Dinámicas


TEMA 10

Tecnologías Web

10.1 INTRODUCCIÓN

Una aplicación Web es un conjunto de páginas Web estáticas y dinámicas. Una página Web está-
tica es aquella que no cambia cuando un usuario la solicita: el servidor Web envía la página al
navegador Web solicitante sin modificarla. Por el contrario, el servidor modifica las páginas Web
dinámicas antes de enviarlas al navegador solicitante. La naturaleza cambiante de este tipo de
página es la que le da el nombre de dinámica. Aquellas tecnologías en las que es el servidor el
que procesa toda la información ya sea de formateo, gestión de contenido, consultas a bases de
datos, etc. , se denominan Tecnologías del lado del servidor.

Como ejemplos de este tipo de tecnologías se pueden nombrar principalmente tres; PHP, ASP y
JSP. A lo largo de los siguientes capítulos se desarrollarán las dos primeras y se explicarán sus
conceptos básicos; lenguaje, acceso a bases de datos, procesamiento de la información, etc.

10.2 PROCESAMIENTO DE PÁGINAS WEB ESTÁTICAS

Un sitio Web estático suele constar de un conjunto de páginas HTML (XHTML y CSS) relacio-
nadas y de archivos alojados en un equipo que ejecuta un servidor Web.

Un servidor Web es un software que suministra páginas Web en respuesta a las peticiones de los
navegadores Web. Una petición de una página se genera cuando un usuario hace clic en un vín-
culo en una página Web, elige un marcador en un navegador o introduce un URL en el cuadro
Dirección del navegador y luego hace clic.

El contenido final de una página Web estática lo determina el diseñador y no cambia cuando se
solicita la página. Un ejemplo:
<html>
10.2 TECNOLOGÍAS WEB

<head>
<title>Prueba</title>
</head>
<body>
<h3>Esto es una prueba<h3>
</body>
</html>
El diseñador escribe todas y cada una de las líneas de código HTML de la página antes de colo-
car la página en el servidor. Dado que el código HTML no cambia una vez colocado en el serv
dor, este tipo de páginas se denomina página estática.

En sentido estricto, una página estática puede no ser estática en absoluto. Por ejemplo, una ima-
gen de sustitución o una película de Macromedia Flash pueden hacer que una página estática
cobre vida. No obstante, en este curso se habla de página estática cuando esta se envía al navega-
dor sin modificaciones.

Cuando el servidor Web recibe una petición de una página estática, el servidor lee la solicitud,
localiza la página y la envía al navegador solicitante, como se muestra en la siguiente figura (Fig.
10.1):

Figura 10.1 Procesamiento de una página estática.

En el caso de las aplicaciones Web, que contienen tanto contenido dinámico como páginas Web
estáticas, algunas líneas de código no están determinadas cuando el usuario solicita la página.
Estas líneas deben determinarse mediante algún mecanismo antes de enviar la página al navega-
dor. En la siguiente sección se describe dicho mecanismo.

Desarrollo de Aplicaciones Web Dinámicas - UNED


PROCESAMIENTO DE PÁGINAS WEB DINÁMICAS 10.3

10.3 PROCESAMIENTO DE PÁGINAS WEB DINÁMICAS

Cuando un servidor Web recibe una petición de una página Web estática, el servidor envía la
página al navegador solicitante sin retraso. El servidor Web reacciona de manera diferente
cuando recibe una petición de una página dinámica: pasa la página a una ampliación de software
especial que se encarga de finalizar la página. Este software especial se denomina servidor de
aplicaciones.

Un ejemplo de servidor de aplicaciones es PHP, el cual se puede instalar desde el DVD del curso
para ejecutarlo con un servidor Web como Apache.

El servidor de aplicaciones lee el código de la página, finaliza la página en función de las instruc-
ciones del código y después elimina el código de la página. El resultado es una página estática
que el servidor de aplicaciones devuelve al servidor Web, que a su vez la envía al navegador soli-
citante. Lo único que el navegador recibe cuando llega la página es código HTML puro. A conti-
nuación se incluye una vista de este proceso (Fig. 10.2):

Figura 10.2 Procesamiento de una página dinámica.

10.4 ACCESO A UNA BASE DE DATOS

Un servidor de aplicaciones le permite trabajar con recursos del lado del servidor, como una base
de datos. Por ejemplo, una página dinámica puede indicar al servidor de aplicaciones que
extraiga datos de una base de datos y los inserte en el código HTML de la página.

Desarrollo de Aplicaciones Web Dinámicas - UNED


10.4 TECNOLOGÍAS WEB

La instrucción para extraer datos de una base de datos recibe el nombre de consulta de base de
datos. Una consulta consta de criterios de búsqueda expresados en un lenguaje de base de datos
denominado SQL (Structured Query Language: Lenguaje de consulta estructurado). La consulta
SQL se escribe en los scripts o etiquetas del lado del servidor de la página.

Un servidor de aplicaciones no puede comunicar directamente con una base de datos porque el
formato propio de la base de datos hace que los datos sean ilegibles, de la misma forma que un
documento de Word resulta ilegible al abrirlo en el Bloc de notas. El servidor de aplicaciones
sólo puede comunicarse mediante un software de controlador de base de datos intermediario que
actúa como un intérprete entre el servidor de aplicaciones y la base de datos.

Cuando el controlador establece la comunicación, se consulta el origen de datos y se crea un


juego de registros que contiene el resultado de la consulta. Un juego de registros es un subcon-
junto de datos extraídos de una o varias tablas de una base de datos. El juego de registros se
devuelve al servidor de aplicaciones y los datos se utilizan en la página dinámica.

A continuación se ofrece una consulta de base de datos sencilla escrita en SQL:


SELECT nombre, apellidos, ciudad
FROM empleados
Esta instrucción crea un juego de registros de tres columnas y lo completa con filas que contie-
nen el apellido, el nombre y la ciudad de todos los empleados de la base de datos. Para más infor-
mación, consulte el manual dw8_using.pdf (en castellano) contenido en el DVD-I y diríjase a la
página 1139 (Nociones básicas de SQL). También puede consultar en la parte del curso dedicada
a MySQL.

La ilustración siguiente (Fig. 10.3) muestra el proceso de consulta de base de datos y de devolu-
ción de los datos al navegador.

Siempre que disponga del controlador de base de datos adecuado, podrá utilizar prácticamente
cualquier base de datos con su aplicación Web. Si tiene intención de desarrollar pequeñas aplica-
ciones de bajo coste, puede utilizar una base de datos basada en archivos, como las que permite
crear Microsoft Access. En cambio, si desea desarrollar aplicaciones empresariales críticas,
puede utilizar una base de datos basada en servidor, como las que permite crear Microsoft SQL
Server, Oracle 9i o MySQL.

Si la base de datos está situada en un sistema distinto del servidor Web, asegúrese de disponer de
una conexión rápida entre ambos sistemas para que la aplicación Web pueda funcionar de forma
rápida y eficiente.

10.5 CREACCIÓN DE PÁGINAS WEB DINÁMICAS

La creación de una página dinámica implica, en primer lugar, escribir el código HTML, luego
añadir los scripts o etiquetas del lado del servidor al código HTML para crear la página dinámica.

Desarrollo de Aplicaciones Web Dinámicas - UNED


CREACCIÓN DE PÁGINAS WEB DINÁMICAS 10.5

Al visualizar el código resultante, el lenguaje aparece incrustado en el código HTML de la


página.

Figura 10.3 Consulta a una base de datos y devolución de los mismos al navegador.

Por esta razón, estos lenguajes se conocen como lenguajes de programación incrustados en
HTML. El siguiente ejemplo utiliza PHP:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Documento sin t&iacute;tulo</title>
</head>

<body>
<?php
$prueba="Hola";
echo $prueba;

Desarrollo de Aplicaciones Web Dinámicas - UNED


10.6 TECNOLOGÍAS WEB

?>
</body>
</html>

Las instrucciones incrustadas anteriormente (entre las etiquetas <?php y ?>) realizan las siguien-
tes acciones:
1 Crean una variable denominada $prueba y le asigna la cadena “Hola”.
2 Muestra el contenido de la variable.

El servidor de aplicaciones devuelve la siguiente página al servidor Web:


<html>
<body>
Hola
<body>
</html>
El lenguaje de scripts o basado en etiquetas empleado depende de la tecnología del servidor. A
continuación se enumeran los lenguajes más utilizados para las cinco tecnologías de servidor que
admite el editor que se utilizará en el curso; Dreamweaver:

10.6 ELECCIÓN DE UNA TECNOLOGÍA DE SERVIDOR

Es posibler utilizar Dreamweaver para crear aplicaciones Web mediante cinco tecnologías de ser-
vidor: ColdFusion, ASP.NET, ASP, JSP o PHP. Cada una de estas tecnologías corresponde a un
tipo de documento en Dreamweaver. La elección de una de ellas para una aplicación Web
depende de diversos factores, entre los que se encuentran el nivel de conocimiento de los diver-
sos lenguajes de scripts y el servidor de aplicaciones que vaya a utilizar.

La elección de la tecnología de servidor también depende del servidor de aplicaciones que se


tenga pensado utilizar para la aplicación Web. Un servidor de aplicaciones es un software que
ayuda al servidor Web a procesar las páginas que contienen scripts o etiquetas del lado del servi-
dor. Por ejemplo, si dispone de ColdFusion, puede optar por ColdFusion como tecnología de ser-
vidor. Si tiene acceso a un servidor que ejecuta Microsoft Internet Information Server 5 (IIS) con
.NET Framework, puede elegir ASP.NET. Puede utilizar PHP si tiene acceso a un servidor Web
con un servidor de aplicaciones PHP, o JSP si tiene acceso a un servidor Web con un servidor de
aplicaciones JSP.

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 11

Servidores WEB. APACHE

11.1 INTRODUCCIÓN

La WEB sigue siendo un fenómeno muy reciente. Tim Berners-Lee inventó la Web a finales de
los 90 cuando trabajaba en el CERN, el Laboratorio Europeo de Física de Partículas. Lo desarro-
lló para que los físicos de varias universidades de todo el mundo tuvieran acceso instantaneo a la
información.

Tim definió los URL, HTTP y HTML y, con Robert Cailliau, escribió su primer servidor Web y
el primer software para clientes Web que posteriomente se bautizó con el nombre de navegador.

Hace solo apenas unos años, tendríamos que haher explicado el significado de estos conceptos a
casi todo el mundo. Ahora, casi no hay gente (por to menos en las naciones desarrolladas) que no
sepa lo que es la W W W.

Poco después del trabajo inicial de Tim, un grupo de Centro Nacional de Actividades de Super-
computación, National Center for Supercomputing Activities (NCSA) de la Universidad de Illi-
nois, en Urbana-Champaign (UIUC) desarrolló el servidor web HTTPd NCSA y el navegador
web gráfico NCSA Mosaic. Mosaic no fue el primer navegador web gráfico aunque la gente lo
crea. Ese honor le corresponde a Viola, escrito por Pei Wei y disponible con anterioridad a
Mosaic, pero Mosaic se apropió rapidamente de esta mención, y se convirtió en el navegador
web mas usado en 1992.

HTTPd NCSA fue el servidor mas utilizado en la Web durante los primeros mños de su existen-
cia. Sin embargo, en 1994, Rob McCool, que es el creador de HTTPd NCSA, dejó el NCSA, y el
proyecto se terminó. Ya no había organización central que desarrollara nuevas caractcristicas y
que distribuyera un producto funcional.
11.2 SERVIDORES WEB. APACHE

Antes de que el código fuente del servidor se pusiera a disposición de todo el mundo, muchos de
sus usuarios habituales habian ya dasarrollado sus propias soluciones a los errores y a sus propias
características. Estas soluciones se comipartian fortuitamente a traves de Usenet, pero no había
un mecanismo central que recuperara y distribuyera dichas soluciones.

Por consiguiente, Apache (al igual que la World Wide Web) fue ensamblado por voluntarios.
Aunque la terminación del proyecto HTTPd NCSA dejara a los desarrolladores con un producto
que no funcionaba bien en la época y con nadie al que reclamar, al final se consiguió un producto
muy superior.

11.1.1 ¿QUIÉN ES EL RESPONSABLE?


En febrero de 1995, Brian Behlendorf y Cliff Skolnick ensamblaron una lista de envío, prepara-
ron una computadora y con el suficiente ancho de banda donado por HotWired, Brian construyó
un arbol CVS (Sisterna de Versiones Simultaneas) en virtud del cual todo aquel que quisiera
podia contribuir a crear nuevas caracteristicas y a reparar errores. De esta forma, un grupo de
desarrolladores podian recoger las modificaciones a sus códigos y crear un producto combinado.
Comenzando con HTTPd 1.3 NCSA, empezaron a aplicar esta solucion. La primera versión de
este producto, llamado Apache, fue la version 0.6.2, lanzada en abril de 1995.

Los ocho socios fundadores del Grupo Apache eran Behlendorf, Skolnick, Roy T. Fielding, Rob
Hamill, David Robinson, Randy Terbush, Robert S. Thau y Andrew Wilson.

Poco después del primer lanzamiento, Thau disenó una arquitectura completamente nueva.
Comenzando con la versibn 0.8.8 en agosto de 1995, Apache se incorporó a esta nueva base de
código.

11.1.2 ACONTECIMIENTOS RECIENTES


Organizaciones como The Wall Street Journal y Forbes están usando el término open source en
sus articulos de primera página.

Esto les podrá parecer extraño a los que han conocido el concepto durante décadas y que estan
acosmmbrados a que se ignore, a incluso sea repudiado, por personas de la industria del software
comercial.

En mayo de 1997, Eric Raymond dió una charla, "La catedral y el bazar", en el Congreso de
Linux Kongress en Wurzhurg, Alemania (véase http://www.linux-kongress.de/1997/). Con esto
empezó una cadena de acontecimientos, entre ellos, la decisión de Netscape de liberar el código
fuente de su navegador web. El mundo del software ya no podia ignorar el movimiento "software
gratuito", que rebautizó a Open Source para desbancar a algunas de las asociaciones negativas
que giraban en tomo al movimiento. Eric ya era muy conocido en el movimiento de software y
había creado un número importance de productos de software, como GNU Emacs, Nei-Jack, nur-
ses y fetchmail. Escribió fetchmail, al menos en parte, para desentrañar el misterio de por que
funcionaba el modelo de desarrollo de software Open Source, mientras que el sentido común

Desarrollo de Aplicaciones Web Dinámicas - UNED


INTRODUCCIÓN 11.3

capitalists traditional decía que no debía funcionar. Puede encontrar el texto completo de la
ponencia del Congreso de Linux, así como otras ponencias adicionales, en su sitio web en http://
www.tuxedo.org/-esr/writings/cathedral-bazaar/.

En junio de 1998, el Grupo Apache anunció que estaba en negociaciones con IBM para seguir
desarrollando el servidor Apache, de forma que IBM pudiera incluir ese código en su producto
WebSphere. Este fue uno de los primeros ejemplos de empresa líder de software que apoyaba un
proyecto Open Source, y constituyó uno de los ejes para hacer que el movimiento Open Source
pareciera viable ante los ojos del resto del mundo del software. El apoyo y sopone financiero de
la empresa de software más grande del mundo hizo ver a otras empresas que el movimiento Open
Source no era un grupo de rebeldes melenudos que trataban de dinamitar la industria del software
comercial, sino que era un metodo probado de crear productos de calidad.

Con anterioridad al acuerdo con IBM, hubo una serie de intentos de hacer que Apache funcionara
en Windows, pero había muchas dificultades técnicas y muy pocos programadores Windows
interesados en el proyecto. Con la financiacion y los recursos provenientes del acuerdo con IBM,
pudieron hacer que Apache se ejecutara en Windows.

Apache en Windows es una gran altemativa a IIS (Internet Information Server), particularmente
para aquellos que ya conozcan Unix/Linux pero que tengan que utilizar Windows. La solución
modular adoptada por Apache supone un alivio si la comparamos con IIS, que instala una aplica-
cion monolítica enorme que hace de todo, hasta cosas que no sirven para nada.

Apache es ligero, y cualquier opción puede ser agregada cargando otro módulo. Apache es facil
de configurar y de administrar, y le permite configurar parámetros que en IIS ni siquiera puede
imaginar. Y si quiere tener una utilidad de configuraci6n gráfica, Comanche la ofrece sin restar
potencia como administrador de servidor.

11.1.3 APACHE Y LA WEB EN LA ACTUALIDAD


Como antes se comentó, es conocido que el servicio web se creó en Europa, en el centro de
investigación NCSA, para que la información de los grupos de investigación pudiera ser compar-
tida con facilidad. Como es el servicio más importante y además integra otros muchos servicios,
muchas personas confunden los términos Internet y servicios Web.

Como el resto de los servicios de Internet, se basa en el modelo cliente-servidor, y existen


muchos tipos de clientes y servidores diferentes de diversas formas, todos basados en el proto-
colo HTTP.

Al cliente se le denomina normalmente navegador o explorador. Los más conocidos son Firefox,
Mozilla e Internet Explorer.

Entre tanto, también existen muchos servidores, aunque dos son los que acaparan la mayor cuota
de mercado; el servidor Apche, software libre que se distribuye bajo licencia GPL, y el servidor
IIS de Microsoft.

Desarrollo de Aplicaciones Web Dinámicas - UNED


11.4 SERVIDORES WEB. APACHE

El número de la versión de Apache va parejo al número de versión del protocolo HTTP. Este pro-
tocolo es cada vez más complejo; de la versión 1.0 se pasó a la versión 1.1 y de ahí directamente
a la versión 2.0. La velocidad y la seguridad también se ha potenciado y el número de métodos
aceptados ha ido en aumento. Valga como muestra el hecho de que la especificación del proto-
colo en su versión 1.0 tuviera 60 páginas, frente a las 161 de la versión 1.1. La necesidad de
conexiones seguras a llevado a añadir cifrado y generar el protocolo HTTPS basado en SSL.

Por otra parte, el lenguaje de documentos web ha sido durante años HTML y, aunque sigue
siendo el lenguaje principal, se tiende a sustituirlo y a adaptarlo al metalenguaje XML. Entre
tanto, han surgido propuestas exitosas como CSS y DHTML.

HTML está orientado a establecer el aspecto de los documentos, mientras que XML está orien-
tado a representar la estructura de la información, pudiendo mostrar la misma de formas muy
diferentes. El lenguaje XSLT facilita el mapeo de las estructuras con su representación, y las ver-
siones más recientes de los navegadores están adaptadas para interpretar este lenguaje.

En resumen, la estructura de los sitios web ha cambiado mucho. En los inicios de la web, las
hojas estáticas eran lo más común, pero ahora la mayoría de los sitios se basan en sistemas de
bases de datos, ya que permiten una gestión de los datos mucho más flexible. Para ello ha hecho
falta un trabajo considerable de programación, desde los primeros programas CGI hasta los sofis-
ticados programas actuales.

Aunque el lenguaje Java parece predominar en este aspecto, otros lenguajes tienen cierta presen-
cia, entre ellos PHP, Perl, Python y ASP y las plataformas web PHP-Nuke, PostNuke, Zope, etc.
Salvo la plataforma ASP de Microsoft, el resto se basan en software libre.

El desarrollo web ha influenciado incluso los paradigmas de programación, y hoy en día se están
popularizando las plataformas de servidores de aplicaciones como Websphere de IBM, Oracle 9i,
o incluso Microsoft.NET.

Además de todo esto, las aplicaciones web tienden a ser cada vez más adaptables a los usuarios
finales, y ofrecen servicios personalizados y cada vez más seguros, aunque todavía hay reticen-
cias y desconfianza hacia las compras y transacciones en Internet.

Con todo, la programación y la seguridad son los protagonistas en los servicios de hoy en día,
tanto en el entorno de redes de área amplia como en los servicios internos de las redes locales, en
las que la web se ha convertido en el componente fundamental del concepto de Intranet.

11.2 CARACTERÍSTICAS DE APACHE

Apache posee varias características que lo han convertido en exitoso: es rápido, potente, eficaz y
flexible. Más del 60% de los servidores web son servidores Apache, duplicando la cifra de los
servidores Microsoft IIS.

Analicemos estas características con más detenimiento:

Desarrollo de Aplicaciones Web Dinámicas - UNED


INSTALACIÓN DE APACHE 11.5

• Es multiplataforma, por lo tanto, no depende del sistema operativo ni de la arquitectura.


Este factor es muy importante, ya que se podrá realizar una migración directa aunque haya
que cambiar los servidores de la empresa. Por ello, muchos administradores de Windows
eligen Apache porque les permite afrontar futuros cambios de sistema operativo sin difi-
cultad.
• Es modular y potente. Apache cuenta con multitud de módulos adicionales muy fáciles de
integrar gracias a su modularidad. De esta manera, Apache forma un conjunto muy pode-
roso junto al sistema de gestión de bases de datos MySQL y el lenguaje de programación
PHP.
• Es libre y abierto. Además de ser gratuito, tiene la garantía de seguridad y flexibilidad del
código abierto. Como valor añadido, toda una comunidad científica proporciona asistencia
en caso de necesidad.
• Se adapta muy rápido a versiones y características nuevas. Ha sido el primer servidor en
incorporar algunas técnicas, por ejemplo, los servidores virtuales, esto es, un mismo servi-
dor puede ofrecer varios sitios a la vez (lo estudiaremos posteriormente). Del mismo
modo, los primeros pasos de seguridad los dio también Apache con el módulo Apache-
SSL.
• Escalabilidad. Algunos servidores web tienen que absorver un gran volumen de tráfico. En
este tipo de sistemas, el servidor, además de ser rápido, tiene que ser escalable, es decir,
que puede aumentar su capacidad de respuesta cuando la demanda aumente.

Apache suele venir incorporado en todas las distribuciones de Linux. De todas maneras, el pro-
ceso en si no se llama Apache sino httpd y se inicia mediante el script /etc/init.d/httpd.

En algunas distribuciones se utiliza el nombre httpd2 en lugar de httpd.

11.3 INSTALACIÓN DE APACHE

11.3.1 REQUISITOS PARA EJECUTAR UN SERVIDOR APACHE


Apache se ejecuta en prácticamente cualquiera de las plataformas que se utilizan hoy en día,
como FreeBSD, OpenBSD, NetBSD, BSDI, Amiga OS 3.x, Mac OS X, Sun OS, Solaris, IRIX,
HPUX, Digital Unix, UnixWare, AIX, SCO, ReliantUNIX, Linux, BeOS y Windows.

Antes de instalar Apache en un servidor web (posteriormente veremos como conseguirlo si no lo


tenemos) es necesario asegurarse de que el computador es lo suficientemente potente para ejecu-
tarlo.

Afortundamente, Apache no necesita grandes recursos en el ordenador para funcionar. Se ejecuta


perfectamente en un sistema Linux de 5 a 12 Mb libres de espacio en el disco duro y 16 Mb de
RAM. Sin embargo, en la mayoría de los casos no se instalará únicamente Apache sino que ade-
más querremos utilizarlo para servir páginas web, lanzar procesos CGI y sacar partido a todo ese
estupendo material que la web tiene que ofrecer.

Desarrollo de Aplicaciones Web Dinámicas - UNED


11.6 SERVIDORES WEB. APACHE

En este caso, será necesario más espacio en el disco duro y en la RAM para poder satisfacer todas
las necesidades.

No obstante hoy en día cualquier computador de última generación está preparado de sobra para
ejecutar este servicio y muchos más.

11.3.2 ¿DÓNDE SE OBTIENE APACHE?


Como ya hemos comentado anteriormente, Apache es un software gratuito por lo que no se
vende en las tiendas. Existen por tanto dos principales maneras de conseguir Apache:
1 Que se incluya en el Sistema Operativo: Esta opción está presente en la mayoría de las dis-
tribuciones Linux. Concretamente, en la versión que hemos instalado de Mandrake se
incluye la versión Apache 2 con múltiples módulos. Por tanto si al realizar la instalación
elegimos el perfil de Servidor, directamente se habrá instalado en nuestro sistema. En el
caso de no haber elegido este perfil, simplemente deberemos ir a al menú de instalación de
paquetes y requerir la instalación del mismo.
2 Desde la página web www.apache.org. En este portal encontraremos las últimas versiones
de Apache en multitud de Sistemas Operativos. Para aquellos que deseen instalar un servi-
dor web en Windows, esta es una opción muy recomendable. En este caso nos bajaremos
un fichero ejecutable el cual nos guiará de forma sencilla a través del proceso de instala-
ción.

 El CD que acompaña a este módulo, contiene una versión para la plataforma W32.

11.4 INICIAR APACHE

Apache funciona como un servicio por lo que habrá que ponerlo en marcha. La manera de
hacerlo varía en función del sistema operativo sobre el que se está corriendo.
1 En el caso de Linux (concretamente la distrubución Mandrake) existen dos formas:
- Ejecutando desde una consola el script /etc/init.d/httpd start. Para ello es necesario
entrar primero en modo de superusuario mediante el comando su.
- Usando la herramienta gráfica de activación de servicios a la cual se accede como
Menu->sistema->Configuración->Configurar su computadora->Sistema-
>Habilitar o deshabilitar los servicios del sistema. (Fig. 11.2)
- Mediante la herramienta webmin.

Desarrollo de Aplicaciones Web Dinámicas - UNED


CREACIÓN DE DIRECTORIOS 11.7

2 En el caso de Windows, una vez instalado el software, se dispone de una herramienta grá-
fica que se encuentra en la Barra de iconos de tareas (Fig. 11.1)

Figura 11.1 Acceso a Apache Service Monitor.

Figura 11.2 Herramienta de activación de servicios.

Una vez que está activo el servidor, es posible comprobar su correcto funcionamiento mediante
un navegador conectándonos a la siguiente url http://localhost.

11.5 CREACIÓN DE DIRECTORIOS

Si Apache está instalado, el mencionado script httpd estara creado en el directorio init.d. Los
ficheros de configuracion suelen crearse en el directorio /etc/httpd/conf, pero la ubicación de los
datos suele variar entre /var/www, /var/httpd o /home/httpd, según la distribución de la que se dis-
ponga. En la version de Mandrake, el directorio utilizado es /var/www, y será el directorio que
usaremos en los ejemplos.

En el caso de Windows, los ficheros de configuración suelen crearse en C:\Archivos de pro-


grama\Apache Group\Apache2\conf y los datos en C:\Archivos de programa\Apache
Group\Apache2\htdocs

A continuación se explicarán los ficheros de configuración más importantes:

Desarrollo de Aplicaciones Web Dinámicas - UNED


11.8 SERVIDORES WEB. APACHE

• /etc/httpd/conf: el directorio en el que se guardan los ficheros de configuración.


• /var/www/htdocs: directorio en el que se guardaran los documentos del sitio web. Será
importante controlar los permisos de acceso en este directorio y sus inferiores.
• /var/www/cgi-bin: el directorio en el que se guardan los CGI. Este directorio tendrá que
tener permisos especiales por razones de seguridad.
• /var/www/icons: el lugar en el que se guardarán los ficheros de los iconos.
• /var/www/include: directorio de los módulos adicionales. Un ejemplo es el directorio xml,
que suele colgar de este directorio.
• /var/www/logs: directorio donde se guarda información sobre los accesos. Esta informa-
cion es fundamental para calcular estadisticas de acceso al sitio.

En el caso de Windows, la estructura de directorios es similar salvo que estos cuelgan de


C:\Archivos de programa\Apache Group\Apache2\

Para estudiar el estado del servidor Apache será necesario explorar estos directorios. Para una
primera aproximación se puede utilizar por ejemplo este comando:
ls -l /var/www

11.6 OPCIONES PRINCIPALES DE CONFIGURACIÓN

Configurar Apache es una tarea ardua, pero controlar los principales parametros no es tan dificil.
Existen ademas varios programas gráficos de configuracion que ayudan en esta labor, como por
ejemplo la herramienta llamada comanche o webmin.

Dentro del directorio de configuracion /etc/httpd/conf (en Windows en el directorio anterior-


mente nombrado) hay varios ficheros importantes. Los más destacados son los siguientes:
• httpd.conf es el fichero de configuración principal. Es algo complicado y en la siguiente
sección se explicará superficialmente. En algunas distribuciones se completa con el
fichero commonhttpd.conf.
• access.conf: en este fichero se guarda información acerca de los permisos de acceso.
Puede entrar en conflicto con las directivas del fichero httpd.conf, por lo que se reco-
mienda no modificar este fichero. En algunas distribuciones ni siquiera se incluye este
fichero (como en el caso de Windows).
• srm.conf sirve para configurar la estructura de directorios mencionada en la sección ante-
rior. En este fichero se define dónde se ubicarán los documentos, los CGI, etc. En algunas
distribuciones tampoco se incluye este fichero, y de existir, se recomienda no modificarlo.
• mime.types o apache-mime.types: el fichero para el control de contenidos multimedia.

11.6.1 EL FICHERO HTTPD.CONF


Este es el fichero en el que se escriben las principales opciones de configuración del servidor
Apache. Es bastante largo y contiene mucha información susceptible de ser modificada para
adaptar el funcionamiento del servidor a nuestras necesidades.

Desarrollo de Aplicaciones Web Dinámicas - UNED


OPCIONES PRINCIPALES DE CONFIGURACIÓN 11.9

Cada vez que el servidor Apache se inicia, lee este fichero de modo que cualquier cambio que
realicemos en el mismo, solo se notará si reiniciamos el servidor apache. Esto se puede hacer eje-
cutando el script /etc/init.d/httpd restart (en Linux) o mediante la herramienta gráfica mostrada
citada en el apartado 11.4 (Iniciar Apache) de la página 6 en el caso de tratarse de un sistema
Windows.

En cada linea especifica el valor de un parametro, ofreciendo información completa de los posi-
bles valores que puede tomar. Muchas veces estas directivas se encuentran desactivadas, con el
caracter # por delante a modo de comentario. Es decir, cualquier linea que comience con el carac-
ter # se considera un comentario y por tanto no se ejecutará.

Es interesante que mientras estudia los posibles valores de los siguientes parámetros, abra el
fichero /etc/httpd/conf/httpd2.conf o en otras distribuciones /etc/httpd/conf/httpd.conf para ir
comprobando el código.

Comentarle antes que dentro de este fichero puede incluirse una sentencia denominada include
nombre-fichero que permite insertar en ese punto el contenido del fichero nombre-fichero. Por
ello, algunos de los parámetros que aquí describiremos no aparecen en el fichero principal
(podrían tambien estar) sino en algunos de los ficheros asociados. Esto se hace así para poder
tener ficheros con distintas configuraciones y con solamente cambiar una linea include hacer que
el servidor trabaje de una forma totalmente distinta.

Los parámetros mas importantes, aquellos que suelen ser modificados en ocasiones, son los
siguientes:
• Modo de inicio. ServerType. Tiene dos opciones: la primera para que el servidor se inicie
directamente (standalone), y la segunda mediante inetd (inetd). Normalmente se utiliza la
opción standalone. El formato es el siguiente:
ServerType standalone
• Máximo número de conexiones: MaxClients. Con este número se puede limitar el maximo
de clientes, para evitar problemas por sobrecargas o ataques de denegación de servicio. Por
ejemplo:
MaxClients 150
• Margen del número de servidores: MinSpareServers, MaxSpareServers, StartServers. Con
estos parametros se puede definir el número de servidores en marcha simultaneamente: el
minimo, el maximo y el valor de inicio. El valor de inicio suele ser cinco en casi todas las
distribuciones. Por ejemplo:
StartServers 5

MinSpareServers 5

MaxSpareServers 15
Por lo tanto, se puede servir entre cinco y quince peticiones simultáneas y en el caso de
que lleguen más, se pondrán en la lista de espera. Por eso es habitual que haya varios pro-
cesos httpd en marcha a la vez.

Desarrollo de Aplicaciones Web Dinámicas - UNED


11.10 SERVIDORES WEB. APACHE

• Puerto: Port. Determina en que puerto debe escuchar el servidor. El valor por defecto es
80, pero para hacer pruebas se utiliza en ocasiones el puerto 8080.
Port 80
• Puerto o IP adicional: Listen. Es complementario del anterior, ya que permite escuchar en
más de un puerto a la vez.
Listen 8080
• Directorio del servicio: ServerRoot. Establece el directorio en el que se van a almecenar
los archivos del servidor.
ServerRoot /etc/httpd
• Directorio raIz de las paginas web: DocumentRoot. En este directorio se situarán las pági-
nas web, por lo que habra que tener especial cuidado con los permisos de los documentos.
En este directorio se pueden utilizar enlaces simbólicos.
DocumentRoot /var/www/html
• Módulos plug-in: LoadModule y AddModule. Como Apache se trata de un programa
modular, es flexible en ese aspecto. De esta manera podemos añadir a Apache habilidades
extra. Suele haber varias líneas de este tipo, una por cada módulo del directorio modules.
He aqui algunos ejemplos:
LoadModule mime_module modules/mod_mime.so

LoadModule proxy module modules/libproxy.so


• Control de seguridad: User, Group. Con estos parámetros se asigna una cuenta y un grupo
al servidor Apache. Cuando el proceso se inicia, la cuenta de inicio es root, ya que de lo
contrario no se podria utilizar el puerto reservado 80. No obstante, razones de seguridad
recomiendan utilizar una cuenta sin privilegios. Normalmente se utiliza apache o nobody.
User apache
• e-mail de administracion: ServerAdmin. Aqui se define la cuenta de correo para la admi-
nistración del sitio web. A esta dirección llegarán los mensajes automáticos que generará
Apache cuando surjan problemas.
ServerAdmin webmaster@localhost
• Equivalencias de directorios: Alias. Suelen ser abreviaturas de caminos absolutos. Pueden
definirse por comodidad o por seguridad. Con estas abreviaturas los usuarios tendran que
teclear direcciones mas cortas:
Alias /libro/ "/var/www/html/publicaciones/actual/libro/"
• Gestión de idiomas: AddLanguage, LanguagePriority. Con el primer parámetro se pueden
especificar los idiomas de los documentos del sitio, y con el Segundo se determina la prio-
ridad entre los mismos. Por ejemplo:
AddLanguage es .es

AddLanguage en .en

AddLanguage eu .eu

Desarrollo de Aplicaciones Web Dinámicas - UNED


HOSTS VIRTUALES 11.11

AddLanguage ca .ca

AddLanguage fr .fr

LanguagePriority es en eu ca fr
• Activación de la función de cache: CacheRoot, CacheSize, CacheMaxExpire, etc. Con
estos parámetros se puede activar (on) o desactivar (off) la función de caché para permitir
que se acumulen las últimas consultas realizadas sobre las paginas dinámicas del sitio, de
forma que se puedan servir con mayor rapidez. En el siguiente comando se especifica el
directorio que se va a utilizar para almacenar archivos con caché.
CacheRoot "/var/cache/httpd"

Estas son unas lineas con los principales parámetros de configuración de Apache. No obstante la
referencia completa y probablemente la mejor guía (en castellano) se encuentra en http://
httpd.apache.org/docs/2.0/.

Se recomienda al lector su visita ya que contiene toda la información de configuración, instala-


ción y manejo del servidor, así como el significado de todos los parámetros junto a sus posibles
valores.

11.7 HOSTS VIRTUALES

El término host virtuales hace referencia a ejecutar mas de un sitio web en el mismo servidor. Se
podría tratar de múltiples nombres que tuvieran el mismo dominio como http://tallerdigi-
tal.uned.es y http://tallerdgital.uned.es o de nombres con dominios distintos, como http://
www.miweb.com y http://www.tuweb.com.

Apache fue el primer servidor web que acuñó esta característica que ha mantenido desde su ver-
sión 1.1 (la versión actual es la 2.0).

Apache soporta dos tipos de hosts virtuales:


• Los hosts virtuales basados en nombres hacen referencia a albergar un sitio en un CNAME
distinto, pero en la misma dirección IP. Un CNAME (nombre canónico) es un alias de un
registro DNS existente. Es decir, se pueden tener comprados los dominios
www.miweb.com y www.tuweb.com, con contenidos distintos y redirigidos al mismo ser-
vidor. Cuando el servidor recibe la petición, Apache es capaz de discernir cuales son las
páginas que debe servir en función del nombre del dominio.
• Los hosts virtuales basados en IP hacen referencia a sitios hosts procedentes de distintas
direcciones de la misma máquina (un servidor puede tener varias IP´s).

11.7.1 HOSTS VIRTUALES BASADOS EN IP


Si no hay medidas de seguridad, es posible ejecutar un servidor en cada dirección IP, y hacerlo
todo en un solo servidor Apache. Esto le exige mucho menos a la máquina (en vez de activar un

Desarrollo de Aplicaciones Web Dinámicas - UNED


11.12 SERVIDORES WEB. APACHE

servidor por cada IP) ya que todas las solicitudes las maneja un solo proceso. Esto se hace con los
hosts virtuales basados en IP.

Los hosts virtuales basados en IP requieren una dirección IP separada en cada host virtual. Para
añadir direcciones IP adicionales a la máquina, es necesario configurar el sistema operativo. Se
puede añadir una tarjeta de red para cada IP o, en la mayoría de sistemas operativos, asignar múl-
tiples direcciones al mismo dispositivo.

La sección <VirtualHost>
Dentro del fichero de configuración de Apache httpd.conf existen los denominados contenedores
los cuales son trozos de código que se ejecutan entre dos marcas, en este caso entre <Virtual-
Host> y </VirtualHost>.

Por ello, entre estas dos etiquetas, incluiremos los parámetros propios de cada uno de los hosts
virtuales que deseemos definir. Se pueden definir tantos bloques <VirtualHost> como se desee.

La sección <VirtualHost> del archivo de configuración del servidor incluye aquellas directivas
que se aplican a un determinado host virtual. Entre ellas se encuentran como mínimo Documen-
tRoot y también puede haber otras como ServerAdmin, ErrorLog, etc.

A continuación se muestra un ejemplo de la sección <VirtualHost>. Este ejemplo define dos


hosts virtuales basados en IP que se ejecutan en el mismo servidor. Vamos a suponer que al servi-
dor se le han asignado dos direcciones IP: 192.168.1.150 y 192.168.1.151.
<VirtualHost 192.168.1.150>

ServerAdmin webmaster@yo.com

DocumentRoot /home/yo/html

ServerName servi1.yo.com

</VirtualHost>

<VirtualHost 192.168.1.151>

ServerAdmin webmaster@tu.com

DocumentRoot /home/tu/html

ServerName servi2.tu.com

</VirtualHost>

11.7.2 HOSTS VIRTUALES BASADOS EN NOMBRES


Es posible usar hosts virtuales basados en nombres cuando no sea posible o deseable asignar
múltiples direcciones IP a la máquina. Los hosts virtuales basados en nombres, poseen la ventaja
añadida de que se puede ejecutar un número ilimitado de hosts virtuales a partir de una dirección
IP.

Desarrollo de Aplicaciones Web Dinámicas - UNED


CONFIGURACIÓN DE APACHE EN MODO GRÁFICO 11.13

Como funciona un hosts virtual basado en nombres


Cuando se envía una solicitud HTTP al servidor, parte de la solicitud identifica el servidor en el
que se está haciendo la solicitud. Esta característica del protocolo HTTP/1.1 la soportan la mayo-
ría de los navegadores, aunque estos no lleguen a soportar completamente el protocolo HTTP/
1.1. Apache puede entonces determinar, en base a esta información, desde que servidor virtual
hay que atender la solicitud, aunque se puedan resolver todas ellas en la misma dirección IP.

La directiva NameVirtualHost
Los hosts virtuales se configuran de manera muy similar a los hosts virtuales basados en direc-
ciones IP, con una diferencia principal: la directiva NameVirtualHost le indica al servidor sobre
qué dirección IP se van a recibir las solicitudes de hosts virtuales basados en nombres. Las sec-
ciones <VirtualHost> tienen el mismo aspecto que cuando se usan hosts virtuales basados en
direcciones IP, con la excepción de que todas ellas señalan a la misma dirección IP.

Veamos el siguiente caso de ejemplo. Supongamos que disponemos de un servidor con la IP


192.168.0.1 asignada. Supongamos también que hemos adquirido dos dominios www.yo.com y
www.tu.com a una empresa y deseamos montar dos portales web distintos de los dominios ante-
riores en la misma máquina. Además hemos dado las instrucciones pertinentes a la empresa de
contratación de dominios para que todas las solicitudes a www.yo.com y a www.tu.com las rediri-
jan a nuestro servidor.

El proyecto consiste en hacer que Apache distinga las solicitudes que llegan de cada dominio y
las redirija a las páginas web propias de cada uno.
NameVirtualHost 192.168.0.1

<VirtualHost 192.168.0.1>

ServerName www.yo.com

DocumentRoot /var/www/yo

</VirtualHost>

<VirtualHost 192.168.0.1>

ServerName www.tu.com

DocumentRoot /var/www/tu

</VirtualHost>

11.8 CONFIGURACIÓN DE APACHE EN MODO GRÁFICO

La configuración de Apache se puede realizar también en modo gráfico, mediante el diálogo de


webmin tal y como se muestra en la (Fig. 11.3). Dentro de la sección servidores, eligiendo el
icono Servidor Web Apache, aparecen las opciones generales estudiadas de forma más sencilla.

Desarrollo de Aplicaciones Web Dinámicas - UNED


11.14 SERVIDORES WEB. APACHE

Aquí podremos configurar completamente nuestro servidor, es decir, en vez de editar a mano el
fichero httpd.conf el sistema lo hace por nosotros añadiendo, modificando o suprimiendo líneas
del mismo en función de las opciones elegidas

Para la gestión del servidor por defecto y de los dominios virtuales se utilizan las opciones que
aparecen tras hacer un clic en uno de los servidores virtuales.

Figura 11.3 Configuración de Apache.

11.9 MAS RECURSOS

Podrá encontar una referencia completa de Apache en http://httpd.apache.org/docs/

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 12

Conceptos básicos sobre bases


de datos

12.1 INTRODUCCIÓN

Antes de entrar en contacto con MySQL se presentarán algunos aspectos fundamentales sobre
bases de datos, que serán de importancia para la compresión de las posibilidades que este Sis-
tema de Gestión de Bases de Datos (SGBD) ofrece. En primer lugar, se dan una serie de defini-
ciones sobre conceptos básicos. A continuación se indican los objetivos que se persiguen con los
SGBD y se tratan los problemas relativos a la abstracción de la información. Por último, antes de
presentar la estructura general de un SGBD, se tratan los modelos de datos que serán de impor-
tancia durante el diseño de bases de datos.

12.2 DEFINICIONES BÁSICAS

• Dato. Conjunto de caracteres (numéricos, alfabéticos, o alfanuméricos) que tienen algún


significado. Un dato refleja el valor de una característica de un objeto. Un dato debe per-
manecer en el tiempo, tener un significado y ser manipulable mediante operadores.
• Información. Conjunto ordenado de datos manejados según la necesidad del usuario. Para
que un conjunto de datos pueda ser procesado eficientemente y pueda dar lugar a informa-
ción, primero se debe guardar en archivos.
• Base de datos. Conjunto de datos organizados y relacionados entre sí, libres de redundan-
cias innecesarias e independientes de los programas que los usan.
• Sistema de Gestión de Bases de Datos (SGBD). En inglés DBMS (Data Base Manager
System). Colección de rutinas software que realizan diversas tareas específicas. Su obje-
tivo principal es proporcionar un entorno que permita extraer, almacenar y manipular
información de la base de datos. Un ejemplo de SGBD es MySQL. Las funciones princi-
pales de un SGBD son: 1) Crear y organizar la base de datos. 2) Establecer y mantener las
12.2 CONCEPTOS BÁSICOS SOBRE BASES DE DATOS

trayectorias de acceso a la base de datos de tal forma que se pueda acceder rápidamente a
los datos. 3) Manejar los datos de acuerdo a las peticiones de los usuarios. 4) Registrar el
uso de las bases de datos. 5) Interaccionar con el manejador de archivos a través de senten-
cias en LMD (Lenguaje de Manipulación de Datos). 6) Disponer de mecanismos que per-
miten la recuperación de los datos en caso de fallo en el sistema de base de datos. 7)
Controlar la interacción entre los usuarios concurrentes para no producir inconsistencia de
datos. 8) Disponer de mecanismos que permitan el control de la consistencia de los datos
evitando que estos se vean perjudicados por cambios no autorizados o no previstos. En la
figura se muestra el SGBD como interfaz entre la base de datos física y las peticiones de
usuario.

Petición de usuario
Base de datos física
Indagaciones

Sistema
SGBD Base de
operativo
datos
Sistema de
manejo de
archivos

Figura 12.1 SGBD como interfaz entre la base de datos física y las peticiones de usuario

• Instancias y esquemas. La información que contiene la base de datos cambia con el


tiempo. Se denomina instancia, al estado que presenta una base de datos en un determi-
nado instante de tiempo. Por otra parte, se entiende por esquema, a la descripción lógica de
la base de datos. El esquema no cambia, los que varían son los datos produciendo nuevas
instancias.
• Independencia de datos. Protección contra los programas de aplicación que puedan origi-
nar modificaciones cuando se altera la organización física o lógica de la base de datos.
Existen dos niveles de independencia de datos. 1) Independencia física de datos, capaci-
dad de modificar el esquema físico sin provocar que se vuelvan a escribir los programas de
aplicación. 2) Independencia lógica de datos, capacidad de modificar el esquema concep-
tual sin provocar que se vuelvan a escribir los programas de aplicación.
• Lenguaje de definición de datos LDD (DDL, Data Definition Language). Permite definir
el esquema de la base de datos por medio de una serie de definiciones que se expresan en
un lenguaje especial, el resultado de estas definiciones se almacena en un archivo especial
llamado diccionario de datos.
• Lenguaje de manipulación de datos LMD (DML, Data Manipulation Language). La mani-
pulación de datos se refiere a las operaciones de insertar, recuperar, eliminar o modificar
datos. Estas operaciones se realizan a través del LMD, que es quién permite el acceso de
los usuarios a los datos. Existen básicamente dos tipos de lenguajes de manipulación de

Desarrollo de Aplicaciones Web Dinámicas - UNED


OBJETIVOS DE LOS SISTEMAS DE BASES DE DATOS 12.3

datos: 1) Procedimentales, requieren que el usuario especifique que datos necesita y cómo
obtenerlos. 2) No procedimentales, requieren que el usuario especifique que datos necesita
sin especificar cómo obtenerlos
• SQL Structured Query Language. Lenguaje orientado al sector de las bases de datos. Los
comandos de SQL se pueden dividir en tres tipos: 1) Los que hacen referencia a la defini-
ción de datos (LDD). 2) Los que hacen referencia a la manipulación de datos (LMD). 3)
Los que hacen referencia al control y seguridad de los datos.
• Consulta. Petición al SGBD para que procese un determinado comando. Incluye peticio-
nes de datos, creación de bases de datos, modificaciones e inserciones, entre otros.
• Usuarios de las bases de datos. Toda persona que tenga contacto con el sistema de base de
datos desde que éste se diseña, elabora, termina y se usa. Pueden ser: 1) Programadores de
aplicaciones, profesionales en computación que interactúan con el sistema por medio de
llamadas en LMD. 2) Usuarios sofisticados, interactúan con el sistema escribiendo sus
preguntas en un lenguaje de consultas de base de datos. 3) Usuarios especializados, usua-
rios sofisticados que escriben aplicaciones de base de datos especializadas que no encajan
en el marco tradicional de procesamiento de datos. 4) Usuarios ingenuos, usuario final que
utiliza el sistema de base de datos sin saber nada del diseño interno del mismo, interactúa
con el sistema invocando alguno de los programas de aplicación del sistema de base de
datos.
• Administrador de base de datos. Persona o conjunto de personas responsables del control
y manejo del sistema de base de datos. Sus funciones principales son: 1) Definición de
esquema, el esquema original de la base de datos se crea escribiendo un conjunto de defi-
niciones que son traducidas por el compilador de LDD a un conjunto de tablas que son
almacenadas permanentemente en el diccionario de datos. 2) Definición de la estructura
de almacenamiento del método de acceso, se crean escribiendo un conjunto de definicio-
nes que son traducidas por el compilador del lenguaje de almacenamiento y definición de
datos. 3) Concesión de autorización para el acceso a los datos, regular las partes de las
bases de datos que van a ser accedidas por varios usuarios. 4) Especificación de límites de
integridad, serie de restricciones que se encuentran almacenados en una estructura espe-
cial del sistema que es consultada por el gestor de base de datos cada vez que se realice
una actualización al sistema.

12.3 OBJETIVOS DE LOS SISTEMAS DE BASES DE DATOS

Los sistemas de base de datos están diseñados para manejar gran cantidad de información. La
manipulación de los datos involucra tanto la definición de estructuras para el almacenamiento de
la información como la provisión de mecanismos para la manipulación de la información, ade-
más un sistema de base de datos debe de tener implementados mecanismos de seguridad que
garanticen la integridad de la información, a pesar de caídas del sistema o intentos de accesos no
autorizados. En este sentido, el objetivo principal de un sistema de base de datos es proporcionar

Desarrollo de Aplicaciones Web Dinámicas - UNED


12.4 CONCEPTOS BÁSICOS SOBRE BASES DE DATOS

a los usuarios una visión abstracta de los datos, escondiendo ciertos detalles sobre cómo se alma-
cenan y mantienen los datos.

Un sistema de base de datos debe tener en cuenta los siguientes aspectos:


• Redundancia de datos. Se dice que hay redundancia de datos cuando la misma informa-
ción es almacenada varias veces en la misma base de datos. Esto es siempre algo a evitar,
la redundancia dificulta la tarea de modificación de datos, y es el motivo más frecuente de
inconsistencia de datos. Además requiere un mayor espacio de almacenamiento, que
influye en mayor coste y mayor tiempo de acceso a los datos.
• Inconsistencia de datos. Sólo se produce cuando existe redundancia de datos, es decir,
cuando no todas las copias redundantes contienen la misma información. Este problema
surge cuando se modifica la información. Si dicha información sólo se cambian en algunos
de los lugares en que se guarda, las consultas que se realicen podrán dar como resultado
respuestas inconsistentes. Puede darse el caso de que dos aplicaciones diferentes propor-
cionen resultados distintos para el mismo dato.
• Integridad de datos. Cuando se trabaja con bases de datos, generalmente los datos se
reparten entre varios ficheros. Si, como pasa con MySQL, la base de datos está disponible
para varios usuarios de forma simultánea, deben existir mecanismos que aseguren que las
relaciones entre registros se mantengan coherentes, que se respetan las dependencias de
existencia y que las claves primarias no se repitan. Este tipo de situaciones son potencial-
mente peligrosas, ya que provocan situaciones con frecuencia imprevistas. Ciertos errores
de integridad pueden provocar que una base de datos deje de ser utilizable. Los problemas
de integridad se suelen producir cuando varios usuarios están editando datos de la misma
base de datos de forma simultánea (un usuario crea un nuevo registro, mientras otro edita
uno de los existentes, y un tercero borra otro). El SGBD debe asegurar que se pueden rea-
lizar estas tareas sin que se produzcan errores que afecten a la integridad de la base de
datos.
• Dificultad para acceder a los datos. Un sistema de base de datos debe contemplar un
entorno de datos que le facilite al usuario el manejo de los mismos. Puede ocurrir que una
petición de información no esté prevista en el diseño del sistema (no existe ninguna aplica-
ción de consulta que permita una determinada solicitud) lo que ocasiona una deficiencia
del sistema.
• Aislamiento de datos. Puesto que los datos están repartidos en varios archivos, y estos no
pueden tener diferentes formatos, es difícil escribir nuevos programas de aplicación para
obtener los datos apropiados.
• Anomalías de accesos concurrente. Para mejorar el funcionamiento global del sistema y
obtener un tiempo de respuesta más rápido, muchos sistemas permiten que múltiples usua-
rios actualicen los datos simultáneamente. En un entorno así la interacción de actualizacio-
nes concurrentes puede dar por resultado datos inconsistentes. Para prevenir esta
posibilidad debe mantenerse alguna forma de supervisión en el sistema.

Desarrollo de Aplicaciones Web Dinámicas - UNED


ABSTRACCIÓN DE LA INFORMACIÓN 12.5

• Seguridad. Algunos datos pueden ser más importantes que otros, por lo que se debe consi-
derar el control de acceso a los mismos, no todos los usuarios pueden visualizar toda la
información, por este motivo para que un sistema de base de datos sea fiable debe mante-
ner un grado de seguridad que garantice la autentificación y protección de los datos.

12.4 ABSTRACCIÓN DE LA INFORMACIÓN

Una base de datos puede verse como una colección de archivos relacionados entre sí, de los cua-
les el usuario puede extraer información sin tener que conocer la estructura de archivos. En este
sentido, un objetivo importante de un sistema de base de datos es proporcionar a los usuarios una
visión abstracta de los datos, es decir, el sistema esconde ciertos detalles de cómo se almacenan
y mantienen los datos. Sin embargo, para que el sistema sea manejable, los datos se deben extraer
eficientemente.

Nivel de visión

Vista 1 Vista 2 Vista n

Nivel
conceptual

Nivel físico

Figura 12.2 Niveles de abstracción

Existen diferentes niveles de abstracción para simplificar la interacción de los usuarios con el sis-
tema (ver figura):
• Nivel físico. Nivel más bajo de abstracción. Se describe de forma detallada como se alma-
cenan los datos en los dispositivos de almacenamiento.
• Nivel conceptual. Siguiente nivel de abstracción. Describe la base de datos completa en
términos de su estructura de diseño (datos almacenados y relaciones entre ellos). El nivel
conceptual lo usan los administradores de bases de datos, responsables de decidir la infor-
mación se va a guardar en la base de datos. En éste nivel se consideran las siguientes defi-
niciones: 1) Definición de los datos, se describen el tipo de datos y la longitud de campo
(atributos y registros conceptuales). 2) Relaciones entre datos, se definen las relaciones
entre datos para enlazar tipos de registros relacionados para el procesamiento de archivos
múltiples. En el nivel conceptual la base de datos aparece como una colección de registros
lógicos, sin descriptores de almacenamiento. En realidad los archivos conceptuales no
existen físicamente. La transformación de registros conceptuales a registros físicos para el
almacenamiento se lleva a cabo por el sistema y es transparente al usuario.

Desarrollo de Aplicaciones Web Dinámicas - UNED


12.6 CONCEPTOS BÁSICOS SOBRE BASES DE DATOS

• Nivel de visión. Nivel más alto de abstracción, es lo que el usuario final puede visualizar
del sistema terminado, describe sólo una parte de la base de datos al usuario acreditado
para verla. El sistema puede proporcionar muchas visiones para la misma base de datos.

12.5 MODELOS DE DATOS

Se puede definir un modelo como una representación de la realidad que contiene las característi-
cas generales de algo que se va a realizar. En base de datos, esta representación se realiza de
forma gráfica.

Un modelo de datos, es una colección de herramientas conceptuales para describir los datos, las
relaciones que existen entre ellos, semántica asociada a los datos y restricciones de consistencia.
Los modelos de datos se dividen en tres grupos: 1) Modelos lógicos basados en objetos. 2)
Modelos lógicos basados en registros. 3) Modelos físicos de datos.
• Modelos lógicos basados en objetos. Se utilizan para describir datos en los niveles concep-
tual y de visión. Los datos se representan como son captados en el mundo real. Estos
modelos tienen una capacidad de estructuración bastante flexible y permiten especificar
restricciones de datos explícitamente. Existen diferentes modelos de este tipo, pero el más
utilizado por su sencillez y eficiencia es el modelo Entidad-Relación (E-R).
• Modelos lógicos basados en registros. Se utilizan para describir datos en los niveles con-
ceptual y físico. Estos modelos utilizan registros e instancias para representar la realidad,
así como las relaciones que existen entre estos registros. A diferencia de los modelos de
datos basados en objetos, se usan para especificar la estructura lógica global de la base de
datos y para proporcionar una descripción a nivel más alto de la implementación. Los tres
modelos de datos más ampliamente aceptados son: modelo relacional, modelo de red y
modelo jerárquico.
• Modelos físicos de datos. Se utilizan para describir a los datos en el nivel más bajo, aunque
existen muy pocos modelos de este tipo, básicamente capturan aspectos de la implementa-
ción de los sistemas de base de datos. Existen dos clasificaciones de este tipo que son:
modelo unificador y memoria de elementos.

12.6 ESTRUCTURA GENERAL DEL SISTEMA

Un sistema de base de datos se encuentra dividido en módulos cada uno de los cuales controla
una parte de las tareas del sistema. En la mayoría de los casos, el sistema operativo proporciona
únicamente los servicios más básicos y el sistema de base de datos debe partir de esa base y con-
trolar además el manejo correcto de los datos. Así, el diseño de un sistema de base de datos debe
incluir la interfaz entre el sistema de base de datos y el sistema operativo.

Los componentes funcionales de un sistema de base de datos, son:

Desarrollo de Aplicaciones Web Dinámicas - UNED


ESTRUCTURA GENERAL DEL SISTEMA 12.7

• Gestor de archivos. Gestiona la asignación de espacio en la memoria del disco y de las


estructuras de datos usadas para representar información.
• Manejador de base de datos. Sirve de interfaz entre los datos y los programas de aplica-
ción.
• Procesador de consultas. Traduce las proposiciones en lenguajes de consulta a instruccio-
nes de bajo nivel. Además convierte la solicitud del usuario en una forma más eficiente.
• Compilador de LDD. Convierte las proposiciones LDD en un conjunto de tablas que con-
tienen metadatos, estas se almacenan en el diccionario de datos.
• Archivo de datos. En él se encuentran almacenados físicamente los datos.
• Diccionario de datos. Contiene la información referente a la estructura de la base de datos.
• Índices. Permiten un rápido acceso a registros que contienen valores específicos.

En la figura se muestra la estructura general del sistema.

Usuarios

Ingenuos Programadores Sofisticados Administrador

Interfaz de Programas de Planificación


Consulta
aplicación aplicación de base de datos

Precompilador Procesador de Compilador


de LMD consultas de LDD

Código objeto de
Gestor de Sistema de Gestión
programas de
archivos de Bases de Datos
aplicación

Gestor de
archivos

Archivo de datos Diccionario


de datos

Almacenamiento en disco

Figura 12.3 Estructura general de un sistema de bases de datos

Desarrollo de Aplicaciones Web Dinámicas - UNED


12.8 CONCEPTOS BÁSICOS SOBRE BASES DE DATOS

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 13

Diseño de bases de datos


relacionales

13.1 INTRODUCCIÓN

El diseño de una base de datos consiste en pasar de un problema real a su implementación en el


ordenador utilizando bases de datos. Para ello se deben seguir los siguientes pasos: 1) Definir el
problema. 2) Crear un modelo lógico basado en objetos (que se denotará por modelo conceptual).
3) A partir del modelo conceptual, construir un modelo lógico basado en registro (que se deno-
tará por modelo lógico). 4) Verificar el modelo lógico. 5) Partiendo del modelo lógico llegar al
modelo físico.

En este tema se tratan los cuatro primeros pasos, dejando el quinto para el resto de los temas
dedicados al lenguaje SQL en el sistema de gestión de bases de datos MySQL.

13.2 PROCESO DE DISEÑO

Como se ha indicado, el proceso de diseño de una base de datos consiste en pasar de un problema
real, planteado por un cliente, a su implementación en el ordenador. Para ello se deben realizar
los siguientes pasos:
• Definición del problema. Para poder definir el problema lo primero que hay que hacer es
hablar con el cliente para saber qué quiere y qué necesita. Esta tarea no es simple, ya que,
por lo general, el cliente tampoco sabe lo qué puede pedir (de hecho, es habitual que ni
siquiera sepa qué es lo que necesita). Los modelos conceptuales ayudan en esta fase del
diseño, pues facilitan una forma clara de ver el proceso en su totalidad mediante una repre-
sentación gráfica. Por otra parte, los modelos conceptuales no están orientados a ningún
sistema físico concreto, ni tienen una orientación informática clara, lo que facilita su com-
prensión por personas sin conocimientos de programación. También es importante obser-
var el funcionamiento del proceso que se quiere informatizar, ya que, generalmente, lo que
13.2 DISEÑO DE BASES DE DATOS RELACIONALES

se quiere hacer ya se realiza de forma manual o con un pequeño apoyo ofimático. El obje-
tivo de esta observación es conocer qué tipo de información se necesita y qué parte de ella
se utiliza con mayor frecuencia.
• Modelo conceptual. Una vez definido el problema, el siguiente paso es crear un modelo
conceptual. El modelo más usado en bases de datos es el modelo Entidad-Relación (E-R).
Durante esta fase, se tendrán que tomar decisiones que en cierto modo limitarán el modelo.
• Modelo lógico. La siguiente fase es convertir el modelo conceptual en un modelo lógico.
Existen varios modelos lógicos, pero el más usado y el que mejor se adapta a MySQL es el
modelo relacional. La conversión entre el modelo conceptual y el lógico es bastante mecá-
nica, aunque no por ello será siempre sencilla.
• Verificación. En el caso del modelo lógico relacional, existe un proceso que sirve para
verificar que se ha realizado bien el modelo, y en caso contrario, corregirlo. Este proceso
se llama normalización.
• Modelo físico. El último paso consiste en codificar el modelo lógico en un modelo físico.
Este proceso está ligado con el SGBD elegido, lo que requiere conocimientos del lenguaje
a utilizar. En el caso de MySQL, se requiere el conocimiento del lenguaje SQL.

13.3 MODELO ENTIDAD-RELACIÓN (E-R)

El modelo Entidad-Relación (E-R), representa la realidad a través de entidades, que son objetos
que existen y que se distinguen de otros por sus características. Las entidades pueden ser de dos
tipos: 1) Tangibles, objetos físicos que se pueden ver, tocar o sentir. 2) Intangibles, eventos u
objetos conceptuales que no se pueden ver, aun sabiendo que existen. Las características de las
entidades en base de datos se llaman atributos. A su vez una entidad se puede asociar o relacio-
nar con más entidades a través de relaciones.

En esencia, el modelo E-R, consiste en buscar las entidades que describan los objetos que inter-
vienen en el problema y las relaciones entre esas entidades. Todo esto se representa en un
esquema gráfico que tiene por objeto, ayudar al programador durante la codificación y al usuario
a comprender el problema y el funcionamiento del programa.

Antes de continuar, se definirán algunos conceptos utilizados en el modelo E-R.


• Entidad. Es una representación de un objeto individual concreto del mundo real. Ejemplo,
un alumno concreto.
• Conjunto de entidades. Es la clase o tipo al que pertenecen entidades con características
comunes. Ejemplo, conjunto de alumnos.
• Atributo. Es cada una de las características que posee una entidad, y que agrupadas permi-
ten distinguirla de otras entidades del mismo conjunto. Ejemplos, nombre y número de
DNI de un alumno.
• Dominio. Conjunto de valores posibles para un atributo.

Desarrollo de Aplicaciones Web Dinámicas - UNED


MODELO ENTIDAD-RELACIÓN (E-R) 13.3

• Relación. Asociación o conexión entre entidades. Ejemplo, la que existe entre un alumno
concreto y una asignatura concreta.
• Conjunto de relaciones. Asociación o conexión entre conjuntos de entidades. Ejemplo, la
que existe entre el conjunto de entidades alumnos y el conjunto de entidades asignaturas.
• Grado. Número de conjuntos de entidades que intervienen en una relación: Ejemplo, la
relación anterior es de grado 2 o binaria.
• Clave. Conjunto de atributos que identifican de forma unívoca una entidad. Cada entidad
se puede distinguir de otra por sus atributos (el conjunto completo de todos los atributos no
se puede repetir nunca). A menudo sólo cierto subconjunto de atributos diferencian una
entidad. En algunas casos se crea un atributo artificial para usarlo sólo como clave (clave
artificial). Ejemplo, en las entidades alumno, el nombre por si mismo, no es una clave, ya
que hay muchas personas con el mismo nombre (lo mismo ocurre con nombre y apelli-
dos). Si se considera el número de DNI, pueden surgir problemas con alumnos de distintas
nacionalidades o con menores de edad, que normalmente no disponen de DNI. En este
caso, se puede crear un atributo artificial número de expediente, para usarlo sólo como
clave.
• Claves candidatas. Una característica que se debe buscar siempre en las claves es que con-
tengan el número mínimo de atributos. Una clave es mínima cuando si se elimina cual-
quiera de los atributos que la componen, deja de ser clave. Si en una entidad existe más de
una de estas claves mínimas, cada una de ellas es una clave candidata. Clave candidata, es
cada una de las claves mínimas existente en un conjunto de entidades.
• Clave primaria o principal. Clave candidata elegida de forma arbitraria, que se utilizará
siempre para identificar una entidad.
• Claves de relaciones. Para definir una relación se utilizarán las claves primarias de las
entidades relacionadas. De este modo, el identificador de una relación es el conjunto de las
claves primarias de cada una de las entidades relacionadas.
• Entidades fuertes y débiles. A menudo la clave de una entidad está ligada a la clave princi-
pal de otra. La diferencia es que las entidades débiles no necesitan una clave primaria, sus
claves siempre están formadas como la combinación de una clave primaria de una entidad
fuerte y otros atributos. Además, la existencia de las entidades débiles está ligada o subor-
dinada a la de la fuerte. Es decir, existe una dependencia de existencia (si se elimina una
entidad fuerte, se deberá eliminar también todos las entidades débiles que dependan de
ella). Ejemplo, una entidad expediente, que usa la clave de un alumno y añade otros atribu-
tos como calificaciones, es una entidad débil, en contraposición a la entidad alumno, que
es una entidad fuerte. Si se elimina a un alumno, se debe eliminar también su expediente.
• Dependencia de existencia. Se produce una dependencia de existencia entre una entidad,
subordinada, y otra, dominante, cuando la eliminación de la entidad dominante, conlleva
también la eliminación de la entidad o entidades subordinadas. Desde cierto punto de
vista, se puede considerar que las entidades dominantes y sus entidades subordinadas for-
man parte de una misma entidad.

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.4 DISEÑO DE BASES DE DATOS RELACIONALES

• Generalización. Es el proceso según el cual se crea un conjunto de entidades a partir de


otros que comparten ciertos atributos. En algunas situaciones es conveniente crear una
entidad como una fusión de otras, en principio, diferentes, aunque con atributos comunes.
Esto disminuye el número de conjuntos de entidades y facilita el establecimiento de rela-
ciones. La idea es crear una entidad con una única copia de los atributos comunes y añadir
los atributos no comunes. Además se debe añadir un atributo que indique que tipo de enti-
dad se está usando, este atributo es un discriminador. La desventaja de la generalización es
que se desperdicia espacio de almacenamiento, ya que sólo algunos de los atributos no
comunes contienen información en cada entidad, el resto se desperdicia. La ventaja es el
mismo tipo de relación con cualquier entidad del conjunto. Ejemplo, en el modelado de
gestión de una biblioteca, en la que además de libros existen revistas y películas, se debe-
rían crear conjuntos de entidades distintos para estos tres tipos de entidades, sin embargo,
todos ellos tienen características comunes (préstamos, ubicaciones, ejemplares, editorial) y
otras específicas (número de revista, duración de película).
• Especialización. Proceso según el cual se crean varios tipos de entidades a partir de una
(proceso inverso al de generalización). Cada una de los conjuntos de entidades resultantes
contendrá sólo algunos de los atributos del conjunto original (las diferencias superan a los
atributos comunes). Es irrelevante que una entidad sea fruto de una generalización o de
una especialización, ya que no deja de ser una entidad, y por lo tanto, no afecta al modelo.

13.3.1 DIAGRAMAS E-R


Un diagrama E-R consiste en representar mediante distintas figuras un modelo completo del pro-
blema a describir, de forma que se definan tanto los conjuntos de entidades que lo componen,
como los conjuntos de relaciones que existen entre ellos.
• Conjunto de entidades. Se representan mediante un rectángulo con nombre. En el caso de
entidades débiles, se pueden representar mediante dos rectángulos inscritos. Las depen-
dencias de existencia entre entidades débiles y fuertes, se representan añadiendo una fle-
cha a la línea que llega al conjunto de entidades débiles.

Entidad Entidad

Figura 13.1 Conjunto de entidades

• Atributo. Se representan mediante elipses, y en su interior el nombre del atributo. Cuando


el atributo es una clave primaria, se suele subrayar su nombre, y si es multivaluado (atri-
buto que para una misma entidad puede tomar varios valores diferentes) se suele utilizar
una doble elipse.

Atributo Atributo Atributo

Desarrollo de Aplicaciones Web Dinámicas - UNED


MODELO ENTIDAD-RELACIÓN (E-R) 13.5

Figura 13.2 Atributo

• Conjunto de relaciones. Se representan mediante rombos, y en su interior el nombre del


conjunto de relaciones.

Relación

Figura 13.3 Conjunto de relaciones

• Cardinalidad de asignación. Es una restricción que expresa el número de entidades con las
que puede asociarse otra entidad, mediante un conjunto de relaciones. En los extremos de
las líneas que parten del rombo del conjunto de relaciones, se pueden añadir unos números
que indican la cantidad de entidades que intervienen. Esto también se suele hacer modifi-
cando el extremo de las líneas o utilizando flechas. Si terminan con un extremo involucran
a una entidad, si terminan en varios extremos o flechas involucrarán a varias entidades.
Sobre las líneas a veces se añade el rol que representa cada entidad. La cardinalidad de
asignación es más útil para describir conjuntos binarios de relaciones, aunque ocasional-
mente contribuyen a la descripción de conjuntos de relaciones que implican más de dos
conjuntos de entidades. Para un conjunto binario de relaciones R entre los conjuntos de
entidades A y B, la cardinalidad de asignación puede ser una de las siguientes: 1) Una a
una (1:1), una entidad A está asociada a lo sumo con una entidad B y viceversa. 2) Una a
muchas (1:N), una entidad A está asociada con un número cualquiera de entidades B, sin
embargo una entidad B puede estar asociada a lo sumo con una entidad A. 3) Muchas a
una (N:1), una entidad A está asociada a lo sumo con una entidad B, aunque una entidad B
puede estar asociada a un número cualquiera de entidades A. 4) Muchas a muchas (N:N),
una entidad A está asociada con un número cualquiera de entidades B, y viceversa.

1 n
Entidad1 Relación Entidad2

Figura 13.4 Cardinalidad de asignación

• Domino. Se representan mediante hexágonos, con la descripción del dominio en su inte-


rior.

Descripción
Dominio

Figura 13.5 Descripción de dominio

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.6 DISEÑO DE BASES DE DATOS RELACIONALES

• Generalización. Se representan mediante un triángulo etiquetado como ISA.

ISA

Figura 13.6 Generalización

Para construir un modelo E-R, se puede dividir el proceso en varias tareas más simples. El pro-
ceso completo es iterativo y una vez terminado se debe volver al comienzo, repasar el modelo
obtenido y, probablemente, modificarlo. Una vez conformes con el modelo obtenido se pasará a
la siguiente fase de diseño (modelo lógico).

Uno de los primeros problemas que se presentan en la construcción del modelo E-R, es decidir
qué son entidades y qué atributos. La regla principal es que una entidad sólo debe contener infor-
mación sobre un único objeto real. Pero en ciertos casos esto puede obligar a crear entidades con
un único atributo. Una regla que puede ayudar en esta decisión es que si una entidad sólo tiene un
atributo, que sirve para identificarlo, entonces esa entidad puede ser considerara como un atri-
buto.

Otro problema frecuente se presenta con los atributos multivaluados. Pero, aunque como su pro-
pio nombre indica no dejan de ser atributos, es mejor considerar a los atributos multivaluados
como entidades débiles subordinadas. Esto evitará muchos problemas con el modelo lógico rela-
cional.

Para crear un diagrama conceptual no existe un procedimiento universal, pero se pueden dar
algunas directrices generales:
• Hablar con el cliente e intentar dejar claros los parámetros y objetivos del problema a
modelar.
• Estudiar el planteamiento del problema para identificar los conjuntos de entidades útiles
para modelar el problema e identificar los conjuntos de relaciones y determinar su grado y
tipo.
• Trazar un primer diagrama E-R.
• Identificar atributos y dominios para los conjuntos de entidades y relaciones.
• Seleccionar las claves primarias para los conjuntos de entidades.
• Verificar que el modelo resultante cumple el planteamiento del problema.

Ejemplo. Crear un diagrama conceptual de una base de datos para un centro de enseñanza que
contenga información sobre los alumnos, las asignaturas y las calificaciones que los alumnos
obtienen en cada una de las asignaturas. Para cada alumno habrá que almacenar su nombre, ape-
llido, DNI y domicilio, y para cada asignatura su nombre y curso al que pertenece.

Una vez planteado el problema se seguirán los siguientes pasos:


• Identificar los conjunto de entidades. Como puede deducirse del enunciado, existen dos
conjuntos de entidades que se nombrarán como ASIGNATURAS y ALUMNOS.

Desarrollo de Aplicaciones Web Dinámicas - UNED


MODELO ENTIDAD-RELACIÓN (E-R) 13.7

• Identificar los conjunto de relaciones. Según se especifica en el enunciado, debe existir


información sobre las calificaciones que ha obtenido cada alumno en cada asignatura, por
lo que es necesario el uso de un conjunto de relaciones para estas entidades, que se deno-
tará como ALUM-ASIG. Como un alumno puede estar matriculado en muchas asignaturas,
y en una asignatura pueden estar matriculados muchos alumnos, la asignación de cardina-
lidad es de muchos a muchos.
• Trazar un primer diagrama E-R.. En la figura se muestran los conjuntos de identidades y
el conjunto de relaciones entre ellos.

ALUMNOS ALUM-ASIG ASIGNATURAS

Figura 13.7 Primer diagrama E-R para el centro de enseñanza

• Indentificar los atributos. Como se indica en el enunciado los atributos para cada conjunto
de entidades serán: ALUMNOS (nombre_alum, apellido, dni, domicilio), ASIGNATU-
RAS (nombre_asig, curso), ALUM-ASIG (nota).
• Seleccionar las claves primarias. Para no complicar el diagrama final, se considerarán
como claves primarias dni para ALUMNOS y nombre_asig para asignaturas. Con ello se
está asumiendo que todo alumno posee DNI y que los nombres de las asignaturas que se
imparten en el centro son distintos. En un planteamiento más realista, y ante la posibiliad
de alumnos sin DNI o asignaturas de distitos cursos con igual nombre, se podría haber
obtado por utizar dos claves artificiales número de expediente y código de asignatura. La
clave de la relación ALUM-ASIG, estará formada por las claves de los dos conjuntos de
entidades.
• Verificar el modelo. En la figura se muestra el modelo E-R resultante, que cumple las espe-
cificaciones del enunciado. En este caso se ha optado por no utilizar flechas para indicar
que la relación es de muchos a muchos, ni subrallar las claves.

dni domicilio

ALUMNOS ALUM-ASIG ASIGNATURAS

nombre_alum apellido nombre_asig curso


nota

Figura 13.8 Modelo E-R para el centro de enseñanza

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.8 DISEÑO DE BASES DE DATOS RELACIONALES

13.4 MODELO RELACIONAL

Entre los modelos lógicos, el modelo relacional está considerado como el más simple y es el más
extendido (MySQL está orientado principalmente a bases de datos relacionales). El modelo rela-
cional se compone de tres partes: 1) Estructura de datos, básicamente formada por relaciones. 2)
Manipulación de datos, conjunto de operadores para recuperar, derivar o modificar los datos
almacenados. 3) Integridad de datos, colección de reglas que definen la consistencia de la base
de datos.

Como se ha apuntado, uno de los aspectos relativos a los datos de los que se ocupa el modelo
relacional es el de su representación o estructura. Una base de datos relacional se representa
mediante un conjunto de tablas, a cada una de las cuales se le asigna un nombre exclusivo. Cada
tabla, está formada por filas y columnas y en ella se encuentran los datos. Además, a cada
columna se le asigna un nombre exclusivo. Por otra parte, todos los datos que aparecen en una
misma columna deben pertenecer a un mismo dominio, entendiéndose por dominio, el conjunto
de valores permitidos para los datos que aparecen en cada una de las columnas.

nombre_1 nombre_2 ... nombre_n


dato_1_1 dato_1_2 ... dato_1_n

dato_2_1 dato_2_2 ... dato_2_n

dato_3_1 dato_3_2 ... dato_3_n

... ... ... ...

dato_m_1 dato_m_2 ... dato_m_n

Tabla 13.1 Relación

Si D1, D2, ..., Dn denotan los dominios correspondientes a cada una de las n columnas de la
tabla, respectivamente, sus filas serán tuplas <d1,d2,...,dn>, donde los valores di pertenecen a los
dominios Di. En tal caso, el producto cartesiano de los distintos dominios D1 x D2 x ... x Dn, es
un conjunto cuyos elemento son todas las posibles tuplas <d1,d2,...,dn>. Por lo tanto, el conte-
nido de una tabla será un subconjunto del producto cartesiano que se conoce con el nombre de
relación.

Como las tablas son esencialmente relaciones, en el modelo relacional se utilizan los términos
relación, atributo y tupla en lugar de los términos tabla, columna y fila, respectivamente.

En términos formales, una relación se compone de dos partes cabecera o conjunto de atributos y
cuerpo o conjunto de tuplas. El grado n (número de atributos) de una relación permanece fijo en
el tiempo mientras que su cardinalidad m (número de tuplas) varía con éste.

Cada una de las relaciones que forma parte de un sistema relacional puede ser de alguno de los
siguientes tipos:
• Relación base. Relación que forma parte de la base de datos.

Desarrollo de Aplicaciones Web Dinámicas - UNED


MODELO RELACIONAL 13.9

• Vista. Relación virtual definida en función de otras relaciones (no posee datos propios
almacenados).
• Instantánea. Relación definida en función de otras relaciones (posee datos propios almace-
nados).
• Resultado de consulta. Relación resultante de alguna consulta especificada.
• Resultado intermedio. Relación resultante de alguna expresión relacional anidada dentro
de otra expresión.
• Relación temporal. Relación que se destruye en algún momento sin que el usuario realice
ninguna acción para ello.

Una base de datos relacional se puede definir como una base de datos percibida por el usuario
como una colección de relaciones normalizadas de diversos grados que varía con el tiempo.

Antes de continuar, se definirán algunos conceptos utilizados en el modelo relacional.


• Relación. Conjunto de datos referentes a un conjunto de entidades organizados en forma
de tabla, que se compone de filas o tuplas y columnas o atributos, en la que cada intersec-
ción de fila y columna contiene un valor. Los conceptos de relación entre el modelo E-R y
el modelo relacional son diferentes. En el modelo E-R, el término relación se utiliza para
referirse a la conexión entre entidades, mientras que en el modelo relacional este término
se refiere a una tabla, y es el paralelo al concepto conjunto de entidades del modelo E-R.
• Tupla. Cada una de las filas de una relación. A menudo se le llama también registro o fila.
Equivale al concepto de entidad del modelo E-R, y define un objeto real. Contiene la infor-
mación relativa a una única entidad. De esta definición se deduce que no pueden existir
dos tuplas iguales en la misma relación.
• Atributo. Cada una de las características que posee una entidad, y que agrupadas permiten
distinguirla de otras entidades del mismo conjunto. También denominado campo o
columna. Corresponde al concepto de atributo del modelo E-R y contiene cada una de las
características que definen una entidad u objeto. Al igual que en el modelo E-R, cada atri-
buto tiene asignado un nombre y un dominio. El conjunto de todos los atributos es lo que
define a una entidad completa, y es lo que compone una tupla. Hay ciertos atributos, para
determinadas entidades, que carecen de valor. El modelo relacional distingue entre valores
vacíos y valores nulos. Un valor vacío se considera un valor tanto como cualquiera no
vacío, sin embargo, un nulo NULL indica la ausencia de valor (valor asignado a un atributo
que indica que no contiene ninguno de los valores del dominio de dicho atributo). El nulo
es importante en el modelo relacional, ya que permite trabajar con datos desconocidos o
ausentes.
• Dominio. Rango o conjunto de posibles valores de un atributo. El concepto de dominio es
el mismo en el modelo E-R y en el modelo relacional. Pero en este último modelo tiene
mayor importancia, ya que será una especificacióno importante a la hora de dimensionar la
relación. En relación con los dominios se puede resaltar lo siguiente: 1) Las comparacio-
nes entre atributos de distintos dominios no tienen sentido. 2) Los dominios pueden ser

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.10 DISEÑO DE BASES DE DATOS RELACIONALES

simples o compuestos. 3) Un dominio corresponde a tipo de datos en un lenguaje de pro-


gramación.
• Modelo relacional. Es un modelo basado en relaciones, en la que cada una de ellas debe
cumplir: 1) No tiene tuplas repetidas. 2) Las tuplas no están ordenadas. 3) Cada atributo
sólo puede tomar un único valor del dominio. 4) Los atributos no están ordenados.
• Cardinalidad. Número de tuplas que contiene una relación. La cardinalidad puede cambiar
a lo largo del tiempo.
• Grado. Número de atributos de cada tupla. El grado de una relación es un valor constante.
Esto no quiere decir que no se puedan agregar o eliminar atributos de una relación, pero si
se hace la relación cambia. Cambiar el grado, generalmente, implicará modificaciones en
las aplicaciones que hagan uso de la base de datos, ya que cambiarán conceptos como cla-
ves e interrelaciones, de hecho, puede cambiar toda la estructura de la base de datos.
• Esquema. Parte constante de una relación (estructura). El esquema es una lista de los atri-
butos que definen una relación y sus dominios.
• Instancia. Conjunto de las tuplas que contiene una relación en un momento determinado.
• Clave. Conjunto de atributos que identifica de forma unívoca a una tupla. Puede estar
compuesto por un único atributo o una combinación de varios. Dentro del modelo relacio-
nal no existe el concepto de clave múltiple. Cada clave sólo puede hacer referencia a una
tupla de una tabla. Por lo tanto, todas las claves de una relación son únicas.
• Clave candidata. Cada una de las posibles claves de una relación. En toda relación existirá
al menos una clave candidata, esto implica que ninguna relación puede contener tuplas
repetidas. Uno o varios atributos de una relación forman una clave candidata si, y sólo si,
se satisfacen las dos propiedades siguientes que no dependen del tiempo: 1) Unicidad, en
cualquier momento no existen dos tuplas en la relación con el mismo valor del atributo o
atributos. 2) Minimalidad, para el caso de varios atributos, no será posible eliminar nin-
guno de ellos sin destruir la propiedad de unicidad.
• Clave primaria (o principal). Es la clave candidata elegida por el usuario para identificar
las tuplas. No existe la necesidad, desde el punto de vista de la teoría de bases de datos
relacionales, de elegir una clave primaria. Además, las claves primarias no pueden tomar
valores nulos. En MySQL, es preferible, por motivos de optimización, que estos valores
sean enteros, aunque no es obligatorio. MySQL sólo admite una clave primaria por tabla.
Respecto a la clave primaria se pueden hacer los siguientes comentarios: 1) Del conjunto
de las claves candidatas se debe elegir una, y sólo una, clave primaria. 2) Toda relación
tiene por lo menos una clave candidata. 3) El razonamiento para elegir la clave primaria,
cuando existen varias claves candidatas, queda fuera del modelo relacional. 4) La clave
primaria es la que tiene verdaderamente importancia. 5) La clave primaria es un concepto
aplicable a las relaciones base. 6) La clave primaria se define por el conjunto de atributos
que la componen. 7) El único modo de localizar una tupla es por el valor de su clave pri-
maria.

Desarrollo de Aplicaciones Web Dinámicas - UNED


MODELO RELACIONAL 13.11

• Clave alternativa. Cada una de las claves candidatas que no son clave primaria, si es que
existen.
• Clave foránea (o externa). Es el atributo (o conjunto de atributos) dentro de una relación
que contienen claves primarias de otra relación. No hay nada que impida que ambas rela-
ciones sean la misma.
• Interrelación. Dos relaciones están interrelacionadas cuando una posee una clave foránea
de la otra. Cada una de las claves foráneas de una relación establece una interrelación con
la relación donde esa clave es la principal. Según esto, existen dos tipos de interrelación:
1) La interrelación entre entidades fuertes y débiles. 2) La interreación pura, entre entida-
des fuertes. Extrictamente hablando, sólo la segunda es una interrelación, pero en el
modelo relacional ambas tienen la forma de relaciones, al igual que las entidades com-
puestas, que son interrelaciones con atributos añadidos. Como en el modelo E-R, existen
varios tipos de interrelación: 1) Uno a uno, a cada tupla de una relación le corresponde una
y sólo una tupla de otra. 2) Uno a varios, a cada tupla una relación le corresponden varias
en otra. 3) Varios a varios, cuando varias tuplas de una relación se pueden corresponder
con varias tuplas en otra.

13.4.1 PASO DEL MODELO E-R AL MODELO RELACIONAL


Existen tres reglas básicas para convertir cada uno de los elementos de los diagramas E-R en
tablas:
• Para cada conjunto de entidades fuertes, se crea una única tabla, a la que se le asigna el
nombre del conjunto de entidades, y cuyas columnas son los atributos del conjunto de enti-
dades.
• Para cada conjunto de entidades débiles, se crea una única tabla, a la que se le asigna el
nombre de la entidad débil, y cuyas columnas son los atributos de la entidad débil más los
de la clave primaria de la entidad fuerte a la que está subordinada.
• Para cada conjunto de relaciones se crea una única tabla a la que se le asigna el nombre del
conjunto de relaciones, y cuyas columnas son las claves primarias de todas las entidades
que relaciona más los atributos propios de la relación.

Cada relación se representan mediante su esquema:

nombre_relación(nombre_atributo_1, ..., nombre_atributo_n)

La clave primaria se suele indicar mediante un subrayado.

Ejemplo. A partir del modelo obtenido en la sección anterior para un centro de enseñanza, obte-
ner su correspondiente modelo relacional.

Para ello se seguirán los tres pasos indicados:


• Para cada conjunto de entidades se crea una tabla. En este caso existirán dos que se deno-
taran por ALUMNOS y ASIGNATURAS. En dichas relaciones existirá una columna para
cada atributo (los atributos subrallados corresponden a las claves primarias):

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.12 DISEÑO DE BASES DE DATOS RELACIONALES

ALUMNOS (dni, nombre_alum, apellido, domicilio)


ASIGNATURAS (nombre_asig, curso)
• Para cada conjunto de relaciones se crea una tabla que contiene una columna para cada
atributo correspondiente a las claves primarias de las entidades relacionadas.
ALUM_ASIG (dni, nombre_asig, nota)

Por lo tanto, el esquema relacional final será:

ALUMNOS (dni, nombre_alum, apellido, domicilio)

ASIGNATURAS (nombre_asig, curso)

ALUM_ASIG (dni, nombre_asig, nota)

13.4.2 MANIPULACIÓN DE DATOS. ÁLGEBRA RELACIONAL


El modelo relacional también define el modo en que se pueden manipular las relaciones. Para
ello se hace uso del álgebra relacional como lenguaje de consulta. Un lenguaje de consulta es un
lenguaje mediante el cual el usuario solicita información contenida en la base de datos. Este tipo
de lenguajes se pueden clasificar en lenguajes procedimentales y lenguajes no procedimentales.
En un lenguaje procedimental, el usuario indica la secuencia de operaciones que se debe realizar
sobre la base de datos para obtener el resultado deseado. Por otra parte, en un lenguaje no proce-
dimental, el usuario describe la información que desea obtener de la base de datos sin dar el pro-
cedimiento para determinarla. El álgebra relacional es un lenguaje de consulta procedimental.

Para realizar las consultas de la base de datos, el álgebra relacional dispone de un conjunto de
operaciones básicas y de la operación de asignación. Esta última asigna el valor de alguna
expresión del álgebra a una relación nombrada. Por otra parte, cada operación toma una o dos
relaciones como entrada y produce una nueva relación como salida.

En el álgebra relacional se definen ocho operaciones básicas clasificadas en dos grupos:


• Operaciones de conjuntos: unión, intersección, diferencia y producto cartesiano.
• Operaciones relacionales: selección, proyección, reunión (natural y theta) y división.

Además de estas ocho operaciones básicas se define la operación renombrar, que permite cam-
biar de nombre los atributos, y otras operaciones adicionales (ampliación, resumen y división
generalizada). Las ocho operaciones básicas no constituyen un conjunto mínimo. Así, las opera-
ciones reunión, intersección y división se pueden definir a partir de las otras cinco.

Para poder definir estas operaciones es necesario saber lo que se entiende por compatibilidad res-
pecto a la unión y compatibilidad respecto al producto:
• Dos relaciones son compatibles respecto a la unión si, y sólo si, sus cabeceras son idénti-
cas, lo que significa que: 1) Las dos tienen el mismo conjunto de nombres de atributos. 2)
Los atributos correspondientes se definen sobre el mismo dominio.
• Dos relaciones son compatibles respecto al producto si, y sólo si, sus cabeceras son disjun-
tas (no contienen nombres de atributos iguales).

Desarrollo de Aplicaciones Web Dinámicas - UNED


MODELO RELACIONAL 13.13

Operación renombrar
En una relación, los nombres de los atributos que forman su cabecera deben ser distintos. Esto no
impide que, en una base de datos relacional, pueda existir más de una relación con un mismo
nombre para alguno de sus atributos. En tal caso, si mediante una operación se llega a otra rela-
ción que los contenga, se estaría incumpliendo la exigencia indicada. Así, si R1 y R2 son dos
relaciones en las que un atributo de R1 y otro atributo de R2 tienen el mismo nombre, y se
obtiene una nueva relación con los atributos de R1 y los atributos de R2, en ésta aparecerán dos
atributos con nombres iguales. Para evitar esta duplicidad se introduce la operación renombrar,
cuya misión es cambiar de nombre los atributos que sean necesarios antes de realizar una opera-
ción que pueda llevar a una relación con una cabecera en la que aparezcan dos atributos con el
mismo nombre.
• Operación renombrar . A partir de una relación R, crea una nueva copia de ésta en la que
sólo se han modificado los nombres de aquellos atributos (atributos_originales) que se
quieren renombrar (atributos_nuevos). La sintaxis del operador es:
R  atributos_nuevos (atributos_originales)

Ejemplo 1. Sea la relación, ALUMNOS (dni, nombre_alum, apellido, domicilio), para cambiar
de nombre los atributos apellido y domicilio, por apellido_alum y domicilio_alum, respectiva-
mente, se utilizará:

ALUMNOS  apellido_alum, domicilio_alum (apellido, domicilio)

Operaciones de conjuntos
• Unión ». La unión de dos relaciones R1 y R2, compatibles respecto a la unión, es otra rela-
ción cuya cabecera es idéntica a la de R1 (o a la de R2), y cuyo cuerpo está formado por
todas las tuplas pertenecientes a R1, a R2 o a las dos. La unión construye una relación for-
mada por todas las tuplas que aparecen en cualquiera de las dos relaciones especificadas.
La sintaxis de la operación es: R1 » R2
• Intersección «. La intersección de dos relaciones R1 y R2, compatibles respecto a la unión,
es una relación cuya cabecera es idéntica a la de R1 (o a la de R2) y cuyo cuerpo está for-
mado por todas las tuplas pertenecientes tanto a R1 como a R2. La intersección construye
una relación formada por todas las tuplas que aparecen en las dos relaciones especificadas.
La sintaxis de la operación es: R1 « R2
• Diferencia -. La diferencia de dos relaciones R1 y R2, compatibles respecto a la unión, es
una relación cuya cabecera es idéntica a la de R1 (o a la de R2) y cuyo cuerpo está formado
por todas las tuplas pertenecientes a R1 pero no a R2. La diferencia construye una relación
formada por todas las tuplas de la primera relación que no aparecen en la segunda de las
dos relaciones especificadas. La sintaxis de la operación es: R1 - R2
• Producto cartesiano x. El producto cartesiano de dos relaciones R1 y R2, compatibles res-
pecto al producto, es una relación cuya cabecera es la combinación de las cabeceras de R1
y R2 y cuyo cuerpo está formado por el conjunto de todas las tuplas t tales que t es la com-

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.14 DISEÑO DE BASES DE DATOS RELACIONALES

binación de una tupla t1 perteneciente a R1 y una tupla t2 perteneciente a R2. El producto


cartesiano, a partir de dos relaciones específicas, construye una relación que contiene
todas las combinaciones posibles de tuplas, una de cada una de las dos relaciones. La sin-
taxis de la operación es: R1 x R2

Ejemplo 2. Sean ALUMNOS_1 y ALUMNOS_2 dos relaciones en las que aparecen las tuplas de
los alumnos con domicilio en madrid y los alumnos de nombre juan, respectivamente.

ALUMNOS_1

dni nombre_alum apellido domicilio


0002 juan garcia madrid

0005 lucia lopez madrid

0007 raquel perez madrid

0016 laura salas madrid

ALUMNOS_2

dni nombre_alum apellido domicilio


0001 juan perez teruel

0002 juan garcia madrid

0003 juan alvarez lugo

Estas relaciones son compatibles respecto a la unión por tener el mismo conjunto de nombres de
atributos y estar los atributos del mismo nombre definidos en el mismo dominio. Por lo tanto,
con ellas se podrán realizar las operaciones: unión, intersección y diferencia.

La unión de las dos relaciones indicadas es otra con la misma cabecera que éstas y en cuyo
cuerpo están todas las tuplas de las dos relaciones. Obsérvese como no aparecen las tuplas repeti-
das.

ALUMNOS_1 » ALUMNOS_2

dni nombre_alum apellido domicilio


0002 juan garcia madrid

0005 lucia lopez madrid

0007 raquel perez madrid

0016 laura salas madrid

0001 juan perez teruel

0003 juan alvarez lugo

Desarrollo de Aplicaciones Web Dinámicas - UNED


MODELO RELACIONAL 13.15

La intersección de éstas relaciones es otra con la misma cabecera y en cuyo cuerpo aparecen las
tuplas que están simultáneamente en ellas.

ALUMNOS_1 « ALUMNOS_2

dni nombre_alum apellido domicilio


0002 juan garcia madrid

La diferencia ALUMNOS_2 - ALUMNOS_1 es una relación con la misma cabecera que las rela-
ciones que aparecen en la expresión y en cuyo cuerpo están las tuplas que pertenecen a
ALUMNOS_1 pero no a ALUMNOS_2. Observesé que este resultado es distinto a
ALUMNOS_2 - ALUMNOS_1.

ALUMNOS_1 - ALUMNOS_2

dni nombre_alum apellido domicilio


0005 lucia lopez madrid

0007 raquel perez madrid

0016 laura salas madrid

Ejemplo 3. Sean las relaciones ALUMNOS y ASIGNATURAS:

ALUMNOS (dni, nombre_alum, apellido, domicilio)

ASIGNATURAS (nombre_asig, curso)

Estas relaciones son compatibles respecto al producto ya que, sus cabeceras no tienen nombres
de atributos iguales. Si en lugar de nombre_alum y nombre_asig, se hubiera utilizado el atributo
nombre en las dos relaciones, para que éstas fueran compatbles respecto al producto, habría que
renombrar el atributo nombre en alguna de las dos relaciones.

El producto cartesiano de estas dos relaciones es otra relación, en cuya cabecera aparecen los
atributos de las dos relaciones:

ALUMNOS x ASIGNATURAS (dni, nombre_alum, apellido, domicilio, nombre_asig, curso)

y su cuerpo está formado por todas las combinaciones de tuplas de las dos relaciones.

Operaciones relacionales
• Selección . La selección de tuplas de una relación R, es otra relación con la misma cabe-
cera que la de R y cuyo cuerpo esta formado por las tuplas de R que verifican una condi-
ción impuesta a los atributos. En la condición pueden aparecer operadores de comparación
(=, <>, >, >=) y booleanos (AND, OR, NOT). La selección extrae las tuplas especificadas
de una relación dada, es decir, restringe la relación sólo a las tuplas que satisfacen la condi-

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.16 DISEÑO DE BASES DE DATOS RELACIONALES

ción. Los atributos que aparecen en la condición deben estar definidos sobre el mismo
dominio. La sintaxis de la operación es:  condición (R)
• Proyección . La proyección de la relación R según los atributos A1, A2, …, An, es otra
relación que tiene como cabecera la formada por los atributos indicados y en cuyo cuerpo
aparecen todas las tuplas de R restringidas a dichos atributos, eliminando las tuplas repeti-
das. La sintaxis de la operación es:  A1, A2, ..., An (R)
• Reunión. La reunión de dos relaciones específicas, es otra relación que contiene todas las
posibles combinaciones de tuplas, una de cada una de las dos relaciones, tales que las dos
tuplas participantes en la combinación satisfacen una condición especificada. Se conside-
ran dos tipos de reunión, la reunión natural y la reunión theta.
• Reunión natural *. Sea (A1, A2, ..., Am, B1, B2, ..., Bn) la cabecera de una relación R1 y
(B1, B2, ..., Bn, C1, C2, ..., Cp) la cabecera de otra relación R2, estando los atributos del
mismo nombre definidos en el mismo dominio. Si se consideran los tres atributos com-
puestos A (A1, A2, ..., Am), B (B1, B2, ..., Bn) y C (C1, C2, ..., Cp), la reunión natural de
R1 y R2 es una relación con la cabecera (A, B, C) y un cuerpo formado por el conjunto de
todas las tuplas (A:a, B:b, C:c) tales que una tupla t1 aparece en R1 con el valor a en A y el
valor b en B, y una tupla t2 aparece en R2 con el valor b en B y el valor c en C. La reunión
natural de dos relaciones específicas, es otra relación que contiene todas las posibles com-
binaciones de tuplas, una de cada una de las dos relaciones, tales que las dos tuplas partici-
pantes en la combinación tengan los mismos valores en los atributos comunes. La sintaxis
de la operación es: R1 * R2
• Reunión theta |x|. Sean las relaciones R1 y R2 compatibles respecto al producto y sea theta
un operador. La reunión theta de la relación R1 según el atributo A con la relación R2
según el atributo B, es una relación con la misma cabecera que el producto cartesiano de
R1 y R2, y un cuerpo formado por el conjunto de todas las tuplas t, tales que t pertenece a
la relación resultante si la evaluación de la condición A theta B resulta verdadera. Los atri-
butos A y B deberán estar definidos en el mismo dominio y la operación theta debe ser
aplicable a dicho dominio. La reunión theta de dos relaciones específicas, es otra relación
con las mismas tuplas que el producto cartesiano eliminando aquellas que no verifican la
condición. La sintaxis de la operación es: R1 |x| A theta B R2
• División ³. Sea (A1, A2, ..., Am, B1, B2, ..., Bn) la cabecera de una relación R1 y (B1, B2,
..., Bn) la cabecera de otra relación R2, estando los atributos del mismo nombre definidos
en el mismo dominio. Si se consideran los dos atributos compuestos A y B, la división de
R1 (dividendo) entre R2 (divisor), es otra relación con la cabecera (A) y un cuerpo for-
mado por el conjunto de todos los valores de R1 en el atributo A, cuyos valores correspon-
dientes en el atributo B incluyen a todos los valores del atributo B en la relación R2. La
división toma dos relaciones, una binaria y otra unaria, y construye una relación formada
por todos los valores de un atributo de la relación binaria que concuerdan, en el otro atri-
buto, con todos los valores en la relación unaria. La sintaxis de la operación es: R1 ³ R2

Desarrollo de Aplicaciones Web Dinámicas - UNED


MODELO RELACIONAL 13.17

Ejemplo 4. Considerese la siguiente relación ALUMNOS:

ALUMNOS

dni nombre_alum apellido domicilio


0002 juan garcia barcelona

0005 lucia lopez madrid

0007 raquel perez barcelona

0016 laura salas madrid

0001 juan perez barcelona

0003 juan alvarez lugo

Para obtener las tuplas de los alumnos con apellido=perez y domicilio=barcelona, se utiliza:

 apellido=’perez’ and domicilio=’barcelona’ (ALUMNOS)

RESULTADO_1

dni nombre_alum apellido domicilio


0007 raquel perez barcelona

0001 juan perez barcelona

Si a partir de la relación anterior, se quieren obtener sólo los valores de sus atributos dni y
nombre_alum, se utilizará la siguiente expresión:

 dni, nombre_alum (RESULTADO_1)

RESULTADO_2

dni nombre_alum
0007 raquel

0001 juan

Si ahora se considera la siguiente relación ALUM_ASIG:

ALUM_ASIG

dni nombre_asig nota


0007 lengua_1 10

0005 idioma_2 4

0016 lengua_3 8

0002 fisica_1 5

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.18 DISEÑO DE BASES DE DATOS RELACIONALES

La reunión natural RESULTADO_2 * ALUM_ASIG, tendrá como resultado:

RESULTADO_3

dni nombre_asig nota nombre_alum


0007 lengua_1 10 raquel

Para obtener una relación con las cabeceras de RESULTADO_2 y ALUM_ASIG, en la que apa-
rezcan las combinaciones de tuplas de estas dos relaciones, tales que, en una misma tupla, el
valor del atributo dni de RESULTADO_2 sea menor que el valor del atributo dni de la relación
ALUM_ASIG, habrá que evaluar las siguientes expresiones.

En primer lugar, como estas dos relaciones no son compatibles respecto al producto, ya que tie-
nen un atributo con el mismo nombre (dni), habrá que obtener primero una relación, que se deno-
tará por RESULTADO_4, a partir de cualesquiera de las relaciones anteriores, con este atributos
renombrados:

RESLUTADO_4  dni_R2 (dni)

RESULTADO_4

dni_R2 nombre_alum
0007 raquel

0001 juan

Y a continuació, evaluar la expresión:

RESULTADO_2 |x| dni_R2 < dni ALUM_ASIG

RESULTADO_5

dni_R2 nombre_alum dni nombre_asig nota


0007 raquel 0016 lengua_3 8

0001 juan 0007 lengua_1 10

0001 juan 0005 idioma_2 4

0001 juan 0016 lengua_3 8

0001 juan 0002 fisica_1 5

Ejemplo 5. Considerense las relaciones DIVIDENDO y DIVISOR:

Desarrollo de Aplicaciones Web Dinámicas - UNED


MODELO RELACIONAL 13.19

DIVIDENDO

atributo_1 atributo_2
dato_1 dato_5

dato_2 dato_5

dato_3 dato_6

dato_1 dato_6

dato_4 dato_7

DIVISOR

atributo_2
dato_5

dato_6

El resultado de evaluar DIVIDENDO ³ DIVISOR, será:

RESULTADO_6

atributo_1
dato_1

13.4.3 INTEGRIDAD DE DATOS


El modelo relacional también provee mecanismos para mantener la integridad. Estos mecanis-
mos se pueden dividir en dos categorías: 1) Restricciones estáticas, que se refieren a los estados
válidos de datos almacenados. 2) Restricciones dinámicas, que definen las acciones a realizar
para evitar ciertos efectos secundarios no deseados cuando se realizan operaciones de modifica-
ción o borrado de datos.

Restricciones sobre claves primarias


En cuanto a las restricciones estáticas, las más importantes son las que afectan a las claves prima-
rias. Ninguna de las partes que componen una clave primaria puede ser NULL. Que parte de una
clave primaria sea NULL indicaría que, o bien esa parte no es algo absolutamente necesario para
definir la entidad, con lo cual no debería formar parte de la clave primaria, o bien no se sabe a
qué objeto concreto se está refiriendo, lo que implica que se está tratando con un grupo de entida-
des. Esto va en contra de la norma que dice que cada tupla contiene datos sólo de una entidad.

Las modificaciones de claves primarias deben estar muy bien controladas. Dado que una clave
primaria identifica de forma unívoca a una tupla en una relación, parece poco lógico que exista
necesidad de modificarla, ya que eso implicaría que no se está definiendo la misma entidad. Ade-

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.20 DISEÑO DE BASES DE DATOS RELACIONALES

más, hay que tener en cuenta que las claves primarias se usan frecuentemente para establecer
interrelaciones, lo cual implica que sus valores se usan en otras relaciones. Si se modifica un
valor de una clave primaria hay que ser muy cuidadoso con el efecto que esto puede tener en
todas las relaciones en las que se guarden esos valores.

Existen varias maneras de limitar la modificación de claves primarias. Tres de ellas son:
• Que sólo un número limitado de usuarios puedan modificar los valores de claves prima-
rias. Estos usuarios deben ser conscientes de las repercusiones de tales cambios, y deben
actuar de modo que se mantenga la integridad.
• La prohibición absoluta de modificar los valores de claves primarias. Modificarlas sigue
siendo posible, pero mediante un mecanismo indirecto. Primero hay que eliminar las
tuplas cuyas claves se quieren modificar y a continuación darlas de alta con el nuevo valor
de clave primaria.
• La creación de un comando distinto, del que se usa para modificar el resto de los atributos,
para modificar atributos que son claves primarias o partes de ellas.

Cada SGBD puede implementar alguno o varios de estos métodos.

Integridad referencial
La integridad referencial se refiere a las claves foráneas. Una clave foránea es un atributo de una
relación, cuyos valores se corresponden con los de una clave primaria en otra o en la misma rela-
ción. Este mecanismo se usa para establecer interrelaciones.

La integridad referencial consiste en que si un atributo o conjunto de atributos se define como


una clave foránea, sus valores deben existir en la tabla en que ese atributo es clave principal. Las
situaciones donde puede violarse la integridad referencial es en el borrado de tuplas o en la modi-
ficación de claves primarias. Si se elimina una tupla cuya clave primaria se usa como clave forá-
nea en otra relación, las tuplas con esos valores de clave foránea contendrán valores sin
referenciar.

Existen varias formas de asegurarse de que se conserva la integridad referencial:


• Restringir operaciones. Borrar o modificar tuplas cuya clave primaria es clave foránea en
otras tuplas, sólo estará permitido si no existe ninguna tupla con ese valor de clave en nin-
guna otra relación. Es decir, si el valor de una clave primaria en una tupla es clave1, sólo
podremos eliminar esa tupla si el valor clave1 no se usa en ninguna otra tupla, de la misma
relación o de otra, como valor de clave foránea.
• Transmisión en cascada. Borrar o modificar tuplas cuya clave primaria es clave foránea en
otras implica borrar o modificar las tuplas con los mismos valores de clave foránea. Si en
el caso anterior, se modifica el valor de clave primaria clave1 por clave2, todas las apari-
ciones del valor clave1 en donde sea clave foránea deben ser sustituidos por clave2.
• Poner a nulo. Cuando se elimine una tupla cuyo valor de clave primaria aparece en otras
relaciones como clave foránea, se asigna el valor NULL a dichas claves foráneas. Si se eli-

Desarrollo de Aplicaciones Web Dinámicas - UNED


NORMALIZACIÓN 13.21

mina la tupla con el valor de clave primaria clave1, en todas las tuplas donde aparezca ese
valor como clave foránea se sustituirá por NULL.

13.4.4 PROPAGACIÓN DE CLAVES


Se trata de un concepto que se aplica a relaciones N:1 ó 1:1, que ahorra la creación de una rela-
ción. Considerense la siguientes base de datos, en donde cada libro sólo puede estar editado por
una editorial (relación N:1).

LIBRO (clave_libro, título, idioma, categoría)

EDITADO_POR (clave_libro, clave_editorial)

EDITORIAL (clave_editorial, nombre, dirección)

En este caso se puede prescindir de la relación EDITADO_POR añadiendo un atributo a la rela-


ción LIBRO, que sea la clave primaria de la EDITORIAL:

LIBRO (clave_libro, título, idioma, categoría, clave_editorial)

Editorial(clave_editorial, nombre, dirección)

A esto se le denomina propagación de la clave de la entidad EDITORIAL a la entidad LIBRO.

Este mecanismo no es válido para relaciones de N:M.

13.5 NORMALIZACIÓN

Considerese el caso de una base de datos para un centro de enseñanza que contenga información
sobre los alumnos, las asignaturas y las calificaciones que los alumnos obtienen en cada una de
las asignaturas. Donde para cada alumno hay que almacenar su nombre, apellido, DNI y domici-
lio, y para cada asignatura su nombre y curso al que pertenece.

Una posibilidad sería crear una tabla, denominada CENTRO, con todos los datos:

CENTRO (dni, nombre_alum, apellido, domicilio, nombre_asig, curso, nota)

Es fácil darse cuenta que esta base de datos no se encuentra demasiado bien diseñada, debido al
alto grado de redundancia que existe. Observese que para cada nueva asignatura, es necesario
introducir de nuevo todos los datos del alumno. Esta redundancia a su vez puede provocar graves
problemas. Si un alumno cambia de domicilio, sería necesario actualizar al nuevo valor todas las
tuplas en las que aparece. Otro problema que se plantea es que, en el momento en no existan
alumnos matriculados en una asignatura, no existirían datos sobre ella.

La normalización es una herramienta que permite verificar el diseño de una base de datos. Si se
han diseñado bien los modelos conceptual y lógico de la base de datos, la normalización general-
mente no requerirá cambios en dicho diseño. Antes de poder aplicar el proceso de normalización,
se debe garantizar que la base de datos cumple con la definición de base de datos relacional.

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.22 DISEÑO DE BASES DE DATOS RELACIONALES

El proceso de normalización consiste verificar el cumplimiento de ciertas reglas que aseguran la


eliminación de redundancias e inconsistencias. Esto se hace mediante la aplicación de ciertos
procedimientos y en ocasiones se traduce en la separación de los datos en diferentes relaciones.
Las relaciones resultantes deben cumplir ciertas características: 1) Se debe conservar la informa-
ción (conservar atributos y tuplas, evitando la aparición de tuplas que no estaban en las relacio-
nes originales). 2) Se deben conservar las dependencias. Este proceso se lleva a cabo aplicando
una serie de reglas llamadas formas normales. Estas reglas permiten crear bases de datos libres
de redundancias e inconsistencias, que se ajusten a la definición de base de datos relacional.
MySQL usa bases de datos relacionales, de modo que se debe aprender a utilizar, al menos, las
tres primeras formas normales.

13.5.1 DEPENDENCIAS FUNCIONALES


Una relación se compone de atributos y dependencias. Los atributos son fáciles de identificar, ya
que forman parte de la estructura de la relación y son elegidos por el diseñador de la base de
datos. Pero no es tan sencillo localizar las dependencias, ya que requieren un análisis de las rela-
ciones entre atributos, y frecuentemente la intuición no es suficiente a la hora de encontrar y cla-
sificar todas las dependencias. Las dependencias se pueden dar entre atributos o entre
subconjuntos de atributos. Estas dependencias son consecuencia de la estructura de la base de
datos y de los objetos del mundo real que describen, y no de los valores almacenados en cada
relación. Para buscar dependencias, no se deben analizar los datos, sino los entes a los que se
refieren esos datos.

La teoría puede ayudar a resolver este problema, clasificando las dependencias en distintos tipos
e indicando sus características:
• Dependencia funcional. Sean X e Y subconjuntos de atributos de una relación R. Se dice
que Y tiene una dependencia funcional de X, o que X determina a Y, si cada valor de X
tiene asociado siempre un único valor de Y.
• Dependencia funcional completa. En una dependencia funcional, cuando X es un conjunto
de atributos, decimos que la dependencia funcional es completa , si sólo depende de X, y
no de ningún subconjunto de X.
• Dependencia funcional elemental. Un dependencia completa es una dependencia funcio-
nal elemental si Y es un atributo, y no un conjunto de ellos.
• Dependencia funcional trivial. Una dependencia funcional es trivial cuando Y es parte de
X. Esto sucede cuando X es un conjunto de atributos, e Y es a su vez un subconjunto de X.
• Dependencia funcional transitiva. Si se tiene una relación R con tres conjuntos de atribu-
tos: X, Y y Z, y X determina Y e Y determina Z, pero Y no determina X. En ese caso, Z
tiene dependencia transitiva con respecto a X, a través de Y.
• Dependencias multivaluadas. Se presentan cuando existen atributos multibaluados. Un
atributo es multivaluado cuando para una misma entidad puede tomar varios valores dife-
rentes, con independencia de los valores que puedan tomar el resto de los atributos. Siem-
pre se puede evitar el problema de los atributos multivaluados separándolos en relaciones

Desarrollo de Aplicaciones Web Dinámicas - UNED


NORMALIZACIÓN 13.23

distintas. En una relación R con los atributos X, Y y Z existe una dependencia multivalu-
dada de Y con respecto a X si los posibles valores de Y para un par de valores de X y Z
dependen únicamente del valor de X.
• Dependencias de reunión. Es una restricción sobre una relación en cuestión. Se dice que la
relación R satisface la dependencia de reunión (X,Y,...,Z) si y sólo si R es igual a la
reunión de sus proyecciones según X,Y,...,Z donde X,Y,...,Z son subconjuntos del conjunto
de atributos de R. Las dependencias de reunión vienen dadas por restricciones que el dise-
ñador impone sobre la tabla.

13.5.2 FORMAS NORMALES


• Primera forma normal (1FN). Una relación R se encuentra en primera forma normal
(1FN) si y sólo si todos los dominios simples subyacentes contienen sólo valores atómicos
(cada columna debe ser atómica). Es decir, el cruce de una fila con una columna sólo con-
tiene un dato. Atómica significa que cada atributo debe contener un único valor del domi-
nio. Los atributos, en cada tabla de una base de datos 1FN, no pueden tener listas o arrays
de valores, ya sean del mismo dominio o de dominios diferentes. Además, cada atributo
debe tener un nombre único. En MySQL la creación de las tablas implica definir cada
columna de un tipo concreto y con un nombre único. Tampoco pueden existir tuplas idén-
ticas. Las restricciones de la primera forma normal coinciden con las condiciones de las
relaciones de una base de datos relacional, por lo tanto, siempre es obligatorio aplicar esta
forma normal. Aplicar la primera forma normal es simple, bastará con dividir cada
columna no atómica en tantas columnas atómicas como sea necesario.
• Segunda forma normal (2FN). Una relación R se encuentra en segunda forma normal
(2FN) si y sólo si está en 1FN y todos los atributos no clave dependen funcionalmente de
manera completa de la clave primaria. Esta regla significa que en una relación sólo se debe
almacenar información sobre un tipo de entidad, y se traduce en que los atributos que no
aporten información directa sobre la clave principal deben almacenarse en una relación
separada. Si una relación R(A,B,C,D) no se encuentra en 2FN, su clave primaria es (A,B)
y D depende funcionalmente de A, entonces la relación R puede descomponerse en dos
relaciones R1(A,D) y R2(A,B,C), estando por lo menos una de ellas en 2FN. Lo primero
que se necesita para aplicar esta forma normal es identificar las claves candidatas. Ade-
más, se puede elegir una clave primaria, pero esto es optativo, ya que el modelo relacional
no obliga a elegir una clave primaria para cada relación, sino tan sólo a la existencia de al
menos una clave candidata. La inexistencia de claves candidatas implica que la relación no
cumple todas las normas para ser parte de una base de datos relacional, ya que la no exis-
tencia de claves implica la repetición de tuplas. En general, si no existe un candidato claro
para la clave principal, se creará una columna específica con ese propósito. Como norma
general se debe volver a aplicar la primera y segunda forma normal a las nuevas tablas. La
primera sólo en el caso de que de se hallan añadido nuevas columnas, la segunda siempre.

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.24 DISEÑO DE BASES DE DATOS RELACIONALES

• Tercera forma normal (3FN). Una relación R se encuentra en tercera forma normal (3FN)
si y sólo si está en 2FN y todos los atributos no clave dependen de manera no transitiva de
la clave primaria. La tercera forma normal consiste en eliminar las dependencias transiti-
vas. Es decir, se debe eliminar cualquier relación que permita llegar a un mismo dato de
dos o más formas diferentes. Si una relación R(A,B,C) con clave primaria (A), donde C
depende funcionalmente de B, no se encuentra en 3FN, entonces la relación R puede des-
componerse en dos relaciones R1(A,B) y R2(B,C), donde al menos una de ellas se encuen-
tre en 3FN.
• Forma normal de Boycce Codd (FNBC). Se define un determinante como un atributo del
cual depende funcionalmente de manera completa de algún otro atributo. Una relación está
en FNBC si y sólo si todo determinante es una clave candidata. Otra definición equivalente
es: una relación está en FNBC si cualquier atributo sólo facilita información sobre claves
candidatas, y no sobre atributos que no formen parte de ninguna clave candidata. Esto sig-
nifica que no deben existir interrelaciones entre atributos fuera de las claves candidatas. En
realidad son muy pocos los casos de relaciones que se encuentran en 3FN y no están en
FNBC. Este tipo de tablas son aquellas en las que se dan las siguientes circunstancias: 1)
Existan varias claves candidatas. 2) Las claves candidatas son compuestas. 3) Las claves
candidatas se solapan (tienen por lo menos un atributo común). En estos casos, si en una
relación R(A,B,C,D) con claves candidatas (A,B) y (B,C) y tal que A y C dependen fun-
cionalmente una de otra, entonces la relación R se puede descomponer de cualquiera de las
dos siguientes maneras R1(A,C) y R2(B,C,D) o R1(A,C) y R2(A,B,D).
• Cuarta forma normal (4FN). Una relación R se encuentra en cuarta forma normal 4FN si y
sólo si está en FNBC y no existen dependencias multivaluadas. La cuarta forma normal
tiene por objetivo eliminar este tipo de dependencias. En caso de tener una relación R en
FNBC y con dependencias multivaluadas, se puede descomponer sin pérdidas la relación
R, deshaciendo además las dependencias multivaluadas. Sea una relación R(A,B,C) con
las siguientes dependencias multivaluadas B depende funcionalmene de A y C depende
funcionalmene de A. Entonces la relación R puede descomponerse como R1(A,B) y
R2(A,C).
• Quinta forma normal (5FN). Una relación R se encuentra en quinta forma normal 5FN si y
sólo si toda dependencia de reunión en R es una consecuencia de las claves candidatas.
Esto viene a decir que una relación estará en 5FN cuando esté en 4FN y siempre que no
existan restricciones impuestas por el creador. Cuando una tabla se encuentra en 4FN y no
en 5FN la solución es N-descomponerla para deshacer las dependencias de reunión. Este
tipo de dependencias raramente se encuentran en las bases de datos.

Desarrollo de Aplicaciones Web Dinámicas - UNED


NORMALIZACIÓN 13.25

Ejemplo 1. Normalizar la siguiente relación hasta la 5FN.

dni nombre calle ciudad


0001 luis goya madrid

0012 lucia real leon

0022 antonio nueva sevilla

0003 maria alta caceres

Lo primero que hay que hacer siempre que se va a normalizar una relación es trazar un diagrama
de dependencias funcionales de la misma. Para ello lo mejor es localizar las claves de la relación
e ir viendo que, atributos dependen de ellas. Después se intentará ver si existe alguna dependen-
cia entre las claves y por último entre el resto de los atributos. En este caso, el diagrama es extre-
madamente sencillo, tal y como aparece a continuación (las flechas indican dependencia
funcional completa).

dni

calle nombre ciudad

La única clave existente es el dni que por el hecho de serlo, proporciona dependencia funcional
completa al resto de los atributos. Además entre ellos no existe ningún tipo de dependencia
debido a que pueden existir las mismas calles en ciudades distintas y a que los nombres pueden
aparecer repetidos aunque cada uno lleve un dni distinto. Con todo esto se pueden hacer las
siguientes afirmaciones:
• La relación se encuentra en 1FN debido a que los dominios son atómicos, es decir sólo se
tiene un dato en cada casilla.
• La relación se encuentra en 2FN debido a que todas las dependencias funcionales son
completas.
• La relación se encuentra en 3FN debido a que no existen dependencias funcionales transi-
tivas.
• La relación se encuentra en FNBC ya que está en 3FN y no se dan las tres características
en cuanto a solapamiento de claves.
• La relación se encuentra en 4FN debido a que no existe ninguna dependencia multiva-
luada.
• Por último afirmar que también se encuentra en 5FN porque no existe ninguna dependen-
cia de reunión.

Por tanto, la relación original se encuentra en la mejor situación posible.

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.26 DISEÑO DE BASES DE DATOS RELACIONALES

Ejemplo 2. Normalizar la siguiente relación hasta la 5FN. En dicha relación, se almacena infor-
mación sobre los artículos que un dependiente vende (codigo y cantidad) e información sobre el
propio dependiente (dni, calle y ciudad).

dni calle ciudad codigo cantidad


0004 goya madrid 1 10

0004 goya madrid 2 3

0023 alta barcelona 1 4

0456 nueva sevilla 3 7

En primer lugar se trazará un diagrama de dependencias funcionales de la relación, para lo cual


es útil localizar primero la clave primaria y establecer a partir de ella las dependencias existentes.

Es fácil darse cuenta que el único conjunto de atributos mediante el cual se puede distinguir una
tupla de otra es el atributo compuesto (dni, codigo) y por tanto no existe ninguna otra clave can-
didata. El diagrama queda entonces como sigue:

dni ciudad
cantidad
codigo
calle

Sin embargo, es sencillo ver que las dependencias de este diagrama no son completas, ya que los
atributos calle y ciudad dependen también del atributo dni por sí solo.

dni ciudad
cantidad
codigo
calle

• La relación se encuentra en 1FN debido a que los dominios son atómicos, es decir sólo se
tiene un dato en cada casilla.
• La relación no se encuentra en 2FN debido a que existen dependencias funcionales que no
son completas. Para solucionar esto se asociarán los atributos A, B, C y D como:
A = (dni), B = (codigo), C = (cantidad), D = (calle, ciudad)
y la relación se descompone en:

 R1(A, D)
R
 R2(A, B, C)
R1 (dni, calle, ciudad)
R2 (dni, codigo, cantidad)

Desarrollo de Aplicaciones Web Dinámicas - UNED


NORMALIZACIÓN 13.27

Ahora habrá estudiar los diagramas de dependencias funcionales de cada relación, y dedu-
cir si R1 y R2 se encuentran en 2FN.

R1 R2

dni
dni
cantidad
codigo
calle ciudad

Como puede verse, las dos relaciones ya se encuentran en 2FN debido a que todas las
dependencias funcionales son completas.
• Las relaciones se encuentran en 3FN debido a que no existen dependencias funcionales
transitivas.
• Las relaciones se encuentran en FNBC ya que está en 3FN y no se dan las tres característi-
cas en cuanto a solapamiento de claves.
• Las relaciones se encuentran en 4FN debido a que no existe ninguna dependencia multiva-
luada.
• Por último afirmar que también se encuentran en 5FN porque no existe ninguna dependen-
cia de reunión.

El resultado entonces de haber normalizado la relación R ha sido la división de esta en otras dos
relaciones llamadas R1 y R2.

Desarrollo de Aplicaciones Web Dinámicas - UNED


13.28 DISEÑO DE BASES DE DATOS RELACIONALES

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 14

Instalación y primeros pasos


con MySQL

14.1 INSTRODUCCIÓN

El objetivo principal de este capítulo, es comentar el proceso a seguir para obtener alguna de las
versiones de MySQL, y dar una serie de nociones mínimas sobre su instalación. También se indi-
can algunas de las ventajas que presenta este sistema de gestión de bases de datos. Otro de los
objetivos del capítulo, es tomar contacto por primera vez con MySQL, desde la consola del orde-
nador, en modo de línea de comandos. En particular, se indica cómo entrar y salir en la ventana
de comandos y cómo utilizar su ayuda. A continuación se pasa a tratar un tema de gran importan-
cia: la asignación de usuarios y privilegios. Cuando se trabaja con bases de datos reales y con
aplicaciones de gestión de bases de datos, es muy importante definir usuarios con distintos privi-
legios, ya que esto ayudará a proteger las bases de datos. Para terminar, se tratan los husos hora-
rios y se presenta un listado de las palabras reservadas en MySQL.

14.2 INSTALACIÓN Y CONFIGURACIÓN

MySQL es un SGBD de libre distribución y de código abierto. Lo que significa que se puede
descargar libremente de Internet (libre distribución) y que cualquier programador puede modifi-
car su código para mejorarlo (código abierto).

Existen cuatro versiones de MySQL: 1) Estándar, incluye el motor estándar y la posibilidad de


usar bases de datos InnoDB. 2) Max, contiene opciones avanzadas. 3) Pro, versión comercial de
la versión estándar. 3) Classic, igual que la estándar pero no dispone de soporte para InnoDB.

El uso de MySQL, excepto en la versión Pro, está sujeto a licencia GNU public license (GPL).
Está licencia permite: 1) El uso de MySQL para crear cualquier tipo de aplicación. 2) Distribuir
copias de los archivos de MySQL, pero no venderlas a otros usuarios. 3) Modificar el código
14.2 INSTALACIÓN Y PRIMEROS PASOS CON MYSQL

fuente de MySQL, pero no distribuir la aplicación con el código modificado. La licencia comer-
cial permite otros usos no reflejados en la licencia GNU.

El primer paso, antes de instalar MySQL, es obtener alguna de sus versiones. Para ello se puede
acceder a la página principal de MySQL: http://www.mysql.com/.

Figura 14.1 Página principal de MySQL

Si, por ejemplo, se quiere descargar la versión 5, se pulsará sobre Download MySQL 5.0, con lo
que se accede a la siguiente ventana:

Figura 14.2 Ventana de descarga

Bajando por esta ventana, se puede acceder a la versión del sistema operativo deseada (Linux,
Windows, etc).

Figura 14.3 Selección de versión en la ventana de descarga

Desarrollo de Aplicaciones Web Dinámicas - UNED


INSTALACIÓN Y CONFIGURACIÓN 14.3

Una vez descargado el fichero, el siguiente paso es descomprimir su contenido en una carpeta y
ejecutar setup.exe, con lo que se entra en la ventana de instalación.

Figura 14.4 Ventana de instalación

Se trata de una ventana de bienvenida. Para seguir el proceso de instalación simplemente hay que
hacer clic en el botón next. Terminar de instalar el servidor depende en gran medida de cada caso,
y es mejor remitirse a la documentación facilitada por MySQL junto a cada paquete. Instalar la
versión para Windows es relativamente sencillo. El programa se instalará en una carpeta MySQL
y los ejecutables en una carpeta bin que estará dentro de la anterior.

Durante la instalación de MySQL se pedirá elegir una clave de acceso, esa clave es la que hay
que introducir para iniciar una sesión con MySQL.

El entorno se puede configurar a mano a través del archivo mysql.ini o utilizando el programa de
configuración incluido en la versión. Tras la instalación hace falta instalar el servidor MySQL de
bases de datos. Existen varias servidores posibles (en la carpeta bin): 1) mysqld, compilado con
depuración completa y chequeo automático de colocación de memoria, enlaces simbólicos,
InnoDB y tablas BDB (es el más genérico para cualquier tipo de ordenador). 2) mysqld-opt, opti-
mizado para equipos Pentium (no tiene soporte de tablas transaccionales). 3) mysqld-nt. optimi-
zado para equipos con Windows NT, 2000 y XP con soporte para pipe names. 4) mysql-max,
optimizado con soporte de enlaces simbólicos, InnoDB y tablas BDB. 5) mysql-max-nt, igual que
el anterior pero combinado las capacidades del servidor mysql-nt. Una vez instalado, se estará en
disposición de poder utilizar MySQL desde la consola del ordenador, en modo de línea de
comandos.

Para más información sobre la instalación y configuración de MySQL se puede aceder a la


siguente dirección:
http://dev.mysql.com/doc/refman/5.0/en/gpl-license.html

Desarrollo de Aplicaciones Web Dinámicas - UNED


14.4 INSTALACIÓN Y PRIMEROS PASOS CON MYSQL

Para acceder a las bases de datos, es útil usar un motor o servidor que hace las funciones de intér-
prete entre éstas y las aplicaciones y usuarios. En esta utilidad se pueden destacar las siguientes
ventajas:
• Acceso a las bases de datos, de forma simultánea, por varios usuarios y aplicaciones.
• Seguridad, en forma de permisos y privilegios. Determinados usuarios tendrán permiso
para consultar o modificar ciertas tablas. Esto permite compartir datos sin que peligre la
integridad de la base de datos y protegiendo su contenido.
• Potencia. SQL es un lenguaje muy potente para consulta de bases de datos, usar un motor
ahorrará gran cantidad de trabajo.
• Portabilidad. SQL es también un lenguaje estandarizado, de modo que las consultas
hechas usando SQL son fácilmente portables a otros sistemas y plataformas.

En concreto, usar MySQL tiene las ventajas adicionales siguientes:


• Escalabilidad. Es posible manipular grandes bases de datos, del orden de seis mil tablas y
alrededor de cincuenta millones de registros, y hasta 32 índices por tabla.
• MySQL está escrito en C y C++ y probado con multitud de compiladores y dispone de
APIs para muchas plataformas diferentes.
• Conectividad. Permite conexiones entre diferentes máquinas con distintos sistemas opera-
tivos. Es corriente que servidores Linux o Unix, usando MySQL, sirvan datos para ordena-
dores con Windows, Linux, Solaris, etc.
• Es multihilo, con lo que puede beneficiarse de sistemas multiprocesador.
• Permite manejar multitud de tipos para columnas.
• Permite manejar registros de longitud fija o variable.

14.3 ENTRAR Y SALIR DE LA VENTANA DE COMANDOS

En esta sección se comenzará a trabajar con el sistema de gestión de bases de datos MySQL.
Existen muchas formas de establecer una comunicación con el servidor de MySQL. Por lo gene-
ral se utilizará un API para realizar las consultas con el servidor. En PHP, por ejemplo, este API
está integrado con el lenguaje, y en C/C++ se trata de librerías de enlace dinámico.

En lo que sigue, se utilizará MySQL de forma directa, mediante un cliente ejecutándose en una
consola (una ventana DOS en Windows, o un Shell en otros sistemas).

Cómo entrar en MySQL


En primer lugar hay que abrir una consola y teclear mysql. Si se trabaja en Windows y no está
definido el camino para MySQL de tendrá que especificar dicho camino
C:\...\mysql\bin\

Para entrar en la consola de MySQL se requieren ciertos parámetros. Hay que tener en cuenta
que el servidor es multiusuario, y que cada usuario puede tener distintos privilegios, tanto de

Desarrollo de Aplicaciones Web Dinámicas - UNED


MANUAL DE REFERENCIA Y AYUDA 14.5

acceso a tablas como de comandos que puede utilizar. La forma general de iniciar una sesión
MySQL es:
mysql -h host -u usuario -p

Se puede especificar el ordenador donde está el servidor de bases de datos (host) y el nombre de
usuario. Los parámetros -h y -u indican que los valores que los siguen son, respectivamente, el
nombre del host y el nombre de usuario. El parámetro -p indica que se debe solicitar una clave de
acceso. En versiones de MySQL anteriores a la 4.1.9 es posible abrir un cliente de forma anó-
nima sin especificar una contraseña, pero las últimas versiones de MySQL no lo permiten.
Durante la instalación de MySQL se pide elegir una clave de acceso para el usuario root (admi-
nistrador), esa clave es la que hay que introducir para iniciar una sesión con el cliente MySQL.
Enter password: *******

Como se ha indicado el programa mysql, permite distintas opciones de arranque. Para conocer-
las, basta con ejecutar desde la línea de comandos:
mysql --help

En la mayoría de instalaciones (sobre todo en Windows) se puede entrar ejecutando sólo:


mysql

En cualquier caso, si se ha accedido bien al monitor, en la línea de comandos aparecerá el


siguiente texto, que indica que el monitor está esperando comandos para ejecutar sobre el servi-
dor:
mysql>

Figura 14.5 Entrar y salir de MySQL

Cómo salir de MySQL


Para salir de una sesión de MySQL se usa el comando QUIT.
mysql> quit

14.4 MANUAL DE REFERENCIA Y AYUDA

Cuando se instala MySQL, se instala también el manual de referencia. Como el objetivo de este
curso no es comentar todos los detalles de MySQL, se debe recurrir a este manual cuando sea
preciso.

También es posible acceder al manual de referencia en la direcció:


http://dev.mysql.com/doc/refman/5.0/en/

Desarrollo de Aplicaciones Web Dinámicas - UNED


14.6 INSTALACIÓN Y PRIMEROS PASOS CON MYSQL

Figura 14.6 Manual de referencia

Otra forma de obtener información sobre los distintos comandos de MySQL es utilizar la ayuda
de la ventana de comandos. Si, una vez dentro de MySQL se teclea help, aparecerán una serie de
direcciones con información sobre MySQL y la lista de comandos. Si se teclea help contents, se
listarán las distintas categorías de comandos. Si se introduce help ‘categoría’, se listan las sen-
tencias correspondientes, y si se teclea help ‘sentencia’, se presenta su sintaxis.
mysql> help

mysql> help contents

Desarrollo de Aplicaciones Web Dinámicas - UNED


MANUAL DE REFERENCIA Y AYUDA 14.7

mysql> help data manipulation

mysql> help select

MySQL utiliza el lenguaje de bases de datos SQL, y sus sentencias serán las que normalmente se
utilizan en el monitor. Sobre los comandos hay que tener en cuenta que: 1) Da lo mismo escribir-
los en mayúsculas o en minúsculas. 2) Para su ejecución, deben terminar con el símbolo “;". 3)
La ejecución ha terminado si en la línea de comandos aparece mysql>. 4) En la misma línea se
pueden colocar dos comandos siempre y cuando los puntos y comas se coloquen de forma ade-
cuada. 5) Una instrucción puede abarcar más de una línea (para informar que no ha terminado la
instrucción, el monitor coloca el símbolo "->", en lugar de mysql>). 6) Una instrucción se puede
anular antes del punto y coma, colocando el texto "\c". 8) Las cadenas de texto literal pueden ir

Desarrollo de Aplicaciones Web Dinámicas - UNED


14.8 INSTALACIÓN Y PRIMEROS PASOS CON MYSQL

entre comillas simples o comillas dobles (si se pulsa Intro antes de cerrar la cadena, el monitor lo
índica mostrando '> o "> en lugar de “->” o mysql>.

Una de las sentencias más importantes de SQL es SELECT, que se sirve para realizar consultas.
Esta sentencia, además de permitir seleccionar datos de la bases de datos, se puede utilizar para
conocer variables del sistema, realizar operaciones o conocer el resultados de evaluar funciones,
entre otros.

Así, para conocer la versión que se está utilizando de MySQL y la fecha actual, se usan los pará-
metros VERSIÓN y CURRENTE DATE, respectivamente.
mysql> select version(), current_date;

Otros ejemplos de utilización de SELECT son:


mysql> select (4*5)/9;

mysql> select sin(9);

14.5 USUARIOS Y PRIVILEGIOS

Cuando se trabaja con bases de datos reales y con aplicaciones de gestión de bases de datos, un
aspecto importante es definir usuarios con distintos privilegios (además del root, que es el admi-
nistrador), lo que ayudará a proteger las bases de datos. Así, se podrán crear usuarios que sólo
tengan posibilidad de consultar datos, de determinadas tablas o bases de datos, pero que no ten-
gan permiso para añadirlos o modificarlos, ni permiso para modificar la estructura de la base de
datos. Otros usuarios podrán insertar datos, y sólo algunos (o mejor, sólo uno) podrán modificar
la estructura de las bases de datos (los administradores).

Los conceptos de usuarios y privilegios están íntimamente relacionados, ya que la necesidad de


crear usuarios está ligada a la necesidad de limitar las acciones que éstos pueden realizar.

Desarrollo de Aplicaciones Web Dinámicas - UNED


USUARIOS Y PRIVILEGIOS 14.9

MySQL permite definir diferentes usuarios, y asignarles, a cada uno de ellos, distintos privile-
gios clasificados en los siguientes niveles:
• Globales. Se aplican al conjunto de todas las bases de datos.
• De base de datos. Se aplican a bases de datos individuales.
• De tabla. Se aplican a tablas individuales.
• De columna. Se aplican a una columna concreta.
• De rutina. Se aplican a los procedimientos almacenados.

14.5.1 CREAR USUARIOS Y ASIGNAR PRIVILEGIOS


En la versión 5.0.2 de MySQL se pueden crear usuarios mediante la sentencia CREATE USER,
mientras que en las versiones anteriores se usa exclusivamente la sentencia GRANT.

En general, es preferible usar GRANT, ya que esta sentencia permite crear usuarios y conceder
privilegios (CREATE USER, sólo permite crear usuarios y los privilegios se asignan con
GRANT).

La sintaxis de GRANT es:


GRANT priv_type [(column_list)]

ON {tbl_name | * | *.* | db_name.*}

TO user [IDENTIFIED BY [PASSWORD] 'password']

Donde:
• priv_type [(column_list)], permite definir el tipo de privilegio concedido para determina-
das columnas.
• ON {tbl_name | * | *.* | db_name.*}, permite conceder privilegios en niveles globales, de
base de datos o de tablas.
• TO user [IDENTIFIED BY [PASSWORD] 'password'], permite identificar usuarios.

A continuación se indica cómo crear distintos tipos de usuarios:

Usuario sin privilegios


Se crea con la siguiente sentencia, donde user es el nombre asignado al usuario y password la
contraseña, que se debe introducir entre comillas. Este tipo de usuario podrá abrir una sesión
MySQL mediante una orden C:\mysql -h localhost -u user -p, pero no podrá hacer mucho más,
ya que no tiene privilegios.
GRANT USAGE ON *.* TO user IDENTIFIED BY 'password';

Usuario con privilegio para seleccionar datos de una tabla concreta


Se crea con la siguente sentencia, donde db_name es el nombre de la base de datos y tbl_name es
el nombre de la tabla. Este tipo de usuarios podrá ver y consultar el contenido de la base de datos,
pero no podrá añadir ni modificar datos, ni crear o eliminar tablas ni bases de datos.
GRANT SELECT ON db_name.tbl_name TO user;

Desarrollo de Aplicaciones Web Dinámicas - UNED


14.10 INSTALACIÓN Y PRIMEROS PASOS CON MYSQL

Usuarios con privilegios globales


Utilizando ON *.*, se indica que los privilegios se conceden en todas las tablas de todas las bases
de datos.
GRANT SELECT ON *.* TO user;

Usuario con privilegios en bases de datos


Utilizando ON db_name.*, se indica que los privilegios se conceden sobre todas las tablas de la
base de datos db_name.
GRANT SELECT ON db_name.* TO user;

Usuario con privilegios a nivel de tabla


Utilizando ON db_name.tbl_name, se indica la tabla sobre la que se conceden privilegios.
GRANT SELECT ON db_name.tbl_name TO user;

Usuarios con privilegios de columna


Utilizando priv_type (column_list), [priv_type (column_list)], se indican los privilegios sobre las
distintas columnas.

Otros privilegios que se pueden conceder son:


• ALL. Para conceder todos los privilegios.
• CREATE. Permite crear nuevas tablas.
• DELETE. Permite usar la sentencia DELETE.
• DROP. Permite borrar tablas.
• INSERT. Permite insertar datos en tablas.
• UPDATE. Permite usar la sentencia UPDATE.

Se pueden conceder varios privilegios en una única sentencia:


GRANT SELECT, UPDATE

ON db_name.tbl_name

TO user IDENTIFIED BY 'password';

Para crear usuarios se debe tener el privilegio GRANT OPTION y sólo se pueden conceder los
privilegios que se posean.

El nombre de usuario user consta de dos partes, separadas por el carácter @: nombre@máquina.
La primera es el nombre asignado al usuario y la segunda es el nombre de la máquina (localhost
para referirse al ordenador local), o cualquier otro nombre o bien una IP. La parte de la máquina
es opcional, y si no se pone, el usuario podrá conectarse desde cualquier máquina. Si se crea un
usuario para una máquina o conjunto de máquinas determinado, ese usuario no podrá conectar
desde otras máquinas.
GRANT USAGE ON * TO name@localhost IDENTIFIED BY password;

Desarrollo de Aplicaciones Web Dinámicas - UNED


HUSOS HORARIOS 14.11

En este caso, el usuario name sólo podrá entrar desde el mismo ordenador donde se está ejecu-
tando el servidor.
GRANT USAGE ON * TO name@11.24.36.14 IDENTIFIED BY password;

En este otro caso, el usuario name sólo puede conectarse desde un ordenador cuyo IP sea
11.24.36.14.

Aunque asignar una contraseña es opcional, por motivos de seguridad es recomendable hacerlo
siempre. La contraseña se puede escribir entre comillas simples cuando se crea un usuario, o se
puede usar la salida de la función PASSWORD() de forma literal, para evitar enviar la clave en
texto legible. Si al añadir privilegios se usa una clave diferente en la cláusula IDENTIFIED BY,
sencillamente se sustituye la contraseña por la nueva.

Si se quieren conocer los privilegios de un usuario se utiliza la sentencia SHOW GRANTS. La


salida de esta sentencia es una lista de sentencias GRANT con los privilegios del usuario.
SHOW GRANTS FOR user;

Si al crear el usuario no se incluye el nombre de la máquina, la salida de de la sentencia SHOW


GRANTS, lo indica usando el comodín % para el nombre de la máquina.

14.5.2 QUITAR PRIVILEGIOS Y ELIMINAR USUARIOS


Los privilegios asignados a un usuario se pueden revocar mediante la sentencia REVOKE:
REVOKE priv_type [(column_list)]

ON {tbl_name | * | *.* | db_name.*}

FROM user

Así, para revocar el privilegio SELECT a un usuario, se utiliza la sentencia:


REVOKE SELECT ON db_name.tbl_name FROM user;

Para eliminar usuarios se usa la sentencia DROP USER.

No se puede eliminar un usuario que tenga privilegios. Para eliminar el usuario primero hay que
revocar todos sus privilegios. Así, para eliminar un usuario que tiene el privilegio SELECT sobre
una determinada tabla, habrá que ejecutar las siguientes sentencias:
REVOKE SELECT ON db_name.tbl_name FROM user;

DROP USER user;

14.6 HUSOS HORARIOS

Cuando el servidor arranca, determina el huso horario del ordenador cliente y lo asigna a la
variable de sistema system_time_zone. Esta variable, indica el huso horario del servidor actual en
el que se está operando. Su valor inicial es SYSTEM, que indica que el huso horario del servidor
es el mismo que el del sistema. El valor inicial puede ser especificado explícitamente con la

Desarrollo de Aplicaciones Web Dinámicas - UNED


14.12 INSTALACIÓN Y PRIMEROS PASOS CON MYSQL

opción default_time_zone=timezone. Si se posee el privilegio SUPER, se puede asignar el valor


global durante la ejecución, con la sentencia:
SET GLOBAL time_zone = timezone

Cada cliente que se conecta tiene su propio huso horario asignado, dado por la variable de sesión
time_zone, pero se puede modificar con la sentencia:
SET time_zone = timezone

Los valores actuales de los husos horarios global y por conexión pueden ser recuperados
mediante la sentencia:
SELECT @@global.time_zone, @@session.time_zone

Durante la instalación de MySQL se crean las tablas de husos horarios en la base de datos mysql,
pero no las carga. Esto se debe hacer de forma manual.

Si el sistema tiene su propia base de datos de información horaria, se debe usar el programa
mysql_tzinfo_to_sql para llenar las tablas de husos horarios. En la línea de comandos, hay que
pasar el nombre de la ruta del directorio con la información de husos horarios a
mysql_tzinfo_to_sql y enviar la salida al programa mysql. Ejemplo:
shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

mysql_tzinfo_to_sql lee los ficheros de husos horarios del sistema y genera sentencias SQL a par-
tir de ellos. MySQL procesa esas sentencias para cargar las tablas de husos horarios.

Para cargar un fichero tz_file, que corresponda a un huso horario llamado tz_name, se utiliza la
sentencia:
shell> mysql_tzinfo_to_sql tz_file tz_name | mysql -u root mysql

Si el huso horario precisa tener en cuenta intervalos de segundos, hay que inicializar la informa-
ción de intervalo de segundos (donde tz_file es el nombre del fichero):
shell> mysql_tzinfo_to_sql --leap tz_file | mysql -u root mysql

Si el sistema no tiene base de datos de husos horarios, como ocurre en Windows, se puede usar el
paquete de tablas de husos horarios prediseñadas que está disponible para su descarga en http://
dev.mysql.com/downloads/timezones.html. Este paquete contiene los ficheros .frm, .MYD y .MYI
para las tablas de husos horarios MyISAM. Estas tablas deben pertenecer a la base de datos mysql,
de modo que deben colocarse esos ficheros en el subdirectirio mysql del directorio de datos del
servidor MySQL. El servidor debe ser detenido mientras se hace esta operación. Este paquete no
se debe utilizar si el sistema tiene una base de datos de husos horarios (usar la utilidad
mysql_tzinfo_to_sql en su lugar), ya que se puede provocar una diferencia en la manipulación de
tiempos entre MySQL y otras aplicaciones del sistema.

Desarrollo de Aplicaciones Web Dinámicas - UNED


PALABRAS RESERVADAS 14.13

14.7 PALABRAS RESERVADAS

Cuando se dan nombres a las bases de datos, tablas, índices, columnas y alias, hay que tener cui-
dado de que dichos nombres no sean palabras reservadas de MySQL, ya que en tal caso, se deben
entrecomillar. A continuación se indican las palabras reservadas en MySQL:
A
ADD, ALL, ALTER, ANALYZE, AND, AS, ASC, ASENSITIVE.
B
BEFORE, BETWEEN, BIGINT, BINARY, BLOB, BOTH, BY.
C
CALL, CASCADE, CASE, CHANGE, CHAR, CHARACTER, CHECK, COLLATE, COLUMN,
CONDITION, CONNECTION, CONSTRAINT, CONTINUE, CONVERT, CREATE, CROSS,
CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR.
D
DATABASE, DATABASES, DAY_HOUR, DAY_MICROSECOND, DAY_MINUTE,
DAY_SECOND, DEC, DECIMAL, DECLARE, DEFAULT, DELAYED, DELETE,
DESC, DESCRIBE, DETERMINISTIC, DISTINCT, DISTINCTROW, DIV, DOUBLE, DROP, DU-
AL.
E
EACH, ELSE, ELSEIF, ENCLOSED, ESCAPED, EXISTS, EXIT, EXPLAIN.
F
FALSE, FETCH, FLOAT, FOR, FORCE, FOREIGN, FROM, FULLTEXT.
G
GOTO, GRANT, GROUP.
H
HAVING, HIGH_PRIORITY, HOUR_MICROSECOND, HOUR_MINUTE, HOUR_SECOND.
I
IF, IGNORE, IN, INDEX, INFILE, INNER, INOUT, INSENSITIVE, INSERT, INT, INTEGER, IN-
TERVAL, INTO, IS, ITERATE.
J
JOIN.
K
KEY, KEYS, KILL.
L
LEADING, LEAVE, LEFT, LIKE, LIMIT, LINES, LOAD, LOCALTIME, LOCALTIMESTAMP,
LOCK, LONG, LONGBLOB, LONGTEXT, LOOP, LOW_PRIORITY.
M
MATCH, MEDIUMBLOB, MEDIUMINT, MEDIUMTEXT, MIDDLEINT,
MINUTE_MICROSECOND, MINUTE_SECOND, MOD, MODIFIES.
N
NATURAL, NOT, NO_WRITE_TO_BINLOG, NULL, NUMERIC.
O
ON, OPTIMIZE, OPTION, OPTIONALLY, OR, ORDER, OUT, OUTER, OUTFILE.
P
PRECISION, PRIMARY, PROCEDURE, PURGE.
R
READ, READS, REAL, REFERENCES, REGEXP, RENAME, REPEAT, REPLACE, REQUIRE,
RESTRICT, RETURN, REVOKE, RIGHT, RLIKE.
S
SCHEMA, SCHEMAS, SECOND_MICROSECOND, SELECT, SENSITIVE, SEPARATOR, SET,
SHOW, SMALLINT, SONAME, SPATIA, SPECIFIC, SQL, SQLEXCEPTION, SQLSTATE, SQL-
WARNING, SQL_BIG_RESULT, SQL_CALC_FOUND_ROWS, SQL_SMALL_RESULT, SSL,
STARTING, STRAIGHT_JOIN
T

Desarrollo de Aplicaciones Web Dinámicas - UNED


14.14 INSTALACIÓN Y PRIMEROS PASOS CON MYSQL

TABLE, TERMINATED, THEN, TINYBLOB, TINYINT, TINYTEXT, TO, TRAILING, TRIGGER,


TRUE.
U
UNDO, UNION, UNIQUE, UNLOCK, UNSIGNED, UPDATE, USAGE, USE, USING, UTC_DATE,
UTC_TIME, UTC_TIMESTAMP.
V
VALUES, VARBINARY, VARCHAR, VARCHARACTER, VARYING.
W
WHEN, WHERE, WHILE, WITH, WRITE, XOR.
Y
YEAR_MONTH.
Z
ZEROFILL.
Existen otras palabras reservadas que pueden ser usadas como nombres sin necesidad de entreco-
millar: ACTION, BIT, DATE, ENUM, NO, TEXT, TIME, TIMESTAMP.

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 15

Creación de bases de datos y


tablas e inserción de datos

15.1 INTRODUCCIÓN

En este tema se trata el proceso para pasar del modelo lógico relacional al modelo físico usando
sentencias SQL y viendo las peculiaridades específicas de MySQL. Una base de datos está for-
mada por el conjunto de relaciones que componen un modelo lógico completo. Desde el punto de
vista de SQL, una base de datos es sólo un conjunto de relaciones o tablas que se distinguen, unas
de otras, por el nombre asociado a cada una de ellas. A nivel de sistema operativo, cada base de
datos se guarda en un directorio diferente.

Cuando se crean bases de datos, tablas, índices, columnas y alias, es necesario asignarles un
nombre. La primera parte de este capítulo, está dedicada a presentar las reglas de asignación de
nombres. A continuación se pasa a la creación de bases de datos y a su eliminación. En el caso de
las tablas, a cada columna se le debe asignar un tipo de dato, es por ello que antes de pasar a la
creación de tablas se indican los tipos disponibles en MySQL. Seguidamente se trata de forma
extensa la creación de tablas y su eliminación. Para finalizar se indica como insertar y modificar
datos en las tablas, y como importar y exportar datos.

15.2 REGLAS PARA ASIGNAR NOMBRES

Se denotará por identificador a los nombres de bases de datos, tablas, índices, columnas y alias.
La longitud máxima para todos ellos es de 64 bytes, excepto en el caso de nombres de alias que
es de 255 bytes. Para los identificadores de bases de datos y tablas están permitidos todos los
caracteres de nombre de directorio a excepción de (/, \, .). Para el resto están permitidos todos los
caracteres. Ningún identificador puede contener el valor ASCII 0 o un byte con el valor 255. Los
nombres de bases de datos, tablas y columnas no pueden terminar con espacios. Si un identifica-
dor es una palabra reservada o contiene caracteres especiales, se debe entrecomillar, para ello se
15.2 CREACIÓN DE BASES DE DATOS Y TABLAS E INSERCIÓN DE DATOS

utiliza la tilde izquierda. Si el modo del servidor SQL incluye la opción de modo
ANSI_QUOTES, también estará permitido entrecomillar con comillas dobles.

MySQL permite nombres con un único identificador o con múltiples identificadores separados
por puntos. Las partes iniciales de un nombre compuesto actúan como calificadores que afectan
al contexto dentro de cual, se interpreta el identificador final. Si cualquiera de los componentes
de un nombre compuesto requiere entrecomillado, hay que entrecomillar cada uno individual-
mente. No es necesario especificar un prefijo de nombre de tabla o de base de datos para hacer
referencia a una columna a no ser que la referencia pueda ser ambigua. Formas de hacer referen-
cia a una columna:
nombre_columna

nombre_tabla.nombre_columna

nombre_basedatos.nombre_tabla.nombre_columna

En MySQL, las bases de datos corresponden a directorios y a las tablas les corresponde, por lo
menos, un fichero dentro del directorio de la base de datos. Por lo tanto, la distinción entre
mayúsculas y minúsculas dependerá del sistema operativo. Así, los nombres de bases de datos y
tablas no son sensibles al tipo en Windows, y sí lo son en la mayor parte de las variantes de Unix.
En cualquier caso, no se debe hacer referencia a una base de datos o tabla usando diferentes tipos
en la misma consulta. Los nombres de columna, índices y alias de columna no son sensibles al
tipo en ninguna plataforma. Si hay problemas para recordar el tipo de letra permitido es mejor
crear siempre las bases de datos y tablas con nombres que sólo contengan caracteres en minúscu-
las.

El modo en que se almacenan los nombres de tablas y bases de datos en disco y son usados en
MySQL depende de la definición de la variable de sistema lower_case_table_names, la cual se
puede asignar cuando se arranca MySQL. Esta variable puede tomar uno de los valores siguien-
tes: 1) 0, los nombres se almacenan usando los tipos de caracteres utilizados para su creación y
las comparaciones son sensibles al tipo. 2) 1, los nombres se almacenan en minúsculas y las
comparaciones no son sensibles al tipo. 3) 2, los nombres se almacenan usando los tipos de
caracteres utilizados para su creación pero se convierten a minúscula al leerlos y las comparacio-
nes de nombres no son sensibles al tipo.

Si se está usando MySQL para un solo tipo de plataforma, generalmente no será necesario modi-
ficar la variable lower_case_table_names, pero se pueden presentar dificultades si se quieren
transferir tablas entre plataformas que tengan sistemas de ficheros con distintas sensibilidades al
tipo. Para evitar este problema, se puede hacer lower_case_table_names=1 en todos los sistemas
o hacer lower_case_table_names=0 en Unix y lower_case_table_names=2 en Windows (antes
de asignar 1 a lower_case_table_names en Unix, se deben convertir los viejos nombres de bases
de datos y tablas a minúscula antes de reiniciar MySQL).

Desarrollo de Aplicaciones Web Dinámicas - UNED


CREAR Y ELIMINAR BASES DE DATOS 15.3

15.3 CREAR Y ELIMINAR BASES DE DATOS

Para crea una base de datos, se utiliza la sentencia CREATE DATABASE:


CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name

[create_specification]

create_specification:

[DEFAULT] CHARACTER SET charset_name

| [DEFAULT] COLLATE collation_name

Donde db_name es el nombre de la base de datos que se desea crear. Para poder usar esta senten-
cia es preciso tener el privilegio CREATE. Si la base de datos ya existe y no se ha especificado IF
NOT EXISTS, se producirá un error. Las opciones create_specification sirven para especificar
características de las base de datos. Estas características se almacenan en el fichero db.opt en el
directorio de la base de datos. La clausula CHARACTER SET especifica el conjunto de caracteres
por defecto para la base de datos, y la clausula COLLATE especifica el conjunto de reglas de
comparación de caracteres por defecto para la base de datos. En MySQL las bases de datos se
implementan como directorios que contienen los ficheros correspondientes a las tablas de la base
de datos. Como no hay tablas en una base de datos cuando esta es creada, la sentencia CREATE
DATABASE sólo crea un directorio bajo el directorio data de MySQL y el fichero db.opt.

Las siguientes sentencias permiten crear una base de datos denominada prueba, conocer cuántas
bases de datos existen en el sistema y seleccionar una base de datos (en este caso prueba), res-
pectivamente. USE, no es una sentencia SQL, sino una opción de MySQL.
CREATE DATABASE prueba;

SHOW DATABASES;

USE prueba;

Para eliminar una base de datos se utiliza la sentencia DROP DATABASE:


DROP DATABASE [IF EXISTS] db_name

Al borrar una base de datos se eliminan las tablas que pueda contener.

Las siguientes sentencias permiten crear una base de datos denominada borrar, comprobar que la
base de datos ha sido creada, eliminar la base de datos borrar y comprobar que ha sido eliminada.

Desarrollo de Aplicaciones Web Dinámicas - UNED


15.4 CREACIÓN DE BASES DE DATOS Y TABLAS E INSERCIÓN DE DATOS

CREATE DATABASE borrar;

SHOW DATABASES;

DROP DATABASE IF EXISTS borrar;

SHOW DATABASES;

15.4 TIPOS DE DATOS

En MySQL existen diversos tipos de datos que pueden agruparse en las siguientes categorías.

15.4.1 TIPO CADENAS DE CARACTERES


CHAR, CHAR(), VARCHAR():

CHAR

Un carácter. Es lo mismo que CHAR(1).

[NATIONAL] CHAR(M) [BINARY | ASCII | UNICODE]

Cadena de caracteres de longitud constante M. Para mantener la longitud de la cadena, se rellena


a la derecha con espacios. Estos espacios se eliminan al recuperar el valor. Los valores válidos
para M son de 0 a 255. Si no se especifica la palabra clave BINARY estos valores se ordenan y
comparan sin distinguir mayúsculas y minúsculas.

[NATIONAL] VARCHAR(M) [BINARY]

Cadena de caracteres de longitud variable. Los valores válidos para M son de 0 a 255. Los espa-
cios al final se eliminan. Si no se especifica la palabra clave BINARY estos valores se ordenan y
comparan sin distinguir mayúsculas y minúsculas.

Desarrollo de Aplicaciones Web Dinámicas - UNED


TIPOS DE DATOS 15.5

15.4.2 TIPO ENTERO


TINYINT, BIT, BOOL, BOOLEAN, SMALLINT, MEDIUMINT, INT, INTEGER, BIGINT :

TINYINT[(M)] [UNSIGNED] [ZEROFILL]

Entero. Rango con signo entre -128 y 127. Rango sin signo de 0 a 255.

BIT, BOOL, BOOLEAN

Sinónimos de TINYINT(1).

SMALLINT[(M)] [UNSIGNED] [ZEROFILL]

Entero. Rango con signo de -32768 a 32767. Rango sin signo de 0 a 65535.

MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]

Entero. Rango con signo entre -8388608 y 8388607. Rango sin signo, entre 0 y 16777215.

INT[(M)] [UNSIGNED] [ZEROFILL]

Entero. Rango con signo entre -2147483648 y 2147483647. Rango sin signo entre 0 y
4294967295.

INTEGER[(M)] [UNSIGNED] [ZEROFILL]

Sinónimo de INT.

BIGINT[(M)] [UNSIGNED] [ZEROFILL]

Entero. Rango con signo de -9223372036854775808 a 9223372036854775807. Rango sin signo


de 0 a 18446744073709551615.

15.4.3 TIPO COMA FLOTANTE


FLOTA, FLOAT(), DOUBLE, DOUBLE PRECISION, REAL, DECIMAL, DEC, NUMERIC,
FIXED:

FLOAT(precision) [UNSIGNED] [ZEROFILL]

Número en coma flotante. precision menor o igual que 24 para números de precisión sencilla y
entre 25 y 53 para números en coma flotante de doble precisión. Son idénticos que los tipos
FLOAT y DOUBLE. FLOAT(X) tiene el mismo rango que los tipos FLOAT y DOUBLE corres-
pondientes, pero el tamaño mostrado y el número de decimales quedan indefinidos.

FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]

Número en coma flotante (precisión sencilla). Rango entre -3.402823466E+38 y -


1.175494351E-38, 0, y entre 1.175494351E-38 y 3.402823466E+38. Si se especifica el modifi-
cador UNSIGNED, los valores negativos no se permiten. El valor M es el ancho a mostrar y D es
el número de decimales. Si se usa sin argumentos o si se usa FLOAT(X), donde X sea menor o
igual que 24, se sigue definiendo un valor en coma flotante de precisión sencilla.

Desarrollo de Aplicaciones Web Dinámicas - UNED


15.6 CREACIÓN DE BASES DE DATOS Y TABLAS E INSERCIÓN DE DATOS

DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

Número en coma flotante (precisión doble). Rango entre -1.7976931348623157E+308 y -


2.2250738585072014E-308, 0, y entre 2.2250738585072014E-308 y
1.7976931348623157E+308. Si se especifica el modificador UNSIGNED, no se permiten los
valores negativos. El valor M es el ancho a mostrar y D es el número de decimales. Si se usa sin
argumentos o si se usa FLOAT(X), donde X esté entre 25 y 53, se sigue definiendo un valor en
coma flotante de doble precisión.

DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL]

REAL[(M,D)] [UNSIGNED] [ZEROFILL]

Sinónimos de DOUBLE.

DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]

Número en coma flotante sin empaquetar. Se comporta igual que CHAR, se almacena como una
cadena con un carácter para cada dígito del valor. El punto decimal y el signo '-' para valores
negativos, no se cuentan en M (pero el espacio para estos se reserva). Si D es 0, los valores no
tendrán punto decimal ni decimales. El rango de los valores DECIMAL es el mismo que para
DOUBLE, pero el rango actual para una columna DECIMAL dada está restringido por la elección
de los valores M y D. Si se especifica el modificador UNSIGNED, los valores negativos no están
permitidos. Si se omite D, el valor por defecto es 0. Si se omite M, el valor por defecto es 10.

DEC[(M[,D])] [UNSIGNED] [ZEROFILL]

NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL]

FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]

Sinónimos de DECIMAL.

15.4.4 TIPO TIEMPOS


DATE, DATETIME, TIMESTAMP, TIME, YEAR:

DATE

Fecha. Rango entre '1000-01-01' y '9999-12-31'. Formato 'AAAA-MM-DD'. Es posible asignar


valores de este tipo usando tanto números como cadenas.

DATETIME

Fecha y hora. Rango entre '1000-01-01 00:00:00' y '9999-12-31 23:59:59'. Formato 'AAAA-MM-
DD HH:MM:SS'. Es posible asignar valores de este tipo usando tanto cadenas como números.

TIMESTAMP[(M)]

Tipo timestamp. Rango entre '1970-01-01 00:00:00' y algún momento del año 2037. Formato
'AAAA-MM-DD HH:MM:SS'. Para convertir este valor a un número, basta con sumar el valor 0.

Desarrollo de Aplicaciones Web Dinámicas - UNED


TIPOS DE DATOS 15.7

Se puede asignar la fecha y hora actual asignando el valor NULL. El argumento M afecta al modo
en que se visualiza. Los valores se almacenan con cuatro bytes. Los valores de TIMESTAMP(M),
cuando M es 8 ó 14 se devuelven como números y para el resto de valores como cadenas.

TIME

Hora. Rango entre '-838:59:59' y '838:59:59'. Formato 'HH:MM:SS'. Se permite asignar valores
TIME usando tanto cadenas como números.

YEAR[(2|4)]

Año en formato de 2 ó 4 dígitos (por defecto es 4). Rango entre 1901 y 2155, y 0000 en el for-
mato de 4 dígitos. Entre 1970-2069 si se usa el formato de 3 dígitos (70-69). Formato AAAA. Se
permite asignar valores YEAR usando tanto cadenas como números.

15.4.5 OTROS TIPOS


TINYBLOB, TINYTEXT, BLOB, TEXT, MEDIUMBLOB, MEDIUMTEXT, LONGBLOB, LONG-
TEXT:

TINYBLOB, TINYTEXT

BLOB o TEXT con una longitud máxima de 255 caracteres (28 - 1).

BLOB, TEXT

BLOB o TEXT con una longitud máxima de 65535 caracteres (216 - 1).

MEDIUMBLOB, MEDIUMTEXT

BLOB o TEXT con una longitud máxima de 16777215 caracteres (224 - 1).

LONGBLOB, LONGTEXT

BLOB o TEXT con una longitud máxima de 4294967298 caracteres (232 - 1).

15.4.6 TIPOS ENUMERADOS Y CONJUNTOS


ENUM, SET:

ENUM('valor1','valor2',...)

Contiene un enumerado. Un objeto de tipo cadena que puede tener un único valor, entre una lista
de valores 'valor1', 'valor2', ..., NULL o el valor especial de error "". Un ENUM puede tener un
máximo de 65535 valores diferentes.

SET('valor1','valor2',...)

Contiene un conjunto. Un objeto de tipo cadena que puede tener cero o más valores, cada uno de
los cuales debe estar entre una lista de valores 'valor1', 'valor2', ... Un conjunto puede tener un
máximo de 64 miembros.

Desarrollo de Aplicaciones Web Dinámicas - UNED


15.8 CREACIÓN DE BASES DE DATOS Y TABLAS E INSERCIÓN DE DATOS

15.5 CREAR Y ELIMINAR TABLAS

Para crear tablas se utiliza la sentencia CREATE TABLE:


CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name

[(definición_create,...)]

[opciones_tabla] [sentencia_select]

Sintaxis de definición_create:
definición_columnas

| [CONSTRAINT [símbolo]] PRIMARY KEY (index_nombre_col,...)

| KEY [nombre_index] (nombre_col_index,...)

| INDEX [nombre_index] (nombre_col_index,...)

| [CONSTRAINT [símbolo]] UNIQUE [INDEX]

[nombre_index] [tipo_index] (nombre_col_index,...)

| [FULLTEXT|SPATIAL] [INDEX] [nombre_index] (nombre_col_index,...)

| [CONSTRAINT [símbolo]] FOREIGN KEY

[nombre_index] (nombre_col_index,...) [definición_referencia]

| CHECK (expr)

Sintaxis de definición_columnas:
nombre_col tipo [NOT NULL | NULL] [DEFAULT valor_por_defecto]

[AUTO_INCREMENT] [[PRIMARY] KEY] [COMMENT 'string']

[definición_referencia]

Sintaxis de tipo:
TINYINT[(longitud)] [UNSIGNED] [ZEROFILL]

| SMALLINT[(longitud)] [UNSIGNED] [ZEROFILL]

| MEDIUMINT[(longitud)] [UNSIGNED] [ZEROFILL]

| INT[(longitud)] [UNSIGNED] [ZEROFILL]

| INTEGER[(longitud)] [UNSIGNED] [ZEROFILL]

| BIGINT[(longitud)] [UNSIGNED] [ZEROFILL]

| REAL[(longitud,decimales)] [UNSIGNED] [ZEROFILL]

| DOUBLE[(longitud,decimales)] [UNSIGNED] [ZEROFILL]

| FLOAT[(longitud,decimales)] [UNSIGNED] [ZEROFILL]

| DECIMAL(longitud,decimales) [UNSIGNED] [ZEROFILL]

| NUMERIC(longitud,decimales) [UNSIGNED] [ZEROFILL]

| DATE | TIME | TIMESTAMP | DATETIME

Desarrollo de Aplicaciones Web Dinámicas - UNED


CREAR Y ELIMINAR TABLAS 15.9

| CHAR(longitud) [BINARY | ASCII | UNICODE]

| VARCHAR(longitud) [BINARY]

| TINYBLOB | BLOB | MEDIUMBLOB | LONGBLOB | TINYTEXT | TEXT

| MEDIUMTEXT | LONGTEXT

| ENUM(valor1,valor2,valor3,...)

| SET(valor1,valor2,valor3,...)

| tipo_spatial

Sintaxis de nombre_col_index:
nombre_col [(longitud)] [ASC | DESC]

Sintaxis de definición_referencia:
REFERENCES nombre_tbl [(nombre_col_index,...)]

[MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]

[ON DELETE opción_referencia]

[ON UPDATE opción_referencia]

Sintaxis de opción_referencia:
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

Sintaxis de opciones_tabla:
opción_tabla [opción_tabla] ...

Sintaxis de opción_tabla:
{ENGINE|TYPE} = {BDB|HEAP|ISAM|InnoDB|MERGE|MRG_MYISAM|MYISAM }

| AUTO_INCREMENT = valor | AVG_ROW_LENGTH = valor

| CHECKSUM = {0 | 1} | COMMENT = 'cadena'

| MAX_ROWS = valor | MIN_ROWS = valor

| PACK_KEYS = {0 | 1 | DEFAULT} | PASSWORD = 'cadena'

| DELAY_KEY_WRITE = {0 | 1}

| ROW_FORMAT = { DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNTANT|COMPACT}

| RAID_TYPE = { 1 | STRIPED | RAID0 }

RAID_CHUNKS=valor

RAID_CHUNKSIZE=valor

| UNION = (nombre_tabla,[nombre_tabla...])

| INSERT_METHOD = { NO | FIRST | LAST }

| DATA DIRECTORY = 'camino de directorio absoluto'

| INDEX DIRECTORY = 'camino de directorio absoluto'

Desarrollo de Aplicaciones Web Dinámicas - UNED


15.10 CREACIÓN DE BASES DE DATOS Y TABLAS E INSERCIÓN DE DATOS

| [DEFAULT] CHARACTER SET nombre_conjunto_caracteres

[COLLATE nombre_cotejo]

CREATE TABLE crea una tabla con el nombre dado en tbl_name. Para ello, se debe tener el privi-
legio CREATE. Por defecto, la tabla se crea en la base de datos actual. Se producirá un error si la
tabla ya existe y no se especifica IF NOT EXISTS, si no hay una base de datos actual o si la base
de datos no existe. El nombre de la tabla se puede especificar como db_name.tbl_name para crear
una tabla en una base de datos específica. Se puede usar la palabra clave TEMPORARY cuando
se quiere crear una tabla temporal que sólo será visible para la conexión actual y que será borrada
cuando se cierre la conexión (para crear este tipo de tabla, se debe tener el privilegio CREATE
TEMPORARY TABLES). Cada tabla tbl_name se representa mediante ficheros en el directorio de
la base de datos. 1) tbl_name.frn, fichero de definición de formato de tabla. 2) tbl_name.MYD,
fichero de datos. 3) tbl_name.MYI, fichero de índices.

Una vez indicado el nombre de la tabla, la sentencia CREATE TABLE permite definir las colum-
nas que la componen. Para crear una columna dentro de una tabla, hay que indicar su nombre
(nombre_col) y tipo de datos que contiene (tipo). Las siguientes sentencias permiten crear una
tabla, denominada gente, que almacena nombres de personas (cadenas de hasta 40 caracteres) y
sus fechas de nacimiento (tipo fecha).
USE prueba

CREATE TABLE gente (nombre VARCHAR(40), fecha DATE);

15.5.1 OPCIONES DE DEFINICIÓN DE COLUMNAS

Valores nulos [NOT NULL | NULL]


Al definir una columna se puede decidir si podrá o no contener valores nulos. Hay que tener en
cuenta que, aquellas columnas que son o forman parte de una clave primaria no pueden contener
valores nulos. Si se define una columna como clave primaria, automáticamente se impide que
pueda contener valores nulos. La opción por defecto es que se permitan valores nulos, NULL, y
para que no se permitan, se usa NOT NULL.
CREATE TABLE tabla (columna1 CHAR(20) NOT NULL, columna2 INT NULL);

Valores por defecto [DEFAULT valor_por_defecto]


La clausula DEFAULT especifica un valor por defecto para una columna. El valor por defecto se
asigna de forma automática cuando no se especifique un valor determinado al añadir filas. Este
valor debe ser una constante, salvo para el tipo TIMESTAMP que puede ser CURRENT TIMES-
TAMP. Si no se especifica un valor explicito por defecto, se asigna automáticamente NULL, si la

Desarrollo de Aplicaciones Web Dinámicas - UNED


CREAR Y ELIMINAR TABLAS 15.11

columna puede tomar dicho valor, o el valor implícito para el tipo de columna, en caso contrario.
El valor por defecto implícito es: 1) 0, para tipos numéricos no declarados con el atributo
AUTO_INCREMENT. 2) El siguiente valor dentro de la secuencia, para columnas
AUTO_INCREMENT. 3) Cero correspondiente al tipo, para fechas y tiempos distintos de TIMES-
TAMP. 4) Hora actual, para la primera columna TIMESTAMP. 5) Cadena vacía, para tipos de
cadena distintos de ENUM. 6) Primero valor de la enumeración, para ENUM. 7) A las columnas
BLOB y TEXT no se les puede asignar un valor por defecto.
CREATE TABLE tabla (columna1 CHAR(20) NOT NULL,

columna2 INT NULL DEFAULT 1000);

Columnas autoincrementadas [AUTO_INCREMENT]


Una columna de tipo entero puede tener el atributo adicional AUTO_INCREMENT. Cuando se
inserta una fila sin valor (NULL) o con valor nulo (0) en una columna AUTO_INCREMENT, su
valor se calcula automáticamente como el valor más alto de esa columna sumándole una unidad
(el valor inicial es 1). Sólo puede existir una columna AUTO_INCREMENT por tabla, debe estar
indexada y no puede tener un valor DEFAULT. Esto permite crear, de una forma sencilla, una
columna con un valor único para cada fila de la tabla. Generalmente, estas columnas se usan
como claves primarias artificiales.
CREATE TABLE tabla (clave INT AUTO_INCREMENT PRIMARY KEY,

columna2 CHAR(10) NOT NULL, columna2 INT NULL DEFAULT 1000);

Claves primarias [[PRIMARY] KEY]


También se puede definir una clave primaria sobre una columna, usando la palabra clave KEY
(normalmente sinónimo de INDEX) o PRIMARY KEY. Sólo puede existir una clave primaria en
cada tabla, y la columna sobre la que se define no puede tener valores NULL. Si esto no se espe-
cifica de forma explícita, MySQL lo hará de forma automática. Usar NOT NULL PRIMARY KEY
equivale a PRIMARY KEY, NOT NULL KEY o sencillamente KEY. Existe una sintaxis mas
potente para crear claves primarias (la que se ha comentado es un alias de la forma general).
CREATE TABLE tabla (columna1 CHAR(10) NOT NULL PRIMARY KEY,

columna2 INT NULL DEFAULT 1000);

Comentarios [COMMENT 'string']


A cada columna de la tabla, se le puede añadir un comentario. Este comentario sirve como infor-
mación adicional sobre alguna característica especial de la columna y forma parte de la docu-
mentación de la base de datos.
CREATE TABLE tabla (

clave INT AUTO_INCREMENT PRIMARY KEY COMMENT 'Clave principal',

columna2 CHAR(20) NOT NULL, columna3 INT NULL DEFAULT 1000);

Desarrollo de Aplicaciones Web Dinámicas - UNED


15.12 CREACIÓN DE BASES DE DATOS Y TABLAS E INSERCIÓN DE DATOS

15.5.2 OPCIONES PARA CREAR ÍNDICES

Claves primarias PRIMARY KEY


Permite crear una clave primaria en la columna especificada. Entre los paréntesis se pueden espe-
cificar varios nombres de columnas, para construir claves primarias compuestas.
CREATE TABLE tabla (columna1 CHAR(20) NOT NULL,

columna2 INT NULL DEFAULT 1000, PRIMARY KEY (columna1));

CREATE TABLE tabla (columna1 CHAR(3) NOT NULL,

columna2 CHAR(3) NOT NULL, columna3 CHAR(50),

PRIMARY KEY (columna1, columna2));

Índices KEY e INDEX


Permiten definir índices sobre una columna, sobre varias, o sobre partes de columnas. Para defi-
nir estos índices se usan indistintamente las opciones KEY o INDEX.
CREATE TABLE tabla(columna1 INT, columna2 CHAR(10), INDEX (columna2));

CREATE TABLE tabla(columna1 INT, columna2 CHAR(10), KEY (columna2));

CREATE TABLE tabla(columna1 INT, columna2 CHAR(10),

INDEX (columna2(4)));

columna2 (4), significa que sólo se utilizan los cuatro primeros caracteres de columna2 para
crear el índice.

Claves únicas UNIQUE


Permite definir índices con claves únicas, sobre una columna, sobre varias o sobre partes de
columnas. La diferencia entre un índice único y uno normal es que en los únicos no se permite la
inserción de filas con claves repetidas. La excepción es el valor NULL, que sí se puede repetir.
Los índices sirven para optimizar las consultas y las búsquedas de datos. Mediante su uso es
mucho más rápido localizar filas con determinados valores de columnas, o seguir un determinado
orden. La alternativa es hacer búsquedas secuenciales, que en tablas grandes requieren mucho
tiempo.
CREATE TABLE tabla(columna1 INT, columna2 CHAR(10), UNIQUE (columna2));

Una clave primaria equivale a un índice de clave única, en la que el valor de la clave no puede
tomar valores NULL (los índices normales y los de claves únicas sí pueden tomar valores
NULL). Las siguientes sentencias son equivalentes:
CREATE TABLE tabla(columna1 INT, columna2 CHAR(10) NOT NULL,

UNIQUE (columna2));

CREATE TABLE tabla(columna1 INT, columna2 CHAR(10),

PRIMARY KEY (columna2));

Desarrollo de Aplicaciones Web Dinámicas - UNED


CREAR Y ELIMINAR TABLAS 15.13

Claves foráneas FOREIGN KEY


En MySQL sólo existe soporte para claves foráneas en tablas de tipo InnoDB. La parte opcional
CONSTRAINT [símbolo] sirve para asignar un nombre a la clave foránea, de modo que pueda
usarse como identificador si se quiere modificar o eliminar una definición de clave foránea. En
las siguientes sentencias se muestra como definir una clave foránea de la columna1 de la tabla1
para la columna1 de la tabla2.
CREATE TABLE tabla1 (columna1 INT AUTO_INCREMENT PRIMARY KEY,

columna2 VARCHAR(40), columna3 DATE) ENGINE=InnoDB;

CREATE TABLE tabla2 (columna1 CHAR(12), columna2 INT NOT NULL,

KEY (columna2), FOREIGN KEY (columna2) REFERENCES tabla1 (columna1)

ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB;

Es imprescindible que la columna que contiene una definición de clave foránea esté indexada.
Pero si no se hace de forma explícita, MySQL lo hará de forma implícita. La definición incluye
las tareas a realizar en el caso de que se elimine una fila en la tabla personas. ON DELETE
<opción>, indica que acciones se deben realizar en la tabla actual si se borra una fila en la tabla
referenciada. ON UPDATE <opción>, es análogo pero para modificaciones de claves. Existen
cinco opciones diferentes: 1) RESTRICT, impide eliminar o modificar filas en la tabla referen-
ciada si existen filas con el mismo valor de clave foránea. 2) CASCADE, borrar o modificar una
clave en una fila en la tabla referenciada con un valor determinado de clave, implica borrar las
filas con el mismo valor de clave foránea o modificar los valores de esas claves foráneas. 3) SET
NULL, borrar o modificar una clave en una fila en la tabla referenciada con un valor determinado
de clave, implica asignar el valor NULL a las claves foráneas con el mismo valor. 4) NO
ACTINO, las claves foráneas no se modifican, ni se eliminan filas en la tabla que las contiene. 5)
SET DEFAULT, borrar o modificar una clave en una fila en la tabla referenciada con un valor
determinado implica asignar el valor por defecto a las claves foráneas con el mismo valor.

15.5.3 MOTOR DE ALMACENAMIENTO


La parte final de la sentencia CREATE TABLE permite especificar varias opciones para la tabla,
pero sólo se comentará la opción del motor de almacenamiento.
{ENGINE|TYPE} = {BDB|HEAP|ISAM|InnoDB|MERGE|MRG_MYISAM|MYISAM }

Se pueden utilizar indistintamente ENGINE o TYPE, pero TYPE desaparece en la versión 5 de


MySQL. Existen seis motores de almacenamiento disponibles. Algunos de ellos serán de uso
obligatorio si se quieren tener ciertas opciones disponibles. Los motores son: 1) BerkeleyDB o
BDB, tablas de transacción segura con bloqueo de página. 2) HEAP o MEMORY, tablas almace-
nadas en memoria. 3) ISAM, motor original de MySQL. 4) InnoDB, tablas de transacción segura
con bloqueo de fila y claves foráneas. 5) MERGE o MRG_MyISAM, colección de tablas MyISAM
usadas como una única tabla. 6) MyISAM, nuevo motor binario de almacenamiento portable que

Desarrollo de Aplicaciones Web Dinámicas - UNED


15.14 CREACIÓN DE BASES DE DATOS Y TABLAS E INSERCIÓN DE DATOS

reemplaza a ISAM. Generalmente se utilizarán tablas MyISAM o tablas InnoDB. En ocasiones,


cuando se requiera una gran optimización, se crearán tablas temporales en memoria.

15.5.4 MOSTRAR TABLAS Y COLUMNAS


Para consultar las tablas existentes en una base de datos, se utiliza la sentencia SHOW TABLES:
USE prueba

SHOW TABLES;

Una vez creadas las tablas, existen sentencias para consultar sus características. Así, se puede ver
la estructura de una tabla usando la sentencia SHOW COLUMNS o DESCRIBE.
SHOW COLUMNS FROM gente;

También se pueden ver las instrucciones utilizadas para crear una tabla, mediante la sentencia
SHOW CREATE TABLE. Si se usa \G en lugar de (;) la salida se muestra en forma de listado, en
lugar de forma de tabla. La sentencia CREATE TABLE mostrada no tiene por qué ser la misma
que se usó al crear la tabla originalmente. MySQL rellena las opciones que se activan de forma
implícita, y usa siempre el mismo formato para crear claves primarias.
SHOW CREATE TABLA gente\G

15.5.5 MODIFICAR TABLAS


Para modificar la estructura de una tabla se utiliza la sentencia ALTER TABLE, con las siguientes
cláusulas: 1) CHANGE, cambiar columnas. 2) RENAME, cambiar el nombre de la tabla. 3)
DROP, eliminar columnas. 4) ADD, añadir columnas. 5) TYPE, cambiar motor de almacena-

Desarrollo de Aplicaciones Web Dinámicas - UNED


CREAR Y ELIMINAR TABLAS 15.15

miento. 6) ADD INDEX, crear índice. 7) ADD PRIMARY KEY, crear clave primaria. 8) DROP
INDEX, eliminar índice. 9) DROP PRIMARY KEY, eliminar clave primaria.
ALTER TABLE tabla CHANGE columna1 columna2 TIPO;

ALTER TABLE tabla1 RENAME tabla2;

ALTER TABLE tabla DROP columna;

ALTER TABLE tabla ADD columna TIPO;

ALTER TABLE tabla TYPE=innoDB;

ALTER TABLE tabla ADD INDEX (columnas);

ALTER TABLE tabla ADD UNIQUE INDEX (columnas);

ALTER TABLE tabla ADD PRIMARY KEY (columnas);

ALTER TABLE tabla DROP INDEX (índice); (DROP INDEX (índice) ON tabla;)

ALTER TABLE tabla DROP PRIMARY KEY;

15.5.6 ELIMINAR TABLAS


Para eliminar una tabla se utiliza la sentencia DROP TABLE. Se pueden añadir IF EXISTS para
evitar errores si la tabla a eliminar no existe.
DROP TABLE [IF EXISTS] tbl_name

Las siguientes sentencias permiten crear una tabla denominada borrar en la base de datos
prueba, comprobar que la tabla ha sido creada, eliminar la tabla borrar y comprobar que ha sido
eliminada.
USE prueba

CREATE TABLE borrar (columna1 VARCHAR(40), columna2 DATE);

SHOW TABLES;

DROP TABLE IF EXISTS borrar;

SHOW TABLES;

Desarrollo de Aplicaciones Web Dinámicas - UNED


15.16 CREACIÓN DE BASES DE DATOS Y TABLAS E INSERCIÓN DE DATOS

15.6 INSERTAR Y MODIFICAR DATOS

En esta sección se muestra cómo agregar, modificar o eliminar los datos que contiene una bases
de datos.

15.6.1 INSERTAR FILAS


Las filas se insertan en las tablas utilizando la sentencia INSERT. Para ello se debe indicar la
tabla a la que se quieren añadir filas y los valores de cada una de sus columnas. Las columnas de
tipo cadena o fechas deben estar entre comillas sencillas o dobles. Para asignar el valor por
defecto a una columna que lo permita, se utiliza DEFAULT. Otra posibilidad es indicar una lista
de columnas (en el orden que se quiera) para las que se van a insertar valores. A las columnas que
no se nombran en la lista se les asigna el su valor defecto.
INSERT INTO tabla VALUES (valor1,valor2);

INSERT INTO tabla VALUES (valor1,valor2), (valor3,valor4);

INSERT INTO tabla VALUES (valor1, DEFAULT);

INSERT INTO tabla (columna1,columna3) VALUES (valo1, valor2),

(valor3,valor4), (valor5,valor6);

Existe otra sintaxis alternativa, que consiste en indicar el valor para cada columna:
INSERT INTO tabla SET columna3=valor1, columna1=valor2;

Cuando se insertan más de una fila en una única sentencia, se obtiene un mensaje que indica el
número de filas afectadas, el número de filas duplicadas y el número de avisos. Para que una fila
se considere duplicada debe tener el mismo valor que una fila existente para una clave principal o
para una clave única. En tablas en las que no exista clave primaria ni índices de clave única no
tiene sentido hablar de filas duplicadas. Si se intentan insertar dos filas con el mismo valor de la
clave única se produce un error y la sentencia no se ejecuta. Existe una opción que se puede utili-
zar para los casos de claves duplicadas: ON DUPLICATE KEY UPDATE. En este caso se puede
indicar qué se debe hacer si se intenta insertar una fila que ya existe en la tabla.

15.6.2 REEMPLAZAR FILAS


La sentencia REPLACE es una alternativa para INSERT. Sólo se diferencia en que si existe algún
registro anterior con el mismo valor para una clave primaria o única, se elimina el viejo y se
inserta el nuevo en su lugar.
REPLACE [LOW_PRIORITY | DELAYED]

[INTO] tbl_name [(col_name,...)]

VALUES ({expr | DEFAULT},...),(...),...

REPLACE [LOW_PRIORITY | DELAYED]

[INTO] tbl_name

Desarrollo de Aplicaciones Web Dinámicas - UNED


INSERTAR Y MODIFICAR DATOS 15.17

SET col_name={expr | DEFAULT}, ...

15.6.3 ACTUALIZAR FILAS


Para actualizar los valores de las filas de una tabla se utiliza la sentencia UPDATE. En su forma
más simple, los cambios se aplican a todas las filas, y a las columnas especificadas.
UPDATE [LOW_PRIORITY] [IGNORE] tbl_name

SET col_name1=expr1 [, col_name2=expr2 ...]

[WHERE where_definition]

[ORDER BY ...]

[LIMIT row_count]

Ejemplos:
UPDATE tabla SET columna=columna*1.05;

UPDATE tabla SET columna1=columna1+1, columna2=columna2*1.05;

También se puede indicar el número de filas a actualizar, utilizando la cláusula WHERE, para
establecer una condición. Sólo las filas que cumplan esa condición serán actualizadas:
UPDATE tabla SET columna1=columna1*1.05 WHERE columna2=valor;

Otra forma de limitar el número de filas afectadas es usar la cláusula LIMIT. Esta cláusula per-
mite especificar el número de filas a modificar. Esta cláusula se puede combinar con WHERE, de
modo que sólo las n primeras filas que cumplan una determinada condición se modifiquen. Tam-
bién se puede asociar a la cláusula ORDER BY. Cuando exista una clave primaria o única, se
usará ese orden por defecto, si no se especifica una cláusula ORDER BY.
UPDATE tabla SET columna=columna-1 LIMIT 2;

(sólo afecta a las dos primeras filas)


UPDATE tabla SET columna=valor ORDER BY columna DESC LIMIT 1;

15.6.4 ELIMINAR FILAS


Para eliminar filas se usa la sentencia DELETE.
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM table_name

[WHERE where_definition]

[ORDER BY ...]

[LIMIT row_count]

Ejemplos:
DELETE FROM tabla;

DELETE FROM tabla WHERE condicion;

DELETE FROM tabla ORDER BY columna DESC LIMIT n;

Desarrollo de Aplicaciones Web Dinámicas - UNED


15.18 CREACIÓN DE BASES DE DATOS Y TABLAS E INSERCIÓN DE DATOS

15.6.5 VACIAR UNA TABLA


Para eliminar todas la filas de una tabla también se puede utilizar la sentencia TRUNCATE. La
diferencia es que DELETE hace un borrado secuencial de la tabla, fila a fila, mientras que TRUN-
CATE, borra la tabla y la vuelve a crear vacía, lo que es mucho más eficiente.
TRUNCATE tabla;

15.7 IMPORTAR Y EXPORTAR DATOS

MySQL permite copiar tablas en diferentes formatos de texto, así como importar datos a partir de
fichero de texto en diferentes formatos. Esto se puede usar para exportar datos de una bases de
datos a otras aplicaciones o para importar datos desde otras fuentes a tablas. También se puede
usar para hacer copias de seguridad y restaurarlas posteriormente.

15.7.1 EXPORTAR DATOS A OTROS FICHEROS


Para extraer datos desde una base de datos a un fichero se usa la sentencia SELECT...INTO
OUTFILE.n se envía a un fichero. La sintaxis de INTO OUTFILE es:
[INTO OUTFILE 'file_name' export_options]

Donde file_name es el nombre del fichero de salida, que no debe existir, ya que en caso contrario
la sentencia fallará. En cuanto a las opciones de exportación estas son FIELDS y LINES:
FIELDS [TERMINATED BY '\t'] [[OPTIONALLY] ENCLOSED BY '']

[ESCAPED BY '\\' ]

LINES [STARTING BY ''] [TERMINATED BY '\n']

Estas cláusulas permiten crear diferentes formatos de ficheros de salida.

La cláusula FIELDS se refiere a las opciones de cada columna:


TERMINATED BY 'carácter'

Permite elegir el carácter delimitador que se usará para separar cada columna. Por defecto, el
valor que se usa es el tabulador, pero se pueden utilizar usar ';' y ',', entre otros.
[OPTIONALLY] ENCLOSED BY 'carácter'

Sirve para elegir el carácter usado para entrecomillar cada columna. Por defecto no se entrecomi-
lla ninguna columna, pero se puede elegir cualquier carácter. Si se añade la palabra OPTIONA-
LLY sólo se entrecomillarán las columnas de texto y fecha.
ESCAPED BY 'carácter'

Sirve para indicar el carácter que se usará para escapar aquellos caracteres que pueden dificultar
la lectura posterior del fichero. Por ejemplo, si se terminan las columnas con ',' y no las entreco-
millamos, un carácter ',' dentro de una columna de texto se interpretará como un separador de

Desarrollo de Aplicaciones Web Dinámicas - UNED


IMPORTAR Y EXPORTAR DATOS 15.19

columnas. Para evitar esto se puede escapar esa coma con otro carácter. Por defecto se usa el
carácter '\'.

La cláusula LINES se refiere a las opciones para cada fila:


STARTING BY 'carácter'

Permite seleccionar el carácter para comenzar cada línea. Por defecto no se usa ningún carácter.
TERMINATED BY 'carácter'

Permite elegir el carácter para terminar cada línea. Por defecto es el retorno de línea, pero se
puede usar cualquier otro carácter o caracteres, por ejemplo '\r\n'.

Así, para obtener un fichero de texto a partir de la tabla, con las columnas delimitadas por ';',
entrecomillando las columnas de texto con '"' y separando cada fila por la secuencia '\r\n', se uti-
lizará la siguiente sentecia:
SELECT * FROM tabla INTO OUTFILE "gente.txt"

FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '\"'

LINES TERMINATED BY '\n\r';

15.7.2 IMPORTAR DATOS A PARTIR DE FICHEROS EXTERNOS


El contenido de un fichero de texto se puede cargar en una tabla utilizando LOAD DATA:
LOAD DATA [LOCAL] INFILE 'file_name.txt' [REPLACE | IGNORE]

INTO TABLE tbl_name

[FIELDS [TERMINATED BY '\t'] [[OPTIONALLY] ENCLOSED BY '']

[ESCAPED BY '\\' ]]

[LINES [STARTING BY ''] [TERMINATED BY '\n']]

[IGNORE number LINES] [(col_name,...)]

La cláusula LOCAL indica, que el fichero está en el ordenador del cliente. Si no se especifica el
fichero de texto se buscará en el servidor, concretamente en el mismo directorio donde esté la
base de datos. Esto permite importar desde el ordenador local a otra máquina.

Las cláusulas REPLACE e IGNORE afectan al modo en que se tratan las filas leídas que conten-
gan el mismo valor para una clave primaria o única para una fila existente en la tabla. Si se espe-
cifica REPLACE se sustituirá la fila actual por la leída. Si se especifica IGNORE el valor leído
será ignorado.

La parte INTO TABLA tbl_name indica en qué tabla se insertarán los valores leídos.

Las cláusulas FIELDS y LINES tienen el mismo significado que en SELEC...INTO OUTFILE.
Permiten interpretar correctamente cada fila y cada columna, adaptándonos al formato del
fichero de texto de entrada.

Desarrollo de Aplicaciones Web Dinámicas - UNED


15.20 CREACIÓN DE BASES DE DATOS Y TABLAS E INSERCIÓN DE DATOS

La misma utilidad tiene la cláusula IGNORE número LINES, que permite que las primeras líneas
no se interpreten como datos a importar.

La última parte de la sentencia, permite indicar la columna a la que será asignada cada una de las
columnas leídas.

Por ejemplo, supóngase que se quiere añadir el contenido de un fichero a una tabla, donde sus
dos primeras filas no contienen datos válidos, las columnas están separadas con comas y las
líneas terminan con "\n\r":
Comentario 1

Comentario 2

Valor11, valor12

Valor21, valor22

La sentencia adecuada para leer los datos es:


LOAD DATA INFILE "fichero.txt"

INTO TABLE tabla

FIELDS TERMINATED BY ','

LINES TERMINATED BY '\r\n'

IGNORE 2 LINES (columna1,columna2);

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 16

Consultas

16.1 INTRODUCCIÓN

El objetivo principal de un sistema de gestión de bases de datos, es poder acceder a la informa-


ción almacenada en las bases de datos que gestiona. En SQL, la sentencia que permite acceder a
la información y seleccionarla, según las necesidades de cada usuario, es la sentencia SELECT.

Este tema está dedicado a las consultas, es decir, a la selección de información utilizando la sen-
tencia SELECT. Básicmente, esta sentencia permite obtener información sobre el contenido de
las columnas que componen las tablas de la base de datos y que verifican una determinada condi-
ción. En las expresiones utilizas se pueden incluir operadores y funciones. La lista de operadores
y funciones se incluye al final del tema. Antes de comenzar con la selección de datos, se reco-
mienda hacer un repaso de dichas secciones..

16.2 SELECCIÓN DE DATOS

Las consultas a las bases de datos se realizan mediante la sentencia SELECT. El formato básico
de esta instrucción es:
SELECT columnas FROM tablas WHERE condición

y su sintaxis completa:
SELECT

[ALL | DISTINCT | DISTINCTROW]

[HIGH_PRIORITY]

[STRAIGHT_JOIN]

[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]


16.2 CONSULTAS

[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]

select_expr,...

[INTO OUTFILE 'file_name' export_options]

| INTO DUMPFILE 'file_name']

[FROM table_references

[WHERE where_definition]

[GROUP BY {col_name | expr | position}

[ASC | DESC], ... [WITH ROLLUP]]

[HAVING where_definition]

[ORDER BY {col_name | expr | position}

[ASC | DESC] ,...]

[LIMIT {[offset,] row_count | row_count OFFSET offset}]

[PROCEDURE procedure_name(argument_list)]

[FOR UPDATE | LOCK IN SHARE MODE]]

16.2.1 VER EL CONTENIDO DE UNA TABLA


La siguiente sentencia, donde el carácter * representa a todas las columnas de una tabla, permite
ver el contenido completo de una tabla.
SELECT * FROM tabla;

16.2.2 PROYECCIÓN
Es una operación del álgebra relacional que consiste en seleccionar determinados atributos de
una relación.
SELECT columna1, columna2 FROM tabla;

16.2.3 EVALUACIÓN DE EXPRESIONES


Esta sentencia SELECT se puede utilizar para evaluar expresiones:
SELECT expresión1, expresión2, ..., expresión;

16.2.4 APLICAR FUNCIONES A TABLAS


Otra posibilidad es aplicar expresiones sobre columnas para generar nuevas columnas.
SELECT columna1, columna2, expresión(columna3) FROM tabla;

16.2.5 ALIAS
Se puede asignar un alias para las consultas utilizando AS. Esta palabra se puede omitir pero no
es recomendable, ya que en ocasiones puede ser difícil distinguir entre el olvido de una coma y la
omisión de AS.

Desarrollo de Aplicaciones Web Dinámicas - UNED


SELECCIÓN DE DATOS 16.3

SELECT columna1, columna2 AS alias FROM tabla;

SELECT columna1, columna2 alias FROM tabla;

16.2.6 FILAS REPETIDAS


Al seleccionar sólo algunas columnas de una tabla, es posible que se produzcan filas repetidas.
En la sentencia SELECT se puede utilizar DISTINCT y DISTINCTROW para mostrar sólo filas
diferentes o ALL para mostrar todas las filas (diferentes o no). Si no se pone nada el valor por
defecto es ALL.
SELECT DISTINCT columna FROM tabla;

16.2.7 SELECCIÓN
Es una operación del álgebra relacional que consistía en seleccionar filas de una tabla que cum-
plen determinadas condiciones. Para ello se utiliza la clausula WHERE. En una cláusula WHERE
se puede usar cualquier función y operador disponible en MySQL, excluyendo las funciones de
grupos que están diseñadas específicamente para usarse en cláusulas GROUP BY y HAVING.
SELECT * FROM tabla WHERE condición;

16.2.8 CLÁUSULA GROUP BY


Permite agrupar filas en la salida de una sentencia SELECT según los distintos valores de una
columna. Esto, en principio, se puede hacer también utilizando DISTINCT, pero la cláusula
GROUP BY es más potente. Cuando se utiliza GROUP BY la salida se ordena según los valores
de la columna indicada y se eliminan los valores duplicados. Por otra parte, la cláusula GROUP
BY permite usar funciones de grupo. Estas funciones también se pueden usar sin la cláusula
GROUP BY siempre que no se proyecten otras columnas.
SELECT columna FROM tabla GROUP BY columna;

SELECT columna1, columna2 FROM tabla GROUP BY columna2;

SELECT columna1, COUNT(*) AS alias FROM tabla GROUP BY columna1;

SELECT MAX(columna1) FROM tabla;

16.2.9 CLÁUSULA HAVING


Permite hacer selecciones en situaciones en las que no es posible usar WHERE. La cláusula
WHERE no se puede aplicar a columnas calculadas mediante funciones de reunión.
SELECT columna1, MAX(columna2)

FROM tabla GROUP BY ciudad HAVING MAX(columna2)>10;

Desarrollo de Aplicaciones Web Dinámicas - UNED


16.4 CONSULTAS

16.2.10 CLÁUSULA ORDER BY


Permite obtener resultados ordenados por una columna. Si se utiliza ASC o DESC, después de
esta cláusula, la ordenación se hace de forma ascendente o descendente, respectivamente. Por
defecto se utiliza ASC.
SELECT * FROM tabla ORDER BY columna;

SELECT * FROM tabla ORDER BY columna DESC;

16.2.11 CLÁUSULA LIMIT


Permite limitar el número de filas devueltas. Admite dos parámetros, el primero indica el número
de la primera fila a recuperar y el segundo el número de filas a recuperar. Si se omite uno de
ellos, se mostrarán las filas indicadas partiendo de la primera.
SELECT * FROM tabla LIMIT n,m;

SELECT * FROM tabla LIMIT m;

16.2.12 PRODUCTO CARTESIANO


Hasta ahora todas las consultas hacían refieren a una sola tabla, pero también es posible hacer
consultas usando varias tablas.

El producto cartesiano es una operación del álgebra relacional que permite, a partir de dos tablas,
obtener las combinaciones de todas sus filas.
SELECT * FROM tabla1,tabla2;

16.2.13 COMPOSICIÓN INTERNA


Se trata del producto cartesiano restringido a las parejas de tuplas que cumplen una determinada
condición. Una composición se denomina interna cuando en la salida no aparece ninguna tupla
que no esté presente en el producto cartesiano. Para realizar una composición interna se parte del
producto cartesiano y se eliminan aquellas tuplas que no cumplen la condición.
SELECT * FROM tabla1,tabla2 WHERE tabla1.columna=tabla2.columna;

Esta misma consulta se puede realizar utilizando JOIN.


referencia_tabla, referencia_tabla

referencia_tabla [INNER | CROSS] JOIN referencia_tabla [condición]

La condición puede ser:


ON expresión_condicional | USING (lista_columnas)

La coma y JOIN son equivalentes, y las palabras INNER y CROSS son opcionales. La condición
en la cláusula ON puede ser cualquier expresión válida para una cláusula WHERE, de hecho, en
la mayoría de los casos, son equivalentes. La cláusula USING permite usar una lista de atributos
que deben ser iguales en las dos tablas a componer.

Desarrollo de Aplicaciones Web Dinámicas - UNED


SELECCIÓN DE DATOS 16.5

La consulta anterior es equivalente a:


SELECT * FROM tabla1 JOIN tabla2

ON (tabla1.columna= tabla2.columna);

SELECT * FROM tabla1 JOIN tabla2

WHERE (tabla1.columna= tabla2.columna);

SELECT * FROM tabla1 INNER JOIN tabla2

ON (tabla1.columna= tabla2.columna);

SELECT * FROM tabla1 CROSS JOIN tabla2

ON (tabla1.columna= tabla2.columna);

SELECT * FROM tabla1 JOIN tabla2 USING(columna);

16.2.14 COMPOSICIÓN INTERNA NATURAL


Consiste en una proyección sobre un producto cartesiano restringido. Es decir, sólo se eligen
determinadas columnas de ambas tablas. No se pueden elegir columnas repetidas.
SELECT tabla1.columna,columna2,columna3,columna4

FROM tabla1,tabla2

WHERE tabla1.columna=tabla2.columna;

También se pueden definir alias para las tablas:


SELECT t1.columna,columna2,columna3,columna4

FROM tabla1 AS t1, tabla2 AS t2

WHERE t1.columna=t2.columna;

Otra posibilidad es usar JOIN y ON en lugar de la coma y WHERE:


SELECT t1.columna,columna2,columna3,columna4

FROM tabla1 AS t1, tabla2 AS t2

ON t1.columna=t2.columna;

Existe una sintaxis alternativa para composiciones internas naturales:


referencia_tabla NATURAL JOIN referencia_tabla

SELECT * FROM tabla1 NATURAL JOIN tabla2;

16.2.15 COMPOSICIONES EXTERNAS


No proceden de un producto cartesiano. Para hacer una composición externa se toman las tuplas
de una de las tablas, una a una, y se combinan con las tuplas de la otra. Como norma general se
usa un índice para localizar las tuplas de la segunda tabla que cumplen la condición, y para cada
tupla encontrada se añade una fila a la tabla de salida. Si no existe ninguna tupla en la segunda
tabla que cumpla las condiciones, se combina la tupla de la primera con una nula de la segunda.

Desarrollo de Aplicaciones Web Dinámicas - UNED


16.6 CONSULTAS

SELECT * FROM tabla1 LEFT JOIN tabla2 USING(columna);

Las sintaxis para composiciones externas son:


referencia_tabla LEFT [OUTER] JOIN referencia_tabla [join_condition]

referencia_tabla NATURAL LEFT [OUTER] JOIN referencia_tabla

referencia_tabla RIGHT [OUTER] JOIN referencia_tabla [condición]

referencia_tabla NATURAL RIGHT [OUTER] JOIN referencia_tabla

La condición puede ser:


ON expresión_condicional | USING (lista_columnas)

La palabra OUTER es opcional.

Existen dos grupos de composiciones externas: izquierda y derecha, dependiendo de cual de las
tablas se lea en primer lugar.

16.2.16 COMPOSICIÓN EXTERNA IZQUIERDA


En estas composiciones se recorre la tabla de la izquierda y se buscan tuplas en la de la derecha.
Se crean usando LEFT.
referencia_tabla LEFT [OUTER] JOIN referencia_tabla [condición]

SELECT * FROM tabla1 LEFT JOIN tabla2 USING(columna);

16.2.17 COMPOSICIÓN EXTERNA DERECHA


En este caso se recorre la tabla de la derecha y se buscan tuplas que cumplan la condición en la
tabla izquierda. Se crean usando RIGHT.
referencia_tabla RIGHT [OUTER] JOIN referencia_tabla [condición]

SELECT * FROM tabla1 RIGHT JOIN tabla2 USING(columna);

Es lo mismo usar una composición derecha de las tablas tabla1 y tabla2 que una composición
izquierda de las tablas tabla2 y tabla1. Es decir, la consulta anterior es equivalente a esta otra:
SELECT * FROM tabla2 LEFT JOIN tabla1 USING(columna);

16.2.18 COMPOSICIÓN NATURAL EXTERNA


Si existen tuplas añadidas con respecto a la composición interna, no se eliminará ninguna
columna.
referencia_tabla NATURAL LEFT [OUTER] JOIN referencia_tabla

referencia_tabla NATURAL RIGHT [OUTER] JOIN referencia_tabla

SELECT * FROM tabla1 NATURAL LEFT JOIN tabla2;

SELECT * FROM tabla1 NATURAL RIGHT JOIN tabla2;

Desarrollo de Aplicaciones Web Dinámicas - UNED


SELECCIÓN DE DATOS 16.7

16.2.19 UNIONES
También es posible realizar la operación unión de álgebra relacional entre varias tablas o proyec-
ciones de tablas. Para hacerlo se usa la sentencia UNION que permite combinar varias sentencias
SELECT para crear una única tabla de salida. Las condiciones para que se pueda crear una unión
son las mismas que se vieron al estudiar el álgebra relacional (las relaciones deben tener el
mismo número de atributos y además deben ser de dominios compatibles).
SELECT * FROM tabla1 UNION

SELECT * FROM tabla2 UNION

SELECT * FROM tabla3;

El resultado se puede ordenar usando ORDER BY y también se puede seleccionar un número


limitado de filas mediante LIMIT.
(SELECT * FROM tabla1) UNION

(SELECT * FROM tabla2) UNION

(SELECT * FROM tabla3) ORDER BY id LIMIT 6;

La sintaxis completa incluye dos modificadores:


SELECT ...

UNION [ALL | DISTINCT]

SELECT ...

[UNION [ALL | DISTINCT]

SELECT ...]

Los modificadores ALL y DISTINCT son opcionales, y si no se usa ninguno el comportamiento


es el mismo que si se usa DISTINCT. Con ALL se muestran todas las filas, aunque estén repeti-
das, con DISTINCT sólo se muestra una copia de cada fila.
SELECT columna1, columna2 FROM tabla1 UNION

SELECT columna1, columna2 FROM tabla2 UNION

SELECT columna1, columna2 FROM tabla3;

SELECT columna1, columna2 FROM tabla1 UNION ALL

SELECT columna1, columna2 FROM tabla2 UNION ALL

SELECT columna1, columna2 FROM tabla3;

Sobre el resultado final no se pueden aplicar otras cláusulas como GROUP BY.

Desarrollo de Aplicaciones Web Dinámicas - UNED


16.8 CONSULTAS

16.3 EXPRESIONES REGULARES

Una expresión regular es una forma de especificar un patrón para una búsqueda compleja.
MySQL soporta operaciones de coincidencia de patrones realizadas con los operadoradores
LIKE y REGEXP en sentencias SQL.

Una expresión regular describe un conjunto de cadenas. Ejemplos: 1) La expresión regular


"hola", coincide solamente con "hola". 2) La expresión regular "Hola|mundo", coincide tanto
con la cadena "Hola" como con la cadena "mundo". 3) La expresión regular "B[an]*s", coincide
con cualquiera cadena que empiece con “B”, termine con “s”, y contenga cualquier número de
caracteres “a” o “n” entre la “B” y la “s”.

16.3.1 EXPRESIONES REGULARES CON LIKE


Considerese la siguiente sentencia:
SELECT * FROM tabla WHERE columna LIKE 'g%';

Su resultado son las tuplas de columna de la relación tabla, que empiecen por “g”. Es decir, el
símbolo % hace de comodín.

Otros ejemplo son:


SELECT * FROM tabla WHERE columna LIKE '%g'; (termine en g)

SELECT * FROM tabla WHERE columna LIKE '%g%'; (contenga una g)

SELECT * FROM tabla WHERE columna LIKE '---'; (tenga 3 caracteres)

16.3.2 EXPRESIONES REGULARES CON REGEXP


En esta sección se resumen las características especiales y las construcciones que pueden ser usa-
das en MySQL para operaciones REGEXP. Una expresión regular para el operador REGEXP
puede usar cualquiera de los siguientes caracteres especiales o contrucciones:

Expresión Significado
^ Coincidencia en principio de cadena
$ Coincidencia en final de una cadena
. Coincidencia de cualquier carácter
a* Coincidencia de cualquier secuencia de cero o más caracteres
a+ Coincidencia de cualquier secuencia de uno o más caracteres
a? Coincidencia de ninguno o de un carácter
de|abc Coincidencia de cualquiera de las secuencias “de" o "abc"
a{n} Coincide exactamente con n instancias de a

Desarrollo de Aplicaciones Web Dinámicas - UNED


EXPRESIONES REGULARES 16.9

Expresión Significado
a{m,n} Coincide con un número entre m y n de instancias de a
[a-dX] Coincidencia de cualquier carácter que sea cualquiera entre 'a', 'b',
'c', 'd' o 'X.
[^a-dX] Coincidencia de cualquier carácter que que no sea cualquiera entre
'a', 'b', 'c', 'd' o 'X'
[.caracteres.] Coincide con la secuencia de caracteres
[=clase_carácter=] Coinciden todos los caracteres con el mismo valor de colección
[:clase_carácter:] Coincide con todos los caracteres pertenecientes a la clase
[[:<:]] Coincidencias con el principio de palabras
[[:>:]] Coincidencias con el final de palabras

Tabla 16.1 Expresiones regulares

Ejemplos:
SELECT 'pato' REGEXP '^pa'; (resultado, 1)

SELECT 'pato' REGEXP 'pa$'; (resultado, 0)

SELECT 'cadena' REGEXP '.'; (resultado, 1)

SELECT 'pato' REGEXP '^pa.'; (resultado, 1)

SELECT 'Bn' REGEXP '^Ba*n'; (resultado, 1)

SELECT 'Bn' REGEXP '^Ba+n'; (resultado, 0)

SELECT 'Baan' REGEXP '^Ba?n'; (Resultado, 0)

SELECT 'pi' REGEXP 'pi|apa'; (Resultado, 1)

mysql> SELECT 'pip' REGEXP '^(pi)*$'; (Resultado, 0)

SELECT 'abcde' REGEXP 'a[bcd]{3}e'; (Resultado, 1)

SELECT 'abcde' REGEXP 'a[bcd]{1,10}e';(resultado, 1)

SELECT 'aXbc' REGEXP '^[a-dXYZ]$'; (Resultado, 0)

SELECT 'gheis' REGEXP '^[^a-dXYZ]+$'; (resultado, 1)

SELECT '~' REGEXP '[[.~.]]'; (resultado, 1)

SELECT 'justalnums' REGEXP '[[:alnum:]]+'; (resultado, 1)

SELECT 'a xword a' REGEXP '[[:<:]]word[[:>:]]'; (resultado,0)

Para usar una instancia literal de un carácter especial en una expresión regular, hay que prece-
derlo por dos caracteres de barra de bajada (\). El analizador sintáctico de MySQL interpreta una
de las barras, y la librería de expresiones regulares interpreta la otra. Por ejemplo, para buscar la

Desarrollo de Aplicaciones Web Dinámicas - UNED


16.10 CONSULTAS

coincidencia de la cadena "1+2" que contiene el carácter especial '+', sólo la última de las
siguientes expresiones regulares es correcta:
mysql> SELECT '1+2' REGEXP '1+2';

mysql> SELECT '1+2' REGEXP '1\+2';

mysql> SELECT '1+2' REGEXP '1\\+2';

Los nombres de clases estándar son: 1) alnum,caracteres alfanuméricos.2) alpha, caracteres alfa-
béticos. 3) blank,carácteres espacio. 4) cntrl, caracteres de control. 5) digit, dígitos. 6) graph,
caracteres gráficos. 7) lower, caracteres alfabéticos en minúsculas. 8) print, caracteres gráficos o
espacios. 9) punct, caracteres de puntuación. 10). space, espacio, tabulador, cambio de línea y
retorno de línea. 11) upper, caracteres alfabéticos en mayúsculas. 12) xdigit, dígitos hexadecima-
les.
SELECT 'justalnums' REGEXP '[[:alnum:]]+'; (resultado, 1)

SELECT '!!' REGEXP '[[:alnum:]]+'; (resultado, 0)

16.4 OPERADORES

En MySQL existen diferentes operadores, para cada tipo de datos, y se utilizan para construir
expresiones. Las expresiones se evalúan de izquierda a derecha. Dentro de una expresión el
orden de prioridad entre los operadores (de menos a mayor) es: 1) :=. 2) ||, OR, XOR. 3) &&,
AND. 4) NOT. 5) BETWEEN, CASE, WHEN, THEN, ELSE. 6) =, <=>, >=, >, <=, <, <>, !=, IS,
LIKE, REGEXP, IN. 7) |. 8) &. 9) <<, >>. 10) *, /, DIV, %, MOD. 11) - (unitario), ~ (comple-
mento). 12) !. 13) BINARY, COLLATE. También se pueden utilizar paréntesis para forzar el
orden de evaluación de las operaciones dentro de una expresión. Las expresión entre paréntesis
se evalúan antes que el resto de las operaciones en el mismo nivel de paréntesis.

16.4.1 OPERADOR DE ASIGNACIÓN

Operador de asignación :=
Permite asignar un valor a una variable mediante la sentencia SELECT. Una variable sin asignar
será de tipo cadena y tendrá el valor NULL.
SELECT @variable:=valor;

Asignación con el signo de igualdad =


Otra posibilidad para asignar un valor a una variable es utilizar el signo de igualdad y la senten-
cia SET.
SET @variable = valor;

Desarrollo de Aplicaciones Web Dinámicas - UNED


OPERADORES 16.11

16.4.2 OPERADORES LÓGICOS


Los operadores lógicos se utilizan para crear expresiones lógicas y permiten el uso de Álgebra de
Bool. En dicho álgebra las variables sólo pueden tomar un valor entre dos valores posibles, ver-
dadero y falso (TRUE o 1 y FALSE o 0). En MySQL se añade un tercer valor NULL.

Operador Y (AND o &&)


El resultado es verdadero sólo si A y B son verdaderos, y falso en el resto de los casos. Sintaxis:
A AND B

A B A AND D
FALSE FALSE FALSE
FALSE TRUE FALSE
TRUE FALSE FALSE
TRUE TRUE TRUE
FALSE NULL FALSE
NULL FALSE FALSE
TRUE NULL NULL
NULL TRUE NULL

Tabla 16.2 Tabla de verdad del operador AND

Operador O (OR o ||)


El resultado es verdadero cuando A o B o ambos lo son. Sintaxis:

A OR B

A B A OR D
FALSE FALSE FALSE
FALSE TRUE TRUE
TRUE FALSE TRUE
TRUE TRUE TRUE
FALSE NULL NULL
NULL FALSE NULL
TRUE NULL TRUE
NULL TRUE TRUE

Tabla 16.3 Tabla de verdad del operador OR

Desarrollo de Aplicaciones Web Dinámicas - UNED


16.12 CONSULTAS

Operador O exclusivo (XOR)


El resultado es verdadero si uno de los operandos es verdadero, y falso si ambos son verdaderos
o ambos falsos. Sintaxis:

A XOR B

A B A XOR D
FALSE FALSE FALSE
FALSE TRUE TRUE
TRUE FALSE TRUE
TRUE TRUE FALSE
FALSE NULL NULL
NULL FALSE NULL
TRUE NULL NULL
NULL TRUE NULL

Tabla 16.4 Tabla de verdad del operador XOR

Operador de negación (NOT o !)


El resultado es verdadero si A es falso, y viceversa. Sintaxis:

NOT A

A NOT A
FALSE TRUE
TRUE FALSE
NULL NULL

Tabla 16.5 Tabla de verdad del operador NOT

16.4.3 OPERADORES DE COMPARACIÓN


Estos operadores realizan una comparación entre dos expresiones y devuelven como resultado
uno de los valores lógicos verdadero o falso (1 o 0).
<expresión> operador <expresión>

Operador igualdad =
Compara dos expresiones y da como resultado 1 si son iguales, o 0 si son diferentes. Se pueden
comparar valores de tipos diferentes.

Desarrollo de Aplicaciones Web Dinámicas - UNED


OPERADORES 16.13

Operador igualdad con NULL seguro <=>


Es similar al operador igualdad, salvo que si en la comparación una o ambas de las expresiones
es nula el resultado no es NULL. Si se comparan dos expresiones nulas, el resultado es verda-
dero.

Operador desigualdad <>, !=


Si las expresiones comparadas son diferentes, el resultado es verdadero, y si son iguales, el resul-
tado es falso.

Operadores menor o igual <=, menor <, mayor >, mayor o igual >=
Comparan dos expresiones dan como resultado 1 si se cumple la comparación, o 0 si no se cum-
ple. Cuando se comparan cadenas, se considera menor la cadena que aparezca antes por orden
alfabético. Si son fechas, se considera que es menor cuanto más antigua sea. En el caso de cade-
nas con números la comparación se realiza en el orden en que aparecen.

16.4.4 OPERADORES ARITMÉTICOS


Los operadores aritméticos se aplican a valores numéricos enteros o de coma flotante. El resul-
tado siempre es un valor numérico, entero o de coma flotante. En el caso de los operadores de
suma, resta, cambio de signo y multiplicación, si los operandos son enteros, el resultado se cal-
cula usando el tipo BIGINT, es decir, enteros de 64 bits. Hay que tener esto en cuenta, sobre todo
en el caso de números grandes. El resultado de las divisiones, por regla general, es un número de
coma flotante. Dividir por cero produce como resultado el valor NULL. El operador división
entera calcula la parte entera del cociente.

Operador Símbolo
Suma +
Resta -
Cambio de signo -
Multiplicación *
División /
División entera DIV

Tabla 16.6 Operadores aritmáticos

16.4.5 OPERADORES DE BITS


Todos los operadores de bits trabajan con enteros BIGINT, es decir con 64 bits. Los bits pueden
tomar valores 0 o 1, pero no valores nulos

Desarrollo de Aplicaciones Web Dinámicas - UNED


16.14 CONSULTAS

Operadores de bits O (|), Y (&), XOR (^), NOT (~)


Son equivalentes a los operadores OR, AND, XOR y NOT lógicos pero aplicados bit a bit entre
valores enteros de 64 bits. Sintaxis:
A | B, A & B, A^B, ~A.

Operador de desplazamiento a la izquierda <<


Los bits del primer operando se desplazan a la izquieda tantos bits como indique el segundo ope-
rando. Por la derecha se introducen otros tantos bits con valor 0. Los bits de la parte izquierda
que no caben en los 64 bits, se pierden. Sintaxis:
A << B

Operador de desplazamiento a la derecha >>


Los bits del primer operando se desplazan a la derecha tantos bits como indique el segundo ope-
rando. Por la izquieda se introducen otros tantos bits con valor 0. Los bits de la parte derecha que
no caben en los 64 bits, se pierden. Sintaxis:
A >> B

Contar bits
Devuelve el número de bits iguales a 1 que contiene el argumento especificado. Sintaxis:
BIT_COUNT()

16.4.6 OPERADORES COMPARACIÓN DE CADENAS


Se trata de operadores para comparación de cadenas, con patrones y con expresiones regulares
(no distingue mayúsculas de minúsculas, salvo que se indique lo contrario). Los patrones son
cadenas de caracteres en las que pueden aparecer los caracteres '%' (coincidencia con cualquier
número de caracteres) y '_' (coincidencia con un único carácter). Tanto si la cadena como el
patrón son NULL, el resultado es NULL. Cuando se usan caracteres concretos para crear patro-
nes, se presenta la dificultad de hacer comparaciones cuando se buscan esos caracteres concretos.
Esta dificultad se supera mediante secuencias de escape. El carácter utilizado para escapar es '\'.
Si se quiere que el patrón contenga los caracteres '%' o '_', se escaparán mediante '\%' y '\_'. Se
pueden utilizar otros caracteres para crear secuencias de escape mediante la cláusula ESCAPE.
Estos operadores también funciona con expresiones numéricas. Otros caracteres como '\n', '\r', ...
también son secuencias de escape, y si se quieren usar como literales, será necesario escaparlos
también.

Operadores LIKE y NOT LIKE


Se utiliza para hacer comparaciones entre cadenas y patrones. Para LIKE, el resultado es verda-
dero (1) si la cadena se ajusta al patrón, y falso (0) en caso contrario.
<expresión> LIKE <patrón> [ESCAPE 'carácter_escape']

Desarrollo de Aplicaciones Web Dinámicas - UNED


OPERADORES 16.15

<expresión> NOT LIKE <patrón> [ESCAPE 'carácter_escape']

Equivale a:
NOT (<expresión> LIKE <patrón> [ESCAPE 'carácter_escape'])

Operadores REGEXP, RLIKE, NOT REGEXP, NOT RLIKE


El operador REGEXP y su equivalente RLIKE, comparan una expresión con un patrón, pero en
este caso, el patrón puede ser una expresión regular extendida. El valor de retorno es verdadero
(1) si la expresión coincide con el patrón, en caso contrario devuelve un valor falso (0). Tanto si
la expresión como el patrón son nulos, el resultado es NULL. El patrón no tiene que ser necesa-
riamente una cadena, puede ser una expresión o una columna de una tabla.
<expresión> RLIKE <patrón>

<expresión> REGEXP <patrón>

<expresión> NOT RLIKE <patrón>

<expresión> NOT REGEXP <patrón>

Equivalen a:
NOT (<expresión> REGEXP <patrón>)

16.4.7 OTROS OPERADORES

Operadores IS NULL e IS NOT NULL


Sirven para verificar si una expresión determinada es o no nula.
<expresión> IS NULL

<expresión> IS NOT NULL

Operador BETWEEN
Se utiliza para comprobar si una expresión está comprendida en un determinado rango de valo-
res.
<expresión> BETWEEN mínimo AND máximo

<expresión> NOT BETWEEN mínimo AND máximo

Operador COALESCE
Sirve para seleccionar el primer valor no nulo de una lista o conjunto de expresiones.
COALESCE(<expr1>, <expr2>, <expr3>...)

Operadores GREATEST y LEAST


Devuelven el valor máximo y mínimo, respectivamente, de la lista de expresiones dada. La lista
de expresiones debe contener al menos dos valores. Los argumentos se comparan según las
siguientes reglas: 1) Si el valor de retorno se usa en un contexto entero, o si todos los elementos

Desarrollo de Aplicaciones Web Dinámicas - UNED


16.16 CONSULTAS

de la lista son enteros, estos se comparan entre si como enteros. 2) Si el valor de retorno se usa en
un contexto real, o si todos los elementos son valores reales, serán comparados como reales. 3) Si
cualquiera de los argumentos es una cadena sensible al tipo (mayúsculas y minúsculas son carac-
teres diferentes), los argumentos se comparan como cadenas sensibles al tipo. 4) En cualquier
otro caso, los argumentos se comparan como cadenas no sensibles al tipo.
GREATEST(<expr1>, <expr2>, <expr3>...)

LEAST(<expr1>, <expr2>, <expr3>...)

Operadores IN y NOT IN
Se utilizan para averiguar si el valor de una expresión determinada está dentro de un conjunto
indicado. El operador IN devuelve un valor verdadero, 1, si el valor de la expresión es igual a
alguno de los valores especificados en la lista. El operador NOT IN devuelve un valor falso en el
mismo caso.
IN (<expr1>, <expr2>, <expr3>...)

NOT IN (<expr1>, <expr2>, <expr3>...)

Operador ISNULL
Equivalente a IS NULL.
ISNULL(<expresión>)

Operador INTERVAL
Se utiliza para calcular el intervalo al que pertenece un valor. Si el valor de la expresión es menor
que límite 1, el operador devuelve el valor 0, si es mayor o igual que límite1 y menor que limite2,
devuelve el valor 1, etc. Todos los valores de los límites deben estar ordenados.

INTERVAL(<expresión>, <límite1>, <limite1>, <limite3>...)

Operador CASE
Se trata de un operador de control de flujo. Existen dos sintaxis para CASE, la primera forma
devuelve el resultado para el valori que coincida con valor y la segunda forma devuelve el resul-
tado para la primera condición verdadera. Si no hay coincidencias, se devuelve el valor asociado
al ELSE, o NULL si no hay parte ELSE.
CASE valor WHEN [valor1] THEN resultado1

[WHEN [valori] THEN resultadoi ...]

[ELSE resultado] END

CASE WHEN [condición1] THEN resultado1

[WHEN [condicióni] THEN resultadoi ...]

[ELSE resultado] END

Desarrollo de Aplicaciones Web Dinámicas - UNED


FUNCIONES 16.17

Operador BINARY
Se trata de un operador de casting. Convierte una cadena de caracteres en una cadena binaria. Si
se aplica a una cadena que forma parte de una comparación, se distinguirán mayúsculas de
minúsculas. Los espacios al final de la cadena se tienen en cuenta en la comparación. Cuando se
usa en comparaciones, afecta a la comparación en conjunto, es indiferente que se aplique a cual-
quiera de las dos cadenas.
BINARY cadena

16.5 FUNCIONES

A continuación se indican los distintos tipos de funciones disponibles en MySQL.

Funciones de control de flujo


• IF. Elección en función de una expresión booleana.
• IFNULL. Elección en función de si el valor de una expresión es NULL
• NULLIF. Devuelve NULL en función del valor de una expresión

Funciones matemáticas
• ABS. Devuelve el valor absoluto
• ACOS. Devuelve el arcocoseno
• ASIN. Devuelve el arcoseno
• ATAN y ATAN2. Devuelven el arcotangente
• CEILING y CEIL. Redondeo hacia arriba
• COS. Coseno de un ángulo
• COT. Cotangente de un ángulo
• CRC32. Cálculo de comprobación de redundancia cíclica
• DEGREES. Conversión de grados a radianes
• EXP. Cálculo de potencias del número e
• FLOOR. Redondeo hacia abajo
• LN. Logaritmo natural
• LOG. Logaritmo en base arbitraria
• LOG10. Logaritmo en base 10
• LOG2. Logaritmo en base dos
• MOD o %. Resto de una división entera
• PI. Valor del número pi
• POW o POWER. Valor de potencias
• RADIANS. Conversión de radianes a grados
• RAND. Valores aleatorios
• ROUND. Cálculo de redondeos
• SIGN. Devuelve el signo

Desarrollo de Aplicaciones Web Dinámicas - UNED


16.18 CONSULTAS

• SIN. Cálculo del seno de un ángulo


• SQRT. Cálculo de la raíz cuadrada
• TAN. Cálculo de la tangente de un ángulo
• TRUNCATE. Elimina decimales

Funciones de cadenas
• ASCII. Valor de código ASCII de un carácter
• BIN. Converión a binario
• BIT_LENGTH. Cálculo de longitud de cadena en bits
• CHAR. Convierte de ASCII a carácter
• CHAR_LENGTH o CHARACTER_LENGTH. Cálculo de longitud de cadena en caracte-
res
• COMPRESS. Comprime una cadena de caracteres
• CONCAT. Concatena dos cadenas de caracteres
• CONCAT_WS. Concatena cadenas con separadores
• CONV. Convierte números entre distintas bases
• ELT. Elección entre varias cadenas
• EXPORT_SET. Expresiones binarias como conjuntos
• FIELD. Busca el índice en listas de cadenas
• FIND_IN_SET. Búsqueda en listas de cadenas
• HEX. Conversión de números a hexadecimal
• INSERT. Inserta una cadena en otra
• INSTR. Busca una cadena en otra
• LEFT. Extraer parte izquierda de una cadena
• LENGTH u OCTET_LENGTH. Calcula la longitud de una cadena en bytes
• LOAD_FILE. Lee un fichero en una cadena
• LOCATE o POSITION. Encontrar la posición de una cadena dentro de otra
• LOWER o LCASE. Convierte una cadena a minúsculas
• LPAD. Añade caracteres a la izquierda de una cadena
• LTRIM. Elimina espacios a la izquierda de una cadena
• MAKE_SET. Crea un conjunto a partir de una expresión binaria
• OCT. Convierte un número a octal
• ORD. Obtiene el código ASCII, incluso con caracteres multibyte
• QUOTE. Entrecomilla una cadena
• REPEAT. Construye una cadena como una repetición de otra
• REPLACE. Busca una secuencia en una cadena y la sustituye por otra
• REVERSE. Invierte el orden de los caracteres de una cadena
• RIGHT. Devuelve la parte derecha de una cadena
• RPAD. Inserta caracteres al final de una cadena
• RTRIM. Elimina caracteres blancos a la derecha de una cadena

Desarrollo de Aplicaciones Web Dinámicas - UNED


FUNCIONES 16.19

• SOUNDEX. Devuelve la cadena "soundex" para una cadena concreta


• SOUNDS LIKE. Compara cadenas según su pronunciación
• SPACE. Devuelve cadenas consistentes en espacios
• SUBSTRING o MID. Extraer subcadenas de una cadena
• SUBSTRING_INDEX. Extraer subcadenas en función de delimitadores
• TRIM. Elimina sufijos y/o prefijos de una cadena.
• UCASE o UPPER. Convierte una cadena a mayúsculas
• UNCOMPRESS. Descomprime una cadena comprimida mediante COMPRESS
• UNCOMPRESSED_LENGTH. Calcula la longitud original de una cadena comprimida
• UNHEX. Convierte una cadena que representa un número hexadecimal a cadena de carac-
teres

Funciones de comparación de cadenas


• STRCMP.Compara cadenas

Funciones de fecha
• ADDDATE. Suma un intervalo de tiempo a una fecha
• ADDTIME. Suma tiempos
• CONVERT_TZ. Convierte tiempos entre distintas zonas horarias
• CURDATE o CURRENTDATE. Obtener la fecha actual
• CURTIME o CURRENT_TIME. Obtener la hora actual
• DATE. Extraer la parte correspondiente a la fecha
• DATEDIFF. Calcula la diferencia en días entre dos fechas
• DATE_ADD. Aritmética de fechas, suma un intervalo de tiempo
• DATE_SUB. Aritmética de fechas, resta un intervalo de tiempo
• DATE_FORMAT. Formatea el valor de una fecha
• DAY o DAYOFMONTH. Obtiene el día del mes a partir de una fecha
• DAYNAME. Devuelve el nombre del día de la semana
• DAYOFWEEK. Devuelve el índice del día de la semana
• DAYOFYEAR. Devuelve el día del año para una fecha
• EXTRACT. Extrae parte de una fecha
• FROM_DAYS. Obtener una fecha a partir de un número de días
• FROM_UNIXTIME. Representación de fechas UNIX en formato de cadena
• GET_FORMAT. Devuelve una cadena de formato
• HOUR. Extrae la hora de un valor time
• LAST_DAY. Devuelve la fecha para el último día del mes de una fecha
• MAKEDATE. Calcula una fecha a partir de un año y un día del año
• MAKETIME. Calcula un valor de tiempo a partir de una hora, minuto y segundo
• MICROSECOND. Extrae los microsegundos de una expresión de fecha/hora o de hora
• MINUTE. Extrae el valor de minutos de una expresión time

Desarrollo de Aplicaciones Web Dinámicas - UNED


16.20 CONSULTAS

• MONTH. Devuelve el mes de una fecha


• MONTHNAME. Devuelve el nombre de un mes para una fecha
• NOW o CURRENT_TIMESTAMP o LOCALTIME o LOCALTIMESTAMP o SYSDATE
. Devuelve la fecha y hora actual
• PERIOD_AD. DAñade meses a un periodo (año/mes)
• PERIOD_DIFF. Calcula la diferencia de meses entre dos periodos (año/mes)
• QUARTER. Devuelve el cuarto del año para una fecha
• SECOND. Extrae el valor de segundos de una expresión time
• SEC_TO_TIME. Convierte una cantidad de segundos a horas, minutos y segundos
• STR_TO_DATE. Obtiene un valor DATETIME a partir de una cadena con una fecha y una
cadena de formato
• SUBDATE. Resta un intervalo de tiempo de una fecha
• SUBTIME. Resta dos expresiones time
• TIME. Extrae la parte de la hora de una expresión fecha/hora
• TIMEDIFF. Devuelve en tiempo entre dos expresiones de tiempo
• TIMESTAMP. Convierte una expresión de fecha en fecha/hora o suma un tiempo a una
fecha
• TIMESTAMPADD. Suma un intervalo de tiempo a una expresión de fecha/hora
• TIMESTAMPDIFF. Devuelve la diferencia entre dos expresiones de fecha/hora
• TIME_FORMAT. Formatea un tiempo
• TIME_TO_SEC. Convierte un tiempo a segundos
• TO_DAYS. Calcula el número de días desde el año cero
• UNIX_TIMESTAMP. Devuelve un timestamp o una fecha en formato UNIX, segundos
desde 1070
• UTC_DATE. Devuelve la fecha UTC actual
• UTC_TIME. Devuelve la hora UTC actual
• UTC_TIMESTAMP. Devuelve la fecha y hora UTC actual
• WEEK. Calcula el número de semana para una fecha
• WEEKDAY. Devuelve el número de día de la semana para una fecha
• WEEKOFYEAR. Devuelve el número de la semana del año para una fecha
• YEAR. Extrae el año de una fecha
• YEARWEEK. Devuelve el año y semana de una fecha

Funciones de búsqueda de texto


• MATCH

Funciones de casting (conversión de tipos)


• CAST o CONVERT. Conversión de tipos explícita

Desarrollo de Aplicaciones Web Dinámicas - UNED


FUNCIONES 16.21

Funciones de encriptado
• AES_ENCRYPT y AES_DECRYPT. Encriptar y desencriptar datos usando el algoritmo
oficial AES
• DECODE. Desencripta una cadena usando una contraseña
• ENCODE. Encripta una cadena usando una contraseña
• DES_DECRYPT. Desencripta usando el algoritmo Triple-DES
• DES_ENCRYPT. Encripta usando el algoritmo Triple-DES
• ENCRYPT. Encripta str usando la llamada del sistema Unix crypt()
• MD5. Calcula un checksum MD5 de 128 bits para la cadena string
• PASSWORD u OLD_PASSWORD. Calcula una cadena contraseña a partir de la cadena
en texto plano
• SHA o SHA1. Calcula un checksum SHA1 de 160 bits para una cadena

Funciones de información
• BENCHMARK. Ejecuta una expresión varias veces
• CHARSET. Devuelve el conjunto de caracteres de una cadena
• COERCIBILITY. Devuelve el valor de restricción de colección de una cadena
• COLLATION. Devuelve la colección para el conjunto de caracteres de una cadena
• CONNECTION_ID. Devuelve el ID de una conexión
• CURRENT_USER. Devuelve el nombre de usuario y el del host para la conexión actual
• DATABASE. Devuelve el nombre de la base de datos actual
• FOUND_ROWS. Calcular cuántas filas se hubiesen obtenido en una sentencia SELECT
sin la cláusula LIMIT
• LAST_INSERT_ID. Devuelve el último valor generado automáticamente para una
columna AUTO_INCREMENT
• USER o SESSION_USER o SYSTEM_USER. Devuelve el nombre de usuario y host
actual de MySQL
• VERSION. Devuelve la versión del servidor MySQL

Miscelánea
• DEFAULT. Devuelve el valor por defecto para una columna
• FORMAT. Formatea el número según la plantilla '#,###,###.##
• GET_LOCK. Intenta obtener un bloqueo con el nombre dado
• INET_ATON. Obtiene el entero equivalente a la dirección de red dada en formato de cuar-
teto con puntos
• INET_NTOA. Obtiene la dirección en formato de cuarteto con puntos dado un entero
• IS_FREE_LOCK. Verifica si un nombre de bloqueo está libre
• IS_USED_LOCK. Verifica si un nombre de bloqueo está en uso
• MASTER_POS_WAIT. Espera hasta que el esclavo alcanza la posición especificada en el
diario maestro

Desarrollo de Aplicaciones Web Dinámicas - UNED


16.22 CONSULTAS

• RELEASE_LOCKLibera un bloqueo
• UUIDDevuelve un identificador único universal

Funciones de grupos
• AVG. Devuelve el valor medio
• BIT_AND. Devuelve la operación de bits AND para todos los bits de una expresión
• BIT_OR. Devuelve la operación de bits OR para todos los bits de una expresión
• BIT_XOR. Devuelve la operación de bits XOR para todos los bits de una expresión
• COUNT. Devuelve el número de valores distintos de NULL en las filas recuperadas por
una sentencia SELECT
• COUNT DISTINCT. Devuelve el número de valores diferentes, distintos de NULL
• GROUP_CONCAT. Devuelve una cadena con la concatenación de los valores de un grupo
• MIN. Devuelve el valor mínimo de una expresión
• MAX. Devuelve el valor máximo de una expresión
• STD o STDDEV. Devuelve la desviación estándar de una expresión
• SUM. Devuelve la suma de una expresión
• VARIANCE. Devuelve la varianza estándar de una expresión

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 17

Tecnología PHP

17.1 INTRODUCCIÓN

PHP es un lenguaje de programación relativamente nuevo, concebido principalmente como


herramienta de desarrollo de aplicaciones Web. PHP permite diseñar páginas dinámicas de servi-
dor, es decir, genera páginas bajo petición capaces de responder de manera inteligente a las
demandas del cliente y que sean capaces de la automatización de gran cantidad de tareas.

Si fuese necesario definir PHP en una sola línea, podría decirse que se trata de un lenguaje inter-
pretado de alto nivel embebido en páginas HTML (o XHTML) y ejecutado en el servidor.

Aunque existe una multitud de lenguajes y entornos de desarrollo concebidos para Internet, PHP
se ha convertido en uno de los lenguajes, del lado del servidor, más ampliamente utilizados para
el desarrollo de páginas dinámicas junto con ASP, JSP, ColdFusion y Perl. En los últimos años, el
número de servidores que utilizan PHP se ha disparado. De hecho, según datos de Netcraft, en
Agosto de 2004 eran casi 17 millones de dominios los que usaban PHP.

En PHP se combinan muchas características que contribuyen notablemente a su masiva utiliza-


ción; entre otras, está el hecho de ser un software de libre distribución y multiplataforma (existen
versiones de PHP para Unix, Windows, Linux, Mac, OS X, etc.) que sigue la filosofía Open
Source.

También ha contribuido a su éxito el hecho de haberse concertido en el complemento ideal para


el popular tandem Linux-Apache en el desarrollo de sitios Web. Pero lo más destacable del len-
guaje y una de las características que más han influido en su popularización es la sencillez de uso
que presenta a los programadores pincipiantes (se pueden desarrollar aplicaciones sencillas en un
corto intervalo de tiempo) combinada con las posibilidades avanzadas que proporciona al progra-
mador profesional (comunicación con bases de datos, comunicación via socket, generación de
gráficos, etc.).
17.2 TECNOLOGÍA PHP

17.2 UN POCO DE HISTORIA

17.2.1 PRIMEROS COMIENZOS DE PHP


PHP comenzó siendo un conjunto de scripts escritos en Perl que permitían a su creador, Rasmus
Lerdorf, el control de los accesos a sus páginas personales. A este conjunto de scripts les deno-
minó Personal Home Page Tools. . Poco a poco, Ramus fue completando las funcionalidades
básicas de su herramienta escribiendo programas en C. En 1995 decidió liberar el código fuente
escrito en C para que cualquiera pudiera utilizarlo e, incluso. colaborar en su mejora. De este
modo nació PHP/Fl.

A finales de 1997 se libera PHP/FI 2.0, pasando de ser el proyecto de una sola persona al desa-
rrollo de un equipo. Tuvo un seguimiento estimado de varios miles de usuarios en todo el mundo.
con aproximadamente 50.000 dominios informando que lo tenían instalado, lo que sumaba alre-
dedor del 1% de los dominios de Internet.

En junio de 1995 se liberó oficialmente PHP 3.0. anunciado como sucesor oficial de PHP/FI 2.0,
si bien había sido completamente reescrito por Andi Gutmans y Zeev Zuraski. Una de las mejores
características de PHP 3.0 que atrajo a docenas de desarrolladores a unirse y enviar nuevos
módulos de extensión era su gran extensibilidad, además de proveer a los usuarios finales de una
sólida infraestructura para muchísimas bases de datos, protocolos y APIs. En su apogeo, PHP 3.0
estaba instalado en aproximadamente un 10% de los servidores Web en Internet.

17.2.2 EVOLUCIÓN DE PHP


El siguiente paso en la evolución de PHP consistió en la reescritura de su núcleo, dando lugar a
un nuevo motor denominado Zend (acrónimo de los apellidos Zeev y Andi). PHP 4.0, basado en
este motor, y acoplado con un gran rango de nuevas características adicionales, fue oficialmente
liberado en mayo de 2000. Además de la mejora de ejecución de esta versión, PHP 4.0 incluía
otras características clave, como el soporte para la mayoría de los servidores Web, sesiones
HTTP de forma nativa, ciertas facilidades de orientación a objetos, compatibilidad con las expre-
siones regulares de Perl, buffers de salida, encriptación, formas más seguras de controlar las
entradas de usuario y muchas nuevas construcciones de lenguaje, etc.

La última y actual versión de PHP, liberada en Noviembre de 2005 es la 5.1.1. Está basada en el
nuevo motor Zend 2. el cual ha vuelto a ser reescrito por completo. Entre sus características y
novedades más resaltables está el completo soporte para la programación orientada a objetos
(que a buen seguro satisfará a los más apasionados y ortodoxos seguidores de este paradigma de
la programación). También incorpora la gestión de excepciones, una nueva libreria de XML
(libxml12), soporte nativo para el sistema gestor de bases de datos SQLite y mejoras en la ges-
tión de las cadenas de caracteres. PHP 5.0 soporta también MySQLi. una nueva ampliación de
MySQL ( diseñada para trabajar con la versión 4.1.2 o superior), la cual, además de la interfaz
habitual, encierra una interfaz basada en objetos.

Desarrollo de Aplicaciones Web Dinámicas - UNED


COMPARATIVA ENTRE ASP Y PHP 17.3

17.2.3 ¿QUÉ SE PUEDE HACER CON PHP?


Aunque principalmente se utiliza para programar scripts que van a ser ejecutados en servidores
Web, no hay que olvidar que puede utilizarse como cualquier otro lenguaje para escribir progra-
mas que se ejecuten desde la línea de comandos, es decir, sin la necesidad de que se ejecute con-
juntamente con un servidor Web. De todas formas, es en el entorno Web donde ha conseguido su
mayor aceptación, y es que PHPno sólo permite realizar todas las acciones propias de un script
CGI tradicional (procesamiento de formularios, manipulación de cookies, generación de páginas
con contenidos dinámicos...) sino que también proporciona las siguientes posibilidades:
1 Soporte para múltiples sistemas operativos: Unix, Linux, Windows, Mac OS X, RIC OS.
Actualmente está en preparación para plataformas IBM OS/390 y AS/400.
2 Soporte para múltiples servidores Web: Apache, IIS, Personal Web Server, Netscape,etc.
3 Soporte para más de 25 gestores de bases de datos.
4 Soporte para ODBC y extensiones DBX.
5 Soporte para comunicarse con otros servicios usando protocolos como LDAP, IMAP,
SNMP, HTTP, POP3, y muchos otros.
6 Puede utilizar objetos Java de forma transparente como objetos PHP.
7 La extensión CORBA puede ser utilizada para acceder a objetos remotos.
8 Soporta WDDX para intercambio de datos entre lenguajes de programación Web.
9 Generación de resultados en múltiples formatos como XHTML, XML, PDF, Flash, etc.
10 Parser de documentos XML, soporte de los estándares SAX y DOM.
11 Funciones de comercio electrónico.

Y un sinfín de posibilidades que van en aumento cada día.

17.3 COMPARATIVA ENTRE ASP Y PHP

El otro lenguaje utilizado para el diseño de páginas dinámicas de servidor y ampliamente exten-
dido es ASP. Es un lenguaje derivado de Visual Basic (aunque se puede programar en otros len-
guajes como VBScript y JScript) desarrollado por Microsoft. Evidentemente, se emplea
principalmente sobre plataformas que funcionan bajo sistemas operativos Windows (aunque
desde hace poco tiempo existe un software de SUN, Sun ONE Active Server Pages, anterior-
mente conocido como Chili Soft ASP, que permite trabajar con ASP en plataformas Unix/Linux).

PHP es en las plataformas Unix/Linux lo que ASP en las plataformas Windows. De hecho,
ambos lenguajes se insertan en documentos HTML haciendo uso de la emulación de etiquetas
(otros lenguajes como Perl deben generar toda la página HTML de respuesta). Pero lo cierto, es
que, a pesar de sus semejanzas, las diferencias entre ambos lenguajes son muchas. Diferencias
que hacen que la balanza se vaya inclinando hacia PHP como una mejor solución para implemen-
tar aplicaciones Web.

La principal diferencia es que ASP es una tecnología propietaria de Microsoft, mientras que PHP
sigue la filosofia Open Source. Esto hace que ASP esté pensado para funcionar principalmente

Desarrollo de Aplicaciones Web Dinámicas - UNED


17.4 TECNOLOGÍA PHP

sobre plataformas Microsoft, a pesar de que existan soluciones (con un coste económico elevado)
como Sun ONE ASP que permiten su utilización sobre Unix/Linux. Sin embargo, PHP permite
que sin ningún problema, se puedan migrar las aplicaciones Web entre todos los sistemas opera-
tivos y servidores en los que funciona.

La filosofía del producto comercial de ASP influye además en que gran cantidad del software
adicional necesario para complementar una aplicación Web suponga un coste económico adicio-
nal, por ejemplo ASPEncrypt (necesario para la encriptación), ServerObject´s Qmail (gestor de
correo electrónico) o Artisans SAFileup (necesario para le gestión de descargas de ficheros). Sin
embargo, en PHP todas estas opciones están incluidas de forma gratuita.

Finalmente, la comunicación de errores en ASP y su solución por parte de Microsoft es muchí-


simo más lenta que en PHP; las revisiones de software y los parches de errores encontrados tie-
nen un tiempo de periodo de desarrollo largo.

Hay que tener en cuenta que la filosofía Open Source de PHP hace que a lo largo del mundo exis-
tan gran cantidad de equipos comprobando el producto, lo cual permite actualizar el producto
con nuevas versiones y revisiones que solventan sus problemas de una forma mucho más rápida.

A nivel técnico, se pueden dar muchas razones a favor de PHP: entre ellas, una mayor rapidez de
ejecución o una gestión de memoria más acertada. ASP, debido a su propia contrucción (basada
en una arquitectura COM), nunca podrá llegar a ser tan rápido como PHP. Todas las operaciones
ASP están controladas por objetos COM (Response, Request, ADO,File System...). Sin embargo,
PHPestá construido de forma modular; esto quiere decir que todos sus componentes se ejecutan
en el mismo espacio de memoria que PHP. De este modo, el código PHP puede ejecutarse más
rápidamente al no sufrir la sobrecarga impuesta por la comunicación con los diferentes objetos
COM y procesos que soporta ASP. Además, cada compilador de ASP se ejecuta en su propio
proceso, de modo que al comienzo de una etiqueta ASP, se produce un cambio de contexto para
salir del parser HTML y elegir el compilador apropiado, volviendo a realizar un salto de con-
texto al encontrar una etiqueta de cierre ASP para volver de nuevo al parser HTML.

Algunos de los problemas de ASP se resuelven en parte con la última versión del producto
ASP.NET. Si bien hay que tener en cuenta que este producto no puede ser considerado como un
lenguaje de programación de páginas Web, sino más bien como una herramienta de desarrollo de
aplicaciones Web (una de las principales realizaciones es la flexibilidad a la hora de elegir el len-
guaje de programación a utilizar, ASP.NET trabaja con lenguajes de script como VBScript, JSS-
cript; PerlScript y Python y con lenguajes compilados como VB, C#, C, Cobol, Smalltalk y
Lisp).

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 18

Instalación

18.1 INSTALACIÓN

Tal y como se ha comentado en el tema anterior, la configuración en la que se encuentra de forma


más habitual el lenguaje PHP suele ser conjuntamente con Apache como servidor Web y MySQL
como gestor de bases de datos. De hecho, está muy extendido el término LAMP, cuyas iniciales
hacen referencia a Linux, Apache, MySQL y PHP.

Debido a que el editor que se utilizará en el curso es Dreamweaver, el cual corre sobre la plata-
forma Windows, se hará en este apartado una breve descripción de como instalar de manera inte-
grada los productos Apache, MySQL y PHP ya que de no disponer de más de un computador, es
del todo probable que se utilice el mismo ordenador como sistema cliente-servidor.

No obstante, si se desea instalar estos productos sobre una máquina real o virtual (VMWare)
corriendo Linux, se recomienda la lecturan del capítulo 1 del libro de texto PHP5.

18.1.1 MODOS DE FUNCIONAMIENTO


El intérprete PHP puede ser ejecutado como servidor Web de dos modos distintos: como módulo
del propio servidor (interfaz SAPI, Server Application Programming Interface) o como pro-
grama externo a éste (modo CGI, Common Gateway Interface).

A grandes rasgos, ejecutar un programa CGI le supone a la máquina donde se está ejecutando el
servidor Web llamar al sistema operativo para que realice las siguientes tareas básicas:
1 Cargar el programa en memoria.
2 Anotarlo en la lista de tareas.
3 Lanzar su ejecución.
4 Esperar a que termine.
5 Descargarlo de la memoria y de la lista de tareas.
18.2 INSTALACIÓN

Es de perogrullo: tantas veces como un cliente pida la ejecución de un programa CGI, tantas
veces se repetirán estas acciones en la máquina servidora.

Es fácil imaginar que, si el número de peticiones es medio-alto, el rendimiento general de ésta se


verá proporcionalmente degradado, no ya solo por el número de tareas simultáneas a realizar,
sinoocupación de la memoria física del equipo servidor con las copias del programa CGI ejecu-
tándose.

Por otro lado, se puede pensar en un SAPI como un protocolo que permite acceder directamente
a las funciones internas del servidor; por tanto, a través del SAPI se pueden añadir nuevas funcio-
nalidades a un servidor Web (por ejemplo, acceso a bases de datos, autenticación de usuarios,
cacheo de páginas, generación de imágenes al vuelo, etc). Lo más interesante de esta caracterís-
tica es que todas estas nuevas funcionalidades se van a ejecutar de forma más rápida y eficiente
ya que lo van a hacer en el espacio de memoria del propio servidor. Esto significa que las ejecu-
ciones de los programas las hará el propio servidor Web y, por tanto, serán mucho más rápidas y
eficaces.

Existen varios tipos de API´s: Apache API para el servidor Apache, ISAPI de Microsoft para su
producto Internet Information Server, NSAPI de AOL para el servidor iPlanet (antes, Netscape
Enterprise Server) y WSAPI que es el SAPI del servidor Website Pro de O’Reilly.

Además del bajo rendimiento, la versión CGI presenta innumerables problemas de seguridad
asociados.

18.2 INSTALACIÓN EN WINDOWS

PHP está portado para las versiones de Windows de 32 bits, esto es, Windows 95/98/Me y Win-
dows NT/2000/XP/2003.

18.2.1 INSTALACIÓN DE APACHE EN WINDOWS


De las dos ramas de desarrollo del servidor Apache 1.3.x y 2.x, se va a instalar esta última por las
ventajas que ofrece en cuanto a rendimiento y amplia gama de posibilidades; de hecho la versión
2.0 es competitiva con el servidor IIS de Microsoft en cuanto a estabilidad y rendimiento.

De momento, la versión 2.x sólo se recmienda para Windows NT/2000/XP/2003, plataformas


claramente orientadas a travajar como servidores.

En el momento de la edición de este capítulo, la última versión liberada y estable para Windows
es la 2.0.55 la cual se bajará de la dirección http://httpd.apache.org/download.cgi. El fichero en
cuestión es el apache_2.0.55-win32-x86-no_ssl.msi. El nombre del fichero permite saber dos
cosas: que será ejecutado por Microsoft System Installer (extensión msi), y que no incorpora las
librerías Secure Sockets Layer necesarias para instalar un servidor seguo con encriptación: sufijo
_no_ssl.

Desarrollo de Aplicaciones Web Dinámicas - UNED


INSTALACIÓN EN WINDOWS 18.3

Antes de lanzar la ejecución del fichero msi desde el explorador de archivos, si hubiera un servi-
dor Apache ya instalado ( y a demás estuviese funcionando), lo primero que habría que hacer es
detener su ejecución. La instalación de Apache en Windows resulta muy sencilla, basta seguir las
indicaciones y rellenar algunos campos de formulario.

Una vez comienza la ejecución de la instalación y después de la presentación y la aceptación de


los términos de la licencia de uso de este paquete de software, aparecerá otra ventana que pedirá
información como el nombre del dominio donde va a estar colgado el servidor, el nombre con el
que se desea que se de a conocer y la dirección de correo del administrador.

En nuestro caso y como vamos a configurarlo con los siguientes parámetros:


• Network Domain: localhost
• Server Name: localhost
• Administrator´s Email: yo@localhost

En la misma pantalla se nos pide además si queremos que este paquete se instale como servicio
de Windows (se ejecutará de manera automática al arrancar el equipo) en el puerto 80, o bien,
que se instale como una copia para el usuario desde el que se está realizando la instalación y en el
puerto 8080. Se recomienda la primera opción.

Una vez rellenado el formulario aparecerá una pamtalla en la que se nos pedirá el tipo de instala-
ción que deseamos hacer. Elegimos Custom fundamentalmente para ver el directorio donde se
instala y alguna cosa más. Por lo general lo mejor es dejar todo por defecto.

El directorio por omisión donde se instalan todos los ficheros de Apache es c:\Archivos de pro-
grama\Apache Group2\Apache2; allí se crearán entre otros los directorios conf, htdocs (directo-
rio raiz por defecto de los documentos Web), bin, logs,etc.

Para comprobar que, efectivamente se ha realizado la instalación de una forma correcta, se


arranca el servidor (ya está disponible desde el menú: Inicio-->Archivos de Programa--> Apa-
che HTTP Server 2.0.55-> Control Apache Server-> Start). Ahora mediante un navegador,
nos conectamos a la dirección http://127.0.0.1/ y si la instalación ha sido correcta podremos ver
la imagen (Fig. 18.1)

Las operaciones de arrancar y parar el servidor se pueden realizar de tres maneras distintas:
• La primera de ellas es a través del programa monitor que viene con la instalación de Apa-
che Inicio-->Archivos de Programa--> Apache HTTP Server 2.0.55-> Control Apa-
che Server-> Monitor Apache Servers.
• Si está instalado como servicio de Windows, se puede hacer desde el entorno de servicios
del sistema operativo.
• También desde una ventana MS-DOS, donde para arrancarlo habrá que ejecutar el
comando:
- net start apache2
- net stop apache2

Desarrollo de Aplicaciones Web Dinámicas - UNED


18.4 INSTALACIÓN

Figura 18.1 Apache funcionando.

18.2.2 INSTALACIÓN DE PHP EN WINDOWS


Los pasos basicos a realizar para la instalacion de PHP en plataformas Windows son:

Obtención de la última distribución de PHP


En la direccion http://www.php.net/downloads.php encontraremos las versiones binarias
del paquete (validas para todas las versiones Windows de 32bits: Win-9x/Me, Win-NT/
2000/XP). De las dos versiones que alli hay, zip y msi, nos bajaremos la primera puesto
que en ella se incluye tanto la version CGI como la version SAPI para Apache. La ultima
version de PHP 5 estable que encontramos es la 5.1.2. También se entrega una versión en
el DVD-I del curso.

Descomprimir el fichero bajado


Una vez tengamos el fichero en nuestro disco duro, el siguiente paso es descomprimirlo.
Nuestra recomendación es hacerlo bajo un directorio cuyo nombre sea el nombre completo
de la distribución usada (en este caso, c:\php- 5.1.2-win32) dado que PHP es un proyecto
que esta en permanente evolucion y, por tanto, aparecen de forma continua nuevas versio-
nes. Albergar la distribución en una carpeta del disco duro que tenga como parte del nom-
bre el núlmero de distribución evitara mezclar versiones y configuraciones diferentes.

Desarrollo de Aplicaciones Web Dinámicas - UNED


INSTALACIÓN EN WINDOWS 18.5

Configuración de PHP: Librerías y php.ini


Es recomendable que todos los ficheros de PHP (ejecutables, librerias, extensiones y
ficheros de configuracion) estén bajo el directorio donde hemos desempaquetado la distri-
bución. En nuestro caso, y para ambos modos de funcionamiento de PHP (módulo y CGI),
tendremos debajo de c:\php-5.0.1-win32 los ejecutables php.exe y php-cgi.exe, la libreria
php5ts.dll, y el fichero de configuración php.ini.

Para obtener este último, en la misma carpeta c:\php-5.1.2-win32, hacemos una copia de
php.ini-recommended sobre php.ini, y lo editamos según nuestras necesidades (ahora lo
veremos). Por ejemplo, para que PHP sea capaz de encontrar las librerias dinámicas que
ofrecen funcionalidades adicionales (acceso a base de datos, criptografía, generación de
documentos en formato PDF, etc.) necesitamos primero modificar la directiva extension_
dir con la ruta donde se encuentran todas las librerias dinámicas, y luego descomentar la
línea correspondiente a la funcionalidad que queramos. Concretamente, ahora que PHP5
no incorpora por defecto el interfaz de acceso a un servidor MySQL, las modificaciones
que habrá que hacer a php.ini serán:
extension_dir = “c:/php-5.1.2-win32/ext/”
extension = php_mysqli.dll
Además, es necesario copiar la librería dinámica lybmysqli.dll, que se encuentra en la car-
peta de la distribución de PHP, en el directorio c:\windows\system32.

Modificación del fichero httpd.conf de Apache


Si el servidor Web elegido es Apache, hay que indicarle un par de cosas para que ejecute el
interprete PHP cuando se le pidan paginas con extension ` . php'. Con esa intención modi-
ficamos su fichero de configuracion httpd.conf (recomendamos guardar una copia de res-
paldo del fichero de configuración) con cualquier editor de texto (bloc de notas, por
ejemplo).

Es de resaltar que, según estemos hablando de directorios de Windows o de nombres de


directorios en los ficheros de configuracion de Apache, la notación cambia: en el primer
caso, se usará la barra inversa o backslash (“ \ ”), mientras queen el segundo sera la barra
normal o slash (“ / ”).

Después de realizar cualquier modificación en el fichero httpd.conf, es conveniente ejecu-


tar desde una ventana de MS-DOS la instrucción "c:\archivos de programa\apache-
group\apache2\bin\apache.exe -t “, para asegurarnos de que los cambios están bien
hechos, ya que esta instrucción comprueba la sintaxis del fichero de configuración httpd.
conf.

Para que Apache sepa dónde encontrar el fichero de configuracion de PHP (php.ini) modi-
ficamos la directive PHPIniDir:
PHPIniDir “c:/php-5.1.2-win32/”

Desarrollo de Aplicaciones Web Dinámicas - UNED


18.6 INSTALACIÓN

A continuación, veremos que pasos son los necesarios para hacer la instalación de PHP,
bajo Apache en Windows en modo SAPI

Modo SAPI: modificación del fichero httpd.conf de Apache


Para que se ejecute como módulo de Apache, solo hay que asegurarse de que las siguientes
líneas están en el fichero de configuración de Apache:
LoadModule php5_module “c:/php-5.1.2-win32/php5apache2.dll”
AddType application/x-httpd-php .php .phtml

Comprobación de la instalación
Para verificar que PHP se está ejecutando, arrancamos Apache, editamos un fichero que
contenga las tres lineas siguientes:
<?
phpinfo()
?>
en la carpeta "c:\archivos de programa\apache group\apache2\htdocs" con el nombre
'prueba.php', por ejemplo, y con un navegador nos conectamos a esa pagina (http://local-
host/prueba.php).

El resultado, si todo ha ido bien, seria el que aparece en la siguiente imagen (Fig. 18.2)

Figura 18.2 Funcionamiento de PHP.

Desarrollo de Aplicaciones Web Dinámicas - UNED


INSTALACIÓN DE MYSQL EN WINDOWS 18.7

18.3 INSTALACIÓN DE MYSQL EN WINDOWS

Lo primero que hacemos, es bajarnos la última distribución estable de MySQL de la dirección


http://dev.mysql.com/downloads/ (las encontradas en el momento de la edición de este tema fue-
ron la 5.0 y la 4.1) y descomprimirla en un directorio temporal. En principio se puede trabajar
con cualquiera de las dos.

Luego, nos cambiamos a dicho directorio y ejecutamos el programa setup.exe el cual hará la ver-
dadera instalación de este paquete.

El directorio por omisión donde se instala MySQL es c:\mysql. En esta carpeta encontraremos,
entre otros, los directorios bin (donde se almacenan los programas para arrancar y parar el servi-
dor), data (donde se almacenan las bases de datos) y doc (documentacion muy util relativa a la
instalacion, mantenimiento, etc).

El servidor lo podemos arrancara con cualquiera de los comandos mysgld.exe, mysgld-nt.exe o


WinMySQLAdmin. exe. Sin embargo, la primera vez que arrancamos el servidor, dado que tiene
que inicializar bases de datos, tablas, indices, etc., utilizaremos WinMySQLAdmin.exe porque la
primera vez que se ejecuta nos pedirá, por medio de una ventana, el nombre y clave del usuario
(es importante apuntarlo) del sistema bajo el que va a ejecutarse el servidor. También creará el
fichero de configuración c:\windows\my.ini. Una vez que esta arrancado, aparecerá un icono en
forma de semáforo en la zona de notificación de la barra de tareas.

WinNysQLAdmin.exe es una herramienta gráfica gracias a la cual podremos realizar de manera


sencilla e intuitiva la administración de nuestro gestor de base de datos. Con ella podremos cono-
cer datos sobre el equipo servidor donde se está ejecutando, los mensajes que se produjeron al
arrancar el servicio, mensajes de error que hayan ocurrido, variables del sistema, procesos en eje-
cución, bases de datos existentes y sobre todo, podremos editar el fichero de configuración.

Si, por el motivo que fuese, necesitáramos instalar la aplicación en un directorio distinto a
c:\mysql, deberemos incluir en el fichero de configuracion c:\my.cnf las siguientes lineas:
[mysqld]
basedir=UNIDAD:/ruta-instalacion/
datadir=UNIDAD:/ruta-datos/
Para evitar que desde fuera de nuestra máquina sepan que tenemos levantado un servidor
MySQL podemos poner la directiva bind-address=127.0.0.1 en el fichero de configuración
my.ini, o añadirla como opción en la linea de comandos. De cualquiera de las dos formas, el ser-
vidor MySQL solo atenderá en el interfaz de red local.

18.4 INSTALACIÓN EN LINUX

Unix es el nombre genérico con el que se denomina a sistemas operativos tales como GNU/
Linux, Solaris (Sun Microsistems), True64 Unix (Compaq), HPUX (HP), AIX (IBM), etc.); esto
es, con este término no nos referimos a un único sistema operativo, sino a una amplia familia.

Desarrollo de Aplicaciones Web Dinámicas - UNED


18.8 INSTALACIÓN

Tanto es asi, que es frecuente encontrarse con expresiones del tipo *ix o u*ix cuando queremos
referirnos a Unix.

De entre todas estas versiones de Unix elegimos GNU/Linux por varios motivos: fiabilidad, esta-
bilidad, robustez (como todos los Unix), pero, sobre todo, por su precio: es gratuito. La versión
más extendida de Linux/GNU es la que corre en arquitecturas Intel, aunque existen versiones que
se pueden instalar y ejecutar en maquinas Alpha de Compaq, McIntosh de Apple, Sparc de Sun
Microsystems, mainframes S/390 de IBM, etc.

Es habitual que las distribuciones de muchas aplicaciones vengan ya precompiladas (en formato
binario o en formato RPM, RedHad Package Manager) para distintas arquitecturas. Pero, preci-
samente por la amplia diversidad de U*ix que podemos encontrarnos, vamos a ver la instalación
de estos paquetes de la forma más genérica posible: desde los fuentes.

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 19

Fundamentos del lenguaje -I

19.1 INTRODUCCIÓN

La sintaxis de PHP es muy parecida a otros lenguajes de programación muy extendidos como C,
JAVA, Perl o, incluso, el lenguaje de script JavaScript. Por tanto, todos aquellos que estén fami-
liarizados con estos lenguajes, no les será en absoluto complicado el aprendizaje de las instruc-
cions y sentencias que presenta el lenguaje PHP.

El vocabulario de PHP es relativamente pequeño, es fácil de comprender y nos proporciona un


amplio número de posibilidades, antes no disponibles. Además, PHP dispone de un conjunto de
herramientas compactas propias que realzan las iteraciones entre los usuarios y las páginas
HTML, permitiéndonos dar servicio a las peticiones más habituales de una forma sencilla.

Finalmente, PHP ofrece, como veremos, las características básicas de un lenguaje orientado a
objetos, pero sin las complejas realizaciones que a compañan a estos lenguajes como Java y C++.

19.2 FORMATO DEL CÓDIGO PHP

A continuación vamos a ir introduciendo las bases sintácticas de la programación en PHP,


comentando sus aspectos más importantes y viendo algunos ejemplos que nos permitan entender
la utilización de las estructuras, tipos de datos, sentencias e instrucciones que definen el lenguaje.

19.2.1 DELIMITADORES
PHP está muy relacionado con el lenguaje de hipertextos HTML; tanto es así que el código PHP
aparece normalmente insertado dentro de un documento HTML. El documento PHP una vez
interpretado correctamente en el servidor, genera una página HTML que será enviada al cliente
tal y como muestra la figura (Fig. 19.1).
19.2 FUNDAMENTOS DEL LENGUAJE -I

Para diferencial ambos lenguajes dentro de un mismo documento, se utilizan etiquetas de


comienzo y final de código PHP. Las etiquetas más habituales para delimitar los bloque de
código PHP son las siguientes:
<?php
intrucciones PHP
?>
Existen otros posibles formatos de etiquetas, menos utilizados que las anteriores, si bien no todas
estas opciones están disponibles en nuestro sistema por defecto (Ver pag. 68 del libro de texto).

Figura 19.1 Ejecución de código PHP.

Veamos un sencillo ejemplo;


<html>
<head>
<title>Prueba2 PHP</title>
</head>
<body>
<?php
echo "<h2>PHP funciona</h2>";
?>
</body>
</html>

 echo es el comando que permite visualizar por pantalla una variable, cadena de caracteres,
etc.

Una vez guardado el fichero como prueba2.php en la carpeta htdocs de Apache, es posible ejecu-
tarlo introduciendo en el navegador la URL http://127.0.0.1/prueba2.php.

Como se puede observar en el ejemplo anterior, el código PHP se halla inmerso dentro de un
documento HTML que da formato a la página. Habitualmente, encontraremos código PHP inser-
tado en cualquier parte del documento HTML y aparecerá tantas veces como sea necesario. Cada
uno de los bloques de código PHP, al ser procesado, generará una salida en el documento HTML
resultado, justo en la posición en que ese bloque está.

Esto no tiene por qué ser siempre así, es decir, el código PHP también puede formar parte de un
documento que no contenga ninguna etiqueta HTML. De esta manera, el siguiente código produ-
cirá la misma salida que el ejemplo anterior
<?php
echo "<h2>PHP funciona</h2>";

Desarrollo de Aplicaciones Web Dinámicas - UNED


FORMATO DEL CÓDIGO PHP 19.3

?>

19.2.2 COMENTARIOS
Para introducir comentarios dentro del código, PHP ofrece la posibilidad de hacerlo de tres for-
mas diferentes que también son utilizadas por otros lenguajes. Las siguientes porciones de
código nos muestran la utilización de estos diferentes tipos de comentarios.
<HTML>
<HEAD>
<TITLE>Prueba Comentarios</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>
<?php
// Comentario inicial
echo "Primer tipo de comentarios"; // Comentario tipo C, C++
// Comentario final
?>
<BR>
<?php
/* Comentario inicial */
echo "Segundo tipo de comentarios"; /* Comentario tipo C, C++ */
/*
Comentario
Final
*/
?>
<BR>
<?php
# Comentario inicial
echo "Tercer tipo de comentarios"; # Comentario tipo shell
# Comentario Final
?>
</H2>
</CENTER>
</BODY>
</HTML>

Tal y como puede verse en el código anterior, es posible realizar comentarios de una sola línes
(caracter //), multilinea (/* ..... */) o tipo shell (caracter #).

19.2.3 FIN DE LINEA


PHP ignora cualquier carácter de espaciado presente en el código, incluyendo espacios en
blanco, tabuladores y saltos de línea, excepto si se ecuentran dentro de una cadena de texto.

El finde sentencia se marca en todas las instrucciones con el caracter punto y coma (;) o bien
aprovechando la etiqueta de cierre (?>), puesto que se asume que el final de la inclusión de
código limita la introducción de nuevas instrucciones.

Desarrollo de Aplicaciones Web Dinámicas - UNED


19.4 FUNDAMENTOS DEL LENGUAJE -I

19.3 SINTAXIS BÁSICA

Para comenzar a programar en PHP, es necesario conocer más detallez de su sintaxis como son:
tipos de variables que puede aceptar el lenguaje, definición de constantes y tipo y uso de los ope-
radores. Además de las breves reseñas que se darán a continuación, se recomienda la lectura del
capítulo 2 del libro de texto.

19.3.1 VARIABLES
Las variables son una parte fundamental de todo lenguaje de programación. En ellas se almace-
nan valores con los que se puede operar, se pueden comparar entre sí y se puede hacer variar el
flujo del programa en función de su valor. Vamos a ver cómo trabajar con variables en PHP.

Declaración y uso
Al contrario que en la mayoría de lenguajes de programación, en PHP NO hace falta declarar las
variables antes de usarlas: tras la primera aparición en el código quedan declaradas. En PHP
todas las variables llevan delante el signo del dólar ‘$’. Por ejemplo:
$var_1 = 123;
$var_2 = ’hola’;
$var_3 = $var_1 * 2;

 PHP distingue entre mayúsculas y minúsculas. No es lo mismo $var que $Var.

Tipado de las variables


Las variables en PHP están débilmente tipadas. Una variable se asocia a un contenido, del tipo
que sea, estando el tipo indicado en el contenido, no en la variable en sí. Visto de otra forma, una
misma variable se puede reutilizar asignándole a lo largo del tiempo datos de distinto tipo. Por
ejemplo:
$mi_variable = ’Inicializamos como una cadena de texto’;
$mi_variable = 3; // Ahora es un entero.
$mi_variable = 3.14 * $mi_variable; // Ahora un float.
$mi_variable = new MiClase(); // Ahora un objeto.
A pesar de esto, el tipo es importante en algunos casos (para efectuar operaciones o llamadas a
funciones.) En estos casos, PHP se encarga de realizar las transformaciones necesarias de forma
automática.
$mivar = ’3’;
$mivar = 2 + $mivar;
En este caso $mivar comienza almacenando la cadena “3”. En la segunda línea, y para realizar la
suma, se convierte al entero 3, se realiza la suma y se asigna a $mivar el entero 5.

También se puede forzar la conversión a un tipo específico, por ejemplo:


$mivar = (string)123;
Y se puede cambiar el tipo de una variable con la función settype():

Desarrollo de Aplicaciones Web Dinámicas - UNED


SINTAXIS BÁSICA 19.5

$mivar = 12;
settype($mivar, "double");

Variables predefinidas
PHP ofrece una gran cantidad de variables predefinidas a cualquier script que se ejecute en su
sistema. Estas variables, guardan información relativa del entorno de ejecución del intérprete y
del propio PHP. Dependen de factores como el tipo de servidor en el que se ejecuta el intérprete
de PHP, la versión y su configuración entre otras cuestiones.

Estas variables se pueden clasificar, por tanto, en dos grandes grupos: por una parte las que el
entorno, el servidor Web, le pasa al intérprete PHP y, por otra parte, las que el intérprete pone a
disposición del programador. Veamos algunas de las variables más utilizadas.
• SERVER_NAME. Indica el nombre del equipo servidor sobre el que se ejecuta el script.
• SERVER_PORT. Indica el puerto del equipo servidor que usa el servidor Web para la
comunicación.
• SERVER_SOFTWARE. Indica qué software está siendo utilizado en el equipo servidor.
• REMOTE_PORT. Contiene el puerto que utiliza el peticionario para comunicarse con el
servidor Web.
• REMOTE_ADDR. Contiene la dirección remota desde la que se realiza la petición.
• DOCUMENT_ROOT. Indica el directorio raiz del documento bajo el que se ejecuta el
script.
• HTTP_REFERER. Contiene la dirección de la página (en caso de haberla) desde la que
el navegador saltó a la página actual.

 Ejercicio: Realizar un pequeño programa en PHP en el que se muestre el contenido de estas


variables en una conexión.

Estas variables se importan desde el espacio de nombres global de PHP desde el entorno en el
que se está ejecutando el intérprete de PHP. La mayoría es proporcionada por el intérprete de
comandos en el que se está ejecutando PHP. Otras variables de entorno son las CGI, para las que
no importa si PHP se está ejecutando como un módulo del servidor o como un intérprete CGI.

La siguiente lista muestra algunas de las variables que PHP ofrece al programador para facilitar
su tarea.
• argv. Array con los elementos que se pasan al script.
• argc. Indica el número de argumentos que se pasan al script.
• PHP_SELF. Indica el nombre del fichero que contiene el script en ejecución, salvo que se
ejecute PHP como intérprete en la línea de comandos, en cuyo caso no estará disponible.
• _COOKIES. Array asociativo (posteriormente se estudiará) con las variables pasadas a
través de cookies.
• _GET. Array asociativo con las variables pasadas a través del método GET.
• _POST. Array asociativo con las variables pasadas a través del método POST.

Desarrollo de Aplicaciones Web Dinámicas - UNED


19.6 FUNDAMENTOS DEL LENGUAJE -I

• _ENV. Array asociativo con las variables pasadas desde el entorno.


• _SERVER. Array asociativo con las variables pasadas desde el servidor.
• _SESSION. Array asociativo con las variables de la sesión.
• _FILES. Array asociativo con información relativa a los ficheros recibidos a través del
método POST.

 Algunos conceptos como el de array asociativo se estudiarán posteriormente.

19.3.2 TIPOS DE DATOS


PHP soporta tres tipos de datos simples:
• integer.
• float.
• string

y dos tipos de datos compuestos:


• array.
• object.

Además hace uso de un tipo lógico aunque no aparece definido como tal en las sintaxis del len-
guaje:
• boolean.

Enteros
Los números enteros son casi siempre de 32 bits, con signo (salvo en algunas arquitecturas). El
entero más grande representable es, por tanto, 231 y el menor posible es el -(231) + 1 (más/menos
dos mil millones aproximadamente). También se pueden representar números enteros directa-
mente en notación octal, hexadecimal o binaria:
<?
$decimal = 42;
$octal = 0755; // Con un 0 delante
$hexadecimal = 0x45D0D0AF; // Con 0x delante
?>
La función echo muestra por defecto siempre la información en decimal, a pesar de que interna-
mente ésta se haya almacenado en la variable con formato distinto. Ya se verán posteriormente
funciones de PHP que permiten formatear la salida.

Coma flotante
Números en coma flotante de 64 bits, según formato estándar de IEEE (salvo algunas arquitectu-
ras que no lo soportan).
<?
$pi = 3.1416; // Notación normal
$cinco_millones_y_medio = 5.5e6; // Notación científica

Desarrollo de Aplicaciones Web Dinámicas - UNED


SINTAXIS BÁSICA 19.7

$siete_milesimas = 7e-3; // Notación científica


?>

Cadenas
Las cadenas son cadenas de texto ASCII normal y corriente (no Unicode). El tamaño máximo de
una cadena viene limitado únicamente por la cantidad de memoria disponible para el proceso de
PHP que se ejecute en ese momento. No existe el tipo carácter.

Las cadenas se encierran bien en comillas simples (‘ ‘) o bien comillas dobles (“ “). Las diferen-
cias son:
• Las comillas simples no tienen en cuenta ningúun carácter de escape, excepto \ (que se
escapa por una comilla simple) y \\ (que se escapa por una contrabarra).
• Las comillas dobles hacen expansión de variables. Esto es, cualquier nombre de variable
(con dólar incluido) que haya dentro de una cadena con comillas dobles será sustituido por
su valor, siempre y cuando la variable sea de un tipo simple (no compuesto).
• Dentro de comillas dobles, no es necesario escapar la comilla simple.
<?
$nombre = ‘Pepe’;
echo ’Hola $nombre<br>’;
$frase = "Hola $nombre<br>";
echo $frase;
echo "Hola \$nombre<br>";
echo "Las cadenas pueden
ocupar varias líneas
sin ningún problema, incluyendo
saltos de línea, pero
hay que tener cuidado de
cerrar las comillas!";
?>

Figura 19.2 Resultado de la ejecución del código.

Desarrollo de Aplicaciones Web Dinámicas - UNED


19.8 FUNDAMENTOS DEL LENGUAJE -I

Los caracteres de escape son \n, \r, \t, \\, \”, \’, \$ y \x00, donde “00 ”es un número hexadecimal,
lo que se sustituye por el carácter ASCII correspondiente.

Las cadenas en PHP son “binary-safe”, es decir, pueden amacenar contenido que no sea texto, sin
riesgo de perder información (recordemos el \0 de C). Esto permite trabajar con imágenes, sonido
y otros formatos de información.

Nulo
El tipo nulo sólo tiene un valor posible: NULL. Se suele usar como valor de retorno para signifi-
car que no hay datos (lo cual es distinto de un cero decimal, o de una cadena vacía).

Arrays
Los arrays o matrices son estructuras que permiten el almacenamiento de un conjunto de datos
bajo un mismo nombre; son una construcción tradicional de los lenguajes de programación. Se
puede definir un array o matriz como un conjunto ordenado de elementos identificados por un
índice, de modo que en cada posición marcada por el índice el array contiene un valor.

Se pueden contruir tantos índices como se quiera aunque el uso habitual de los arrays es en forma
de matriz unidimensional. En PHP la longitud de un array se modifica de forma dinámica siem-
pre que se le añade un elemento.

En PHP, los arrays pueden estar compuestos de elementos de diferente naturaleza y su primer
elemento o posición es la 0. Además, existen unos arrays especiales denominados asociativos en
los que el índice es un valor de tipo string, de modo que cada posición está definida por el par
(clave, valor), pudiendo acceder al contenido (valor) a través de la clave.

Figura 19.3 Array por índice y asociativo.

La imagen anterior (Fig. 19.3) nos muestra dos posibles estructuras de arrays como un conjunto
de elementos cada uno de los cuales tiene asociada una posición o una clave.

Para manejar un array de forma global, utilizaremos el nombre asignado a la variable que lo con-
tiene y, para manejar cada uno de sus elementos, tendremos que hacer referencia a su posición o
clave dentro del conjunto global.

A modo de introducción y para familiarizarnos con su uso, vamos a ver un ejemplo en el que se
muestra como definir y manejar los arrays de la forma más sencilla. Si bien, dada la importancia
que estos componentes tienen en la programación con PHP, los veremos en detalle más adelante.

Desarrollo de Aplicaciones Web Dinámicas - UNED


SINTAXIS BÁSICA 19.9

<HTML>
<HEAD>
<TITLE>Variables con matrices</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Trabajando con matrices o <I>arrays</I></H2>
<?php
$matriz1[0]="cougar";
$matriz1[1]="ford";
// la tercera posición del array esta vacía
// por eso le asignamos una cadena sin contenido
$matriz1[2]="";
$matriz1[3]="2.500";
$matriz1[4]="V6";
$matriz1[5]=182;
$matriz1[]=182;
// para añadir el último elemento a una matriz
// no es necesario poner el número de índice

// creamos la matriz asociativa


$matriz2['modelo']="cougar";
$matriz2['marca']="ford";
// para marca una posición sin contenido también
// se puede utilizar <null>
$matriz2['fecha']=null;
$matriz2['cc']="2.500";
$matriz2['motor']="V6";
$matriz2['potencia']=182;
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD></TD>
<TD>Modelo</TD>
<TD>Marca</TD>
<TD>Fecha</TD>
<TD>CC</TD>
<TD>Motor</TD>
<TD>Potencia</TD>
</TR>
<TR ALIGN="center">
<TD BGCOLOR="yellow">matriz1</TD>
<?php
echo "<TD> $matriz1[0] </TD>";
echo "<TD> $matriz1[1] </TD>";
echo "<TD> $matriz1[2] </TD>";
echo "<TD> $matriz1[3] </TD>";
echo "<TD> $matriz1[4] </TD>";
echo "<TD> $matriz1[5] </TD>";
?>
</TR>
<TR ALIGN="center">
<TD BGCOLOR="yellow">matriz2</TD>
<?php
echo "<TD>". $matriz2['modelo'] ."</TD>";
echo "<TD>". $matriz2['marca'] ."</TD>";

Desarrollo de Aplicaciones Web Dinámicas - UNED


19.10 FUNDAMENTOS DEL LENGUAJE -I

echo "<TD>". $matriz2['fecha'] ."</TD>";


echo "<TD>". $matriz2['cc'] ."</TD>";
echo "<TD>". $matriz2['motor'] ."</TD>";
echo "<TD>". $matriz2['potencia'] ."</TD>";
?>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>

Figura 19.4 Trabajando con arrays.

Objetos
Si se tiene un conocimiento de la programación orientada a objetos, se entenderá mejor el con-
cepto de objeto; no obstante, a modo de introducción, diremos que un objeto es una estructura
que mantiene en si misma tanto sus características básicas (denominadas propiedades), como las
posibles funcionalidades que admite (denominadas métodos). En capítulos posteriores veremos
con más detalle este tipo de datos, así como la forma en la que se declaran, crean y utilizan dentro
de PHP.

Conversión de tipos
Como antes comentamos, PHP es un lenguaje debilmente tipado, es decir, puede contener distin-
tos tipos o valores a lo largo de su vida. Por tanto, en PHP el tipo de una variable se determina
por el contexto. Asi, una variable a la que se le asigna un valor entero será de tipo integer; si,
seguidamente, sobre esa misma variable se le asigna una cadena de caracteres, la variable en
cuestión pasará a ser de tipo string. Además, cuando operamos con variables de distinto tipo, el
intérprete de PHP tiende a homogeneizar sus diferentes tipos en función de la operación que se
pretende realizar y de los operandos que forman parte de ella.

Un caso muy claro es el que se produce con el operador suma "+". Veámoslo con un ejemplo:
<HTML>

Desarrollo de Aplicaciones Web Dinámicas - UNED


SINTAXIS BÁSICA 19.11

<HTML>
<HEAD>
<TITLE>Conversión automática de tipos</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Conversión de tipos automática</H2>
<?php
$numero=19;
$cadena1="21";
$cadena2="23abc";
$cadena3="2211.5";
$suma=$numero+$cadena1;
echo "El resultado de sumar $numero y '$cadena1' es: $suma <BR>";
$suma=$numero+$cadena2;
echo "El resultado de sumar $numero y '$cadena2' es: $suma <BR>";
$suma=$numero+$cadena3;
echo "El resultado de sumar $numero y '$cadena3' es: $suma <BR>";
$suma=$cadena1+$cadena2;
echo "El resultado de sumar '$cadena1' y '$cadena2' es: $suma
<BR>";
$suma=$cadena1+$cadena3;
echo "El resultado de sumar '$cadena1' y '$cadena3' es: $suma
<BR>";
?>
</CENTER>
</BODY>
</HTML>
El intérprete intentará convertir las cadenas en valores numéricos para que éstos se puedan sumar
correctamente (una cadena que no pueda convertirse a un valor numérico es evaluada con el
valor 0 para poder operar aritméticamente con ella). El resultado que obtenemos lo podernos ver
en la siguiente imagen (Fig. 19.5):

Figura 19.5 Conversión de tipos.

Desarrollo de Aplicaciones Web Dinámicas - UNED


19.12 FUNDAMENTOS DEL LENGUAJE -I

Además de la conversión automática realizada por el intérprete de PHP, es posible convertir las
variables de un tipo a otro cuando el programador lo desee. Se trata de obligar a que una variable
sea evaluada con un tipo concreto. Es similar a la conversión de tipos que se da en el lenguaje C
y que se denomina comúnmente como casting. Para ello se escribe entre paréntesis el tipo
deseado (integer, float, string, boolean, array, object) antes de la variable a la que se pretende
convertir. En el siguiente ejemplo se ven algunas conversiones de tipos:
<HTML>
<HEAD>
<TITLE>Casting de tipos</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Conversión de tipos por <I>casting</I></H2>
<?php
$cadena="3.1416 es el valor de Pi";
echo "El valor de \$cadena es: <B> $cadena </B><BR><BR>";
$aux=(integer)$cadena;
echo "El resultado de convertirla en entero es: $aux <BR>";
$aux=(double)$cadena;
echo "El resultado de convertirla en doble es: $aux <BR>";
?>
</CENTER>
</BODY>
</HTML>
Como podemos observar en la siguiente imagen (Fig. 19.6), el casting de la cadena inicial a
entero nos devuelve un valor de tipo integer en un caso y de tipo float en el otro. De igual forma,
podríamos haber convertido la cadena inicial en cualquiera de los restantes tipos con los que tra-
baja PHP.

Figura 19.6 Conversión de tipos.

Desarrollo de Aplicaciones Web Dinámicas - UNED


SINTAXIS BÁSICA 19.13

19.3.3 OTROS COMPONENTES ASOCIADOS A LAS VARIABLES

Variables de variables
Consiste en reutilizar el valor de las variables como nombre de otra variable al mismo tiempo.
Las variables de variables se pueden establecer y usar dinámicamente; de hecho, habitualmente
se utilizan en scripts en los que se genera código de forma dinámica. El siguiente ejemplo mues-
tra la utilización de este tipo de variables:
<HTML>
<HEAD>
<TITLE>Variables de Variables</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Variables de variables</H2>
<?php
$cadena="modelo";
echo "El valor de \$cadena es: <B> $cadena </B><BR>";
echo 'Después de asignar a $$cadena "Cougar" ...<BR><BR>';
$$cadena="Cougar";
echo "El valor de \$\$cadena es: $$cadena <BR>";
echo "El valor de \$modelo es: $modelo <BR>";
?>
</CENTER>
</BODY>
</HTML>
La siguiente imagen muestra el resultado de visualizar el ejemplo anterior:

Figura 19.7 Variables de variables.

Funciones para variables


PHP proporciona un conjunto de funciones de gran utilidad a la hora de tratar con las variables.
Estas funciones son:

Desarrollo de Aplicaciones Web Dinámicas - UNED


19.14 FUNDAMENTOS DEL LENGUAJE -I

• gettype (variable): Devuelve el tipo de dato pasado comno parámetro, pudiendo devolver
corno valor: integer, float, string, array, class, object y unknown type.
• settype (variable, tipo) : Establece el tipo de dato a guardar en una variable. Tiene dos
argumentos: el nombre de la variable y el tipo que se quiere establecer. Con esta función
podernos realizar conversiones de un tipo de datos a otro. Devolverá valor true si ha tenido
éxito; en caso contrario, devolverá false.

El siguiente ejemplo muestra la utilización de ambas funciones:


<HTML>
<HEAD>
<TITLE>Funciones para Variables</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Usando gettype() y settype() </H2>
<?php
$cadena="3.1416 es el valor de PI";
echo "El valor de \$cadena es: <B> $cadena </B><BR>";
echo "Es de tipo ".gettype($cadena)."<BR><BR>";
settype($cadena,"double");
echo "Si lo paso a doble obtengo : $cadena <BR>";
settype($cadena,"integer");
echo "Si lo paso a entero obtengo : $cadena <BR>";
?>
</CENTER>
</BODY>
</HTML>

Figura 19.8 gettype y settype.

• isset (variable) : Indica si una variable ha sido inicializada con un valor, en cuyo caso
devuelve true y, en caso contrario, devuelve false.

Desarrollo de Aplicaciones Web Dinámicas - UNED


SINTAXIS BÁSICA 19.15

• unset (variable) : Destruye una variable liberando los recursos dedicados a dicha variable.
Es necesario indicar corno parámetro el nombre de la variable a destruir.
• empty (variable) : Devuelve valor true si la variable aún no ha sido inicializada, o bien,
tiene un valor igual a 0 o es una cadena vacía y, en caso contrario, devuelve false.
• is_int(variable), is_integer(variable), is_long(variable): Estas funciones devuelven true
si la variable pasada como argumento es de tipo integer; en caso contrario, devuelven
false.
• is_float(variable), is_real(variable), is_double(variable): Estas funciones devuelven
true si la variable pasada como argumento es de tipo float; en caso contrario, devuelven
false.
• is_numeric (variable) : Esta función devuelve true si la variable pasada como argumento
es un número o una cadena numérica; en caso contrario, devuelve false.
• is_bool (variable) : Esta función devuelve true si la variable pasada como argumento es
de tipo lógico; en caso contrario, devuelve false.
• is_array (variable) : Esta función devuelve true si la variable pasada como argumento es
de tipo array en caso contrario, devuelve false.
• is_string (variable) : Esta función devuelve true si la variable pasada como argumento es
de tipo string; en caso contrario, devuelve false.
• is_obj ect (variable) : Esta función devuelve true si la variable pasada corno argumento es
de tipo obj ect; en caso contrario, devuelve false.
• intval(variable,base), floatval(variable), strval(variable): Estas funciones sirven para
realizar conversiones de tipos (casting), de modo que convierten a integer, float o string,
respectivamente, el valor de la variable que se le pasa como parámetro. Estas funciones no
pueden utilizarse para convertir arrays u objetos. En particular, la función intval( ) puede
recibir además un segundo parámetro que representa la base a utilizar en la conversión
(10-decimal, 8-octal y 16-hexadecimal), tomando por defecto la base 10 de los números
decimales.
<HTML>
<HEAD>
<TITLE>Casting de tipos</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Conversión de variables</H2>
<?php
$cadena="38E6";
echo "El valor de \$cadena es: <B> $cadena </B><BR><BR>";
$aux=intval($cadena);
echo "El resultado de convertirla en entero es: $aux <BR>";
$aux=intval($cadena,8);
echo "El resultado de convertirla en entero octal: $aux <BR>";
$aux=intval($cadena,16);
echo "El resultado de convertirla en entero hexadecimal: $aux
<BR>";
$aux=doubleval($cadena);

Desarrollo de Aplicaciones Web Dinámicas - UNED


19.16 FUNDAMENTOS DEL LENGUAJE -I

echo "El resultado de convertirla en doble es: $aux <BR>";


$aux=strval($cadena);
echo "El resultado de convertirla en cadena es: $aux <BR>";
?>
</CENTER>
</BODY>
</HTML>

Figura 19.9 Conversión de variables.

19.3.4 CONSTANTES
Una constante es una variable que mantiene el mismo valor durante toda la ejecución del pro-
grama. Se puede asegurar que la constante mantiene siempre el mismo valor; en ninguna parte
del script se puede cambiar el valor de una constante una vez que se define. De hecho, los inten-
tos de cambio provocan errores.

Funciones para constantes


Para trabajar con constantes, PHP nos proporciona las siguientes funciones:
• define(constante,valor): Esta función nos permite crear una constante asignándole su
nombre y su valor a través de los parámetros que recibe.
• defined(constante): Esta función devuelve true si la constante pasada como argumento
está definida y, por tanto, existe; en caso contrario, devuelve false.

Para hacer referencia a las constantes, no es necesario anteponer el carácter $ al nombre, ya que
no se trata de una variable. Bastará con hacer referencia a ellas con el nombre con el que se defi-
nieron. En caso de necesitar redefinir el valor de una variable, habrá que volver a utilizar la fun-
ción define( ) . Veamos un ejemplo del uso de las variables:
<HTML>
<HEAD>
<TITLE>Constantes</TITLE>

Desarrollo de Aplicaciones Web Dinámicas - UNED


SINTAXIS BÁSICA 19.17

</HEAD>
<BODY>
<CENTER>
<H2>Trabajando con constantes</H2>
<?php
define("euro",166.386);
echo "El valor de la constante 'euro' es: <B>". euro ."</B><BR>";
echo "Luego 1€ son ".euro."ptas.<BR><BR>";
echo "La constante 'centimo' ";
echo (defined("centimo"))?"está".centimo:"no está";
echo " definida<BR>";
define("centimo",1.66);
echo "El valor de la constante 'centimo' es: <B>". centimo ."</
B><BR><BR>";
?>
</CENTER>
</BODY>
</HTML>

Figura 19.10 Trabajando con constantes.

Constantes predefinidas
El propio intérprete de PHP tiene un conjunto de constantes predefinidas y siempre disponibles
para el programador. No se podrán definir constantes propias de nuestros programas con los mis-
mos nombres ya que se tomará por defecto la constante predefinida. Algunas de estas constantes
son:
• PHP VERSION: Cadena que representa la versión del intérprete de PHP en uso.
• PHP OS: Cadena con el nombre del sistema operativo en el que se está ejecutando el
intérprete de PHP.
• TRUE: Verdadero.
• FALSE: Falso.
• E_ERROR: Información sobre errores distintos a los de interpretación del cual no es posi-
ble recuperarse.

Desarrollo de Aplicaciones Web Dinámicas - UNED


19.18 FUNDAMENTOS DEL LENGUAJE -I

• E_PARSE: Informa que el intérprete encontró una sintaxis inválida en el archivo de


comandos. Finaliza la ejecución.
• E_NOTICE: Informa que se produjo algo incorrecto que puede provenir o no de un error.
La ejecución continúa.
• E_WARNING: Denota un error que no impide que continúe la ejecución.
• E_ALL: Conjunto con todos los errores que se han producido.
<HTML>
<HEAD>
<TITLE>Constantes</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Tabajando con constantes</H2>
<?php
echo "Estamos trabajando con <B>PHP versión ". PHP_VERSION ."</
B><BR><BR>";
echo "Sobre un sistema operativo <B>". PHP_OS ."</B>";
?>
</CENTER>
</BODY>
</HTML>

Figura 19.11 Constantes predefinidas.

19.3.5 EXPRESIONES
Las expresiones son la base principal de PHP, que es, en sí, un lenguaje orientado a expresiones,
ya que casi todo en él es una expresión. La forma más ajustada de definir qué es una expresión
es: "cualquier cosa que tiene o produce un valor".

Una expresión puede ser algo tan simple como un número o una variable, o puede incluir muchas
variables, constantes, operadores y funciones conjuntamente. Las expresiones como grupo, si son
correctas, son evaluadas a un valor simple. Este valor resultante debe ser clasificado dentro de
uno de los tipos de datos que maneja PHP (integer, float, string, boolean, array, object).

Las expresiones más básicas son las variables y las constantes. Otro tipo de expresiones lo for-
man las expresiones de comparación que se evalúana 0 ó 1 correspondiendo con el valor false o

Desarrollo de Aplicaciones Web Dinámicas - UNED


SINTAXIS BÁSICA 19.19

true, respectivamente. También tenemos las expresiones que surgen corno resultado de la combi-
nación de operador y operandos. Así, podríamos continuar enumerando todos los posibles tipos
de expresiones.

19.3.6 OPERADORES
Los operadores en PHP son muy parecidos a los de otros lenguajes como C, Java y JavaScript. Se
utilizan para determinar un valor, o bien, para obtener un valor final a partir de uno o más operan-
dos. Podemos encontrar varios tipos de operadores, que se clasifican según su uso en los grupos
que veremos a continuación.

Operadores aritméticos
Estos operadores funcionan igual que en la aritmética básica y se pueden aplicar a las variables y
constantes numéricas. Son los siguientes:
• +
• -
• *
• /
• %: Resto de la división entera.

Operadores de asignación
El operador de asignación más utilizado es "="; su función básica es asignar un valor a una varia-
ble, para que de este modo se pueda conservar dicho valor en memoria. El operador de asigna-
ción es un operador binario que siempre toma la forma:
variable = expresión
Este operador de asignación hace que la variable de la izquierda tome el valor de la expresión de
la derecha. Este operador lo hemos utilizado básicamente hasta ahora para asignar valores a las
variables con las que hemos trabajado. PHP soporta otros operadores de asignación, que real-
mente son una combinación del operador de asignación básico con operadores aritméticos y con
el operador de concatenación de cadenas. La siguiente tabla resume los operadores de asigna-
ción:

Tabla 19.1 Operadores.

Desarrollo de Aplicaciones Web Dinámicas - UNED


19.20 FUNDAMENTOS DEL LENGUAJE -I

Operadores de cadenas
A lo largo de los ejemplos anteriores hemos utilizado el operador de concatenación de cadenas
representado por un punto (" . "); como hemos comprobado, devuelve como resultado la concate-
nación de sus operandos izquierdos y derechos; también hemos visto el operador de concatena-
ción y asignación, representado por un punto seguido del signo de igualdad (" . ="). Como su
funcionalidad es la vista hasta el momento, no es necesario profundizar más en estos operadores.

Operadores de incremento y decremento


Al igual que otros lenguajes de programación como C, PHP soporta operadores específicos para
incrementar y decrementar el valor de las variables.

Además, el momento de su ejecución dependerá de la posición en la que aparezcan respecto de la


variable a la que son aplicados. La siguiente tabla muestra las posibilidades de estos operadores:

Tabla 19.2 Operadores de incremento y decremento.

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 20

Fundamentos del lenguaje - II

20.1 INTRODUCCIÓN

No todos los problemas que se nos plantean tienen una solución basada en la ejecución secuen-
cial de instrucciones; por eso, es necesario dotar a los lenguajes de programación de herramientas
que los permitan adaptarse a las diferentes situaciones o condiciones que se pueden dar a la hora
de intentar resolver un problema.

Las estructuras de control o sentencias de control nos permiten modificar el flujo de ejecución
básico del programa, es decir, gracias a ellas la ejecución no tiene por qué ser totalmente secuen-
cial, vamos a poder controlar el flujo lógico de cualquier programa. Estas estructuras nos permi-
ten bifurcar el flujo del programa y así ejecutar unas partes u otras de código según se cumplan
una serie de condiciones, hacer que un determinado código no llegue a ejecutarse nunca o que lo
haga tantas veces como queramos.

A continuación enumeramos las distintas estructuras de control que nos podemos encontrar en un
programa PHP. Son comunes en cuanto a concepto en la mayoría de los lenguajes de programa-
ción de alto nivel y casi idénticas a las que presentan lenguajes como C, C++, Java y también
Perl.

20.2 SENTENCIAS CONDICIONALES

Son las estructuras de control más sencillas, se basan en el uso de la sentencia if . . . else y en las
diferentes formas que ésta puede presentar. Utilizando estas sentencias, somos capaces de hacer
que el programa elija entre dos caminos de ejecución diferentes en función de la evaluación de
una expresión lógica.
20.2 FUNDAMENTOS DEL LENGUAJE - II

20.2.1 IF
Es una de las más utilizadas e importantes en la mayoría de los lenguajes de programación. Su
sintaxis es la siguiente:
if (condicion)
{ [sentencias]
}
El intérprete de PHP lo que hace es evaluar la condicion, que debe ser una expresión lógica y, si
resulta verdadera, se ejecutarán las sentencias comprendidas entre las llaves "{" y "}" y, si es
falsa, PHP ignorará las sentencias y seguirá con la ejecución normal del programa. es decir, nos
permite tomar decisiones en torno a una condición.

En el siguiente ejemplo podemos observar la utilización de la sentencia if para saber cuál es el


mayor de un conjunto de tres valores. Para descubrir dicho valor, utilizarnos tres sentencias if,
cada una de las cuales, a través de una expresión lógica, pregunta si un valor determinado es
mayor que los otros dos:
<HTML>
<HEAD>
<TITLE>Estructuras de Control</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Sentencia <I>if</I></H2>
<?php
$a=3;
$b=7;
$c=9;
echo "<BR>Los tres números a comparar son: ";
echo "<B>$a, $b </B>y<B> $c</B><BR><BR>";
echo " y el mayor es el <B>";
if (($a>$b)&&($a>$c)){
echo $a;
}
if (($b>$a)&&($b>$c)){
echo $b;
}
if (($c>$a)&&($c>$b)){
echo $c;
}
echo "</B>";
?>
</CENTER>
</BODY>
</HTML>
Como podernos observar (Fig. 20.1), la expresión a evaluar puede ser tan compleja como se
necesite. En este ejemplo el resultado obtenido es el siguiente:

Las sentencias i f se pueden anidar, es decir, podemos poner dentro de un bloque if otras senten-
cias if, lo cual proporciona una flexibilidad completa para ejecuciones condicionales. Haciendo

Desarrollo de Aplicaciones Web Dinámicas - UNED


SENTENCIAS CONDICIONALES 20.3

uso de ifs sanidados, el siguiente código da el mismo resultado que el mostrado en el ejemplo
anterior:

Figura 20.1 Sentencia if.

<HTML>
<HEAD>
<TITLE>Estructuras de Control</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Sentencia <I>if</I></H2>
<?php
$a=3;
$b=7;
$c=9;
echo "<BR>Los tres números a comparar son: ";
echo "<B>$a, $b </B>y<B> $c</B><BR><BR>";
echo " y el mayor es el <B>";
if ($a>$b){
if($a>$c){
echo $a;
}
}
if ($b>$a){
if($b>$c){
echo $b;
}
}
if ($c>$a){
if($c>$b){
echo $c;
}
}
echo "</B>";
?>
</CENTER>
</BODY>

Desarrollo de Aplicaciones Web Dinámicas - UNED


20.4 FUNDAMENTOS DEL LENGUAJE - II

</HTML>

20.2.2 IF...ELSE
A menudo nos interesa ejecutar un código distinto si la evaluación de la expresión que acompaña
a la instrucción if no es cierta. Utilizamos entonces la sentencia if ... else; ésta consta de un blo-
que if que se ejecuta cuando la expresion se evalúa a true y de un bloque else cuyas instrucciones
se ejecutan cuando se evalúa a false. La sintaxis de la instrucción if ... else es la siguiente:
if (expresion)
{ sentencias
} else {
sentencias
}

20.2.3 IF...ELSEIF
Hay muchas ocasiones en que se quiere evaluar una nueva comprobación utilizando una senten-
cia if dentro del cuerpo de una sentencia else; para estos casos se puede utilizar la sentencia elseif
que nos permite combinar ambas sentencias en una sola. La sintaxis de la sentencia if . . . elseif es
la siguiente:
if (expresión)
{ sentencias
} elseif (expresión)
{ sentencias
}
[elseif (expresión)
{ sentencias }]...
[else {
sentencias } ]
La sentencia elseif se ejecuta si, y sólo si, se evalúa a true y la expresión if precedente y cualquier
expresión elseif precedente se evalúan a falce. Su comportamiento, por lo demás, coincide con el
de las sentencias if anteriores.

El siguiente ejemplo nos muestra un posible uso de esta estructura aplicado al ejemplo anterior:
<HTML>
<HEAD>
<TITLE>Estructuras de Control</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Sentencia <I>if</I></H2>
<?php
$a=3;
$b=7;
$c=9;
echo "<BR>Los tres números a comparar son: ";
echo "<B>$a, $b </B>y<B> $c</B><BR><BR>";
if ($a>$b){
if($a>$c){
$elmayor=$a;
}

Desarrollo de Aplicaciones Web Dinámicas - UNED


SENTENCIAS CONDICIONALES 20.5

else {
$elmayor=$c;
}
}
elseif($b>$c){
$elmayor=$b;
}
else {
$elmayor=$c;
}
echo " y el mayor es el <B>$elmayor</B>";
?>
</CENTER>
</BODY>
</HTML>

20.2.4 EXPRESIÓN CONDICIONAL (IF COMPACTO)


PHP utiliza dos operadores ("?" y ": ") para formar expresiones condicionales que devolverán
uno de dos posibles valores basándose en el valor lógico obtenido al evaluar una expresión. La
sintaxis de estos operadores es:
<expresionl> ? <expresion2> : <expresion3>;
De este modo, considerando expresion1, si ésta se evalúa a true, entonces se devolvería la eva-
luación de expresion2; en caso contrario, el valor devuelto sería el resultado de evaluar la
expresion3. El siguiente ejemplo nos muestra su uso combinado con operadores de comparación:
<HTML>
<HEAD>
<TITLE>Operadores</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Operadores de comparación y condicionales</H2>
<?PHP
$a=3; $b=7; $c=9;
echo "<BR>Los tres números a comparar son:";
echo "<B>$a, $b </B>y<B> $c</B><BR><BR>";
// obtenemos el mayor de $a y $b
$elmayor=($a>$b)?$a:$b;
echo " y el mayor es el <B>";
// mostramos el mayor de los tres valores
echo ($elmayor<$c)?$c:$elmayor;
echo "</B>";
?>
</CENTER>
</BODY>
</HTML>

20.2.5 SWITCH
La sentencia switch se utiliza para comparar un dato con un conjunto de posibles valores. Esta
tarea se puede realizar utilizando múltiples sentencias if o con una sentencia if...elseif múltiple,
pero la sentencia switch es mucho más legible y nos permite especificar un conjunto de senten-

Desarrollo de Aplicaciones Web Dinámicas - UNED


20.6 FUNDAMENTOS DEL LENGUAJE - II

cias por defecto, en el caso de que el dato no tenga un valor con que compararlo (equiparable a la
cláusula else de la sentencia if). La sintaxis de la sentencia switch es la siguiente:
switch ($variable) {
case valorl: [sentencias;]
[break;]
case valor2: [sentencias;]
[break;]
case valorN: [sentencias;]
[break;]
[ default: sentencias;]
}
En el caso de que el valor de la variable no coincida con ninguna cláusula case, se ejecutará la
opción default. Esta opción se puede omitir del switch y, entonces, no habría ninguna acción por
defecto. La sentencia break dentro de cada una de las cláusulas case permite que, una vez encon-
trado el valor buscado, no se sigan realizando más comparaciones; fuerza la finalización de la
sentencia switch. Si no se utiliza la sentencia break dentro de las cláusulas case, la ejecución de
una cláusula continúa por la siguiente.

El siguiente ejemplo nos muestra la utilización de esta cláusula.


<HTML>
<HEAD>
<TITLE>Estructuras de Control</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Sentencia <I>if</I></H2>
<?php
echo "Hoy es <B>";
$dia = date("D");

switch($dia){
case "Mon": echo "Lunes";
break;
case "Tue": echo "Martes";
break;
case "Wed": echo "Miércoles";
break;
case "Thu": echo "Jueves";
break;
case "Fri": echo "Viernes";
break;
case "Sat": echo "Sábado";
break;
default: echo "Domingo";
}
echo "</B>";
?>
</CENTER>
</BODY>
</HTML>

Desarrollo de Aplicaciones Web Dinámicas - UNED


SENTENCIAS DE BUCLE 20.7

20.3 SENTENCIAS DE BUCLE

La utilización de bucles dentro de un script sirve para muchos propósitos. Un uso sencillo, pero
habitual, es utilizar los bucles para contar. También se utilizan para recorrer objetos o estructuras
compuestas por más de un elemento, como ocurre con las estructuras de tipo array.

20.3.1 FOR
Esta instrucción nos permite realizar un conjunto de instrucciones un determinado número de
veces. Es una de las estructuras de control sintácticamente más complejas de PHP.

La sintaxis de esta estructura de control es la siguiente:


for ([exp_inicialización];[exp_condición];[exp_bucle]){
[sentencias]
}
Las tres expresiones cerradas entre paréntesis son opcionales, pero es necesario escribir los
caracteres punto y coma ("; ") que las separan aunque las expresiones se omitan, para que cada
expresión permanezca en el lugar apropiado. Vamos a detallar las opciones que nos permite esta
sentencia:
• exp_inicialización normalmente se utiliza para inicializar y declarar la variable o variables
que se van utilizar como contadores del bucle; sólo se ejecuta una vez al principio del
bucle. Si hay más de una variable, se separan por comas. Suele ser de la forma:
$variable = valor inicial

• exp_condición define una o más condiciones que han de cumplirse (evaluarse a true) para
poder ejecutar las sentencias encerradas entre las llaves. Mientras estas condiciones sean
ciertas, se estarán ejecutando las sentencias delimitadas entre llaves. La expresión se eva-
lúa antes de cada iteración y, si no se cumple la condición, ya no se ejecutan las sentencias.
Es muy importante comprobar la corrección de esta expresión porque, si inicialmente no
se cumple el cuerpo de la sentencia, no llegaría a ejecutarse nunca y si, al contrario, siem-
pre se evalúa a true, estaríamos ante un caso de bucle infinito. Suele tener la forma:
$variable <= límite

• Finalmente, la expresión exp_bucle modifica el valor de la variable o variables (separadas


por coma) utilizadas como contadores del bucle. Se ejecuta cada vez que finaliza una itera-
ción. No sigue un patrón fijo; algunas de las formas que presenta son:
$variable++
$variable--
$variable+=valor
El siguiente ejemplo nos muestra su funcionamiento para imprimir la suma de los 10 primeros
números:
<HTML>

Desarrollo de Aplicaciones Web Dinámicas - UNED


20.8 FUNDAMENTOS DEL LENGUAJE - II

<HEAD>
<TITLE>Estructuras de Control</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Sentencia <I>for</I></H2>
<?php
echo "la suma de los 10 primeros números enteros es:";
$suma=0;
for($i=1;$i<=10;$i++){
$suma+=$i;
echo ($i==10)?"$i = ":"$i+";
}
echo "<B>$suma</B>";
?>
</CENTER>
</BODY>
</HTML>

Figura 20.2 Sentencia for.

20.3.2 FOREACH
Esta sentencia nos permite recorrer las estructuras de tipo array de una forma sencilla, obte-
niendo en cada paso de la iteración uno de sus elementos componentes. También se suele utilizar
para traducir tablas de tipo hash, tal y como veremos más adelante.

Tiene dos sintaxis. La primera de ellas es la siguiente:


foreach (nombre_array as $variable) {
sentencias;
}
Lo que hace este bucle es recorrer cada uno de los elementos del array que tiene por nombre
nombre_array, asignando en cada paso el valor del elemento actual del array al contenido de la
variable $variable. El bucle hace uso de un puntero interno que apunta a la posición actual del
array (comenzando por la primera y siguiendo en orden ascendente) y que va actualizando de
forma automática en cada una de las iteraciones.

El siguiente ejemplo nos muestra dos formas de recorrer un array. En la primera se utiliza un
bucle for y en la segunda un bucle foreach. Comno podernos observar en el segundo caso, no es

Desarrollo de Aplicaciones Web Dinámicas - UNED


SENTENCIAS DE BUCLE 20.9

necesario conocer la cantidad de elementos que conforman el array, puesto que la sentencia man-
tiene un puntero interno para recorrerlo:
<HTML>
<HEAD>
<TITLE>Estructuras de Control</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Sentencia <I>foreach</I></H2>
<?php
// creamos el array y llenamos de datos
$matriz[0]="cougar";
$matriz[1]="ford";
// posición sin contenido
$matriz[2]=null;
$matriz[3]="2.500";
$matriz[4]="V6";
$matriz[5]=182;
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<?php
for($i=0;$i<6;$i++){
echo "<TD> $matriz[$i] </TD>";
}
?>
</TR>
<TR ALIGN="center" BGCOLOR="yellow">
<?php
foreach($matriz as $valor){
echo "<TD> $valor </TD>";
}
?>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>

Figura 20.3 Sentencia foreach.

Desarrollo de Aplicaciones Web Dinámicas - UNED


20.10 FUNDAMENTOS DEL LENGUAJE - II

La segunda sintaxis que nos ofrece la sentencia foreach es la siguiente:


foreach (nombre_array as $clave => $valor){
sentencias
}
Con esta nueva sintaxis podernos realizar la misma operación que con la anterior, pero, además,
nos permite conocer en todo instante la posición exacta (el índice) del componente actual dentro
de la estructura del array, a través de la variable $clave, es decir, se realiza el mismo procedi-
miento de asignación de valores a la variable $valor y, además, la clave (o índice) del elemento
actual se asigna a la variable $clave en cada iteración. Con foreach no hace falta inicializar el
puntero interno del array a la primera posición ya que se hace automáticamente.
<HTML>
<HEAD>
<TITLE>Estructuras de Control</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Sentencia <I>foreach</I></H2>
<?php
// creamos el array y llenamos de datos
$matriz[0]="cougar";
$matriz[1]="ford";
// posición sin contenido
$matriz[2]=null;
$matriz[3]="2.500";
$matriz[4]="V6";
// saltamos una posición
$matriz[6]=182;
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD>posición</TD>
<TD>contenido</TD>
</TR>
<?php
foreach($matriz as $key => $valor){
echo "<TR ALIGN='center'>";
echo "<TD> $key </TD>";
echo "<TD> $valor </TD>";
echo "</TR>";
}
?>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>
El resultado de este ejemplo nos los muestra la imagen (Fig. 20.4)

Corno podernos observar, aunque una posición del array esté vacía (la posición 2), el recorrido
no la salta, si bien una posición no utilizada (posición 5) no aparece en este tipo de recorridos.

Desarrollo de Aplicaciones Web Dinámicas - UNED


SENTENCIAS DE BUCLE 20.11

Figura 20.4 Sentencia foreach.

Finalmente, se debe decir que esta sentencia se puede aplicar también a un arrue de tipo asocia-
tivo, en el que el índice de cada elemento no es de tipo numérico.

20.3.3 WHILE
La sentencia while actúa de forma muy parecida a la sentencia for, pero se diferencia de ésta en
que no incluye en su declaración la inicialización de la variable de control del bucle ni su incre-
mento o decremento. Por tanto, dicha variable se deberá declarar antes del bucle while y su incre-
mento o decremento se deberá realizar dentro del cuerpo de dicho bucle. La sintaxis de la
instrucción while es la siguiente:
while (condición)(
sentencias;
}
Con esta instrucción se va a poder ejecutar un conjunto de instrucciones un indeterminado
número de veces, siempre y cuando el resultado de comprobar la condición sea verdadera (debe
ser una expresión que se evalúe a un valor lógico). Si la condición se evalúa a true, se ejecutan
las sentencias del cuerpo del bucle; después de ejecutarlas, se volverá a evaluar la condición, de
forma que, si ésta sigue cumpliéndose, se volverán a ejecutar las sentencias. Esto se repite hasta
que la condición se evalúa a false, en cuyo caso no se ejecutarán las sentencias del cuerpo del
bucle y continuará la ejecución del script por la instrucción siguiente a la sentencia while.
<HTML>
<HEAD>
<TITLE>Estructuras de Control</TITLE>
</HEAD>
<BODY>
<CENTER>

Desarrollo de Aplicaciones Web Dinámicas - UNED


20.12 FUNDAMENTOS DEL LENGUAJE - II

<H2>Sentencia <I>while</I></H2>
<?php
echo "la suma de los 10 primeros números enteros es: ";
$suma=0;
$i=1;
while($i<=10){
$suma+=$i;
echo ($i==10)?"$i = ":"$i+";
$i++;
}
echo "<B>$suma</B>";
?>
</CENTER>
</BODY>
</HTML>
Como podemos observar en el código, la inicialización de la variable que se utiliza para controlar
el final del bucle, $i, se realiza fuera de él, mientras que su actualización forma parte de las ins-
trucciones del cuerpo de la sentencia while. Es muy importante comprobar la corrección de la
condición porque, si inicialmente no se cumple, el cuerpo de la sentencia no llegaría a ejecutarse
nunca y si, por el contrario, siempre se evalúa a true, estaríamos ante un caso de bucle infinito.

20.3.4 DO...WHILE
Esta sentencia funciona exactamente igual que el bucle while, excepto que la condición no se
comprueba hasta que se ha realizado una iteración (la condición se comprueba al final de cada
iteración). Esto garantiza que, al menos, el cuerpo del bucle se realiza una vez, aunque la expre-
sión condición se evalúe a false. Como siempre, condición debe ser una expresión que se evalúe
a un valor lógico.

La sintaxis del bucle do ... while es la siguiente:


do {
sentencias;
} while (condición);

20.3.5 BREAK Y CONTINUE


Cuando explicamos la sentencia switch, vimos que era habitual utilizar la instrucción break para
interrumpir su ejecución una vez que encontrábamos la cláusula case que coincidía con el valor
origen de la comparación. A veces, cuando utilizamos bucles, también se nos plantea la necesi-
dad de finalizarlos antes de que sus condiciones no se cumplan; para ello, utilizaremos las sen-
tencias break.

Asimismo, es posible que nos interese que la ejecución del cuerpo del bucle no contemple siem-
pre las mismas instrucciones, es decir, que, al alcanzar una cierta posición dentro del cuerpo del
bucle, las sentencias restantes no se ejecuten y que vuelva a evaluarse de nuevo la expresión del
bucle (si existe) continuando con la siguiente iteración; para ello, utilizaremos la instrucción con-
tinue.

Desarrollo de Aplicaciones Web Dinámicas - UNED


SENTENCIAS DE BUCLE 20.13

Las instrucciones break y continue se pueden utilizar dentro de los cuerpos de todas las senten-
cias de control de bucles, desde el for hasta el do..while.

El siguiente ejemplo nos muestra la utilización de la instrucción break para finalizar la ejecución
de un bucle:
<HTML>
<HEAD>
<TITLE>Estructuras de Control</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Sentencia <I>break</I></H2>
<?php
$numero=6;
echo "<BR><B>$numero!</B> = ";
$factorial=1;
while (1){
echo $numero." x ";
$factorial*=$numero;
$numero--;
if ($numero==1){
break;
}
}
echo "1 = <B>$factorial</B>";
?>
</CENTER>
</BODY>
</HTML>

Figura 20.5 Sentencia break.

Como podemos observar en el código, la condición de salida del bucle nunca se cumple; por
tanto, estaríamos ejecutando un bucle infinito de no ser por la existencia de la instrucción break
dentro de su cuerpo.

Desarrollo de Aplicaciones Web Dinámicas - UNED


20.14 FUNDAMENTOS DEL LENGUAJE - II

El siguiente ejemplo, que obtiene los números múltiplos de 3 y 5 comprendidos entre el 1 y el


1.000, nos muestra la utilización de la instrucción continue para saltar la ejecución de algunas
instrucciones dentro de un bucle:
<HTML>
<HEAD>
<TITLE>Estructuras de Control</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Sentencia <I>continue</I></H2>
<?php
echo "Múltiplos de 3 y 5 entre 1 y 1000:<BR><BR>";
for($i=1;$i<1000;$i++){
if (($i%3 !== 0)||($i%5 !== 0)) {
continue;
}
echo "$i, ";
}
?>
</CENTER>
</BODY>
</HTML>

Figura 20.6 Sentencia continue.

Como podernos observar en el código, sólo cuando encontrarnos un número divisible por 3 y por
5, éste se muestra por pantalla a través de la instrucción echo; en el resto de las ocasiones, la ins-
trucción continue hace que la ejecución salte a la siguiente iteración del bucle sin tener en cuenta
las instrucciones que aparecen por debajo de ella. El resultado se muestra en la figura (Fig. 20.6).

Finalmente, se debe comentar que ambas sentencias admiten un parámetro opcional con el que
podemos indicar el número de estructuras de control que deben saltarse en caso de que en el
código existan anidamientos de bucles. Esto nos permite decidir el nivel de ruptura que queremos
dentro del bucle cuando se ejecuta alguna de estas dos sentencias. Las sentencias break y conti-

Desarrollo de Aplicaciones Web Dinámicas - UNED


INCLUSIÓN DE FICHEROS 20.15

nue, por defecto, sólo saltan un nivel de anidamiento, el del bucle más interno que las contiene
(consultar libro de texto y manual on line).

20.4 INCLUSIÓN DE FICHEROS

Las funciones que abordarnmos en esta sección deben incluirse dentro de las estructuras de con-
trol del lenguaje, puesto que pueden influir en gran manera en el flujo de ejecución e interpreta-
ción de los scripts que las contengan (sobre todo si los ficheros a incluir contienen a su vez
código PHP). Deben ser consideradas más bien corno construcciones del lenguaje, no como sim-
ples funciones.

Esta facilidad del lenguaje se utiliza principalmente para la definición de librerías comunes a
varios scripts, permitiendo, de este modo, una reutilización y mantenimiento del código más
óptimos. La naturaleza del fichero externo a incluir puede ser de cualquier tipo PHP, HTML,
TXT, etc.

20.4.1 INCLUDE()
Esta función incluye y evalúa un fichero externo cada vez que es interpretada. Ambos pasos, la
inclusión del fichero externo y su posterior evaluación, se realizan cada vez que el flujo del pro-
grama llega a una línea que contenga la llamada a esta función. En caso de que el fichero a incluir
no exista o su referencia sea errónea, la función genera un aviso o warning, continuando con la
ejecución por la siguiente instrucción.
include(“nombre de fichero”)
Cuando un archivo se incluye con include() , el intérprete sale del modo PHP y entra en modo
HTML al principio del archivo referenciado, y vuelve de nuevo al modo PHP al acabar de leer
dicho archivo. Por esta razón, cualquier código dentro del archivo referenciado que debiera ser
ejecutado como código PHP debe ser encerrado dentro de etiquetas válidas de comienzo y fin de
PHP

Todas las funciones y variables definidas con anterioridad a la llamada a la función include() son
accesibles para el código presente en el fichero importado. De igual forma, todos los elementos
definidos en el código PHP del fichero incluido estarán disponibles para el script llamante una
vez se haya terminado la lectura y ejecución del fichero incluido.

El ámbito de las variables que se definen en los scripts del fichero incluido depende del lugar
desde el que se realiza la llamada. Si la llamada se realiza desde el cuerpo de una función, las
variables tendrán ámbito local (a no ser que estén definidas con el modificador global); en cual-
quier otro caso tendrán ámbito global.

La función include( ) puede utilizarse en combinación con otras estructuras de control de flujo.
El contenido del fichero se incluirá y evaluará sólo cuando se interprete la llamada. Si el flujo de
ejecución del script nunca alcanza la línea en la que se realiza la llamada, el fichero nunca será

Desarrollo de Aplicaciones Web Dinámicas - UNED


20.16 FUNDAMENTOS DEL LENGUAJE - II

incluido. Cuando esta función se utiliza dentro de estructuras de bucle o condicionales, siempre
debe aparecer entre llaves, pues, en otro caso, podría obtenerse un resultado no deseado.

 Consultar manual de PHP 5 para mayor información.

20.4.2 INCLUDE_ONCE()
Su funcionamiento es idéntico al de la función include O , con la única salvedad de que esta fun-
ción sólo cargará y evaluará cada script una vez como máximo. Con esta función nos aseguramos
de que un fichero sólo se ha cargado una vez a lo largo de la interpretación de nuestro script, evi-
tando, de este modo, los errores producidos por la redefinición de funciones o la reasignación de
valores a variables.

 Ejercicio: Idear un ejemplo con dos ficheros en los que se ponga de manifiesto las diferen-
cias entre include() e include_once().

20.4.3 REQUIRE()
Esta función se comporta en líneas generales corno la función include() , pero con las siguientes
salvedades:
1 require( ) sólo incluye el fichero referenciado, es decir, no lo interpreta. Su comporta-
miento es equivalente a la directiva #include del lenguaje C.
2 require() no puede ser utilizado con estructuras condicionales o de control de bucles por-
que el contenido del fichero referenciado se incluye antes de que se evalúe la sentencia que
lo contiene y se incluye siempre aunque la condición que lo contiene no se cumpla. No
obstante, si la línea en la que aparece require() no se ejecuta, tampoco se ejecutará el
código del archivo al que esta llamada haga referencia.
3 En caso de que el fichero referenciado por require() no exista, se genera un error fatal que
no nos permite continuar con la ejecución del script.
4 Se desaconseja pasar variables corno parámetros de la función require() , si bien este tipo
de construcción funciona.

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 21

Cadenas

21.1 INTRODUCCIÓN

El tratamiento de cadenas es de gran importancia en el uso de PHP, puesto que, en la mayoría de


los casos, el objetivo final del procesamiento de un fichero PHP está relacionado con la genera-
ción de documentos (casi siempre documentos HTML). Por ello, existe un amplio conjunto de
funciones para el manejo de cadenas, de las que veremos las principales, agrupadas en torno al
tipo de función que realizan.

21.2 DELIMITACIÓN DE CADENAS

Como vimos en temas anteriores, una cadena está formada por cero o más caracteres encerrados
entre dobles comillas (" ") o entre comillas simples (‘ ‘). Es obligatorio utilizar siempre el mismo
tipo de comilla para rodear cada cadena, aunque en algunos casos se puede entremezclar el uso
de los dos tipos de entrecomillado, principalmente para insertar una cadena literal dentro de otra
(aunque para este tipo de acciones también se utiliza el enmascarado (escuped) de las comillas,
es decir, anteponer a las comillas el carácter "\").

Se debe recordar que, cuando utilizamos comillas dobles, podemos incluir dentro de la cadena
nombres variables o caracteres especiales que serán evaluados (sustituidos por sus respectivos
valores) a la hora de mostrar la información, cosa que no ocurre si introducimos nombres de
variables dentro de una cadena encerrada entre comillas simples.

En el siguiente ejemplo se verá el comportamiento de PHP ante cadenas con comillas dobles o
simples, y cómo insertar una comilla doble dentro de una cadena delimitada por comillas dobles:
<HTML>
<HEAD>
<TITLE>Trabajando con Cadenas</TITLE>
21.2 CADENAS

</HEAD>
<BODY>
<CENTER>
<H2>Comillas dobles y simples</H2>
<?php
$cadena='un tesoro';
echo "la cadena '$cadena' contiene: $cadena<br><br>";
echo "la cadena \"$cadena\" contiene: $cadena<br><br>";
echo 'la cadena "$cadena" contiene: $cadena<br><br>';
?>
</CENTER>
</BODY>
</HTML>

Figura 21.1 Comillas dobles y simples.

21.3 VISUALIZACIÓN DE CADENAS

Comenzamos con las funciones que nos permiten visualizar y formatear cadenas de caracteres,
permitiéndonos gestionar, de este modo, la salida de los datos por pantalla:
• echo(cadena), print(cadena) : No son funciones propiamente dichas, sino construcciones
del lenguaje. Ambas muestran información por la salida estándar; no soportan ningún atri-
buto de formato de salida y sólo admiten una única cadena corno argumento en su llamada
(cuando necesitamos pasar más de un argumento a cualquiera de estas funciones, debere-
mos utilizar las comillas).
• printf(formato [, argumentos] ): Imprime información por la salida estándar soportando
diferentes formatos de salida. Admite múltiples tipos de argumentos a visualizar.

Imprime una cadena cuya estructura depende del formato descrito en el argumento for-
mato. Esta cadena está formada por una ristra de caracteres, algunos de los cuales se mos-
trarán directamente, mientras que otros, los que van precedidos por el carácter "%",
conocidos corno especificaciones de conversión, son utilizados para formatear la informa-
ción.

Desarrollo de Aplicaciones Web Dinámicas - UNED


VISUALIZACIÓN DE CADENAS 21.3

Cada especificación de conversión se compone de los siguientes elementos (en orden):


1 Un carácter de relleno -opcional-, que se utilizará para rellenar y ajustar el resultado hasta
lograr el tamaño de cadena correcto, por ejemplo, el espacio en blanco para caracteres
(valor por defecto) o el cero para valores numéricos.
2 Un carácter de alineamiento -opcional-, para indicar si el resultado debe alinearse a la
izquierda (carácter "-") o a la derecha (valor por defecto).
3 Un indicador de tamaño -opcional-, que indica el tamaño mínimo de caracteres que ocu-
pará el argumento tras la conversión.
4 Un indicador de precisión -opcional-, formado por un punto (".") seguido del número de
dígitos decimales que deberán mostrar los números en punto flotante. No tiene efecto con
otros tipos de datos.
5 Finalmente, un identificador de tipo de datos, que especifica cómo se deberá tratar el dato.
Los tipos disponibles son:

El siguiente ejemplo nos muestra la utilidad de esta función para formatear resultados en panta-
lla:
<HTML>
<HEAD>
<TITLE>Trabajando con Cadenas</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Función <I>printf</I></H2>
<?php
$euro=166.386;
printf ("%s--- %02d/%02d/%04d ---","<B>Convertidor de Euros ", 3,
4, 2001);
echo "</B><BR><BR>";
for ($i=100;$i<1100;$i+=100)
printf("%4d Ptas. -> %02.2f €%s",$i,$i/$euro,"<BR>");
?>
</CENTER>
</BODY>
</HTML>

Desarrollo de Aplicaciones Web Dinámicas - UNED


21.4 CADENAS

Figura 21.2 Funcición printf.

• sprintf( formato [ , argumentos] ): Es muy parecida a printf() , pero se diferencia de ésta en


que devuelve una cadena de caracteres, la cual lo habitual es almacenarla en una variable.

 No se debe abusar del uso de estas funciones cuando no haya que aplicar un formato especí-
fico a los datos o el formato no sea importante, porque se obtienen mejores resultados
haciendo uso de la función echo y concatenando las cadenas con el operador ". ".

21.4 ACCESO AL CONTENIDO

Podemos acceder a cada uno de los caracteres que componen una cadena haciendo referencia a la
posición que ocupan dentro de ella, de igual modo a como referenciamos los diferentes compo-
nentes de una matriz o array. Para ello, se hace indispensable conocer el tamaño de la cadena a
recorrer.
• strlen(cadena): Devuelve la longitud de la cadena pasada como argumento. El siguiente
ejemplo nos muestra un modo básico de recorrer los diferentes componentes de una
cadena:
<HTML>
<HEAD>
<TITLE>Trabajando con Cadenas</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Función <I>strlen</I></H2>

Desarrollo de Aplicaciones Web Dinámicas - UNED


BÚSQUEDA EN CADENAS 21.5

<?php
$cadena="Saludos";
echo "<TABLE BORDER='1'CELLPADDING='2' CELLSPACING='2'>\n";
echo "<TR BGCOLOR='yellow'><TD>Carácter</TD><TD>Posición</TD></
TR>\n";
for($i=0;$i<strlen($cadena);$i++)
echo "<TR ALIGN='center'><TD>".$cadena[$i]."</TD><TD>".$i."</
TD></TR>\n";
echo "</TABLE>\n";
?>
</CENTER>
</BODY>
</HTML>

Figura 21.3 Función strlen().

21.5 BÚSQUEDA EN CADENAS

Una de las operaciones más habituales sobre las cadenas es la búsqueda de caracteres y subcade-
nas componentes, para su posterior tratamiento. Dentro de este tipo de funciones destacan las
siguientes:
• strstr(cadena, cadBusq), strchr(cadena, cadBusq):Busca la aparición de una cadena dentro
de otra y devuelve la subcadena comprendida entre la primera aparición de la cadena bus-
cada (incluyéndola) hasta el final de la cadena en la que se realiza la búsqueda. En caso de
no encontrar la cadena, devuelve una cadena vacía. La búsqueda diferencia entre mayús-
culas y minúsculas.
• strrchr (cadena, cadBusq) : Busca la aparición de un carácter (aunque se utilice una
cadena de búsqueda sólo tiene en cuenta su primer carácter) en una cadena y devuelve la
subcadena comprendida entre la última aparición del carácter (incluido) hasta el final de la

Desarrollo de Aplicaciones Web Dinámicas - UNED


21.6 CADENAS

cadena en la que se realiza la búsqueda. En caso de no encontrar el carácter en la cadena,


se devuelve una cadena vacía. La búsqueda diferencia entre mayúsculas y minúsculas. Si
el elemento a buscar no es una cadena, se convierte a entero y se aplica como el valor ordi-
nal de un carácter.

El siguiente código nos muestra el funcionamiento de ambas funciones:


HTML>
<HEAD>
<TITLE>Trabajando con Cadenas</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Funciones <I>strchr y strrchr</I></H2>
<?php
$cadena="Saludos para todos...";
$car1="do";
$car2="pc";
echo "<TABLE BORDER='1'CELLPADDING='2' CELLSPACING='2'>\n";
echo "<TR ALIGN='center'><TD BGCOLOR='yellow'>cadena</TD><TD>$cadena</TD></TR>\n";
echo "<TR ALIGN='center'><TD BGCOLOR='yellow'>strchr(cadena,'$car1')</TD>";
echo "<TD>".strchr($cadena,$car1)."</TD></TR>\n";
echo "<TR ALIGN='center'><TD BGCOLOR='yellow'>strrchr(cadena,'$car1')</TD>";
echo "<TD>".strrchr($cadena,$car1)."</TD></TR>\n";
echo "<TR ALIGN='center'><TD BGCOLOR='yellow'>strchr(cadena,'$car2')</TD>";
echo "<TD>".strchr($cadena,$car2)."</TD></TR>\n";
echo "<TR ALIGN='center'><TD BGCOLOR='yellow'>strrchr(cadena,'$car2')</TD>";
echo "<TD>".strrchr($cadena,$car2)."</TD></TR>\n";
echo "</TABLE>\n";
?>
</CENTER>
</BODY>
</HTML>

Figura 21.4 Funciones strchr y strrchr.

• stristr(cadena, cadBusq) : El comportamiento de esta función es igual al de la función


strstr( ), salvo que ésta no diferencia entre mayúsculas y minúsculas.
• strpos(cad1 , cad2 [ , desplz ] ) : Encuentra la primera posición de aparición de una cadena
a partir de una cierta posición (si no se indica, el valor por defecto para el desplazamiento
es 0). La búsqueda diferencia entre mayúsculas y minúsculas.
• strrpos(cadena, carácter) : Devuelve la posición de la última aparición de un carácter
determinado en una cadena (aunque se utilice una cadena de búsqueda sólo tiene en cuenta
su primer carácter). En caso de no encontrar el carácter en la cadena, se devuelve false. La

Desarrollo de Aplicaciones Web Dinámicas - UNED


COMPARACIÓN DE CADENAS 21.7

búsqueda diferencia entre mayúsculas y minúsculas. Si el elemento a buscar no es una


cadena, se convierte a entero y se aplica como el valor ordinal de un carácter.
• strspn( cadena, máscara) : Obtenemos la longitud de la subcadena más larga que está for-
mada sólo por caracteres contenidos en una máscara. Una vez encontrado un carácter que
no está contenido en la máscara, se abandona la búsqueda. La búsqueda diferencia entre
mayúsculas y minúsculas.
• strespn(cadena, máscara) : Obtenemos la longitud de la subcadena que está formada sólo
por caracteres no contenidos en una máscara (esta función es la complementaria a strspn()
). Una vez encontrado un carácter que está contenido en la máscara, se abandona la bús-
queda. La búsqueda diferencia entre mayúsculas y minúsculas.

21.6 COMPARACIÓN DE CADENAS

Otra operación común con cadenas es compararlas para saber cuál es mayor. Dentro de este tipo
de funciones destacan las siguientes:
• strcmp(cad1, cad2) : Compara dos cadenas y devuelve un valor menor que 0, si la segunda
cadena es mayor que la primera: mayor que 0, en caso contrario, y 0, si ambas cadenas son
iguales. La comparación distingue entre mayúsculas y minúsculas.
• strcasecmp(cad1 , cad2) : Se comporta igual que strcmp( ) , excepto en que no diferencia
mayúsculas de minúsculas.
• strncmp(cad1, cad2 , long) : Funciona como strcmp() , sólo que permite comparar los long
primeros caracteres de dos cadenas. Si alguna cadena es menor que el número de caracte-
res a comparar, se usará su longitud como long para la comparación. Diferencia mayúscu-
las de minúsculas.
• strnatcmp(cadl , cad2) : Se comporta igual que strcmp( ), excepto en que utiliza una com-
paración "natural" de las cadenas alfanuméricas. Distingue entre mayúsculas y minúscu-
las.
• strnatcasecmp(cadí , cad2) : Se comporta igual que strnatcmp(), excepto en que no dife-
rencia entre mayúsculas y minúsculas.

21.7 OPERAR CON SUBCADENAS

No siempre nos interesan todos los caracteres que componen una cadena, sino que sólo estamos
interesados en trabajar con un conjunto. Para ello contarnos con un conjunto de funciones prepa-
radas para extraer subcadenas de una cadena original. Entre las más utilizadas están:
• substr(cadena, inicio [ , tamaño] ) : Devuelve la subcadena que se encuentra a partir de
una posición dada y llega hasta el final de la cadena original, pudiendo de forma opcional
decidir el tamaño de la subcadena a recuperar. Los argumentos enteros pueden ser núme-
ros negativos de modo que:

Desarrollo de Aplicaciones Web Dinámicas - UNED


21.8 CADENAS

- Una posición de inicio con valor negativo significa que se debe comenzar desde el
final de la cadena.
- Un tamaño con valor negativo indica cuántos caracteres del final de la cadena no se
tendrán en cuenta.
<HTML>
<HEAD>
<TITLE>Trabajando con Cadenas</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Funciones <I>substr</I></H2>
<?php
$cadena="abcdefghi";
$ini1 = 2;
$ini2 = -2;
$tam1 = 3;
$tam2 = -3;
echo "<TABLE BORDER='1'CELLPADDING='2' CELLSPACING='2'>\n";
echo "<TR ALIGN='center'><TD BGCOLOR='yellow'>cadena</TD>";
echo "<TD>$cadena</TD></TR>\n";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>substr(cadena,$ini1)</TD>";
echo "<TD>".substr($cadena,$ini1)."</TD></TR>\n";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>substr(cadena,$ini1,$tam1)</TD>";
echo "<TD>".substr($cadena,$ini1,$tam1)."</TD></TR>\n";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>substr(cadena,$ini2)</TD>";
echo "<TD>".substr($cadena,$ini2)."</TD></TR>\n";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>substr(cadena,$ini1,$tam2)</TD>";
echo "<TD>".substr($cadena,$ini1,$tam2)."</TD></TR>\n";
echo "</TABLE>\n";
?>
</CENTER>
</BODY>
</HTML>

Figura 21.5 Función substr.

Desarrollo de Aplicaciones Web Dinámicas - UNED


OPERAR CON SUBCADENAS 21.9

• substr_replace(cadl, cad2, inicio 1, tamaño]): Devuelve una cadena que es resultado de la


sustitución de parte del contenido de una cadena original (indicado por una posición de
inicio y opcionalmente por un tamaño) por el contenido de otra cadena. La cadena original
no sufre ninguna modificación. Distingue entre mayúsculas y minúsculas. Los argumentos
enteros pueden ser números negativos de modo que:
- Una posición de inicio con valor negativo significa que se debe comenzar desde el
final de la cadena.
- Un tamaño con valor negativo indica cuántos caracteres del final de la cadena no se
tendrán en cuenta.
• str_replace (cadBus, cadRee, cadena) : Devuelve una cadena, que es resultado de la susti-
tución de todas las apariciones de una subcadena, por otro contenido en la cadena original.
La cadena original no sufre ninguna modificación. Diferencia entre mayúsculas y minús-
culas.
• strtr(cadena, cadBus, cadRee) : Devuelve una cadena, que es resultado de la sustitución de
cada una de las apariciones, en la cadena original, de cada uno de los caracteres de una
subcadena, por sus correspondientes caracteres dentro de una cadena de sustitución dada.
La cadena original no sufre ninguna modificación.
<HTML>
<HEAD>
<TITLE>Trabajando con Cadenas</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Funciones <I>strtr</I></H2>
<?php
$cadena="abcdefghi";
$cadB="aei";
$cadS="AEI";
echo "<TABLE BORDER='1'CELLPADDING='2' CELLSPACING='2'>\n";
echo "<TR ALIGN='center'><TD BGCOLOR='yellow'>cadena</TD>";
echo "<TD>$cadena</TD></TR>\n";
echo "<TR ALIGN='center'><TD BGCOLOR='yellow'>patrón</TD>";
echo "<TD>$cadB</TD></TR>\n";
echo "<TR ALIGN='center'><TD BGCOLOR='yellow'>reemplazo</TD>";
echo "<TD>$cadS</TD></TR>\n";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>strtr(cadena,patrón,reemplazo)</TD>";
echo "<TD>".strtr($cadena,$cadB,$cadS)."</TD></TR>\n";
echo "</TABLE>\n";
?>
</CENTER>
</BODY>
</HTML>

Desarrollo de Aplicaciones Web Dinámicas - UNED


21.10 CADENAS

Figura 21.6 Función strtr.

• substr_count(cadena, patron) : Devuelve el número de apariciones de una subcadena den-


tro de una cadena. Diferencia entre mayúsculas y minúsculas.

21.8 MODIFICACIÓN DEL CONTENIDO

21.8.1 LIMPIEZA DE CADENAS


• chop (cadena) : Devuelve la cadena argumento sin los espacios en blanco y caracteres de
fin de línea que se encuentren al final de la cadena.
• rtrim ( cadena) : Se comporta igual que chop() .
• ltrim(cadena) : Elimina espacios en blanco que se encuentran al principio de una cadena
de texto. Recibe como parámetro una cadena de caracteres y devuelve la misma cadena
pero sin los espacios iniciales.
• trim(cadena) : Elimina los espacios en blancos que se encuentran al principio y al final de
una cadena de texto. Recibe como argumento una cadena de caracteres y devuelve como
resultado esa cadena sin los espacios iniciales y finales.

21.8.2 RELLENO DE CADENAS


• str_pad(cadena, long): Rellena una cadena con un carácter de relleno (por defecto, es el
espacio en blanco) hasta que la cadena resultante tenga la longitud deseada. Opcional-
mente se puede indicar el modo de relleno con los siguientes valores:
- STR_PAD_RIGHT: Rellena por la derecha (opción por defecto).
- STR_PAD_LEFT: Rellena por la izquierda.
- STR_PAD_BOTH: Intenta rellena con el mismo número de caracteres por la dere-
cha y por la izquierda.

Desarrollo de Aplicaciones Web Dinámicas - UNED


MODIFICACIÓN DEL CONTENIDO 21.11

21.8.3 CONVERSIÓN ENTRE MAYÚSCULAS Y MINÚSCULAS


• strtolower(cadena) : Convierte una cadena de caracteres a minúsculas. Recibe como argu-
mento una cadena y devuelve la misma cadena con los caracteres alfabéticos en minúscu-
las.
• strtoupper(cadena) : Funciona de forma contraria a la función anterior. Convierte una
cadena de caracteres a mayúsculas.
• ucfirst(cadena) : Se encarga de convertir a mayúsculas el primer carácter de una cadena de
caracteres, siempre que éste sea alfabético
• ucwords(cadena) : Se comporta igual que la función anterior, salvo que ésta convierte a
mayúsculas el primer carácter de cada palabra que compone la cadena, siempre y cuando
sean caracteres alfanuméricos.

Veamos el siguiente ejemplo:


<HTML>
<HEAD>
<TITLE>Trabajando con Cadenas</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Funciones <I>strtoupper, strtolower, ucfirst y ucwords</I></
H2>
<?php
$frase="saludos PARA todos...";
echo "<TABLE BORDER='1'CELLPADDING='2' CELLSPACING='2'>\n";
echo "<TR ALIGN='right'>";
echo "<TD BGCOLOR='yellow'>frase</TD><TD>$frase</TD>\n";
echo "<TR ALIGN='right'>";
echo "<TD BGCOLOR='yellow'>strtoupper(frase)</TD>";
echo "<TD>".strtoupper($frase)."</TD></TR>\n";
echo "<TR ALIGN='right'>";
echo "<TD BGCOLOR='yellow'>strtolower(frase)</TD>";
echo "<TD>".strtolower($frase)."</TD></TR>\n";
echo "<TR ALIGN='right'>";
echo "<TD BGCOLOR='yellow'>ucfirst(frase)</TD>";
echo "<TD>".ucfirst($frase)."</TD></TR>\n";
echo "<TR ALIGN='right'>";
echo "<TD BGCOLOR='yellow'>ucwords(frase)</TD>";
echo "<TD>".ucwords($frase)."</TD></TR>\n";
echo "</TABLE>\n";
?>
</CENTER>
</BODY>
</HTML>
El cual produce el resultado mostrado en la figura (Fig. 21.7)

21.8.4 ENMASCARAMIENTO DE CARACTERES


Al generar documentos, es habitual que los caracteres que tienen un significado especial (meta-
caracteres) aparezcan precedidos por una barra invertida ("\"), esto es, aparezcan enmascarados,

Desarrollo de Aplicaciones Web Dinámicas - UNED


21.12 CADENAS

para que el intérprete de PHP los considere como a otro cualquiera. Para realizar operaciones con
caracteres especiales, PHP cuenta con las siguientes funciones:

Figura 21.7 Conversión entre mayúsculas y minúsculas.

• addslashes(cadena) : Devuelve una cadena de caracteres igual que la original en la que se


han escapado los caracteres especiales comillas dobles (“), comillas simples (‘) y barra
invertida (\).
• stripslashes(cadena) : Tiene una función contraria a la función addslashes() ya que
devuelve la cadena resultante de eliminar las barras invertidas que protegen los caracteres
comillas dobles ("), comillas simples (`) y barra invertida (\).
• addcslashes(cadena) : Nos permite enmascarar cualquier carácter que desee el usuario. Al
estilo del lenguaje C, los caracteres con código ASCII inferior a 32 y superior a 126 son
convertidos a representación octal.
• stripcslashes(cadena) : Realiza la operación contraria a addcslashes().
• quotemeta(cadena) : Devuelve una cadena de caracteres igual que la original en la que se
han escapado los caracteres especiales: . , \ \, +, *, ?, [, ^, ] , {, $, y }.

Veamos un ejemplo del funcionamiento de las funciones anteriores:


<HTML>
<HEAD>
<TITLE>Trabajando con Cadenas</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Funciones <I>addslashes y stripslashes</I></H2>
<?php
$cadena='path=["\usr\$usuario"]|\usr';
echo "<TABLE BORDER='1'CELLPADDING='2' CELLSPACING='2'>\n";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>cadena</TD><TD>$cadena</TD>\n";

Desarrollo de Aplicaciones Web Dinámicas - UNED


MODIFICACIÓN DEL CONTENIDO 21.13

echo "<TR ALIGN='center'>";


echo "<TD BGCOLOR='yellow'>addslashes(cadena)</TD>";
echo "<TD>".addslashes($cadena)."</TD></TR>\n";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>addcslashes(cadena,'$|')</TD>";
echo "<TD>".addcslashes($cadena,"$|")."</TD></TR>\n";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>quotemeta(cadena)</TD>";
echo "<TD>".quotemeta($cadena)."</TD></TR>\n";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>stripslashes(cadena)</TD>";
echo "<TD>".stripslashes($cadena)."</TD></TR>\n";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>stripcslashes(cadena)</TD>";
echo "<TD>".stripcslashes($cadena)."</TD></TR>\n";
echo "</TABLE>\n";
?>
</CENTER>
</BODY>
</HTML>

Figura 21.8 Enmascaramiento de caracteres.

21.8.5 DIVISIÓN DE CADENAS


• strtok(cadena, divisor): Divide una cadena en diferentes subcadenas.

Veamos un ejemplo de la función anterior:


<HTML>
<HEAD>
<TITLE>Trabajando con Cadenas</TITLE> </HEAD>
<BODY>
<CENTER>
<H2>Función <I>strtok</I></H2>
<?php
$patron=";";
$cadena="datol;dato2;dato3:dato4;dato5";

Desarrollo de Aplicaciones Web Dinámicas - UNED


21.14 CADENAS

$datos = strtok($cadena,$patron);
echo "<TABLE BORDER='1'CELLPADDING='2' CELLSPACING='2'>\n";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>cadena</TD><TD>$cadena</TD>\n";
echo "<TR ALIGN='center'>"; echo "<TD COLSPAN='2'
BGCOLOR='yellow'>substr_count(cadena,'$patron')</TD>";
echo "</TR>\n";
while($datos){
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>subcadena</TD>";
echo "<TD>$datos</TD></TR>\n";
$datos=strtok($patron);
}
echo "</TABLE>\n"
?>;
</CENTER>
</BODY>
</HTML>

Figura 21.9 Función strtok().

• chunk_split(cadena [, long [, separador]]): Permite marcar una cadena en porciones dife-


renciadas de tamaño menor. Podemos indicarle el tamaño de estas porciones e, incluso, el
carácter o cadena con el que las separará. No modifica la cadena original.
• split(patron, cadena) : Devuelve un array resultado de dividir una cadena en diferentes
subcadenas. El número total de elementos del arrav puede ser elegido a través de un pará-
metro opcional.
• explode(patron, cadena) : Devuelve un array resultado de dividir una cadena en diferentes
subcadenas. El número de elementos del array puede ser elegido a través de un parámetro
opcional.
• implode(nexo, cadena) : Devuelve una cadena resultado de unir todos los elementos de un
array en el mismo orden en el que aparecen, pero con una cadena en medio de ellos.

Desarrollo de Aplicaciones Web Dinámicas - UNED


RELACIÓN CON HTML 21.15

21.9 RELACIÓN CON HTML

Gran parte de las cadenas con las que trabaja PHP tienen como función convertirse en partes de
un documento HTML que será enviado al usuario. Para facilitar algunas de los problemas que
tiene la transformación de texto en código HTML válido, PHP proporciona las siguientes funcio-
nes entre otras:
• htmlspecialchars(cadena) : Se encarga de convertir los caracteres con un significado espe-
cial en HTML en entidades HTML según la tabla siguiente.

Tabla 21.1 HTML.

• htmlentities(cadena) : Es similar a la función anterior, salvo que esta función traduce todos
los caracteres a su correspondiente entidad en HTML.

21.10 OTRAS FUNCIONES

• chr(entero) : Recibe corno argumento un valor entero correspondiente a un código ASCII


y devuelve el carácter asociado a dicho código.
• count_chars(cadena [ , modo] ) : Cuenta el número de apariciones de cada carácter dentro
de la cadena. El modo en que devuelve esta información depende de un parámetro opcio-
nal cuyos valores son:

Tabla 21.2 Modos de la función count_char().

Desarrollo de Aplicaciones Web Dinámicas - UNED


21.16 CADENAS

• str_repeat (cadena, num_veces ) : Recibe corno argumento una cadena y un número entero
para devolver, a continuación, la cadena repetida tantas veces corno indique el número
entero.
• strrev (cadena) : Devuelve la cadena invertida.

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 22

Arrays

22.1 INTRODUCCIÓN

Los arrays o matrices forman una parte muy importante de la programación en PHP ya que per-
miten manejar grupos de valores relacionados: nos permiten almacenar múltiples valores en una
sola estructura y, de esta forma, asociarlos bajo una misma denominación. Como veremos, PHP
tiene gran cantidad de funciones cuyos parámetros, tanto de llamada como de resultados, son
variables de tipo array. En especial, son ampliamente utilizados en las funciones ligadas a las
bases de datos.

En este tema profundizaremos en los distintos tipos de arrays que podemos definir, escalares y
asociativos, tanto unidimensionales como multidimensionales, y las distintas formas de hacerlo.
Veremos las principales funciones para su manejo y tratamiento.

22.2 ARRAYS ESCALARES

Un array escalar, o simple, está formado por un conjunto de valores ordenados respecto a un
índice de tipo entero. Este índice indicará la posición del elemento dentro de esta colección orde-
nada, de modo que, en cada posición marcada por el índice dentro del array, haya un valor.

Existen diferentes formas de crear arrays. La más sencilla consiste en asignar el valor de cada
elemento de manera explícita, es decir, indicando cada uno de los valores que lo componen e,
incluso, la posición que ocupan dentro del array. El siguiente ejemplo nos muestra estas dos for-
mas equivalentes de definir el mismo array:
<HTML>
<HEAD>
<TITLE>Trabajando con Matrices</TITLE>
</HEAD>
<BODY>
22.2 ARRAYS

<CENTER>
<H2>Arrays <I>simples</I></H2>
<?php

$matriz1[0]="cougar";
$matriz1[1]="ford";
$matriz1[2]="";
$matriz1[3]="2.500";
$matriz1[4]="V6";
$matriz1[5]=172;

$matriz2[]="cougar";
$matriz2[]="ford";
$matriz2[]="";
$matriz2[]="2.500";
$matriz2[]="V6";
$matriz2[]=172;

?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD>índice</TD>
<?php
for($i=0;$i<=5;$i++)
echo "<TD>$i</TD>";
?>
</TR>
<TR ALIGN="center">
<TD BGCOLOR="yellow">$matriz1</TD>
<?php
echo "<TD> $matriz1[0] </TD>";
echo "<TD> $matriz1[1] </TD>";
echo "<TD> $matriz1[2] </TD>";
echo "<TD> $matriz1[3] </TD>";
echo "<TD> $matriz1[4] </TD>";
echo "<TD> $matriz1[5] </TD>";
?>
</TR>
<TR ALIGN="center">
<TD BGCOLOR="yellow">$matriz2</TD>
<?php
echo "<TD> $matriz2[0] </TD>";
echo "<TD> $matriz2[1] </TD>";
echo "<TD> $matriz2[2] </TD>";
echo "<TD> $matriz2[3] </TD>";
echo "<TD> $matriz2[4] </TD>";
echo "<TD> $matriz2[5] </TD>";
?>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>

Desarrollo de Aplicaciones Web Dinámicas - UNED


ARRAYS ESCALARES 22.3

Como observamos en el código anterior, un array puede combinar elementos de naturaleza dis-
tinta: en el ejemplo, valores enteros y cadenas de caracteres (que deben aparecer entrecomilla-
dos) e, incluso, elementos vacíos. El resultado se muestra en la siguiente imagen :

Figura 22.1 Matrices simples.

Cuando, al generar el array, no indicamos la posición de sus elementos, éstos se van situando
secuencialmente respecto a la última asignación realizada sobre el array. La asignación numérica
de posiciones dentro del array no tiene por qué ser secuencial, es decir, podemos definir el orden
numérico que nos interese.

La otra forma de definir arrays es utilizar el constructor array ( ) proporcionado por el lenguaje.
Este constructor no es una función regular; tiene la siguiente definición:
array array (mixed valores,...)
El siguiente ejemplo nos muestra cómo utilizar este constructor para definir el mismo array que
en ejemplos anteriores:
<HTML>
<HEAD>
<TITLE>Trabajando con Matrices</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>El constructor <I>array</I></H2>
<?php
$matriz1 = array("cougar","ford",null,"2.500","V6",172);
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD>índice</TD>
<?php
for($i=0;$i<=5;$i++)
echo "<TD>$i</TD>";
?>
</TR>
<TR ALIGN="center">

Desarrollo de Aplicaciones Web Dinámicas - UNED


22.4 ARRAYS

<TD BGCOLOR="yellow">$matriz1</TD>
<?php
echo "<TD> $matriz1[0] </TD>";
echo "<TD> $matriz1[1] </TD>";
echo "<TD> $matriz1[2] </TD>";
echo "<TD> $matriz1[3] </TD>";
echo "<TD> $matriz1[4] </TD>";
echo "<TD> $matriz1[5] </TD>";
?>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>
El constructor array ( ) también nos permite asignar los elementos del array en el orden en que
queramos. Para ello, indicamos el índice, seguido del símbolo "=>" y el valor del elemento. Por
ejemplo:
<HTML>
<HEAD>
<TITLE>Trabajando con Matrices</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>El constructor <I>array</I></H2>
<?php
$matriz1 = array("cougar","ford",null,"2.500","V6",172);
$matriz2 = array(2=>"cougar","ford",1=>null,0=>"2.500","V6",172);
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD>índice</TD>
<?php
for($i=0;$i<=5;$i++)
echo "<TD>$i</TD>";
?>
</TR>
<TR ALIGN="center">
<TD BGCOLOR="yellow">$matriz1</TD>
<?php
echo "<TD> $matriz1[0] </TD>";
echo "<TD> $matriz1[1] </TD>";
echo "<TD> $matriz1[2] </TD>";
echo "<TD> $matriz1[3] </TD>";
echo "<TD> $matriz1[4] </TD>";
echo "<TD> $matriz1[5] </TD>";
?>
</TR>
<TR ALIGN="center">
<TD BGCOLOR="yellow">$matriz2</TD>
<?php
echo "<TD> $matriz2[0] </TD>";
echo "<TD> $matriz2[1] </TD>";
echo "<TD> $matriz2[2] </TD>";
echo "<TD> $matriz2[3] </TD>";
echo "<TD> $matriz2[4] </TD>";
echo "<TD> $matriz2[5] </TD>";
?>
</TR>

Desarrollo de Aplicaciones Web Dinámicas - UNED


ARRAYS ASOCIATIVOS 22.5

</TABLE>
</CENTER>
</BODY>
</HTML>

Figura 22.2 El constructor array.

Como se muestra en la imagen anterior (Fig. 22.2), los elementos a los que no se les asigna explí-
citamente un índice toman la posición secuencial relativa a la última asignación de posición den-
tro del array.

22.3 ARRAYS ASOCIATIVOS

A diferencia de los arrays simples, los arrays asociativos (también conocidos como tablas hash o
arrays indexados por cadena) están formados por un conjunto de valores que están ordenados res-
pecto a un índice de tipo string, es decir, una cadena de caracteres. De este modo, nuestro array
va a estar compuesto por pares clave-valor, siendo necesario proporcionar la clave para poder
acceder al valor almacenado en el array.

De igual forma que ocurre con los arrays simples, podernos utilizar el constructor del lenguaje
array ( ) para definirlos, o bien, hacerlo especificando de forma explícita cada uno de sus compo-
nentes. El siguiente ejemplo nos muestra ambas posibilidades:
<HTML>
<HEAD>
<TITLE>Trabajando con Matrices</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Arrays <I>asociativos</I></H2>
<?php
$matriz1 = array("modelo"=>"cougar","marca"=>"ford",
"fecha"=>null,"cc"=>"2.500","motor"=>"V6",
"potencia"=>172);

$matriz2['modelo']="cougar";

Desarrollo de Aplicaciones Web Dinámicas - UNED


22.6 ARRAYS

$matriz2['marca']="ford";
$matriz2['fecha']=null;
$matriz2['cc']="2.500";
$matriz2['motor']="V6";
$matriz2['potencia']=182;
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD></TD>
<TD>Modelo</TD>
<TD>Marca</TD>
<TD>Fecha</TD>
<TD>CC</TD>
<TD>Motor</TD>
<TD>Potencia</TD>
</TR>
<TR ALIGN="center">
<TD BGCOLOR="yellow">$matriz1</TD>
<?php
echo "<TD>".$matriz1['modelo']."</TD>";
echo "<TD>".$matriz1['marca']."</TD>";
echo "<TD>".$matriz1['fecha']."</TD>";
echo "<TD>".$matriz1['cc']."</TD>";
echo "<TD>".$matriz1['motor']."</TD>";
echo "<TD>".$matriz1['potencia']."</TD>";
?>
</TR>
<TR ALIGN="center">
<TD BGCOLOR="yellow">$matriz2</TD>
<?php
echo "<TD>".$matriz2['modelo']."</TD>";
echo "<TD>".$matriz2['marca']."</TD>";
echo "<TD>".$matriz2['fecha']."</TD>";
echo "<TD>".$matriz2['cc']."</TD>";
echo "<TD>".$matriz2['motor']."</TD>";
echo "<TD>".$matriz2['potencia']."</TD>";
?>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>

22.4 ARRAYS MULTIDIMENSIONALES

PHP nos permite definir arrays multidimensionales mediante la combinación de arrays unidi-
mensionales (que pueden ser tanto de tipo escalar, como asociativos). Los siguientes ejemplos
nos muestran las diferentes formas de definirlos.
• Array multidimensional de tipo escalar:
<HTML>
<HEAD>
<TITLE>Trabajando con Matrices</TITLE>
</HEAD>
<BODY>

Desarrollo de Aplicaciones Web Dinámicas - UNED


ARRAYS MULTIDIMENSIONALES 22.7

<CENTER>
<H2>Arrays <I>multidimensionales</I></H2>
<?php
$matriz1[0][0] = "peseta";
$matriz1[0][1] = 166.386;
$matriz1[1][0] = "dolar";
$matriz1[1][1] = 0.96;

$matriz2[0] = array("peseta",166.386);
$matriz2[1] = array("dolar",0.96);

$matriz3 = array(array("peseta",166.386),array("dolar",0.96));
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD></TD>
<TD>Moneda</TD>
<TD>Cambio €</TD>
</TR>
<?php
for($i=0;$i<2;$i++){
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz1[$i]</TD>";
for($j=0;$j<2;$j++){
echo "<TD>".$matriz1[$i][$j]."</TD>";
}
echo "</TR>";
}
for($i=0;$i<2;$i++){
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz2[$i]</TD>";
for($j=0;$j<2;$j++){
echo "<TD>".$matriz2[$i][$j]."</TD>";
}
echo "</TR>";
}
for($i=0;$i<2;$i++){
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz3[$i]</TD>";
for($j=0;$j<2;$j++){
echo "<TD>".$matriz3[$i][$j]."</TD>";
}
echo "</TR>";
}
?>
</TABLE>
</CENTER>
</BODY>
</HTML>

• Array multidimensional de tipo asociativo


HTML>
<HEAD>
<TITLE>Trabajando con Matrices</TITLE>
</HEAD>

Desarrollo de Aplicaciones Web Dinámicas - UNED


22.8 ARRAYS

<BODY>
<CENTER>
<H2>Arrays <I>multidimensionales</I></H2>
<?php
$matriz1['peseta']['moneda'] = "peseta";
$matriz1['peseta']['cambio'] = 166.386;
$matriz1['dolar']['moneda'] = "dolar";
$matriz1['dolar']['cambio'] = 0.96;

$matriz2['peseta']=array("moneda"=>"peseta","cambio"=>166.386);
$matriz2['dolar']=array("moneda"=>"dolar","cambio"=>0.96);

$matriz3 = array("peseta"=>array("moneda"=>"peseta","cambio"=>166.386),
"dolar"=>array("moneda"=>"dolar","cambio"=>0.96));
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD></TD>
<TD>Moneda</TD>
<TD>Cambio €</TD>
</TR>
<?php
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz1</TD>";
echo "<TD>".$matriz1['peseta']['moneda']."</TD>";
echo "<TD>".$matriz1['peseta']['cambio']."</TD>";
echo "</TR>";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz1</TD>";
echo "<TD>".$matriz1['dolar']['moneda']."</TD>";
echo "<TD>".$matriz1['dolar']['cambio']."</TD>";
echo "</TR>";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz2</TD>";
echo "<TD>".$matriz2['peseta']['moneda']."</TD>";
echo "<TD>".$matriz2['peseta']['cambio']."</TD>";
echo "</TR>";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz2</TD>";
echo "<TD>".$matriz2['dolar']['moneda']."</TD>";
echo "<TD>".$matriz2['dolar']['cambio']."</TD>";
echo "</TR>";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz3</TD>";
echo "<TD>".$matriz3['peseta']['moneda']."</TD>";
echo "<TD>".$matriz3['peseta']['cambio']."</TD>";
echo "</TR>";
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz3</TD>";
echo "<TD>".$matriz3['dolar']['moneda']."</TD>";
echo "<TD>".$matriz3['dolar']['cambio']."</TD>";
echo "</TR>";
?>
</TABLE>
</CENTER>
</BODY>
</HTML>

• Array multidimensional combinado


<HTML>
<HEAD>

Desarrollo de Aplicaciones Web Dinámicas - UNED


RECORRER UN ARRAY 22.9

<TITLE>Trabajando con Matrices</TITLE>


</HEAD>
<BODY>
<CENTER>
<H2>Arrays <I>multidimensionales</I></H2>
<?php
$matriz1[0]['moneda'] = "peseta";
$matriz1[0]['cambio'] = 166.386;
$matriz1[1]['moneda'] = "dolar";
$matriz1[1]['cambio'] = 0.96;

$matriz2[0]=array("moneda"=>"peseta","cambio"=>166.386);
$matriz2[1]=array("moneda"=>"dolar","cambio"=>0.96);

$matriz3 = array(array("moneda"=>"peseta","cambio"=>166.386),
array("moneda"=>"dolar","cambio"=>0.96));
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD></TD>
<TD>Moneda</TD>
<TD>Cambio €</TD>
</TR>
<?php
for($i=0;$i<2;$i++){
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz1</TD>";
echo "<TD>".$matriz1[$i]['moneda']."</TD>";
echo "<TD>".$matriz1[$i]['cambio']."</TD>";
echo "</TR>";
}
for($i=0;$i<2;$i++){
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz2</TD>";
echo "<TD>".$matriz2[$i]['moneda']."</TD>";
echo "<TD>".$matriz2[$i]['cambio']."</TD>";
echo "</TR>";
}
for($i=0;$i<2;$i++){
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz3</TD>";
echo "<TD>".$matriz3[$i]['moneda']."</TD>";
echo "<TD>".$matriz3[$i]['cambio']."</TD>";
echo "</TR>";
}
?>
</TABLE>
</CENTER>
</BODY>
</HTML>

22.5 RECORRER UN ARRAY

Como hemos visto en los ejemplos anteriores, una operación habitual a realizar cuando trabaja-
mos con arrays es recorrerlos para obtener sus elementos, para modificarlos o trabajar con ellos.

Desarrollo de Aplicaciones Web Dinámicas - UNED


22.10 ARRAYS

22.5.1 RECORRIDOS EN ARRAYS SECUENCIALES


De los ejemplos anteriores podemos destacar que recorrer los diferentes elementos que compo-
nen un array secuencial es relativamente sencillo, pues, haciendo uso de un bucle e iterando en
función del valor del índice, podemos realizar la operación. El problema principal en este tipo de
recorridos es conocer a priori el número de elementos que componen el array. Precisamente para
solventar este problema, PHP proporciona la función count () , que devuelve el número de ele-
mentos que tiene la variable que recibe como argumento.

Una vez conocido el número de elementos del array, podemos utilizar un bucle para ir reco-
rriendo sus elementos, tal y como muestra el siguiente ejemplo, en el que nos permite recorrer un
array multidimensional:
<HTML>
<HEAD>
<TITLE>Trabajando con Matrices</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Arrays función <I>count</I></H2>
<?php
$matriz1[0][0] = "peseta";
$matriz1[0][1] = 166.386;
$matriz1[1][0] = "dolar";
$matriz1[1][1] = 0.96;
$matriz1[2][0] = "marco";
$matriz1[2][1] = 1.85;
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD></TD>
<TD>Moneda</TD>
<TD>Cambio 1€</TD>
</TR>
<?php
for($i=0;$i<count($matriz1);$i++){
echo "<TR ALIGN='center'>";
echo "<TD BGCOLOR='yellow'>\$matriz1[$i]</TD>";
for($j=0;$j<count($matriz1[$i]);$j++){
echo "<TD>".$matriz1[$i][$j]."</TD>";
}
echo "</TR>";
}
?>
</TABLE>
</CENTER>
</BODY>
</HTML>
Otra función relacionada con el recorrido de arrays es sizeof (), que obtiene el número de elemen-
tos del array pasado como argumento en la llamada a la función.

Desarrollo de Aplicaciones Web Dinámicas - UNED


RECORRER UN ARRAY 22.11

22.5.2 RECORRIDOS EN ARRAYS NO SECUENCIALES


A primera vista, un array no secuencial no parece muy fácil de recorrer, puesto que no sólo nece-
sitamos saber el número de elementos que componen el array, sino también su posición dentro
del array. Este mismo problema se presenta con los arrays asociativos, puesto que, además del
número de elementos que componen el array, necesitamos conocer las claves para poder acceder
a los valores almacenados. Para poder trabajar con arrays estructurados de modo no secuencial,
tanto de tipo escalar como asociativos, PHP cuenta con el siguiente conjunto de funciones (estas
funciones también son aplicables a arrays estructurados secuencialmente):
• current (matriz) : Devuelve el valor de la posición actual del puntero dentro del array:
todos los arrays tienen un puntero interno que apunta a la posición del elemento actual con
el que se está trabajando en un momento dado. Devuelve false cuando el puntero está al
final del array o cuando el array no contiene ningún elemento.
• pos (matriz) : Es idéntica a la funcióna anterior.
• key (matriz) : Devuelve el índice de la posición actual del array pasado como argumento:
un número, en caso de que el array sea de tipo escalar, o una cadena de caracteres, en el
caso de que el array sea de tipo asociativo.
• next (matriz) : Devuelve el valor del elemento siguiente al actual (si existe) y avanza el
puntero interno una posición. En caso de que el elemento actual sea el último del array,
devuelve false.
• prev (matriz) : Devuelve el valor del elemento anterior al actual (si existe) y retrocede el
puntero interno una posición. En caso de que el elemento actual sea el primero del array,
devuelve false.
• end (matriz) : Coloca el puntero interno en el último elemento de un array escalar.
• reset (matriz) : Devuelve el valor del primer elemento del array y sitúa el puntero interno
en su primera posición.

El siguiente ejemplo muestra la utilización de alguna de estas funciones:


<HTML>
<HEAD>
<TITLE>Trabajando con Matrices</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Arrays funciones <BR><I>reset, end, next, prev, current y key</I></H2>
<?php
$matriz1[3]="cougar";
$matriz1[5]="ford";
$matriz1[7]="2.500";
$matriz1[ ]="V6";
$matriz1[ ]=172;

$matriz2['modelo']="cougar";
$matriz2['marca']="ford";
$matriz2['fecha']=null;
$matriz2['cc']="2.500";
$matriz2['motor']="V6";
$matriz2['potencia']=182;
?>

Desarrollo de Aplicaciones Web Dinámicas - UNED


22.12 ARRAYS

<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">


<TR ALIGN="center" BGCOLOR="yellow">
<TD>Posición</TD>
<?php
echo "<TD BGCOLOR='yellow'>".key($matriz1)."</TD>";
while(next($matriz1)){
echo "<TD BGCOLOR='yellow'>".key($matriz1)."</TD>";
}
?>
</TR>
<TR ALIGN="center">
<TD BGCOLOR="yellow">Valor</TD>
<?php
echo "<TD>".reset($matriz1)."</TD>";
while(next($matriz1)){
echo "<TD>".current($matriz1)."</TD>";
}
?>
</TABLE><BR>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD>Clave</TD>
<?php
end($matriz2);
echo "<TD BGCOLOR='yellow'>".key($matriz2)."</TD>";
while(prev($matriz2)){
echo "<TD BGCOLOR='yellow'>".key($matriz2)."</TD>";
}
?>
</TR>
<TR ALIGN="center">
<TD BGCOLOR="yellow">Valor</TD>
<?php
end($matriz2);
echo "<TD>".current($matriz2)."</TD>";
while(prev($matriz2)){
echo "<TD>".current($matriz2)."</TD>";
}
?>
</TABLE>
</CENTER>
</BODY>
</HTML>

Como podemos observar en la siguiente imagen (Fig. 22.3), el recorrido del segundo array (en
orden inverso) se detiene en el instante en que se encuentra un elemento vacío, mientras que el
primero se muestra completamente.
• each (matriz) : Se usa para recorrer arrays (sobre todo los asociativos), pues devuelve un
par de valores correspondientes a la clave y al valor asociado a esa clave. Además, avanza
el puntero interno hasta el siguiente elemento. Si el puntero interno apunta a la última posi-
ción del array, la ejecución de esta función devuelve false.
• list ( ) : Asigna una lista de variables en una sola operación. Suele utilizarse en combina-
ción con la función anteriormente vista, each () .

Desarrollo de Aplicaciones Web Dinámicas - UNED


RECORRER UN ARRAY 22.13

Figura 22.3 Recorriendo matrices.

El siguiente ejemplo muestra el recorrido por dos arravs no secuenciales haciendo uso de ambas
funciones:
<HTML>
<HEAD>
<TITLE>Trabajando con Matrices</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Arrays funciones <I>each y list</I></H2>
<?php
$matriz1[3]="cougar";
$matriz1[5]="ford";
$matriz1[7]="2.500";
$matriz1[ ]="V6";
$matriz1[ ]=172;

$matriz2['modelo']="cougar";
$matriz2['marca']="ford";
$matriz2['fecha']=null;
$matriz2['cc']="2.500";
$matriz2['motor']="V6";
$matriz2['potencia']=182;
?>
<TABLE BORDER="0" CELLPADDING="4" CELLSPACING="6">
<TR ALIGN="center"><TD>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD>Posición</TD><TD>Valor</TD></TR>
<?php
while(list($pos,$valor)=each($matriz1)){
echo "<TR ALIGN='center'><TD>".$pos."</TD>";
echo "<TD>".$valor."</TD></TR>";
}
?>
</TABLE></TD><TD>

Desarrollo de Aplicaciones Web Dinámicas - UNED


22.14 ARRAYS

<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">


<TR ALIGN="center" BGCOLOR="yellow">
<TD>Clave</TD><TD>Valor</TD></TR>
<?php
while(list($clave,$valor)=each($matriz2)){
echo "<TR ALIGN='center'><TD>".$clave."</TD>";
echo "<TD>".$valor."</TD></TR>";
}
?>
</TABLE></TD></TR>
</TABLE>
</CENTER>
</BODY>
</HTML>

Como podemos observar en la siguiente imagen (Fig. 22.4), el recorrido de ambos arrays es com-
pleto independientemente de que tengan elementos vacíos:

Figura 22.4 Funciones each y list.

• array_keys (matriz) : Devuelve las claves que forman el array matriz. Admite un paráme-
tro opcional que nos permite seleccionar sólo las claves cuyo valor coincida con un patrón
dado.
• array_values (matriz) : Devuelve los valores que forman parte del array pasado como
parámetro.

22.6 ORDENAR UN ARRAY

Veremos a continuación varias funciones que PHP pone a nuestra disposición para poder ordenar
los elementos de un array, ya que es frecuente que necesitemos tener los elementos de un array
ordenados para después, por ejemplo, poder listarlos en orden alfabético.

Desarrollo de Aplicaciones Web Dinámicas - UNED


ORDENAR UN ARRAY 22.15

• sort (matriz) : Ordena alfanuméricamente los valores de los elementos de un arrav de


menor a mayor. Para ordenar de manera inversa, disponemos de la función rsort (matriz).
<HTML>
<HEAD>
<TITLE>Trabajando con Matrices</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Arrays funciones <I>sort y rsort</I></H2>
<?php
$matriz1[0]="Madrid";
$matriz1[1]="Zaragoza";
$matriz1[2]="Bilbao";
$matriz1[3]="Valencia";
$matriz1[4]="Lerida";
$matriz1[5]="Alicante";
?>
<TABLE BORDER="0" CELLPADDING="4" CELLSPACING="6">
<TR ALIGN="center"><TD>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD>Posición</TD><TD>Valor</TD></TR>
<?php
sort($matriz1);
while(list($pos,$valor)=each($matriz1)){
echo "<TR ALIGN='center'><TD>".$pos."</TD>";
echo "<TD>".$valor."</TD></TR>";
}
?>
</TABLE></TD><TD>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD>Posición</TD><TD>Valor</TD></TR>
<?php
rsort($matriz1);
while(list($pos,$valor)=each($matriz1)){
echo "<TR ALIGN='center'><TD>".$pos."</TD>";
echo "<TD>".$valor."</TD></TR>";
}
?>
</TABLE></TD></TR>
</TABLE>
</CENTER>
</BODY>
</HTML>

Podemos comprobar el resultado de la ejecución del código anterior en la figura (Fig. 22.5).

Para evitar este efecto lateral en el que se redefinen los índices, tanto para los arravs escalares
corno asociativos, podemos usar las siguientes funciones:
• asort (matriz) : Ordena alfanuméricamente los valores de los elementos de un arrav de
mayor a menor, pero manteniendo la relación existente entre los índices y sus valores aso-
ciados. Esto es posible debido a que la ordenación se hace sobre los elementos del array y
no sobre los índices.
• arsort (matriz) : realiza la ordenación inversa.

Desarrollo de Aplicaciones Web Dinámicas - UNED


22.16 ARRAYS

Figura 22.5 Funciones sort y rsort.

<HTML>
<HEAD>
<TITLE>Trabajando con Matrices</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Arrays funciones <I>asort y arsort</I></H2>
<?php
$matriz1[0]="Madrid";
$matriz1[1]="Zaragoza";
$matriz1[2]="Bilbao";
$matriz1[3]="Valencia";
$matriz1[4]="Lerida";
$matriz1[5]="Alicante";
?>
<TABLE BORDER="0" CELLPADDING="4" CELLSPACING="6">
<TR ALIGN="center"><TD>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD>Posición</TD><TD>Valor</TD></TR>
<?php
asort($matriz1);
while(list($pos,$valor)=each($matriz1)){
echo "<TR ALIGN='center'><TD>".$pos."</TD>";
echo "<TD>".$valor."</TD></TR>";
}
?>
</TABLE></TD><TD>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="yellow">
<TD>Posición</TD><TD>Valor</TD></TR>
<?php
arsort($matriz1);
while(list($pos,$valor)=each($matriz1)){

Desarrollo de Aplicaciones Web Dinámicas - UNED


ORDENAR UN ARRAY 22.17

echo "<TR ALIGN='center'><TD>".$pos."</TD>";


echo "<TD>".$valor."</TD></TR>";
}
?>
</TABLE></TD></TR>
</TABLE>
</CENTER>
</BODY>
</HTML>

Figura 22.6 Funciones asort y arsort.

• ksort (matriz) : Ordena alfanuméricamente las claves de un array de menor a mayor man-
teniendo las correlaciones entre clave y valor asociado. La función que realiza la ordena-
ción inversa es krsort (matriz).
• usort (matriz, func_comparar) : Ordena los valores de un array según el criterio de la fun-
ción pasada por el usuario como argumento. La función hay que pasarla como una cadena
de caracteres, es decir, entre comillas (las funciones se verán en profundidad en un tema
posterior).
• uksort (matriz, func_comparar) : Ordena las claves de un array en base a una función
pasada por el usuario como argumento, manteniendo las correlaciones existentes entre
clave y valor asociado. La función de comparación debe devolver un entero menor, igual o
mayor que cero, si el primer argumento es, respectivamente, menor que, igual que o mayor
que el segundo. Si los dos argumentos resultan ser iguales, su orden en la matriz ordenada
será cualquiera.
• uasort (matriz, func_comparar) : Ordena los valores de un array según el criterio de la fun-
ción pasada por el usuario como argumento, manteniendo las correlaciones entre clave y
valor asociado.

Desarrollo de Aplicaciones Web Dinámicas - UNED


22.18 ARRAYS

22.7 OTRAS OPERACIONES

Veremos a continuación un grupo de funciones que nos serán de gran utilidad a la hora de traba-
jar con un arras ya existente.

22.7.1 MODIFICAR UN ARRAY


• array_merge (matrizl, matriz2) : Combina en un solo array los valores de los arrays que
recibe como argumentos. Los elementos van siendo añadidos al final del array precedente.
Si estamos juntando arrays asociativos, hay que tener en cuenta que las claves con igual
nombre no se añaden al arrav, sino que se actualizan con el último valor suministrado.

• array_pad(matriz, tamaño, relleno): Devuelve un array igual a matriz, pero modificando


su número de elementos hasta alcanzar la longitud deseada (tamaño) añadiendo nuevos
elementos por la derecha (tamaño es positivo) o por la izquierda (tamaño es negativo).

• array_walk(matriz, func_usuario [, parametro]): Nos permite aplicar una función definida


por el usuario a cada uno de los elementos de un array. La función func_usuario ( ) recibe,
al menos, dos parámetros (el valor del elemento y su clave asociada); si func_usuario ( )
necesitara más parámetros, se pasan como parámetros a la función array_walk ( ) . Una
vez aplicada la función, el puntero interno del array se encontrará al final de él.

22.7.2 TRABAJANDO CON PORCIONES DEL ARRAY


De igual forma que es habitual trabajar con porciones de cadenas de caracteres (modificar,
extraer, etc.), también pueden realizarse este tipo de operaciones sobre urruvs. PHP nos propor-
ciona, entre otras, las siguientes funciones:
• array_slice(matriz, desplazamiento [, int tamaño]): Devuelve los elementos del arrav que
están situados a partir de una posición determinada por desplazamiento. Opcionalmente,
podemos indicar el total de elementos que queremos. Los parámetros desplazamiento y
tamaño pueden ser valores positivos o negativos. Esto da lugar a las siguientes interpreta-
ciones reflejadas en la tabla de abajo:

Tabla 22.1 Parámetros de desplazamiento.

Desarrollo de Aplicaciones Web Dinámicas - UNED


OTRAS OPERACIONES 22.19

• array_splice(matriz , despl [,tam [array substituto]]): Elimina elementos de un array, sus-


tituyéndolos opcionalmente por los elementos de otro array (substituto). Elimina y, si está
indicado, sustituye los elementos que están situados a partir de la posición indicada por
despl. Devuelve los elementos eliminados. Los significados de los diferentes valores que
pueden tomar desplazamiento y tamaño se especifican en la siguiente tabla:

Tabla 22.2 Desplazamiento y tamaño.

22.7.3 USANDO ARRAYS COMO PILAS


Las pilas son estructuras de datos en las que la inserción y la recuperación de los datos que alma-
cenan se realiza bajo un orden prefijado. Son estructuras con una gestión de tipo LIFO (Last ln
First Out), es decir, el último en llegar es el primero en salir. PHP proporciona las siguientes fun-
ciones que nos permiten trabajar con los arrays como si fuesen pilas:
• array_push (matriz , valorl [, valor2 , ... ]) : Inserta uno o más elementos al final de
matriz. Devuelve el nuevo número de elementos.
• array_pop (matriz) : Devuelve y elimina el último elemento del array (el que se corres-
ponde con la cima de la pila).
• array_shift (matriz) : Devuelve y elimina el primer elemento del arrav (el que se corres-
ponde con la base de la pila).
• array_unshift(matriz, valor' [, valor2, ..]): Inserta uno o más elementos al principio del
array. Devuelve el número total de elementos contenidos en él.
• array reverse (matriz) : Devuelve el array pasado como parámetro, pero con sus compo-
nentes en orden inverso.
• range(limite_inf, limite_sup): Devuelve un array con los valores enteros comprendidos
entre el primer argumento y el segundo que recibe la función, ambos inclusive.
• array_count_values (matriz) : Recibe corno argumento un array y devuelve otro cuyos
índices son los mismos que los del array original y sus valores asociados son la frecuencia
con la que se repiten dichos valores en el array original.
• in_array(elemento_busqueda, matriz): Con esta función podremos saber si un elemento
está contenido dentro de un array.

Desarrollo de Aplicaciones Web Dinámicas - UNED


22.20 ARRAYS

• compact ( ) : Esta función recibe como argumento una lista de variables que han sido pre-
viamente definidas, que pueden aparecer como cadenas de caracteres o como arrays y
devuelve un nuevo array en el que los índices son los nombres de las variables y el conte-
nido de los elementos del array son sus correspondientes valores.

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 23

Funciones

23.1 FUNCIONES

La mayor parte de las secciones del código de un script PHP deben ser ejecutadas tan pronto
como dicho script es interpretado pero, otras veces, es preferible que el código actúe después de
que se haya producido alguna acción específica o sólo si se dispara un evento. También es habi-
tual que partes del código se repitan un número indeterminado de veces durante la ejecución del
script PHP. Estas necesidades hacen que nazca la idea de dividir el código de un script en partes
menores, para que cada una de las cuales sirva a un propósito específico e individual.

Una función PHP es simplemente una sección separada de código a la que se le ha dado un nom-
bre (cualquier instrucción PHP válida puede aparecer en el cuerpo de la función, incluso la lla-
mada a otra función o la definición de clases). Utilizando este nombre, en un script se puede
llamar a esta sección de código tantas veces como se quiera y en los momentos en que se nece-
site. Por tanto, las funciones dividen las tareas que debe hacer un script, agrupando instrucciones
relacionadas para la ejecución de una tarea. Esta estructuración del código nos permite escribir
scripts más sencillos, legibles y fáciles de entender.

Las funciones pueden recibir valores desde las sentencias que las llaman. Estos valores se deno-
minan parámetros o argumentos y pueden devolver valores. Los parámetros, como veremos más
adelante, se usarán como variables locales dentro del bloque de sentencias que conforman la fun-
ción.

La sintaxis para definir una función en PHP es la siguiente:


function nombreFunción(parametros){
[sentencias]
}
23.2 FUNCIONES

La palabra reservada function se utiliza para especificar un nombre, nombreFunción, el cual sirve
como identificador para el conjunto de sentencias comprendidas entre las llaves. Encerrados
entre paréntesis y separados por comas, se encuentran los nombres de los parámetros, que son
los que recibirán los valores con los que es llamada la función. Técnicamente, los argumentos
son variables que contienen informacion necesaria para que la función realice correctamente su
labor y que son pasados a ella en la sentencia de llamada. Aunque no se incluyan parámetros, en
la declaración de la función deben escribirse los paréntesis. Las sentencias, que conforman el
núcleo de la función, son ejecutadas cada vez que se llama a la función.

23.1.1 LLAMADA A UNA FUNCIÓN


Una vez declarada una función, ésta no se ejecuta hasta que se le llama desde cualquier parte del
script. Para llamar a una función, sólo hay que escribir una sentencia que contenga el nombre de
la función y, entre paréntesis, los valores de los argumentos de llamada de ella. En el momento en
que ocurre esto, la ejecución del programa salta inmediatamente a la primera línea de la función
llamada. Después de ejecutar las sentencias que componen el cuerpo de la función, el programa
salta de nuevo a la posición en que fue llamada la función y continúa su ejecución. El resultado
es el mismo que se hubiese obtenido al insertar todas las sentencias de la función en la posición
de llamada a ella. Para volver a hacer uso de la función, simplemente hay que volver a llamarla:
una función puede ser llamada tantas veces como se necesite.

El siguiente ejemplo nos muestra de una forma sencilla cómo definir y llamar a una función.
Como podemos observar, se trata de una función declarada sin parámetros:
<HTML>
<HEAD>
<TITLE>Trabajando con Funciones</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Funciones de Usuario<I></I></H2>
<?php

function cuentaAtras(){
for($i=10;$i>0;$i--)
echo $i,"...<BR>";
echo "¡ Booooom !";
}

?>
<TABLE BORDER="0" CELLPADDING="4" CELLSPACING="6">
<TR ALIGN="center">
<TD BGCOLOR="#FFBBAA">
<?php
cuentaAtras();
?>
</TD>
<TD BGCOLOR="#FFFBAD">
<?php
cuentaAtras();
?>
</TD>
</TR>

Desarrollo de Aplicaciones Web Dinámicas - UNED


FUNCIONES 23.3

</TABLE>
</CENTER>
</BODY>
</HTML>

Figura 23.1 Primera función.

23.1.2 PASO DE PARÁMETROS


En ocasiones, necesitaremos definir funciones que aceptan parámetros o argumentos. De esta
forma conseguimos que la función sea más utilizable dentro del propósito general para el que
está definida. Por ejemplo, podemos querer utilizar una función múltiples veces a lo largo del
programa, pero algunos de sus valores internos pueden variar con cada llamada. La mejor solu-
ción a este problema es definir una función que pueda aceptar argumentos en su llamada para
cada valor con el que queramos trabajar.

Otra forma de solucionar este problema es utilizar variables globales (las veremos en una
próxima sección del tema) que puedan ser modificadas tanto dentro, como fuera de la función.
Pero esto incrementa la confusión del código y su mantenimiento, pues se hace más difícil seguir
su comportamiento.

El siguiente ejemplo muestra una modificación de la función presente en el código anterior para
que el inicio de la cuenta pueda ser configurable por el usuario. Como podemos observar, los
parámetros se utilizan como variables dentro del cuerpo de la función:
<HTML>
<HEAD>
<TITLE>Trabajando con Funciones</TITLE>
</HEAD>
<BODY>
<CENTER>

Desarrollo de Aplicaciones Web Dinámicas - UNED


23.4 FUNCIONES

<H2>Funciones de Usuario<I></I></H2>
<?php

function cuentaAtras($inicio){
for($i=$inicio;$i>0;$i--)
echo $i,"...<BR>";
echo "¡ Booooom !";
}

?>
<TABLE BORDER="0" CELLPADDING="4" CELLSPACING="6">
<TR ALIGN="center">
<TD BGCOLOR="#FFBBAA">
<?php
cuentaAtras(8);
?>
</TD>
<TD BGCOLOR="#FFFBAD">
<?php
cuentaAtras(5);
?>
</TD>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>

Figura 23.2 Función con parámetros.

Dado que en la llamada pasamos valores a la función, esta información puede suministrarse
mediante una lista de variables y/o constantes separadas por comas.

PHP permite pasar los parámetros de tres formas distintas: por valor (el comportamiento por
defecto que hemos visto en los ejemplos anteriores), por referencia y con parámetros por defecto.

Desarrollo de Aplicaciones Web Dinámicas - UNED


FUNCIONES 23.5

Parámetros por valor


Cuando pasamos una variable como argumento en la llamada a una función, podríamos pensar
que las modificaciones que se realicen con dicho argumento dentro del cuerpo de la función afec-
tan a la variable. En el caso del paso de parámetros por valor, que es la opción por defecto en
PHP, lo que recibe la función es una copia del valor de la variable pasada como parámetro; de
esta forma, las modificaciones que puedan hacerse dentro del cuerpo de la función a la variable
parámetro no afectan al valor final de la variable pasada como argumento.

Parámetros por argumento


En el caso de que queramos que los cambios que se producen en el cuerpo de la función afecten a
la variable que se pasó corno argumento en la llamada a la función deberemos pasar el parámetro
por referencia. Como su propio nombre indica, en este caso, a la función le llega una referencia a
la variable y, por tanto, los cambios que realice sobre el parámetro se realizan sobre la variable.

Para indicar qué parámetros se pasan por referencia, hay que marcarlos en la definición de la fun-
ción, anteponiendo el símbolo ampersand (&) al nombre del parámetro.

Parámetros por defecto


Los parámetros por defecto son la forma en que PHP implementa los parámetros opcionales en la
llamada a las funciones. De este modo, este tipo de parámetros toma un valor predefinido
cuando, desde la llamada a la función, no se les ha proporcionado ningún argumento. Para definir
un parámetro por omisión, hay que, además de nombrar el parámetro, escribir el operador de
asignación ("=") y, a continuación, el valor que vaya a recibir el parámetro en caso de no especi-
ficarse en la llamada.

Cuando se usan parámetros por defecto, éstos tienen que situarse los últimos en la declaración, es
decir, a la derecha de cualquier parámetro normal: de otra manera, las cosas no funcionarán de la
forma esperada. Cuando se utiliza el valor por defecto de un parámetro, obligatoriamente han de
utilizarse todos los valores por defecto de todos aquellos parámetros que se encuentren a su dere-
cha.

El siguiente ejemplo nos muestra el uso de estos tres tipos de parámetros:


<HTML>
<HEAD>
<TITLE>Trabajando con Funciones</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Funciones de Usuario<I></I></H2>
<?php

$mifinal=0;

function cuentaAtras($inicio, &$fin, $mensaje="¡ Booooom !"){


for(;$inicio>$fin;$inicio--)
echo $inicio,"...<BR>";
$fin=$fin+2;

Desarrollo de Aplicaciones Web Dinámicas - UNED


23.6 FUNCIONES

echo $mensaje;
}
?>
<TABLE BORDER="0" CELLPADDING="4" CELLSPACING="6">
<TR ALIGN="center">
<TD BGCOLOR="#FFBBAA">
<?php
// $mifinal vale 0
cuentaAtras(6,$mifinal);
// $mifinal vale 2
?>
</TD>
<TD BGCOLOR="#FFFBAD">
<?php
// $mifinal vale 2
cuentaAtras(8,$mifinal,"¡ Despierta !");
// $mifinal vale 4
?>
</TD>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>

Figura 23.3 Tipos de parámetros.

23.1.3 ÁMBITO DE LAS VARIABLES


Una vez vistas las funciones, podernos abordar el problema del ámbito o alcance de las variables,
es decir, del contexto dentro del cual existen las variables. De esta forma podremos determinar
desde qué partes del código del programa o script son accesibles las variables. Básicamente,
podemos definir dos tipos de variables respecto a su ámbito:
• Variables globales son todas aquéllas que se definen fuera del cuerpo de una función y son
accesibles, en general, desde cualquier punto del código. En PHP, las variables globales
deben ser declaradas globales dentro de la función si van a ser utilizadas dentro de dicha

Desarrollo de Aplicaciones Web Dinámicas - UNED


FUNCIONES CON NÚMERO INDETERMINADO DE PARÁMETROS 23.7

función, anteponiendo a su definición la palabra reservada global. Un segundo método


para acceder a las variables globales desde un ámbito local es usando el arrav $GLOBALS
(es un arrav asociativo con el nombre de la variable global como clave y los contenidos de
dicha variable como el valor del elemento del arrav).
• Variables locales aparecen definidas dentro del cuerpo de una función y sólo pueden ser
accedidas desde dentro de esta función. Cualquier variable que se use dentro de una fun-
ción está, por defecto, limitada al ámbito local de la función. Esto quiere decir que. si
declaramos una variable local con el mismo nombre que una variable global. dentro de la
función trabajaremos con la versión local de la variable.
• Variables locales estáticas son variables locales que tienen ámbito local; por defecto, se
crean cada vez que se comienza a ejecutar la función que las define, y se destruyen cuando
se acaba la función. Para evitar que una variable local pierda su valor entre diferentes lla-
madas a la función que la define, hay que definirla corno variable estática, anteponiendo a
su nombre la palabra reservada static. Una variable estática existe sólo en el ámbito local
de la función, pero no pierde su valor cuando la ejecución del programa abandona este
ámbito.

23.1.4 DEVOLUCIÓN DE VALORES


Del mismo modo que las funciones pueden recibir valores, también pueden devolverlos. La
devolución de un valor desde una función trabaja de igual forma que la devolución de un valor en
una expresión, de manera que el valor devuelto desde una función puede ser asignado a una
variable o utilizado dentro de una expresión. Se puede devolver cualquier tipo de valores inclu-
yendo listas y objetos, pero sólo un único valor; para devolver múltiples valores, deberemos uti-
lizar un array.

Para poder hacerlo, se utiliza la palabra reservada return acompañada de una expresión. En el
instante en que aparece dentro del cuerpo de una función una sentencia con esta palabra reser-
vada, la función deja de ejecutarse para devolver el flujo de ejecución al punto del programa
donde se llamó a la función. Si después de return hay más líneas de código, dichas líneas no se
ejecutarán nunca; por eso, es habitual que aparezca como última instrucción del cuerpo de la fun-
ción.

23.2 FUNCIONES CON NÚMERO INDETERMINADO DE PARÁMETROS

PHP nos permite definir funciones en las que el número de parámetros no está fijado a priori, es
decir, en PHP se consiente que una función reciba como parámetro una lista de valores de longi-
tud variable. No se necesita de una sintaxis específica, pero su funcionamiento se basa en el
siguiente conjunto de funciones definidas en PHP:
• func_num_args ( ) : Devuelve el número de argumentos pasados a la función.
• func_get_args ( ) : Devuelve un array con los argumentos pasados a la función.

Desarrollo de Aplicaciones Web Dinámicas - UNED


23.8 FUNCIONES

• func_get_arg ( ) : Devuelve un elemento de la lista de argumentos pasados a la función.


Los argumentos comienzan en la posición 0, al igual que los arrays. Si se solicita un argu-
mento de una posición que no existe, devuelve false.

El siguiente ejemplo muestra la utilización de estas tres funciones:


<HTML>
<HEAD>
<TITLE>Trabajando con Funciones</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Funciones de Usuario<I></I></H2>
<?php
function elMayor($dato1,$dato2){
$num_args = func_num_args();
$args = func_get_args();

$elmayor=($dato1>$dato2)?$dato1:$dato2;
for($i=2;$i<$num_args;$i++)
$elmayor=($elmayor>$args[$i])?$elmayor:func_get_arg($i);
return $elmayor;
}
?>
<TABLE BORDER="0" CELLPADDING="4" CELLSPACING="6">
<TR ALIGN="center">
<TD BGCOLOR="#FFFBAD">
<?php
echo "El mayor de 17, 5, 22 y 19 es <BR><H2>".elMayor(17,5,22,19)."</
H2>";
?>
</TD>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>

Figura 23.4 Función con un número indeterminado de parámetros.

Desarrollo de Aplicaciones Web Dinámicas - UNED


FUNCIONES VARIABLES 23.9

23.3 FUNCIONES VARIABLES

Son una herramienta muy útil de PHP que permite implementar, entre otras cosas, retrollamadas
(callbacks) y tablas de llamadas. Su funcionamiento es el siguiente: si una variable tiene unos
paréntesis añadidos al final, PHP buscará una función con el mismo nombre que el contenido de
la variable e intentará ejecutarla.

El siguiente ejemplo muestra la utilización de estas funciones:


<HTML>
<HEAD>
<TITLE>Trabajando con Funciones</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Funciones de Usuario<I></I></H2>
<?php
$array_func=array("aEuros","aDolares","aYens");
$precios=array(1000,2300,7000);

function aEuros($dato){
return sprintf("%02.2f",$dato/166.386);
}
function aDolares($dato){
return sprintf("%02.2f",$dato/195.6);
}
function aYens($dato){
return sprintf("%02.2f",$dato/206.36);
}
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="YELLOW">
<TD>Pesetas</TD><TD>Euros</TD><TD>Dólares</TD><TD>Yens</TD>
</TR>
<?php
for($i=0;$i<sizeof($precios);$i++){
echo "<TR ALIGN='center'>";
echo "<TD>$precios[$i]</TD>";
for($j=0;$j<sizeof($array_func);$j++){
$funcion=$array_func[$j];
echo "<TD>".$funcion($precios[$i])."</TD>";
}
echo "</TR>";
}
?>
</TABLE>
</CENTER>
</BODY>
</HTML>

23.4 FUNCIONES RECURSIVAS

Se dice que una función es recursiva cuando en algún punto de su cuerpo se llama a sí misma.
Hay que tener cuidado al escribir una función recursiva, ya que puede ocurrir que se llame a sí
misma indefinidamente. Por tanto, es esencial asegurarse de implementar una forma adecuada de
terminar la recursión: es lo que se denomina como condición de parada.

Desarrollo de Aplicaciones Web Dinámicas - UNED


23.10 FUNCIONES

Figura 23.5 Funciones variables.

La recursión nos vale para solucionar algunos problemas complejos; un ejemplo típico de recur-
sión es hallar el factorial de un número.

El siguiente ejemplo nos muestra cómo implementarlo en PHP (de forma recursiva y no recur-
siva):
<HTML>
<HEAD>
<TITLE>Trabajando con Funciones</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Funciones de Usuario<I></I></H2>
<?php
function factorial($numero){
if ($numero==0) return 1;
return $numero * factorial($numero-1);
}

function factorial2($numero){
echo "$numero! = ";
for($factorial=1;$numero>1;$numero--){
$factorial*=$numero;
echo "$numero x ";
}
echo "1 = $factorial";
return $factorial;
}
?>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="2">
<TR ALIGN="center" BGCOLOR="YELLOW">
<TD>F. Recursiva</TD>
<TD>Función No Recursiva</TD>
</TR>
<TR ALIGN="center">
<TD><?php echo factorial(2); ?></TD>
<TD><?php factorial2(2); ?></TD>
</TR>

Desarrollo de Aplicaciones Web Dinámicas - UNED


FUNCIONES RECURSIVAS 23.11

<TR ALIGN="center">
<TD><?php echo factorial(3); ?></TD>
<TD><?php factorial2(3); ?></TD>
</TR>
<TR ALIGN="center">
<TD><?php echo factorial(4); ?></TD>
<TD><?php factorial2(4); ?></TD>
</TR>
<TR ALIGN="center">
<TD><?php echo factorial(5); ?></TD>
<TD><?php factorial2(5); ?></TD>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>

Figura 23.6 Funciones recursivas.

Desarrollo de Aplicaciones Web Dinámicas - UNED


23.12 FUNCIONES

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 24

Funciones de fecha y hora

24.1 INTRODUCCIÓN

Es muy importante en muchos problemas y aplicaciones llevar un control con la fecha y la hora
en un determinado momento, o bien, conocer la fecha para saber si tenemos que ejecutar un pro-
grama u otro...; existe un montón de circunstancias donde es necesario conocer estos datos. PHP
nos ofrece una gran variedad de funciones para abordar con mayor rapidez y de una forma más
sencilla los distintos problemas relacionados con el manejo de fechas y tiempos que nos puedan
ir saliendo a la hora de realizar nuestros programas.

En casi todos los sistemas informáticos hay una fecha de inicio común, a partir de la cual se
empieza a contar el tiempo. En el caso de los sistemas UNIX la fecha elegida como comienzo es
el día 1 de enero de 1970 a las 00:00:00 GMT, fecha que se conoce como el principio de la era
UNIX. El contador de tiempo se conoce como marca de tiempo (timestamp) y representa el
número de segundos transcurridos desde una fecha dada. En PHP todas las funciones de fecha/
hora que trabajan con marcas de tiempo hacen referencia a esta fecha.

24.2 FUNCIONES DE FECHA Y HORA

• time ( ) : Devuelve la marca de tiempo correspondiente al instante en que se ejecuta.


• checkdate (mes, dia, anio): Verifica si la fecha que se le pasa como parámetro es una fecha
correcta. Esta función es bastante útil en los formularios en los cuales hay que rellenar
campos de tipo fecha. Si pasamos una fecha correcta, es decir, todos los parámetros están
dentro de los rangos establecidos: anio es un número entero positivo, mes es un número
entre 1 y 12 y dia entre 1 y 31 (teniendo en cuenta el total de días que hay en cada mes,
incluyendo los años bisiestos); la función devuelve un valor verdadero en caso contrario,
la función devuelve un valor falso.
24.2 FUNCIONES DE FECHA Y HORA

• date (formato [ , timestamp] ) : Esta función nos permite darle un formato específico a una
cadena que contendrá una fecha y una hora. Acepta como parámetros una cadena de for-
mato y un parámetro timestamp; si éste se omite, se tomará el instante de ejecución de la
orden. Hay una serie de parámetros que tienen un significado propio y son reconocidos
dentro de la cadena de formato. Estos caracteres son:

Tabla 24.1 Formatos.

Los caracteres distintos a los que aparecen en la tabla, que estén dentro de la cadena for-
mato, se imprimirán tal cual aparecen. Para que los caracteres utilizados en la cadena for-
mato se puedan imprimir, es necesario enmascararlos, es decir, deben ir precedidos del
carácter "V".
• getdate ( [timestamp]) : Esta función devuelve un array asociativo que contiene informa-
ción sobre la fecha y hora asociadas a la marca de tiempo, timestamp, pasada como pará-
metro. En caso de no pasar ningún parámetro a la función, ésta obtendrá la marca de
tiempo del instante en que se ejecuta. La estructura del array asociativo devuelto es la
siguiente:

Desarrollo de Aplicaciones Web Dinámicas - UNED


FUNCIONES DE FECHA Y HORA 24.3

Tabla 24.2 Array asociativo de la función getdate ( ).

• gettimeofday ( ) : Esta función obtiene la hora actual en un array asociativo, cuya estruc-
tura contiene los siguientes campos:

Tabla 24.3 Array asociativo de la función gettimeofday ( ).

• gmdate ( format [, timestamp] ) : Esta función es muy parecida a la función date ( ) ante-
riormente vista, con una salvedad: la hora devuelta por esta función tiene formato GMT
(Greenwich Mean Time).
• gmmktime(hora, min, seg, mes, dia, anio [,is_dst]): Es muy parecida a la función mktime(),
a excepción de que los parámetros que se pasan en la llamada a la función representan la
fecha en formato GMT.
• gmstrftime (format, timestamp) : Da formato a una fecha/hora GMT según las convencio-
nes locales. Al igual que en las funciones anteriores, la fecha devuelta es la de GMT; por lo
demás, es muy parecida a la función strftime ( ).
• microtime (void) : Devuelve una cadena compuesta de dos elementos "msec sec". La
segunda parte, sec, representa los segundos transcurridos desde la fecha inicial de referen-
cia, es decir, el 1 de enero de 1970 a las 00:00:00, mientras que la primera parte, msec,
representa los microsegundos restantes. Ambas porciones se devuelven en unidades de
segundo.
• mktime (hora, min, seg, mes, dia, anio [ , isdst]) : Esta función devuelve la marca de
tiempo (el número de segundos transcurridos desde el 1 de enero de 1970 a las 00:00:00),
correspondiente a la fecha y hora pasadas a la función como parámetros. Esta función es
especialmente útil para realizar cálculos matemáticos con las fechas o validaciones de
ellas.

Desarrollo de Aplicaciones Web Dinámicas - UNED


24.4 FUNCIONES DE FECHA Y HORA

Es muy importante tener en cuenta que esta función posee la característica avanzada de
calcular la marca de tiempo para parámetros que estén fuera de rango: aproxima los datos
introducidos a la fecha más cercana correcta, es decir, cuando ejecutamos la función sobre
una fecha incorrecta, por ejemplo, "32 de marzo de 2001", obtendremos el valor de times-
tamp correspondiente al "1 de abril de 2002".

También hay que tener en cuenta que la función admite que el parámetro anio sea codifi-
cado como un valor de dos dígitos. En este caso, la función realiza la siguiente equipara-
ción automática de fechas: los valores comprendidos entre 0 y 69 se ajustan a los años
2000 a 2069 y los valores entre 70 y 99, a los años 1970 a 1999.

Existe una última aclaración de esta función consistente en que el último día de cada mes
puede indicarse como el día "0" del mes anterior.
• strftime (format [ , timestamp] ) : Esta función nos permite dar un formato específico de
hora y fecha a la marca de tiempo que se le pasa como parámetro. En caso de no propor-
cionar este parámetro, se tomará por defecto la marca de tiempo correspondiente al ins-
tante en que se ejecuta la función. Los formatos posibles a tener en cuenta se especifican
en la siguiente tabla:

Tabla 24.4 Posibles formatos.

Desarrollo de Aplicaciones Web Dinámicas - UNED


EJEMPLO DE USO 24.5

• strtotime (cad_fecha [ , timestamp] ) : Esta función traduce una cadena que contiene un
texto en inglés que hace referencia a una fecha en su correspondiente marca de tiempo
relativa a la marca de tiempo dada en el parámetro opcional timestamp, o bien, a la marca
de tiempo actual, si este parámetro no se proporciona en la llamada a la función. Esta fun-
ción se comporta de acuerdo con la sintaxis de fechas de GNU; por tanto, se le pueden
pasar como argumento cadenas del tipo now, next Friday, +1 day, etc.

24.3 EJEMPLO DE USO

A través de un programa de ejemplo que mostrará un calendario con el mes deseado por el usua-
rio, vamos a ver la utilización habitual de las funciones de fecha y hora vistas en este capítulo.

El ejemplo consta de dos ficheros, uno primero de HTML que contiene un formulario en el que el
usuario podrá introducir el día, mes y año de una fecha en particular. El código de esta primera
página es el siguiente:
<HTML>
<HEAD>
<TITLE>Funciones de Fecha y Hora</TITLE>
<STYLE>
TABLE {font-family:Verdana;font:12px;}
INPUT {text-align:right;}
</STYLE>
</HEAD>
<BODY>
<CENTER>
<H2>Funciones de Fecha y Hora</H2><BR><HR>
<FORM METHOD="GET" ACTION="fechas1.php">
<TABLE CELLPADDING="0" CELLSPACING="0">
<TR BGCOLOR="YELLOW" ALIGN="CENTER"><TD>Dia</TD><TD>Mes</TD><TD>Año</TD></TR>
<TR>
<TD><INPUT TYPE="TEXT" NAME="dia" MAXLENGTH="2" SIZE="3"></TD>
<TD><INPUT TYPE="TEXT" NAME="mes" MAXLENGTH="2" SIZE="3"></TD>
<TD><INPUT TYPE="TEXT" NAME="anio" MAXLENGTH="4" SIZE="5"></TD>
</TR>
</TABLE><BR>
<INPUT TYPE="SUBMIT" VALUE="Obtener Calendario">
</FORM><HR>
<CODE>
<B>NOTA:</B>Cualquier dato no codificado
<BR>se tomará como el valor
<BR>correspondiente de la fecha actual
</CODE>
</CENTER>
</BODY>
</HTML>

El segundo fichero del ejemplo es el script, que se encarga de generar, a partir de la fecha dada en
el formulario, el calendario del mes que contiene dicha fecha (si el usuario no proporciona nin-
guna fecha, el programa asume la del día en curso).

El código completo del segundo script es el siguiente:

<HTML>
<HEAD>
<TITLE>Funciones de Fecha y Hora</TITLE>
<style>
body {font: 12px Verdana;}
table {font: 12px Verdana;color:orange;text-align:right;}
tr.cabecera {background-color:#808080;color:#F8F8F8;font-weight:bold;}
tr.semana {background-color:#FFFBAD;color:#808080;font-weight:bold;}
a {text-decoration:none;color:orange;}
a.marcado {background-color:green;}
a.festivo {color:#B00000;}
a.opc {color:gray;font-weight:bold;}
p.error {font:14px;color:red;font-weight:bold;}

Desarrollo de Aplicaciones Web Dinámicas - UNED


24.6 FUNCIONES DE FECHA Y HORA

</style>
</HEAD>

<?php
$meses_txt=array("","Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio", "Agosto","Septiem-
bre","Octubre","Noviembre","Diciembre");
$dias_txt=array("L","M","X","J","V","S","D");

// Función que transforma el dia de la semana para que el 0 sea el lunes y


// el 6 el domingo
function actualiza_dia_semana($dia){
return ($dia>0)?$dia-1:6;
}
// Función que informa si un día pertenece al fin de semana
function festivo($dia){
return ($dia>4)?true:false;
}

?>
<BODY>
<CENTER>
<H3>Funciones de Fecha y Hora</H3>
<?php
$hoy=getdate();
$dia=!empty($_GET['dia'])?$_GET['dia']:$hoy['mday'];
$mes=!empty($_GET['mes'])?$_GET['mes']:$hoy['mon'];
$anio=!empty($_GET['anio'])?$_GET['anio']:$hoy['year'];
if($anio<=99) $anio+=2000;
if(!checkdate($mes,$dia,$anio)||$anio<1971){
echo "<HR><P CLASS='error'>ERROR: La fecha introducida no es válida...</P>";
echo "<BR>< <A HREF='fechas1.html'>volver</A> ><HR>";
} else {
// obtenemos el día de la semana del primer día del mes
$primer_dia=actualiza_dia_semana(date("w",mktime(0,0,0,$mes,1,$anio)));
// obtenemos el último día del mes
$ultimo_dia=date("t",mktime(0,0,0,$mes,1,$anio));

// escritura de la tabla que representa el calendario de un MES


echo "<TABLE BORDER='0' CELLPADDING='2' CELLSPACING='0' WIDTH='50%'>\n";
// escribir la cabecera que incluye el mes y el año del calendario
echo "<TR CLASS='cabecera'>";
echo "<TD COLSPAN='7'>",$meses_txt[$mes]," $anio</TD></TR>\n";
// escribir la cabecera que indica los días de la semana
echo "<TR CLASS='semana'>";
for ($i=0; $i<7; $i++)
echo "<TD>$dias_txt[$i]</TD>";
echo "</TR>\n<TR>";
// escribir los días del mes
$contador_de_dias=1;
while ($contador_de_dias <= $ultimo_dia)
{
for ($i=0; $i<7; $i++)
if (($i < $primer_dia) || ($contador_de_dias > $ultimo_dia))
echo "<TD>&nbsp;</TD>";
else {
echo "<TD><A HREF='fechas1.php?dia=$contador_de_dias&mes=$mes&anio=$anio'";
if($contador_de_dias==$dia)
echo " class='marcado'";
if(festivo($i))
echo " class='festivo'";
echo ">$contador_de_dias</A></TD>";
$contador_de_dias++;
}
// la siguiente semana comienza por lunes (dia 0)
$primer_dia=0;
echo "</TR><TR>";
}
echo "</TR></TABLE><BR>";
$fecha=getdate(mktime(0,0,0,$mes,$dia,$anio));
echo "<P STYLE='color:red;'>Día juliano nº <B>",$fecha['yday']+1,"</B></P><BR>";
$url = "fechas1.php?dia=$dia&mes=$mes&anio=".($anio-1);
echo "<PRE>< <A CLASS='opc' HREF='$url'>año-</A> | ";
$url = "fechas1.php?dia=$dia";
if ($mes==1)
$url .= "&anio=".($anio-1)."&mes=12";
else
$url .= "&anio=$anio&mes=".($mes-1);
echo "<A CLASS='opc' HREF='$url'>mes-</A> | ";
echo "<A CLASS='opc' HREF='fechas1.php?'>hoy</A> | ";
$url = "fechas1.php?dia=$dia";
if ($mes==12)
$url .= "&anio=".($anio+1)."&mes=1";
else
$url .= "&anio=$anio&mes=".($mes+1);
echo "<A CLASS='opc' HREF='$url'>mes+</A> | ";

Desarrollo de Aplicaciones Web Dinámicas - UNED


EJEMPLO DE USO 24.7

$url = "fechas1.php?dia=$dia&mes=$mes&anio=".($anio+1);
echo "<A CLASS='opc' HREF='$url'>año+</A> >";
echo "<BR>< <A CLASS='opc' HREF='fechas1.html'>nueva fecha</A> ></PRE>";
}
?>
</CENTER>
</BODY>
</HTML>

Figura 24.1 Formulario de entrada.

Figura 24.2 Calendario.

Vamos a ver pormenorizadamente cada una de las acciones que realiza el código. Lo primero que
hacemos es recuperar la información enviada desde el cliente para procesarla. Del código del pri-
mer fichero HTML podemos observar que hemos elegido utilizar el método GET (se estudiarán
los formularios en capítulos posteriores):

Desarrollo de Aplicaciones Web Dinámicas - UNED


24.8 FUNCIONES DE FECHA Y HORA

<FORM METHOD="GET" ACTION="fechas1.php">


</FORM>
Como se ha comentado anteriormente, el usuario puede optar por no completar todos los datos
referentes a la fecha con la que quiere trabajar, en cuyo caso se asumirá que desea utilizar los
valores de la fecha actual del sistema.
$hoy=getdate();
$dia=!empty($_GET['dia'])?$_GET['dia']:$hoy['mday'];
$mes=!empty($_GET['mes'])?$_GET['mes']:$hoy['mon'];
$anio=!empty($_GET['anio'])?$_GET['anio']:$hoy['year'];
En la variable $hoy obtenemos, haciendo uso de la función getdate ( ) , un array que contiene la
información de la fecha actual del sistema. De este modo, si el usuario no proporciona cualquiera
de los datos solicitados (día, mes y año que se almacenan en las variables $dia, $mes y $anio,
respectivamente), los obtendremos de la fecha actual del sistema.

Antes de pasar a validar la fecha, se hace una última comprobación con el año mandado por el
usuario; si éste se compone de dos dígitos solamente, se le complementa hasta cuatro sumándole
2000.
if($anio<=99) $anio+=2000;
Una vez que la fecha ha sido recuperada y completada, se valida a través de la función checkdate.
Además, se comprueba que el año proporcionado no sea inferior a 1970. Hay que tener en cuenta
que, aunque la fecha esté correctamente formada, si el año es anterior a 1970 (año de comienzo
de la era UNIX), todas las funciones que generan una marca de tiempo de tipo UNIX fallarían:
if(!checkdate($mes,$dia,$anio)||$anio<1971){
echo "<HR><P CLASS='error'>ERROR: La fecha NO valida</P>";
echo "<BR>< <A HREF='fechas1.html'>volver</A> ><HR>";
} else {
//tratamiento de la fecha correcta

Si la comprobación ha validado la fecha, pasamos a generar el calendario del mes que contiene
dicha fecha. Lo primero que hacemos es recuperar algunos datos esenciales para poder generar
correctamente el calendario.
• Día de la semana del primer día del mes (almacenado en la variable $primer_dia): para
ello, utilizamos las funciones date ( ) y mktime ( ) . Con esta última obtenemos la marca de
tiempo del primer día del mes de la fecha dada. Este valor se pasa a su vez como argu-
mento a la función date ( ) indicándole en la llamada, a través de la opción de formato "w",
que lo que deseamos obtener es el día de la semana. El valor devuelto varía entre 0 para el
domingo y 6 para el sábado. Comno dicho valor no coincide con la estructura de semana
que deseamos utilizar (el lunes comno primer día de la semana), llamamos a la función
actualiza_dia_semana ( ) , que se encarga de actualizarlo con nuestras preferencias.

$primer_dia=actualiza_dia_semana(date("w",mktime(0,0,0,$mes,1,$anio)));

• Número de días del mes (almacenado en la variable $ultimo_dia): para ello, utilizamos
también la misma combinación de funciones date ( ) y mktime ( ) que anteriormente, sólo
que esta vez solicitarmos a través de la opción de formato "t" una información diferente:

Desarrollo de Aplicaciones Web Dinámicas - UNED


EJEMPLO DE USO 24.9

$ultimo_dia=date("t",mktime(0,0,0,$mes,1,$anio));

Una vez obtenidos estos valores, podemos generar el calendario del mes deseado. Para ello
vamos a utilizar una tabla en la que la primera fila corresponde a una columna que contiene el
nombre del mes y el año consignados en la fecha:
// escritura de la tabla que representa el calendario de un MES
echo "<TABLE BORDER='0' CELLPADDING='2' CELLSPACING='0' WIDTH='50%'>\n";
// escribir la cabecera que incluye el mes y el año del calendario
echo "<TR CLASS='cabecera'>";
echo "<TD COLSPAN='7'>",$meses_txt[$mes]," $anio</TD></TR>\n";

Cabe destacar que el array $meses_txt, del cual se obtiene el nombre del mes solicitado en caste-
llano, pues de las funciones proporcionadas por PHP sólo podemos obtener información textual
en inglés, tiene una primera posición vacía para hacer coincidir el número de mes proporcionado
por el usuario con su posición dentro del array.
meses_txt=array("","Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio",
"Agosto","Septiembre","Octubre","Noviembre","Diciembre");

Las siguientes filas están compuestas de siete columnas cada una: una por día. La primera de
estas filas contiene una etiqueta por cada uno de los días de la semana:
// escribir la cabecera que indica los días de la semana
echo "<TR CLASS='semana'>";
for ($i=0; $i<7; $i++)
echo "<TD>$dias_txt[$i]</TD>";
echo "</TR>\n<TR>";

A partir de aquí se completan las diferentes filas con cada una de las semanas que componen el
mes. Hay que tener en cuenta que en la primera y última de estas filas se pueden producir colum-
nas vacías, puesto que es habitual que un mes no comience en lunes, o bien, no acabe en
domingo. Por esto, el código que genera el calendario debe considerar si se produce esta circuns-
tancia.

Desarrollo de Aplicaciones Web Dinámicas - UNED


24.10 FUNCIONES DE FECHA Y HORA

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 25

Formularios, Cookies y Sesiones

25.1 INTRODUCCIÓN

En este capítulo vamos a ver cómo PHP procesa o gestiona la información que el cliente (el
navegador) envía, a través del uso de formularios, al servidor y cómo éste genera una respuesta
adecuada a la petición solicitada.

25.2 EL PROTOCOLO HTTP

Aunque sabemos que PHP puede funcionar desde la línea de comandos, su uso principal está
relacionado con los sitios Web; de hecho, PHP puede ser definido como un servicio complemen-
tario a los proporcionados por los servidores Web. Estos servidores fundamentan su funciona-
miento en el uso del protocolo HTTP, del Protocolo de Transferencia de Hipertextos. Por ello,
para entender el funcionamiento de las técnicas que se proponen en este capítulo, se hace necesa-
rio un conocimiento previo del protocolo HTTP.

Éste es un sencillo protocolo cliente-servidor que articula los intercambios de información entre
los clientes los servidores web a través de operaciones simples de tipo solicitud/respuesta. Bási-
camente controla el modo en el que los clientes web solicitan recursos de los servidores web y el
modo en que éstos les envían dichos recursos de vuelta. Todos los recursos proporcionados por
un servidor web (documentos HTML, gráficos, videos, ficheros de sonido...) están asociados a
un URL o Localizador Uniforme de Recursos.

25.2.1 ESTRUCTURA DE LOS MENSAJES HTTP


Las peticiones y respuestas se envían como mensajes de texto que se componen de dos partes,
una cabecera y un cuerpo (ambos elementos se separan en el mensaje mediante una línea en
blanco). Sólo existen dos tipos de mensajes, uno para realizar peticiones y otro para responderlas.
25.2 FORMULARIOS, COOKIES Y SESIONES

Las peticiones siempre cuentan con cabecera y, en algunas ocasiones, con cuerpo; sin embargo,
las respuestas en la mayoría de las ocasiones cuentan con ambos componentes. La estructura de
estos mensajes se puede resumir en la siguiente tabla:

Tabla 25.1 Mensajes HTTP.

Comandos HTTP
La primera línea de un mensaje de petición, el comando HTTP, tiene la siguiente estructura:
método_HTTP URL_recurso versión del_protocolo

Es decir, proporciona el comando HTTP utilizado (normalmente se denomina método), la URL


del recurso del servidor al que deseamos acceder y la versión del HTTP utilizada. La siguiente
tabla (Tabla 25.2) muestra los métodos HTTP disponibles:

Tabla 25.2 Métodos HTTP.

Desarrollo de Aplicaciones Web Dinámicas - UNED


EL PROTOCOLO HTTP 25.3

A pesar de contar con todos los métodos enumerados en la tabla anterior, los más utilizados son
get, post y head, además de ser los más estándares. Algunos de los métodos restantes están en
desuso o tienen una utilización experimental.

Cabeceras de petición y respuesta


Las cabeceras de petición proporcionan información sobre el cliente Web utilizado, normalmente
un navegador, los tipos de contenidos que es capaz de aceptar, la longitud de los contenidos, etc.
Por su parte, las cabeceras de respuesta proporcionan información referente al software del servi-
dor y a la naturaleza de la información incluida en el cuerpo de la respuesta. El formato general
de una cabecera es el siguiente:
variable de cabecera: valor

Existen cabeceras comunes a peticiones y resultados y cabeceras específicas. Las siguientes


tablas (Tabla 25.3) (Tabla 25.4) y (Tabla 25.5) muestra las cabeceras más habituales:

Tabla 25.3 Cabeceras comunes.

Resultados de la petición
Ante cada petición, el servidor HTTP genera un mensaje de respuesta en el que inserta una pri-
mera línea denominada línea de estado en la que se informa sobre el resultado de la operación. El
formato de esta primera línea del mensáje es la siguiente:

versión_del_protocolo_HTTP código_de_estado descripción

Es decir, la versión empleada del protocolo HTTP, un código numérico de tres cifras que indica
el estado de la solicitud y un texto que contiene una breve descripción del código cíe estado
devuelto.

Desarrollo de Aplicaciones Web Dinámicas - UNED


25.4 FORMULARIOS, COOKIES Y SESIONES

Tabla 25.4 Cabeceras de petición.

Tabla 25.5 Cabeceras de Respuesta.

Existen cinco categorías de mensajes de estado, codificadas en función del primer dígito del
código; éstas son:

Desarrollo de Aplicaciones Web Dinámicas - UNED


EL PROTOCOLO HTTP 25.5

Tabla 25.6 Categorias de los mensajes.

La siguiente tabla muestra algunos de los mensajes más habituales:

Tabla 25.7 Mensajes habituales.

25.2.2 FUNCIONES PHP RELACIONADAS


PHP proporciona las siguientes funciones para obtener la información contenida en las cabeceras
HTTP: apache_request_headers ( ) (denominada getallheaders ( ) en versiones anteriores a la
4.3.0) para los mensajes de petición y apache_response_headers ( ) para los mensajes de res-
puesta. Ambas funciones devuelven un array asociativo que contiene todas las cabeceras HTTP
de la petición/respuesta de la operación actual.

El siguiente ejemplo nos muestra cómo recuperar las cabeceras de petición:


<HTML>
<HEAD>
<TITLE>Cabeceras HTTP</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Cabeceras HTTP</H2>
<H2>- peticiones -</H2>
<?php

Desarrollo de Aplicaciones Web Dinámicas - UNED


25.6 FORMULARIOS, COOKIES Y SESIONES

//$cabecera=getallheaders();
$cabecera=apache_request_headers();
echo "<TABLE BORDER='1' WIDTH='80%'><TR BGCOLOR='yellow'>";
echo "<TD>Campo</TD><TD>Contenido</TD></TR>";
foreach($cabecera as $campo => $contenido)
echo "<TR><TD>$campo</TD><TD>$contenido</TD></TR>";
echo "</TABLE>";
?>
</CENTER>
</BODY>
</HTML>

Figura 25.1 Peticiones.

PHP también nos proporciona funciones para la gestión de las cabeceras; éstas son: header(),
para enviar cabeceras http, y headers_sent ( ) , para confirmar que las cabeceras han sido envia-
das correctamente. Su sintaxis es la siguiente:
header (cadena [, reemplazar[, http_reponse_code]])

headers_sent()
El primer parámetro opcional de la función header ( ), de carácter booleano, nos permite indicar
si la cabecera debe reemplazar a una cabecera similar previamente fijada o, por el contrario, debe
añadir una nueva cabecera del mismo tipo (el valor por defecto es true). El segundo parámetro
opcional, un valor entero, fuerza el código de respuesta que debe enviarse al procesar la solicitud.

El siguiente ejemplo nos permite indicar al navegador que el contenido de la información que se
le envía es de tipo XML:

Desarrollo de Aplicaciones Web Dinámicas - UNED


EL PROTOCOLO HTTP 25.7

<?php
header("Content-type: application/xml");
?>
<alumno>
<matricula>x0500</matricula>
<nombre>Jorge</nombre>
<apellidos>Tejedor Cerbel</apellidos>
<datos_personales>
<direccion tipo="calle">Hermosilla</direccion>
<num>9</num>
<piso>7</piso>
<puerta>A</puerta>
<provincia>Madrid</provincia>
<poblacion>Madrid</poblacion>
<codpostal>28005</codpostal>
</datos_personales>
<datos_academicos>
<asignatura>Sistemas Operativos</asignatura>
<estado>aprobada</estado>
<nota>9.0</nota>
</datos_academicos>
</alumno>

Figura 25.2 cabecerasHTTP2.php

Corno se puede observar, de los ejemplos anteriores la función header ( ) debe aparecer antes de
que se genere cualquier tipo de contenido en el documento, puesto que va a definir un compo-
nente de las cabeceras HTTP del mensaje.

Desarrollo de Aplicaciones Web Dinámicas - UNED


25.8 FORMULARIOS, COOKIES Y SESIONES

25.2.3 VARIABLES PHP RELACIONADAS


Las variables PHP directamente relacionadas con la información manejada por el protocolo
HTTP son $_SERVER, $_GET, $_POST y $_REQUEST. Estas tres últimas serán vistas en pro-
fundidad en el apartado dedicado a formularios.

La variable global $_SERVER es un array asociativo que contiene, entre otras, toda la informa-
ción de las cabeceras tanto de petición como de respuesta.

 Consultar los contenidos de esta variable en el libro de texto.

El siguiente ejemplo muestra la utilización de la variable $_SERVER para recuperar información


sobre las cabeceras HTTP:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Variable $_SERVER</title>
</head>

<body>
<h1 align="center">Variable $_SERVER </h1>
<?php
echo "<table border='1' width='80%' cellpadding='2'>";
foreach($_SERVER as $clave=>$valor){
echo "<TR>";
echo "<TD> $clave </TD>";
echo "<TD> $valor </TD>";
echo "</TR><BR>";
}
echo "</table>";
?>

</body>
</html>

Un uso habitual de las cabeceras HTTP en conjunción con los campos PHP_AUTH_USER y
PHP_AUTH_PW de la variable $_SERVER nos permite realizar una autentificación básica de
usuarios para el acceso a recursos restringidos. El siguiente ejemplo muestra su funcionamiento:
<?php
if (!isset($_SERVER[PHP_AUTH_USER])) {
header('WWW-Authenticate: Basic realm="WebPHP"');
header('HTTP/1.0 401 Unauthorized');
echo '<CENTER><H2>Acceso restringido...</H2>';
echo '<HR>Es necesario contar con autorización para acceder a este recurso.<BR>';
echo '<BR>Póngase en contacto con el ';
echo '<A HREF="mailto:'.$_SERVER[SERVER_ADMIN].'">admninistrador</A><BR><HR>';
echo '</CENTER>';
exit;
} elseif (($_SERVER[PHP_AUTH_USER]!='cursoPHP')||($_SERVER[PHP_AUTH_PW]!='acceso')) {
header('WWW-Authenticate: Basic realm="WebPHP"');
header('HTTP/1.0 401 Unauthorized');
echo '<CENTER><H2>Acceso restringido...</H2>';
echo '<HR>Es necesario contar con autorización para acceder a este recurso.<BR>';
echo '<BR>Póngase en contacto con el ';
echo '<A HREF="mailto:'.$_SERVER[SERVER_ADMIN].'">admninistrador</A><BR><HR>';
echo '</CENTER>';
exit;
} //else {
// Acceso concedido...
// echo '<CENTER><H2>Acceso concedido...</H2></CENTER>';

Desarrollo de Aplicaciones Web Dinámicas - UNED


FORMULARIOS EN HTML 25.9

// exit;
//}
?>

Figura 25.3 Caja de diálogo.

25.3 FORMULARIOS EN HTML

Esta primera sección pretende ser un resumen de los conceptos más importantes asociados a la
definición de formularios en HTML. Como ya sabemos (repasar tema XHTML), un formulario
HTML es una sección de un documento que contiene texto normal, etiquetas HTML y elementos
especiales llamados controles (casillas de verificación o checkboxes, radiobotones o radiobu-
ttons, menús desplegables, etc.) y rótulos (labels) asociados a estos controles.

Los usuarios normalmente completan un formulario modificando sus controles (introduciendo


texto, seleccionando objetos de un menú, etc.), antes de enviar el formulario a un agente para que
lo procese (por ejemplo, a un servidor Web, a un servidor de correo, etc.).

25.3.1 EL ELEMENTO FORM


Todos los controles presentes en un formulario, para que sean efectivos, deben aparecer incluidos
dentro de un elemento form de HTML. La etiqueta FORM actúa, por tanto, como contenedor de
controles. Pero, además, especifica entre otros:
• El programa que manejará los datos del formulario una vez haya sido completado y
enviado (atributo action). El programa receptor debe ser capaz de interpretar las parejas
nombre/valor para poder hacer uso de ellas.
• La forma en la que se enviarán los datos del usuario al servidor (atributo method).
• El tipo MIME usado para enviar los datos del formulario (atributo enctype). El valor por
defecto de este atributo es application/x-wwwform-urlencoded.
• Juegos de caracteres que acepta el servidor para poder manejar este formulario (atributo
accept-charset). Los agentes de usuario pueden avisar al usuario del valor de este atributo
y/o restringir al usuario la posibilidad de introducir caracteres no reconocidos.

Desarrollo de Aplicaciones Web Dinámicas - UNED


25.10 FORMULARIOS, COOKIES Y SESIONES

25.3.2 ENVÍO DE FORMULARIOS AL SERVIDOR


El atributo method del elemento form especifica el método HTTP usado para enviar los datos del
formulario al agente procesador. Este atributo puede tener dos valores:
• get: El conjunto de datos del formulario se agrega (con el carácter "?" como separador) al
URI especificado en el atributo action (el programa que tratará los datos) y este nuevo URI
se envía al agente procesador.
• post: Los datos del formulario se incluyen en el cuerpo del mensaje que se envía al agente
procesador.

El conjunto de datos del formulario que se envía al agente servidor es una secuencia de parejas
nombre_ de_ control /valor construida a partir de los elementos del formulario. Cada uno de los
controles tiene asociado un nombre que viene dado por su atributo name. De igual forma, cada
control tiene tanto un valor inicial, como un valor actual, que son ambos cadenas de caracteres.
En general (excepto en el caso del elemento textarea), el valor inicial de un control puede especi-
ficarse con el atributo value del elemento de control. El valor actual del control se iguala en un
primer momento al valor inicial y, a partir de ese momento, el valor actual del control puede ser
modificado a través de la interacción con el usuario y/o mediante scripts que se ejecuten en el
cliente. El valor inicial de un control no cambia. Así, cuando se reinicializa el formulario, el
valor actual de cada control se iguala a su valor inicial. Si el elemento de control no tiene un
valor inicial, se le asigna el valor nulo.

El método get debería usarse cuando el formulario es idempotente (es decir, cuando no tiene
efectos secundarios). Muchas búsquedas en bases de datos no tienen efectos secundarios visibles
y constituyen aplicaciones ideales del método get. Si el servicio asociado con el procesamiento
de un formulario causa efectos secundarios (por ejemplo, si el formulario modifica una base de
datos o la suscripción a un servicio), debería usarse el método post.

25.4 FORMULARIOS EN PHP

Cuando se envía un formulario para su procesamiento, se produce el emparejamiento de sus con-


troles, a través de sus respectivos nombres, con los valores actuales que tienen. Estas parejas
variable-valor configuran el conjunto de datos del formulario que se envían al agente servidor.
Como hemos visto, dependiendo del método HTTP usado (get o post), unas veces la información
se enviará formando parte de la cadena de consulta (query string) que configura la solicitud y,
otras veces, formando parte del cuerpo del mensaje.

PHP, a través de un conjunto de variables globales, es capaz de recuperar el conjunto de datos del
formulario que han sido enviados desde el cliente (esto es, el navegador) para, después, poder
trabajar con ellos. Las tres variables principales para realizar esta operación son:

Desarrollo de Aplicaciones Web Dinámicas - UNED


FORMULARIOS EN PHP 25.11

Tabla 25.8 Variables de formulario en PHP.

25.4.1 FORMULARIOS EN PHP 4.2.X Y VERSIONES SUPERIORES


El siguiente ejemplo muestra el paso de información y su posterior procesamiento, haciendo uso
del método get. Para ello, hemos escrito un documento HTML que contiene un formulario que
hace uso de dicho método:
<HTML>
<HEAD>
<TITLE>Formularios</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Formularios: método GET</H2><HR>
<FORM METHOD="GET" ACTION="formularios1.php">
<TABLE>
<TR>
<TD ALIGN="LEFT">Modelo:</TD>
<TD ALIGN="RIGHT" COLSPAN="3"><INPUT TYPE="TEXT" NAME="modelo" SIZE=25"></TD>
</TR>
<TR>
<TD ALIGN="LEFT">Marca:</TD>
<TD ALIGN="RIGHT" COLSPAN="3"><INPUT TYPE="TEXT" NAME="marca" SIZE=25"></TD>
</TR>
<TR ALIGN="LEFT">
<TD>Motor:</TD>
<TD><INPUT TYPE="TEXT" NAME="motor" SIZE="5"></TD>
<TD>Cilindrada:</TD>
<TD><INPUT TYPE="TEXT" NAME="cc" SIZE="5"></TD>
</TR>
<TR>
<TD ALIGN="LEFT">Combustible:</TD>
<TD ALIGN="RIGHT" COLSPAN="3">
<INPUT TYPE="RADIO" NAME="combustible" VALUE="gasolina" CHECKED>Gasolina
<INPUT TYPE="RADIO" NAME="combustible" VALUE="diesel">Diesel
</TD>
</TR>
</TABLE><HR><BR>
<INPUT TYPE="SUBMIT"> <INPUT TYPE="RESET">
</FORM>
</CENTER>
</BODY>
</HTML>

El script encargado de procesar dicha información (valor del atributo action del formulario) es el
siguiente:
<HTML>
<HEAD>
<TITLE>Formularios</TITLE>
</HEAD>
<BODY>
<CENTER>
<?php
$metodo=$_SERVER['REQUEST_METHOD'];

Desarrollo de Aplicaciones Web Dinámicas - UNED


25.12 FORMULARIOS, COOKIES Y SESIONES

$cad_consulta=$_SERVER['QUERY_STRING'];

echo "<H2>Formularios: método $metodo</H2>";


echo "<I>Query String</I>: $cad_consulta <HR>";
foreach ($_GET as $clave => $valor)
echo "<I>$clave</I> = $valor <BR>";
echo "<HR>$_GET[marca] $_GET[modelo] $_GET[motor] ($_GET[cc] cc -$_GET[combustible]-)<BR><HR>";
echo "<PRE><A HREF='javascript:history.go(-1)'>volver</A></PRE>";
?>
</CENTER>
</BODY>
</HTML>

Figura 25.4 Formularios.

 Ejercicio. Realizar el ejemplo anterior utilizando el método POST. ¿Qué diferencias se pro-
ducen?.

25.4.2 FORMULARIOS AVANZADOS


Además de la traslación directa de las variables de un formulario en variables de PHP, se puede
hacer un uso avanzado de estas variables: en el formulario HTML podemos agrupar variables
relacionadas en forma de array. Posteriormente, desde PHP podemos acceder a estos mismos

Desarrollo de Aplicaciones Web Dinámicas - UNED


FORMULARIOS EN PHP 25.13

arrays y, como tales, recorrerlos para obtener sus claves y respectivos valores. Esta característica
también se puede usar para recuperar los valores de un campo select de tipo múltiple.

El siguiente ejemplo nos muestra dicha utilización:


<HTML>
<HEAD>
<TITLE>Formularios</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Formularios: variables complejas</H2><HR>
<FORM METHOD="POST" ACTION="formularios2.php">
<TABLE>
<TR>
<TD ALIGN="LEFT">Modelo:</TD>
<TD ALIGN="RIGHT" COLSPAN="3"><INPUT TYPE="TEXT" NAME="coche[modelo]" SIZE=25"></TD>
</TR>
<TR>
<TD ALIGN="LEFT">Marca:</TD>
<TD ALIGN="RIGHT" COLSPAN="3"><INPUT TYPE="TEXT" NAME="coche[marca]" SIZE=25"></TD>
</TR>
<TR ALIGN="LEFT">
<TD>Motor:</TD>
<TD><INPUT TYPE="TEXT" NAME="coche[motor]" SIZE="5"></TD>
<TD>Cilindrada:</TD>
<TD><INPUT TYPE="TEXT" NAME="coche[cc]" SIZE="5"></TD>
</TR>
<TR>
<TD ALIGN="LEFT">Combustible:</TD>
<TD ALIGN="RIGHT" COLSPAN="3">
<INPUT TYPE="RADIO" NAME="coche[combustible]" VALUE="gasolina" CHECKED>Gasolina
<INPUT TYPE="RADIO" NAME="coche[combustible]" VALUE="diesel">Diesel
</TD>
</TR>
<TR>
<TD ALIGN="LEFT">Opciones:</TD>
<TD ALIGN="RIGHT" COLSPAN="3">
<SELECT MULTIPLE NAME="opciones[]">
<OPTION VALUE="AA">Aire Acondicionado</OPTION>
<OPTION VALUE="CD">Radio CD</OPTION>
<OPTION VALUE="CA">Climatizador</OPTION>
<OPTION VALUE="SN">Sistema de Navegación</OPTION>
</SELECT>
</TD>
</TR>
</TABLE><HR><BR>
<INPUT TYPE="SUBMIT"> <INPUT TYPE="RESET">
</FORM>
</CENTER>
</BODY>
</HTML>

Como podemos ver en el formulario, se definen dos variables de tipo array (una de ellas de tipo
asociativo).

Para recuperar la información suministrada por el cliente, se utiliza el siguiente código:


<HTML>
<HEAD>
<TITLE>Formularios</TITLE>
</HEAD>
<BODY>
<CENTER>
<?php
echo "<H2>Formularios</H2>";
echo "<HR>";
foreach ($_POST as $clave => $valor)
echo "<I>$clave</I> = $valor <BR>";
echo "<HR>";
foreach ($_POST['coche'] as $clave => $valor)
echo "<I>$clave</I> = $valor <BR>";
echo "<HR><I>Opciones = </I>";
foreach ($_POST['opciones'] as $clave => $valor)
echo "$valor ";
echo "<HR>{$_POST['coche']['marca']} {$_POST['coche']['modelo']} {$_POST['coche']['motor']}
({$_POST['coche']['cc']}cc -{$_POST['coche']['combustible']}-)<BR><HR>";
echo "<PRE><A HREF='javascript:history.go(-1)'>volver</A></PRE>";
?>

Desarrollo de Aplicaciones Web Dinámicas - UNED


25.14 FORMULARIOS, COOKIES Y SESIONES

</CENTER>
</BODY>
</HTML>

 Ejercicio. Realizar el ejemplo anterior utilizando un único fichero. Consultar libro de texto.

25.5 COOKIES EN PHP

Como comentarnos anteriormente, el protocolo HTTP está definido de forma que nunca se alma-
cena información acerca de las conexiones y desconexiones que haya habido entre cliente y ser-
vidor, es un protocolo stateless. Por tanto, cuando necesitarnos que algún dato o información de
relevancia (preferencias del usuario, número de accesos, recursos visitados...) esté disponible
entre diferentes conexiones, es necesario implementar un mecanismo que nos permita almacenar
y acceder a dicha información. Para llevar a cabo dicha facilidad, tenernos varias soluciones
posibles:
• Hacer uso de elementos de formularios ocultos. Efectivamente, si enviamos esta informa-
ción en campos ocultos de un formulario (elementos input de tipo hidden), podremos
manejarlos entre las diferentes páginas de nuestra aplicación y arrastrar esa información de
una página a otra. El problema principal que presenta esta posible solución es que los datos
tendrán vigencia, existirán, mientras el cliente esté navegando y, además, lo haga de una
manera ordenada, esto es, siga la secuencia de páginas prevista en la aplicación.
• Almacenar la información en el servidor. Esta solución nos permite que, si el usuario deja
de navegar, cuando retome el uso de nuestra aplicación Web, sus datos los tendremos dis-
ponibles. El único problema de esta solución está en el hecho de que un número muy
grande de usuarios supone, por parte del servidor, la reserva de gran cantidad de recursos
de almacenamiento, por tanto, es una solución válida cuando el número de posibles usua-
rios de nuestra aplicación Web no vaya a ser alto.
• Almacenar la información en los equipos clientes. Esta solución es la más utilizada en las
aplicaciones Web puesto que el almacenamiento se realiza en los equipos clientes y el ser-
vidor no debe preocuparse por la reserva de recursos. Además, se potencia la distribución
natural de la información. El problema principal que presenta es el de la integridad de la
información, puesto que el servidor no puede asegurar que los datos almacenados (supues-
tamente) en el equipo cliente están disponibles en el instante en que son requeridos. A
estas estructuras de información que se almacenan en el equipo cliente se las denomina
cookies.

25.5.1 ESTRUCTURA DE LAS COOKIES


Básicamente, las cookies son ficheros de texto ASCII que almacenan información siguiendo una
estructura básica de pares identificador = valor. Su tamaño es relativamente pequeño, no supe-
rando en ningún caso los 4 Kb. El modo en que se almacenan, los directorios en que se almace-

Desarrollo de Aplicaciones Web Dinámicas - UNED


COOKIES EN PHP 25.15

nan y resto de características propias de una operación de lectura/escritura sobre disco dependen
en gran manera del sistema operativo y del navegador que tenga instalado el equipo cliente. De
igual forma, la posibilidad de hacer uso de cookies depende de que el software utilizado para
acceder a la aplicación Web (normalmente un navegador) cuente con esta característica y que,
además, esté habilitada.

La siguiente tabla (Tabla 25.9) nos muestra la estructura básica de una cookie:

Tabla 25.9 Estructura de una cookie.

Es muy importante tener en cuenta que todo el tratamiento de las cookies se realiza en la cabe-
cera del mensaje HTTP y, por tanto, deben ser manejadas antes de que se envíe cualquier otra
información al navegador (la parte del cuerpo del mensaje HTTP); en caso contrario, obtendre-
mos un error.

Por otra parte, el valor de una cookie tiene preferencia sobre los valores pasados mediante un for-
mulario, es decir, cuando un formulario y una cookie hacen uso de los mismos identificadores,
los valores de las cookies sobrescribirán los valores de las entradas del formulario.

25.5.2 UTILIZACIÓN DE COOKIES EN PHP


PHP propone una sola función para el manejo básico de cookies (creación y borrado) cuya sin-
taxis es la siguiente:
int setcookie (string nombre [, string valor]
[, int caducidad] [, string ruta]
[, string dominio] [, int seguro]);

Para acceder al contenido, se hará uso de una variable global, tal y como veremos más adelante.

Creación de cookies
Corno se puede observar en la definición de la función setcookie ( ), cada uno de los parámetros
coincide con los elementos que componen la estructura básica de una cookie. También vemos
que el único argumento obligatorio en la llamada a la función es el nombre que se le asigna a la

Desarrollo de Aplicaciones Web Dinámicas - UNED


25.16 FORMULARIOS, COOKIES Y SESIONES

cookie. Sin embargo, en el caso de la creación es necesario, al menos, que se le asigne un valor
inicial.

Cuando no queramos hacer uso de los parámetros de tipo string, se deben reemplazar con la
cadena vacía (““) y los de tipo int, con un valor 0. Si no usamos el parámetro caducidad, se
tomará por defecto el tiempo que dure la sesión de trabajo activa en el navegador. De igual modo,
si no se utilizan los parámetros ruta y dominio, se tomarán por defecto el camino y el dominio del
servidor en los cuales se ha creado la cookie.

Eliminación de cookies
Como ya sabernos, para borrar una cookie, usamos la misma función que para crearla:
setcookie ( )
sólo que en este caso la llamada a la función sólo contendrá como parámetro el nombre de la coo-
kie que deseamos eliminar del sistema.
setcookie(“nombre_de_la_cookie”);

Consulta de contenidos
Para poder acceder a los contenidos de las cookies, PHP proporciona una variable global consis-
tente en un array asociativo formado por todas las variables pasadas a través de las cookies. Es la
variable $_COOKIE:
$_COOKIE["nombre_ de la cookie"]

Una vez que conocemos los tres pasos esenciales para trabajar con cookies, vamos a ver un ejem-
plo que hace uso de esta técnica para implementar un contador de accesos. Nuestro primer script
contendrá la creación y actualización de la cookie:
<?php
$accesos=1;
if(isset($_COOKIE["num_accesos"])){
$accesos=$_COOKIE["num_accesos"]+1;
}
setcookie("num_accesos",$accesos,time()+3600);
?>
<HTML>
<HEAD>
<TITLE>Trabajando con Cookies</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Trabajando con cookies</H2><br>
<H3>Contador de accesos</H3>
<?php
if($accesos>1)
echo "Has accedido a esta página <B>$accesos</B> veces";
else
echo "Es la primera vez que accedes a esta página";
?>
<BR><BR><BR>
<PRE><A HREF="cookies1.php">Actualizar</A> | <A HREF="cookies2.php">Eliminar</A></PRE>
</CENTER>
</BODY>
</HTML>

Desarrollo de Aplicaciones Web Dinámicas - UNED


SESIONES EN PHP 25.17

Corno podernos observar, la cookie creada, num_accesos, tiene un tiempo de expiración de una
hora (3.600 segundos). El segundo script contiene la eliminación de la cookie creada para alber-
gar el contador:
<?php
setcookie("num_accesos");
?>
<HTML>
<HEAD>
<TITLE>Trabajando con Cookies</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Trabajando con cookies</H2><br>
<H3>Contador de accesos borrado</H3>
<BR><BR><BR>
<PRE><A HREF="cookies1.php">volver</A></PRE>
</CENTER>
</BODY>
</HTML>

 Ejercicio. Realizar el ejercicio de la pag. 145 del libro de texto (cookies con múltiples valo-
res).

25.6 SESIONES EN PHP

A lo largo de este tema hemos visto que teníamos tres formas básicas de hacer que la información
generada en un script estuviera disponible en scripts diferentes al de creación: utilizando formu-
larios, pasando las variables y sus valores a través de la URL, o bien, definiendo cookies. Estos
métodos no son todo lo útiles que desearíamos cuando los scripts que deben compartir la infor-
mación no se ejecutan secuencialmente, o bien, están distantes los unos de los otros dentro del
flujo de ejecución normal de nuestra aplicación. Aunque, a priori, el uso de cookies parece ade-
cuado para solventar este problema (pueden ser consultadas en cualquier momento hasta su eli-
minación del sistema de cliente), hay que tener en cuenta que no todos los navegadores tienen
disponible esta funcionalidad y que, incluso teniéndola, ésta puede aparecer deshabilitada por
parte del usuario.

Para solventar esta situación, PHP proporciona las variables de sesión, que son variables que
estarán disponibles en las diferentes peticiones a lo largo del intervalo de tiempo que el usuario
necesite para hacer uso de nuestra aplicación. Son algo así como variables globales a la aplica-
ción entera pues van a estar accesibles para todos los programas de la aplicación. El ciclo de vida
de una sesión comienza en el instante en que el usuario se conecta a nuestra aplicación y acaba en
el instante en que sale de la aplicación, cierra el navegador, o bien, permanece un lapso de tiempo
(fijado por el sistema) sin interaccionar con la aplicación.

Todas las variables de sesión se almacenan en el servidor, por tanto, en un momento dado, podre-
mos tener muchas variables con el mismo nombre pero con contenidos diferentes. Para evitar
confusiones, cada variable de sesión está vinculada a una única sesión/usuario, que se identifica
con un identificador de sesión único. El modo de mantener de forma persistente este identifica-
tivo a lo largo de la sesión es utilizar cookies, o bien, propagarlo a través de la URL.

Desarrollo de Aplicaciones Web Dinámicas - UNED


25.18 FORMULARIOS, COOKIES Y SESIONES

25.6.1 CREACIÓN DE SESIONES


La configuración por defecto de PHP tiene deshabilitadas las sesiones; esto quiere decir que,
cuando queramos hacer uso de ellas, deberemos indicárselo de forma explícita. Cambiando la
configuración (modificando el valor de la directiva session.auto_start a 1 en el fichero de confi-
guración php.ini), podernos activar por defecto las sesiones en PHP de modo que en el primer
acceso de cada usuario a nuestro sistema se le cree una sesión.

El modo principal de activar el uso de sesiones cuando lo deseemos es hacer uso de la función
sessionstart ( ) cuya sintaxis es la siguiente:

bool session_start()

Esta función crea una nueva sesión y genera el nuevo identificador, o retorna la sesión en caso de
que existiera, utilizando el identificador de sesión que se había propagado haciendo uso de la
URL o de cookies.

 Si se está haciendo uso de sesiones basadas en cookies, la función session_start( ) debe ser
llamada al principio de nuestro script (antes de abrir cualquier etiqueta o de imprimir cual-
quier contenido). En caso contrario, se genera un error.

Como hemos dicho anteriormente, en el instante en que se crea una sesión, se genera un identifi-
cador único para ella. Haciendo uso de la función session_id ( ) , podemos recuperar o modificar
dicho valor. Su sintaxis es la siguiente:

string session_id ([string id])

Si llamarnos a la función sin hacer uso del parámetro id, obtendremos una cadena con el identifi-
cador de la sesión actual (debe ser llamada una vez que exista la sesión). Si, por el contrario,
hacemos uso del citado parámetro, estaremos reemplazando el identificativo de la sesión actual
por el valor dado al parámetro (debe ser llamada antes de crear la sesión).

También es posible identificar a las sesiones asignándoles un nombre específico. Para ello, utili-
zaremos la función session_name ( ) que tiene la siguiente sintaxis:

string session_name ([string nombre])

Si no hacemos uso del parámetro nombre, obtendremos el nombre de la sesión actual; si, por el
contrario, proporcionamos dicho parámero, la sesión actual pasará a tener por nombre el argu-
mento pasado.

25.6.2 ACCESO A LAS VARIABLES DE SESIÓN


El modo de acceso a las variables de sesión es a través del array asociativo $_SESSION disponi-
ble como variable global ($HTTPSESSIONS_VARS en las versiones anteriores a la 4.2.0). El

Desarrollo de Aplicaciones Web Dinámicas - UNED


SESIONES EN PHP 25.19

siguiente ejemplo muestra la creación de una sesión y de una variable de sesión al igual que su
acceso, actualización y eliminación para poder obtener un contador de accesos:
<?php
session_start();
if (isset($_SESSION['contador'])) {
$_SESSION['contador']++;
}
else {
$_SESSION['contador'] = 0;
}
$nombre_anterior = session_name('SESION_CONTADOR');
?>
<HTML>
<HEAD>
<TITLE>Trabajando con Sesiones</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Trabajando con Sesiones</H2>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="4">
<TR ALIGN="center" BGCOLOR="yellow">
<TD COLSPAN="2"><B>Información de la Sesión</B></TD>
</TR>
<TR>
<TD BGCOLOR="yellow">ID</TD>
<TD><?php echo session_id() ?></TD>
</TR>
<TR>
<TD BGCOLOR="yellow">Número de accesos</TD>
<TD><?php echo $_SESSION['contador'] ?></TD>
</TR>
<TR>
<TD BGCOLOR="yellow">Nombre actual</TD>
<TD><?php echo session_name() ?></TD>
</TR>
<TR>
<TD BGCOLOR="yellow">Nombre anterior</TD>
<TD><?php echo $nombre_anterior ?></TD>
</TR>
</TABLE>
<BR><PRE>
<A HREF="sesiones1.php">Actualizar</A> | <A HREF="sesiones2.php">Resetear contador</A>
</PRE>
</CENTER>
</BODY>
</HTML>

Como podemos observar, para crear una nueva variable de sesión, sólo hay que definirla dentro
del array $_SESSION. En el código se pregunta si la variable de sesión tiene valor (si está defi-
nida) y, de este modo, saber si hay que crearla o actualizar su valor. El ejemplo, además, obtiene
el identificador de sesión y modifica el nombre asignado por defecto. La siguiente imagen mues-
tra el resultado después de haber realizado 10 accesos a la página que contiene el contador:

Figura 25.5 Trabajando con sesiones.

Desarrollo de Aplicaciones Web Dinámicas - UNED


25.20 FORMULARIOS, COOKIES Y SESIONES

El segundo script de este ejemplo se encarga de borrar la variable de sesión creada en el script
anterior.
<?php
session_start();
unset($_SESSION['contador']);
?>
<HTML>
<HEAD>
<TITLE>Trabajando con Sesiones</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Trabajando con Sesiones</H2><BR><BR>
<P>Variable <B>'contador'</B> actualizada<BR>
de la sesión <B><?php echo session_id() ?></B><BR>
con nombre <B><?php echo session_name() ?></B>
<BR><BR><A HREF="sesiones1.php">volver</A></P>
</CENTER>
</BODY>
</HTML>

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 26

Ficheros y directorios

26.1 INTRODUCCIÓN

Como es bien sabido, la información que se necesita guardar de manera permanente está almace-
nada en ficheros. Por esto, es bastante habitual que las aplicaciones, sean del tipo y del entorno
que sean, necesiten realizar operaciones con ficheros del sistema local. Por ejemplo, poner un
simple contador de visitas en una página nos obliga a guardar en un fichero el total de visitas
recibidas para que, cuando llegue la siguiente, abramos el fichero, leamos el número que con-
tiene y lo modifiquemos convenientemente.

Para poder implementar este tipo de tareas, PHP dispone de funciones predefinidas para la utili-
zación y manejo de ficheros. Gracias a estas funciones, podremos acceder a un fichero que poda-
mos haber creado previamente, podremos consultar los datos que contenga, añadir otros,
modificarlos, o bien, borrarlos.

26.2 OPERACIONES CON FICHEROS (NIVEL INTERNO)

PHP nos provee de funciones que nos permiten realizar operaciones típicas de ficheros: abrir,
cerrar, leer, escribir, recorrer...

26.2.1 ABRIR UN FICHERO


fopen (nombre, modoApertura [, ruta busqueda])

Para poder abrir un fichero, disponemos de la función fopen ( ) . PHP nos permite abrir ficheros
locales o remotos. Que el fichero esté en el disco duro de nuestra máquina o en otra dependerá de
cómo esté formado el parámetro nombre: si éste comienza por http: // o ftp: //, indicará que es un
fichero remoto y que se accederá a él vía el protocolo correspondiente. En caso contrario, se tra-
26.2 FICHEROS Y DIRECTORIOS

tará de un fichero que PHP buscará en el sistema de ficheros del servidor, razón por la cual habrá
que tener atención a la hora de indicar el camino o ruta de acceso al archivo deseado.

Si PHP no pudiera encontrar el fichero en la ruta especificada en nombre y el parámetro


ruta_busqueda estuviera a 1, entonces PHP lo buscaría además en los directorios que estuvieran
definidos en la directiva include_path del fichero de configuración php. ini.

El segundo parámetro (modoApertura) puede tener los siguientes valores expresados en la tabla
siguiente:

La función fopen ( ) devuelve un descriptor de fichero, esto es, el canal por el que vamos a poder
acceder a él; por tanto, los descriptores serán imprescindibles a la hora de realizar operaciones
sobre ficheros tales como lectura, escritura, cerrado, etc. De aquí deducimos que usaremos, tan-
tas variables que almacenen descriptores, como ficheros abiertos simultáneamente vayamos a
necesitar.

En el caso de que el fichero no se pudiera abrir por la causa que sea, fopen ( ) devolverá FALSE.
Característica por la cual la forma más habitual de abrir un fichero es:
<?php
if (! $descriptor = fopen ("un_fichero_cualquiera", "r")) {
echo "*** ERROR: el fichero no se puede abrir. <br>";
} else {
echo "podemos acceder al fichero a través de '\$descriptor'. <br>"); }

26.2.2 CERRAR UN FICHERO


fclose (descriptor_ fichero)

Con la función fclose ( ) cerramos el fichero que está referenciado por el descriptor que pasamos
como argumento. Por supuesto, este descriptor es el devuelto por la función fopen ( ) vista ante-

Desarrollo de Aplicaciones Web Dinámicas - UNED


OPERACIONES CON FICHEROS (NIVEL INTERNO) 26.3

riormente. fclose ( ) devuelve true, si el fichero se cierra correctamente, y false, si no se ha


podido cerrar.

Dado que un fichero abierto consume recursos del sistema, es conveniente cerrar todo aquél que
se prevea que no se va a usar más. De todas formas, en el caso de que no se cierre expresamente
un fichero, PHP lo hará automáticamente al terminar de ejecutar el script.

26.2.3 LECTURA DESDE UN FICHERO


PHP tiene distintas y variadas formas de leer el contenido de un fichero. Lógicamente, usaremos
siempre la más conveniente para nuestras necesidades:
• fgetc (descriptor) : Devuelve un carácter del fichero referenciado por descriptor. Si se ha
llegado al final del fichero, devuelve FALSE. De aquí, que una forma común de leer un
fichero entero sea mediante el bucle:
while {$caracter = fgetc($df)) }

• fgets (descriptor, [total_cars_a_leer ] ) : Devuelve una cadena de total _cars_a_leer-1


caracteres o de menor longitud si se ha encontrado un cambio de línea (que se incluiría en
la cadena a devolver) o se ha llegado al final del fichero.
• fgetss (descriptor, tamaño, etiq_permitidas): Es idéntica a fgets ( ) , excepto en que purga
del texto leído las etiquetas HTML que haya encontrado. En el parámetro etiq_permitidas
indicamos las etiquetas que sí queremos obtener.
• fread (descriptor, total_cars_a_leer): Es idéntica a fgets ( ) , excepto en que no deja de leer
cuando encuentra un cambio de línea y en que devuelve exactamente total_cars_a_leer (si
los hubiera).
• fscanf (descriptor, formato [, var1...]): Según lee la entrada, la procesa de acuerdo con el
formato especificado en el segundo parámetro formato para asignarla convenientemente
en las variables que se indiquen. Sigue el mismo formato que printf ( ).
• feof (identificador): No es una función de lectura propiamente dicha, pero es muy útil
cuando leemos ficheros: indica si se ha llegado al final (no quedan más datos por leer) o
no.
• file (nombre_ fichero [, ruta_busqueda]): Lee todo el contenido de un fichero y lo
devuelve en forma de array: una línea en cada posición. Corno puede apreciarse, esta fun-
ción necesita el nombre del fichero y no un descriptor.
• readfile (nomb_fichero [, ruta busqueda] ): Lee el contenido de un fichero y lo muestra
por la salida estándar. Devuelve el total de caracteres leídos.
• fpassthru (descriptor) : Igual a readfile ( ) , excepto en que el parámetro que necesita es un
descriptor de fichero, y en que lee y muestra a partir de donde se encuentre la posición del
puntero de lectura.

Desarrollo de Aplicaciones Web Dinámicas - UNED


26.4 FICHEROS Y DIRECTORIOS

26.2.4 RECORRER UN FICHERO


En muchas ocasiones necesitamos colocarnos en una determinada parte del fichero para poder
leer o escribir cadenas de texto a partir de esa posición. Para poder movernos a determinados
puntos de fichero, PHP nos ofrece las siguientes funciones:
• rewind (descriptor): Sitúa el puntero de lectura/escritura al principio del fichero.
• fseek (descriptor, desplaz [ , desde _donde] ) : Desplaza la posición del puntero de lectura/
escritura desplaz posiciones. El tercer parámetro puede tomar los valores SEEK_SET,
SEEKCUR y SEEK_END, lo que significará que los desplazamientos son relativos al
principio del fichero, la posición actual del puntero o al final del fichero (entonces desplaz
será negativo), respectivamente.
• ftell (descriptor) : Devuelve la posición del puntero.

26.2.5 ESCRITURA DE UN FICHERO


Para escribir, disponemos de dos funciones: fwrite ( ) y fputs ( ) . Estas funciones se pueden usar
de manera indistinta pues en la práctica son la misma, o sea, puede pensarse que una es un alias
de la otra.
fwrite(descript, cadena [, total_cars]);

fputs(descript, cadena [, total_cars]);


Ambas funciones escriben la cadena (completa) pasada como parámetro. Si se hace uso del tercer
parámetro, sólo se escribirán los total_cars indicados. Devuelve el total de caracteres escritos o
FALSE en caso de producirse algún error.

En general, dado que son muy lentas todas las operaciones en las que está implicado un acceso al
sistema de ficheros (al disco duro, para ser más exactos), se recurre a la escritura mediante
buffers para hacerlas más eficaces. Esto quiere decir que la escritura no se hace efectiva en el
fichero hasta que no se llena esta memoria intermedia. Por defecto, el buffer de escritura de PHP
tiene un tamaño de 8 Kb, pero, si en algún momento necesitáramos cambiar esta cifra por otra,
podríamos hacerlo con la función set_file_buffer ( ) :
set_file_buffer (descript, buffer_tamaño);

26.2.6 INFORMACIÓN SOBRE FICHEROS


• file_exists (nombr_fich) : Comprueba si el fichero nombr_fich existe. Devuelve TRUE si
nombr_fich existe; en caso contrario, devuelve FALSE. Esta función nos ahorrará desagra-
dables mensajes de error si antes de abrir un fichero hacemos uso de ella.
• is_file ( fichero) : Devuelve verdadero si el tipo del fichero es un fichero normal. En caso
contrario, devuelve FALSE .
• is_dir (fichero) : Devuelve verdadero si el nombre del fichero pasado como argumento es
un directorio. En caso de que no exista o no lo sea, devuelve FALSE.

Desarrollo de Aplicaciones Web Dinámicas - UNED


OPERACIONES CON FICHEROS (NIVEL EXTERNO) 26.5

• is_executable (fichero): Devuelve verdadero si el nombre del fichero pasado como argu-
mento tiene permisos de ejecución (Unix) o es un fichero ejecutable (extensión exe, com o
bat).
• is readable (fichero): Devuelve verdadero si el fichero tiene permiso de lectura. Si no tiene
dicho permiso o no existe, devuelve FALSE.
• is_writeable (fichero): Devuelve verdadero si el fichero tiene permiso de escritura. Si no
tiene dicho permiso o no existe, devuelve FALSE.
• filemtime (fichero): Devuelve el instante (timestamp) de la última modificación hecha
sobre el contenido del fichero.
• filesize (fichero): Devuelve un número entero que indica el tamaño en bytes del fichero
pasado como parámetro. En caso de error, devuelve FALSE.

26.3 OPERACIONES CON FICHEROS (NIVEL EXTERNO)

Con los ficheros podemos realizar operaciones para simplificar nuestros programas cuando utili-
zamos ficheros. Veamos algunas de estas operaciones:
• copy (origen, destino): Copia un fichero destino. Si no ha habido ningún error, devuelve
TRUE.
• rename (nom_original, nom_final) : Cambia el nombre a un fichero o directorio.
• unlink (nom_fichero) : Borra un fichero.
• link (fich_original, fich_enlazado): Crea un enlace duro (válido sólo en Unix).
• tempnam (directorio, prefijo): Crea un fichero único (no existente) en el directorio que se
le indica como primer parámetro. Si el directorio no existiese o fuese la cadena vacía, el
fichero se creará en el directorio temporal del sistema. El nombre generado empezará por
lo que se pase como segundo parámetro. Devuelve el nombre del fichero creado. Es muy
útil cuando necesitamos crear ficheros auxiliares en entornos multiusuario.
• touch (fichero [, instante]) : Modifica las fechas de último acceso y modificación del
fichero. Por defecto, esto es, sin el segundo parámetro, toma la fecha actual. Si no existe el
fichero, lo crea.

26.4 MANEJO DE DIRECTORIOS

Al igual que tenemos funciones específicas para ficheros, también tenemos a nuestra disposición
una serie de funciones predefinidas para el manejo y utilización de directorios. Con ellas podre-
mos crear, borrar, leer las entradas que tiene un directorio, averiguar en qué directorio nos encon-
trarnos, cambiarnos a otro, etc.
• opendir (nombre) : Abre el directorio pasado como parámetro. Devuelve un descriptor de
directorio.

Desarrollo de Aplicaciones Web Dinámicas - UNED


26.6 FICHEROS Y DIRECTORIOS

Si se están escribiendo scripts para plataformas Windows, un par de consejos en beneficio


de la portabilidad: usar el carácter "/" como separador de directorios (en lugar de "\") y no
hacer referencia a la unidad de almacenamiento (ejemplos, C : , A : , etc.)
• readdir (descriptor) : Lee una entrada del directorio a partir del descriptor devuelto por
opendir ( ).
• closedir (descriptor) : Cierra el directorio indicado por el descriptor.
• rewinddir (descriptor) : Sitúa el puntero de lectura al principio del directorio.
• getcwd ( ) : Devuelve el directorio actual de trabajo (también llamado activo) del script.
• chdir (nuevo_dir) : Establece nuevo_dir como nuevo directorio de trabajo. Devuelve
FALSE en caso de error.
• chroot (nuevoDirRaiz) : Cambia el directorio raíz del proceso actual al directorio que
viene indicado en el parámetro que se pasa a la función. Se suele usar para limitar el
acceso a determinados recusos. No funciona en Windows. Sólo funciona correctamente
cuando se usa CGI.

 Ejercicio: Realizar un navegador de archivos que nos permita movernos por la estructura de
directorios del disco duro del servidor.

26.5 OPERACIONES CON DIRECTORIOS

Veamos algunas funciones básicas para trabajar con directorios:


• mkdir (nombre_dir, permisos): Creamos el directorio nombre_dir con los permisos indica-
dos en el segundo parámetro.
• rmdir (nombre_dir) : Borra el directorio nombre_dir.

Dado que la operación de crear un directorio es atómica en cualquier sistema operativo, pues así
se garantiza la consistencia de la estructura de árbol de un sistema de ficheros, podemos crear
una región crítica haciendo uso de las funciones de creación y borrado de directorios, esto es,
podemos garantizar el acceso ordenado de múltiples procesos a un recurso compartido.

Este mecanismo se basa en el uso de semáforos: para que un proceso pueda acceder a un recurso,
necesita previamente consultar si tiene permiso. Esta autorización se implementa de manera muy
sencilla: si existe un directorio (de nombre convenido previamente), significará que hay otro pro-
ceso haciendo uso del recurso; en caso contrario, creará el directorio y accederá a dicho recurso.
Una vez satisfechas las necesidades de uso del recurso, borrará el directorio.

 Ejercicio: Realizar un programa de acceso a un formulario que garantice que sólo un usua-
rio se encuentra introduciendo datos.

Ejercicio: Realizar un contador de accesos a una determinada página.

Desarrollo de Aplicaciones Web Dinámicas - UNED


OTRAS FUNCIONES 26.7

 Estudiar en el libro de texto la información concerniente a Ficheros y directorios en Unix/


Linux.

26.6 OTRAS FUNCIONES

En este apartado incluirnos, a modo de miscelánea, funciones que de alguna manera están rela-
cionadas con los ficheros:
• basename (ruta) : Ésta no es una operación de ficheros propiamente dicha, sino, más bien,
de cadenas de caracteres ya que tanto lo que pasarnos a la función, como lo que obtenemos
de ella, es un string: dada una cadena de caracteres que definen una ruta o posición de un
fichero en el disco duro (separados los directorios por el carácter " /" o "\"), basename ( )
nos devuelve los caracteres que están después del último carácter que usamos como sepa-
rador. Por ejemplo, si le aplicamos esta función a la cadena /hola/que/tal, obtendremos tal.
• dirname (ruta) : Hace el inverso de la función basename ( ) , es decir, devuelve la ruta de
directorios y subdirectorios donde está ubicado el fichero: los directorios por los que hay
que pasar para encontrarlo; aplicado a "/hola/que/tal", obtendremos "/hola/que".
• disk_free_space (dir) : Esta función toma una ruta a un directorio y devuelve el espacio
libre en octetos (bytes) disponibles en el sistema de ficheros que contiene al directorio.
• disk_total_space (dir) : Toma una ruta a un directorio y devuelve el tamaño del sistema de
ficheros donde está situado dicho directorio.

26.7 TRANSFERENCIA DE FICHEROS ENTRE EL CLIENTE Y EL SERVIDOR

Por último, las operaciones en las que están involucrados ficheros que nos quedan por ver son
aquéllas en que el cliente le envía un fichero al servidor y a la inversa: el servidor le envía un
fichero al cliente.

26.7.1 SUBIR FICHEROS AL SERVIDOR


No es raro encontrarse con páginas que nos permiten transmitir ficheros desde el cliente al servi-
dor, es decir, lo que vulgarmente se conoce como subir ficheros o hacer uploads. Casos como
éste lo encontramos, por ejemplo, en páginas donde se ha de rellenar un curriculum vitae y uno
de los campos a rellenar es incluir una fotografía de la persona interesada. También en los clien-
tes de correo vemos esta posibilidad: en la página de componer mensajes lo normal es poder
adjuntar archivos para enviarlos junto con la redacción del mensaje.

El problema de subir ficheros al servidor se divide en dos escenarios: uno es la página HTML
donde el usuario indicará (a través de etiquetas) qué fichero de su disco local quiere subir; el otro
se encuentra en la parte programática: gracias a la página HTML (en realidad, gracias al proto-
colo HTTP), el fichero ya ha sido transferido al servidor y ahora lo que tenemos que hacer es
poder acceder a él para realizar las tareas que consideremos oportunas.

Desarrollo de Aplicaciones Web Dinámicas - UNED


26.8 FICHEROS Y DIRECTORIOS

En la página HTML sólo necesitamos dos etiquetas: la etiqueta <input> (en realidad, tantas
como ficheros queramos subir), gracias a la cual el navegador mostrará una cajita, y un botón de
navegación (broivsing), para que el usuario seleccione el fichero deseado:
<input file='file' name=' nombre_fichero_a_subir'>
La segunda etiqueta necesaria es la que nos permite construir un formulario (<form>), pero con
una serie de cláusulas adicionales:
form action="subir_fich.php" method="post" enctype="multipart/form-data">

Es decir, tenemos que indicar que el método de transferencia de los datos del formulario es
mediante POST (viajan junto a la página), y que viajarán codificados como multipart/form-data.

Opcionalmente, se puede expresar el tamaño máximo que podrá tener un fichero para poder ser
enviado con un campo de datos oculto (tendríamos entonces tres etiquetas) al que hay que identi-
ficarlo como max_file_size (si no se indica, se tomará la directiva upload_max_filesize, comen-
tada más abajo). Por ejemplo, limitamos el tamaño máximo a 1.000 caracteres:
<input type='hidden' name='max_file_size' value='1000'>
Veamos un sencillo ejemplo de página HTML desde la que se podría enviar un mensaje junto con
un fichero adjunto:
<HTML>
<HEAD>
<TITLE> subir ficheros </TITLE>
</HEAD>
<BODY>
<h2>Componer Mensaje</h2>
<FORM method='post' action='subir_fich.php'
enctype='multipart/form-data'>
<INPUT type='hidden' name='max_file_size' value='250000'>

Texto del Mensaje:<br>


<textarea cols='50' rows='5' name=.texto.>
</textarea>
<br><br>Fich. a Adjuntar:<input type='file' name='f_adjunto'>
<br><br><input type='submit' value='enviar datos!'>
</FORM>
</BODY>
</HTML>

Después de pulsar el botón de enviar, el fichero se encuentra en el servidor. Evidentemente, el


fichero transferido no está en un directorio al azar: se almacena en el directorio que se especifica
en el fichero php. ini a través de la directiva upload_tmp_dir.

Para poder trabajar con los ficheros así transmitidos, PHP nos proporciona el array asociativo
$_FILES. Este array tiene dos dimensiones: en la primera columna se indican los ficheros que
han sido subidos usando como claves los identificadores que usamos en la etiqueta <input>,
mientras que las claves de la segunda columna se corresponderán con las características de cada
fichero:

Desarrollo de Aplicaciones Web Dinámicas - UNED


TRANSFERENCIA DE FICHEROS ENTRE EL CLIENTE Y EL SERVIDOR 26.9

Tabla 26.1 Claves del array $_FILES.

 Revisar en el libro de texto los códigos de error.

También disponemos de un par de funciones que son muy útiles para trabajar con estos ficheros.
Una nos vale para saber si el fichero ha sido subido:
• is_uploaded_file($_FILES[' identif_fich']['tmp_name'1)
• move_uploaded_file(nom_fich_original, destino) nos sirve para renombrar o mover el
fichero temporal a otro que será permanente.

Veamos un ejemplo de cuál sería el programa que trataría los datos introducidos en la página
HTML anterior:
<?
foreach ($_FILES['f_adjunto'] as $clave => $valor)
echo "\$_FILES[$clave]: ($valor)<br>";

if (!is_uploaded_file($_FILES['f_adjunto']['tmp_name']))
{
$error=$_FILES['f_adjunto']['error'];
die("<h3>** ERROR: fichero no transferido: $error </h3>");
}

if ($_FILES['f_adjunto']['type'] != 'application/x-zip-compressed')
echo "<h3>** ERROR: el fichero enviado no está comprimido</h3>";
?>

26.7.2 DIRECTIVAS DE PHP.INI INVOLUCRADAS


Por último, hay que considerar tres directivas del fichero de configuración php.ini que nos deter-
minarán el comportamiento del intérprete PHP en lo que a transferencia de ficheros al servidor se
refiere:

Desarrollo de Aplicaciones Web Dinámicas - UNED


26.10 FICHEROS Y DIRECTORIOS

Tabla 26.2 Directivas de PHP.INI.

26.7.3 BAJAR FICHEROS DEL SERVIDOR


La transferencia de ficheros entre cliente y servidor también puede hacerse en sentido contrario
al visto hasta ahora: desde el servidor podernos enviar un fichero al cliente forzándo a éste a que
lo almacene en su disco duro. Por ejemplo, queremos enviarle un fichero gráfico (por ejemplo,
un fichero de tipo jpg) que no queremos que lo visualice en el navegador, sino que lo guarde
automáticamente. Para realizar esta transferencia, enviamos al cliente, gracias a la función hea-
der ( ), los siguientes comandos del protocolo HTTP:
<?php
$nom_fich="saco";
header("Content-Disposition: attachment; filename='$nom_fich'");
header("Content-Length:filesize($nom_fich));
header("Content-Type: application/octet-stream; name='$nom_fich'");
header("Content-Description: mensaje que quiera"); // opcional
?>

26.8 CONTROL DE LA SALIDA ESTÁNDAR

Hemos visto que, por defecto, la salida generada por cualquiera de las funciones readfile ( ) ,
fpassthru ( ) , echo ( ) , print ( ) , etc., se envía directamente a la salida estándar, es decir, la recibe
directamente el cliente. Por ello, el resultado de estas funciones no podemos asignarlo a una
variable o pasarlo como parámetro a otra.

PHP nos ofrece toda una familia de funciones para poder controlar todo aquello que se dirige a la
salida estándar. En la práctica, lo que hacen es trabajar con el contenido de una serie de memorias
intermedias (buffers):
• ob_start ( ) : Activa el almacenamiento en memoria intermedia, por lo tanto, cualquier
texto enviado a la salida estándar no llegará al navegador del cliente.
• ob_end_flush ( ) : Envía el contenido del buffer a la salida estándar y luego lo vacía. Ade-
más, da por terminado el almacenamiento intermedio.
• ob_end_clean ( ) : Borra el contenido del buffer y da por terminado el buffering.
• ob_get_contents ( ) : Devuelve el contenido de la memoria intermedia.

Desarrollo de Aplicaciones Web Dinámicas - UNED


CONTROL DE LA SALIDA ESTÁNDAR 26.11

• ob_get_length ( ) : Devuelve el número de octetos de lo que hay en el buffer.


• ob_flush ( ) : Envía el contenido del buffer a la salida estándar. Esta función no vacía el
buffer.

Desarrollo de Aplicaciones Web Dinámicas - UNED


26.12 FICHEROS Y DIRECTORIOS

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 27

Bases de datos

27.1 INTRODUCCIÓN

Puede parecer extraño decir que Internet no sería lo que es actualmente si no fuera por la existen-
cia de las bases de datos. De hecho, el propio PHP probablemene no seria tan popular o útil si no
fuera por su soporte integrado de numerosos tipos de bases de datos. (Como regla general, el
soporte de bases de datos por parte de PHP y su facilidad de uso son cosas que no encontraremos
utilizando scripts CGI.

Una base de datos es una colección de tablas (una tabla está a su vez compuesta por filas y
columnas) que almacenan información. Las bases de datos se utilizan por todo Internet. Los
sitios de comercio electrónico utilizan bases de datos para almacenar las especificaciones de los
productos (como su precio y color, por ejemplo), así como los datos de los clientes, mientras que
los sitios de contenido colocan artículos y noticias en la base de datos.

Existen actualmente muchos servidores de bases de datos o Sistemas de administración de bases


de datos DBMS (Database Matunettleal Systems), que funcionan en distintas plataformas. (Téc-
nicamente, un DBMS es el software que interactúa con la base de datos apropiada). Sin embargo,
cada vez más y mas personas utilizan los términos de base de datos y DBMS como sinónimos.

En cualquier sistema operativo, Oracle está considerado como el mejor DBMS, pero su precio lo
coloca fuera del alcance de la mayoría y se utiliza fundamentalmente para grandes aplicaciones
corporativas y con buena financiación. En el caso de Microsoft se suele recurrir a Access y SQL
Server; ambos sistemas muy útiles pero incompaibles con la plataforma cruzada.

Durante esta parte del curso usaremos MySQL como ejemplo de DBMS. Aunque MySQL, el
cual está disponible para la mayoría de las plataformas, no es tan potente como otros servidores
de bases de datos, tiene la suficiente velocidad y funcionalidad como para ser usado en muchísi-
27.2 BASES DE DATOS

mos proyectos (algunos de gran envergadura) y su precio (gratuito) lo convierten en una de las
opciones mas comunes para el desarrollo web.

27.2 GUIA DE ESTUDIO DEL TEMA

Este tema se estudiará en su totalidad haciendo uso del libro de texto. Para ello es necesario cen-
trarse en los siguientes temas:
• Tema 9: Introducción a las bases de datos y SQL. En este tema se hace un rápido repaso al
diseño de bases de datos, configuración e instalación de MySQL y al propio lenguaje de
consultas SQL.
• Tema 10: Recuperar datos de MySQL mediante PHP. En este tema se estudian los meca-
nismos que proporciona PHP para acceder a los datos almacenados en una base de datos
MySQL.
• Tema 11: Utilizar PHP para manipular datos en MySQL. A lo largo del tema se estudia
comorealizar modificaciones en los datos a través de PHP.

En el curso virtual, se le indicarán diversos ejercicios para que practique los conocimientos
adquiridos.

Desarrollo de Aplicaciones Web Dinámicas - UNED


TEMA 28

PHP Avanzado

Una vez vistos los conceptos generales de programación con PHP es necesario abordar una serie
de tecnologías que corresponden a técnicas avanzadas de programación. Dichas técnicas de
programación son especialmente útiles cuando los proyectos de desarrollo involucran un
conjunto elevado de personas que tienen distintas responsabilidades. Habitualmente se emplean
tres tipos de perfiles en el desarrollo de aplicaciones web: analistas, programadores y diseñadores
multimedia. Los analistas se encargan de realizar el diseño lógico de la aplicación, indicando
cuales son las funcionalidades requeridas y dando unas estructuras a los programadores para que
puedan implementar las funcionalidades requeridas. Los programadores emplean las estructuras
(habitualmente compuestas por diagramas con una notación que deben comprender) para escribir
el código necesario que desarrolla las funciones descritas para la aplicación web. De otra parte,
los diseñadores multimedia (en otras referencias, se les denomina diseñadores Web) se encargan
de realizar el aspecto gráfico que la aplicación web mediante el uso de lenguajes como XHTML
o DHTML, más los recursos multimedia que consideren necesarios. Teniendo en cuenta lo
anterior, se puede concluir:
1 Debe existir una coordinación entre los distintos roles para asegurar la productividad del
equipo de desarrollo y facilitar la consecución de los objetivos temporales.
2 Cada rol debe desarrollar una serie de estructuras que debe enviar a los roles dependientes.
Esto es, el analista enviará un conjunto de diagramas de notación conocida a los programa-
dores que implementarán el código de la aplicación. A su vez los programadores deberán
enviar aquellos scripts PHP que deben ser modificados para adecuarlos al aspecto Web que
los diseñadores multimedia han realizado. Los diseñadores multimedia remitiran a los pro-
gramadores los scripts modificados para verificar que no se ha modificado la lógica de
programación.

En el punto 2 se describe el proceso de coordinación y las interdepencias entre los distintos


componentes. Si el proceso de desarrollo estuviera descrito de forma completa desde un
28.2 PHP AVANZADO

principio (requerimientos completos, procesos de prueba, etc.) se dispondría de una fabrica de


software que sería muy productiva. Sin embargo, en el proceso existen muchas incertidumbres
que aparecen durante la elaboración de la aplicación: nuevas funcionalidades requeridas por el
cliente, cambios en las librerías software usadas en el desarrollo, fallos lógicos en las pruebas del
código, modificaciones del aspecto visual, etc. Estas incertidumbres tienen un impacto directo en
la planificación del proyecto, que pueden ser desde muy leves (cambios en las librerías software)
hasta muy graves (fallos lógicos de diseño por parte del analista). Para minimizar los efectos de
estas incertidumbres se pueden usar una serie de técnicas que alivian los problemas surgidos: la
programación orientada a objetos y el uso de plantillas de diseño.

La programación orientada a objetos se emplea en el desarrollo de la aplicación e implica a los


roles de analista y programador. Básicamente consiste en usar una notación conocida
(denominada Unified Modelling Language, UML) para que los cambios efectuados en el diseño
de la aplicación se transmitan rápidamente a los programadores, mejorando los tiempos de
coordinación. Otra de las ventajas principales de la POO, como se verá en el Tema 1 de este
módulo, consiste en la encapsulación del código lo que permite a distintos desarrolladores
centrarse en sus propios “objetos” y emplear aquellas funciones de otros “objetos” desarrollados
por otros programadores sin conocer como están implementados. Es decir, en un entorno de
desarrollo PHP lo habitual es escribir scripts PHP que contienen toda la lógica asociada a la
acción que implementan (registro de un usuario, comprar un producto, etc.) por lo que cualquier
acción dependiente necesita conocer el código desarrollado. Sin embargo, en un entorno de POO
se definen elementos (“objetos”) que especifican las acciones (funciones PHP) que otros
elementos emplearan en la ejecución de los scripts PHP.

El uso de plantillas de diseño resuelve el problema de coordinación entre programadores y


diseñadores multimedia mediante una notación específica que evita a los diseñadores tener que
aprender PHP para poder modificar el aspecto visual de las aplicaciones web basadas en PHP. En
el tema 2 de este módulo se presentan los conceptos de plantillas mediante el uso de un motor de
plantillas denominado Smarty.

Finalmente, en el último tema se realiza una introducción al empleo de XML como estándar de
comunicación de datos entre aplicaciones y como se puede un API específico de PHP usar para
generar y modificar documentos XML.

28.1 PROGRAMACIÓN ORIENTADA A OBJETOS

28.1.1 INTRODUCCIÓN
Para comenzar a hablar de programación orientada a objetos en PHP es necesario recordar cúales
son sus conceptos básicos. Estos conceptos varían dependiendo de las diferentes fuentes
consultadas, pero se pueden mencionar algunos que son básicos y necesarios para cualquier
lenguaje del cual pueda decirse que es orientado a objetos:

Desarrollo de Aplicaciones Web Dinámicas - UNED


PROGRAMACIÓN ORIENTADA A OBJETOS 28.3

- Tipos de datos abstractos e información encapsulada.

- Herencia.

- Polimorfismo.

La encapsulación en PHP se codifica utilizando clases:

<?php

class Something {

var $valor;

function setValor($v) {

$this->x=$v;

function getX() {

return $this->x;

?>

Las propiedades de los objetos son definidas en PHP utilizando la declaración “var” dentro de la
clase. Cuando se declara una propiedad la misma no tiene tipo, hasta que se le asigne algún valor
en particular, asumiendo el tipo del valor asignado. Una propiedad puede ser un entero, un
vector, un vector asociativo, e inclusive puede ser otro objeto. Los métodos son definidos como
funciones, también dentro de la clase. Para acceder a las propiedades de la instancia de esa clase
es necesario referirse a las propiedades con la sentencia $this->propiedad. En caso de no utilizar
el “$this->” la variable será local al método y una vez terminada la ejecución del mismo se
perderá su valor. Para crear una instancia de un objeto se debe ejecutar el operador “new”, que
devuelve en una variable un objeto de la clase que se le indica:

$obj = new Something;

Una vez instanciado el objeto podemos utilizar sus métodos:

$obj->setX(5);

$entero=$obj->getX();

El método setX ejecutado en el objeto $obj hace que se asigne un 5 a la propiedad ”x” de dicha
instancia. Se puede notar en este punto que se podría haber inicializado la propiedad “x” con
cualquier tipo de variable, por ejemplo una cadena de texto (tipo string). Para asignarle el valor
entero 5 a la propiedad “x” del objeto $obj se podría haber puesto en el código directamente

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.4 PHP AVANZADO

“$obj->x=5;”, sin la necesidad de llamar a ningún método, pero el problema consistiría en que en
que se estaría violando la regla de encapsulamiento de los objetos. Una buena práctica de la
programación orientada a objetos consiste en acceder a las propiedades solamente mediante
métodos propios de la clase y nunca usar directamente el acceso a las variables.
Lamentablemente PHP en su versión 4.x no ofrece la posibilidad de declarar las propiedades
privadas, pero ha sido corregido en la versión 5. De esta manera se pueden usar modificadores de
acceso para catalogar las propiedades e implementar así la encapsulación de datos.

La herencia en PHP se implementa mediante la sentencia “extends”

<?php

class Another extends Something {

var $y;

function setY($v) {

$this->y=$v;

function getY() {

return $this->y;

?>

Los objetos de la clase “Another” poseen todas las propiedades y metodos de su clase padre
“Something”, más las propiedades y métodos propios. Ahora se pueden ejecutar por ejemplo los
siguientes comandos:

$obj2=new Another;

$obj2->setX(6);

$obj2->setY(7);

En PHP una clase de objetos no puede ser “hija” de más de un “padre”, lo que es conocido como
herencia múltiple. En PHP se pueden reescribir métodos de la clase padre en la clase hija (técnica
conocida como overriding). Para esto sólo hace falta volver a definir la función en el objeto hijo.
Por ejemplo si se desea redefinir el método getX para la clase “Another” simplemente se define
la función en la clase “Another”. Una vez hecho esto no es posible para los objetos de la clase
“Another” ejecutar el código del método getX de “Something”.

En caso de declararse una propiedad en la clase “hija” con el mismo nombre que en la clase
padre, la propiedad de la clase padre se encontraría “oculta”.

Desarrollo de Aplicaciones Web Dinámicas - UNED


PROGRAMACIÓN ORIENTADA A OBJETOS 28.5

En las clases se pueden definir constructores. Los constructores son métodos que se ejecutan al
momento de instanciar la clase (cuando se ejecuta la sentencia new). La característica para que
un método sea el constructor de una clase (en las versiones PHP 4.x) es que debe tener el mismo
nombre que la clase.

<?php

class Something {

var $x;

function Something($y) {

$this->x=$y;

function setX($v) {

$this->x=$v;

function getX() {

return $this->x;

?>

Entonces, se puede crear el objeto de la siguiente manera:

$obj=new Something(6);

Automáticamente el constructor asigna el valor entero 6 a la propiedad “x”. Todos los métodos,
incluyendo los constructores, son funciones normales de PHP, por lo que se le pueden asignar
valores por defecto. Supongamos que tenemos el constructor definido de la siguiente manera:

function Something($x="3",$y="5")

En este caso se puede crear el objeto de la siguiente manera:

$obj = new Something(); // x=3 y y=5

$obj = new Something(8); // x=8 y y=5

$obj = new Something(8,9); // x=8 y y=9

Los argumentos por omisión son utilizados en C++ y son una vía para cuando no hay valores
poder pasar por parámetro las variables a las funciones. Cuando el parámetro no es encontrado
por la función que es invocada, toma el valor por omisión que le es especificada en su definición.

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.6 PHP AVANZADO

Otro mecanismo interesante de la POO consiste en la utilización de las interfaces. Son clases que
no son instanciables y están hechas para el único propósito de definir una especificación de
funciones para otras clases que implementarán dichas funciones. Los analistas usualmente
utilizan estas clases para forzar a los programadores a asegurarse que cada clase tiene una cierta
funcionalidad predefinida.

El polimorfismo se define como la habilidad de un objeto de determinar que método debe


invocar para un objeto pasado como argumento en tiempo de ejecución. Por ejemplo si se tiene
una clase figura que tiene un método “dibujar” y sus clases derivadas circulo y rectángulo,
cuando se reemplaza el método “dibujar” se puede tener una función que cuente con un
argumento “x” y después llamar a $x->dibujar(). Mediante el polimorfismo la ejecución de
código asociado a la llamada del método “dibujar” dependerá del tipo de objeto que se envie a la
función. El polimorfismo es muy fácil de aplicar y utilizar en lenguajes interpretados como PHP:

<?php

function niceDrawing($x) {

//Este es un método de la clase Pizarra.

$x->draw();

$obj=new Circle(3,187);

$obj2=new Rectangle(4,5);

$pizarra->niceDrawing($obj); //Llama al método draw de circulo.

$pizarra->niceDrawing($obj2); //Llama al método draw de rectángulo.

?>

28.1.2 DESCRIPCIÓN DETALLADA DE LA POO


En la sección anterior se presentaron los conceptos básicos de la POO, pero para profundizar en
el tema se deben leer los Capítulos 12 y 13 del libro:

Fundamentos de PHP 5

que se envió anteriormente. En el capítulo 12 se describe de manera detallada y con ejemplos los
elementos de la POO soportados en PHP5, mientras que en el capítulo 13 se describen los
principios del lenguaje unificado de modelado (UML) usado en la descripción de una aplicación
que usa la POO. Es muy importante la lectura de este capítulo porque permite tener una visión
global del modelo de desarrollo de la POO.

Desarrollo de Aplicaciones Web Dinámicas - UNED


PROGRAMACIÓN ORIENTADA A OBJETOS 28.7

28.1.3 TÉCNICAS AVANZADAS DE PROGRAMACIÓN ORIENTADA A OBJETOS

Serialización
PHP no soporta la persistencia de objetos. En la POO los objetos persistentes son objetos que
mantienen su estado y funcionalidad a través de múltiples invocaciones de la aplicación. Esto
puede resolverse salvando el objeto en un archivo o en una base de datos y restaurando los datos
cada vez que se ejecuta dicha aplicación. El mecanismo es conocido como serialización. PHP
proporcione un método de serialización que puede ser llamado por los objetos. El método de
serialización devuelve un string representando el objeto. La serialización guarda las propiedades
del objeto pero no sus métodos.

En PHP si se serializa un objeto sobre el string $s, se destruye el objeto, y entonces utilizando la
deserialización de objeto en $obj se puede mantener el acceso a las propiedades del objeto. Esto
no se recomienda por dos razones: la primera es porque no se garantiza que en futuras versiones
esto siga funcionando. La segunda es porque si se serializa un objeto, se guarda a disco el string
y se sale del script, al ejecutar en el futuro dicho script puede ser posible que los métodos del
objeto no sean los mismos, ya que en la serialización sólo se guardaron las propiedades.
Concluyendo, la serialización es útil en PHP para guardar las propiedades de un objeto (se puede
serializar un vector asociativo para salvarlos a disco por ejemplo).

<?php

$obj=new Classfoo();

$str=serialize($obj);

// Se salva $str al disco

//...algunos años más tarde

// Se recupera str del disco

$obj2=unserialize($str)

?>

En este caso se dispone de las propiedades recuperadas pero no se pueden utilizar los métodos ya
que no existe información sobre ellos.

Instanciación dinámica de clases


Una de las cosas útiles de PHP y la POO consiste en la capacidad para definir de una manera
sencilla las clases necesarias para resolver cierto tipo de problemas y usar la clase apropiada
cuando se desee. Suponga que tenemos un formulario html donde un usuario selecciona un
producto por medio de su identificador de producto (ID). Supongase también que se tienen los
datos del producto en una base de datos y se desea mostrar el producto, su precio y demás
características. Si se tienen productos de diferentes tipos, es probable que en la misma acción se
disponga de diferentes recursos multimedia para diferentes familias de productos. Por ejemplo

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.8 PHP AVANZADO

para algunos productos se reproducirá un sonido mientras que para otros productos se mostrará
una foto del mismo guardada en la base de datos. Se puede definir una clase Producto, con los
métodos que la clase debe tener (por ejemplo “display”), y entonces se definen clases para cada
tipo de producto como una extensión (extends) de la clase Producto, por ejemplo clase
ItemSonoro, ItemVisible, etc., redefiniendo los métodos que ya se definieron en Producto para
cada una de las clases hijas. Lo que resulta conveniente en este caso es nombrar las clases de
acuerdo con los tipos de “columna” que se guardan en la base de datos por cada tipo de producto
(id, tipo, precio, etc.).

De esta manera cuando se procese el script se puede pedir el tipo desde la base de datos e
instanciar un objeto de la clase del tipo de producto:

<?php

$obj=new $type(); // $type almacena el nombre de la clase a instanciar

$obj->display();

?>

Esto propiedad de PHP permite llamar al método “display” por ejemplo del tipo de objeto que se
desea usar. Con esta técnica no es necesario modificar el script de proceso (el formulario) cuando
se agrega un nuevo tipo de objeto, solamente se debe añadir la nueva la clase. Esta es una
funcionalidad muy interesante (disponible sólo en lenguajes interpretados como PHP). Sólo se
debe cuidar la definición de los métodos que todos los objetos deben tener de acuerdo a los tipos
que se especificaron, generando las diferentes maneras para los diferentes tipos.

Copia y clonación de objetos


Cuando se crea un objeto $obj se puede copiar un objeto usando el operador de asignación
$obj2=$obj. El nuevo objeto es una copia del objeto $obj, es decir que tiene el estado que $obj
tenia en el momento que se realizó la asignación. Algunas veces no es necesario esto, puesto que
solo se pretende crear un nuevo objeto de la misma clase que $obj, llamando al contructor en el
momento de la creación del nuevo objeto y copiar las propiedades del objeto. A esto se le llama
clonación y se puede realizar mediante el uso de la serialización y una clase de la que todas las
demás clases sean extensión.

Cuando se serializa un objeto se obtiene un string de un formato propio. Se pueden comprobar


los distintos atributos que se almacena en dicha cadena, como por ejemplo el nombre de la clase::

<?php

$obj_serializado=serialize($obj);

$vec=explode( ':',$obj_serializado);

$nombre_clase=str_replace( "\"", '',$vec[2]);

?>

Desarrollo de Aplicaciones Web Dinámicas - UNED


PROGRAMACIÓN ORIENTADA A OBJETOS 28.9

Teniendo en cuenta lo anterior, si especificamos una clase “Universal” y se fuerza a que todas las
clases sean extensión de ella (como hace Java, en donde todas las clases heredan directamente de
la clase Object) se puede definir un método “clone”:

<?php

class Universal {

function clone() {

$obj=serialize($this);

$vec=explode( ':',$obj);

$name=str_replace( "\"", '',$vec[2]);

$ret=new $name;

return $ret;

//Entonces:

$obj=new Something();

//Something extiende a Universal !!

$other=$obj->clone();

?>

28.1.4 EJERCICIOS
1 Se desea definir una clase Forma con dos métodos dibujar() y borrar(), de la cual heredan
tres clases: Circulo, Cuadrado y Rectángulo. Para cada una de las clases se deben redefinir
los métodos dibujar() y borrar(), imprimiendo un mensaje en cada llamada a dichos méto-
dos (por ejemplo, echo ‘Dibujo un circulo’ y echo ‘Borro el círculo’). Desarrolle un script
php que demuestre el funcionamiento del polimorfismo mediante la generación aleatoria
de diez objetos de las clases Circulo, Rectángulo y Triángulo. Cada objeto instanciado de
las clases anteriores se tratará como un objeto de la clase Forma (a esto se le denomina
casting) y se realizarán sendas llamadas a los métodos dibujar() y borrar(). Explique qué
ocurre y porqué.
2 Cree una clase base (padre) con dos métodos, de tal forma que en la implementación del
primer método se llame al segundo. Cree una clase hija de la anterior y sobrescriba el seg-
undo método de forma que imprima un mensaje indicando el nombre de la clase hija.
Escriba un script php que cree un objeto de la clase hija, convierta dicho objeto (casting) a
un objeto de la clase padre, y realice una llamada al primer método usando los dos objetos
(padre e hijo). Ejecute el script y explique qué ocurre y porqué.

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.10 PHP AVANZADO

3 Defina una interface Conmutador con tres métodos: on(), off() y switch() y desarrolle dos
clases que implementen la interface. La primera es un conmutador de tipo semaforo que
está en verde cuando está encencido y rojo cuando está apagado. La segunda es un con-
mutador telefónico que permite enviar sonido cuando está encendido y finaliza la emisión
cuando se apaga. Escriba un script php (o varios, según necesite) que permita seleccionar
el tipo de conmutador (creando así un objeto del tipo apropiado) y una vez seleccionado se
pueda invocar a los métodos on(), off() y switch() apropiados, mostrándo en pantalla el
estado del objeto. Por ejemplo al invocar el método on() de un conmutador tipo semáforo
se debe mostrar en pantalla un mensaje indicando “Estoy en verde”.
4 Desarrolle una aplicación PHP que almacene los resultados del formulario/encuesta
desarrollado en Javascript en el módulo anterior en el servidor mediante el uso de la serial-
ización de objetos. Esto debe permitir al usuario almacenar de manera parcial o total los
resultados en una cadena de texto en el servidor, mediante un botón Guardar respuestas.
5 Realize el diseño de clases (mediante UML, vea el capítulo 13) de un “hipotético” sistema
de control de acceso y de autorización a los usuarios de una tienda virtual de compra on-
line. Se debe tener en cuenta que funcionalidades que pueden realizar los usuarios, depen-
diendo el pérfil, las controla el sistema de autorización mientras que el sistema de acceso
valida la información de conexión.

28.2 PLANTILLAS DE DISEÑO SMARTY

Las plantillas (del término ingles Template) consisten en una técnica que permite diseñar de
manera visual los documentos HTML que se enviarán desde servidor y que emplea la
información generada por los scripts para mostrar el contenido completo de la página HTML (el
documento diseñado más la información dinámica). Mediante el uso de plantillas se puede crear
rápidamente gran cantidad de documentos de un aspecto parecido, simultáneamente, separando
la lógica de programación (scripts y funciones php) del lado visual. Una plantilla individual
puede ser utilizada un número interminable de veces, incluso para la construcción de la siguiente
plantilla. Esta separación del desarrollo de los scripts php y la parte visual permite definir un
entorno de trabajo que sitúa a los editores web en la generación de los documentos HTML y a los
pogramadores en el desarrollo de las funcionalidades.

En Internet se pueden encontrar diferentes sistemas de plantillas que se pueden combinar con
PHP:
• PHPLib (http://phplib.sourceforge.net/)
• TemplatePower (http://templatepower.codocad.com/)
• TemplateLite (http://templatelite.sourceforge.net/)
• Smarty (http://smarty.php.net/)

Se podrían usar cualquiera de estos sistemas de plantillas, pero se va a emplear Smarty por ser el
más usado en los sistemas de desarrollo basados en PHP. El mecanismo de funcionamiento en

Desarrollo de Aplicaciones Web Dinámicas - UNED


PLANTILLAS DE DISEÑO SMARTY 28.11

todos es muy parecido (salvo quizás la notación usada para pasar la información que necesita la
página HTML para ser generada), por lo que se recomienda al estudiante que una vez finalizado
el estudio del sistema Smarty, lo compare con el resto de las alternativas.

28.2.1 INTRODUCCIÓN A SMARTY


Básicamente las plantillas contienen la estructura completa del documento HTML que se
visualizará en el navegador del cliente, y al cual se le pasan los valores de ciertas variables. Es
comparable al impreso para la declaración de impuestos: es único para todas las personas físicas,
pero cada individuo escribe en él sus propios datos calculados. En Smarty se crea la estructura
completa de un documento HTML, y en el lugar donde debe desplegarse el valor de la variable,
insertamos los corchetes y el valor de la variable: {$var}.

En principio no parace de mucha utilidad puesto que se podrían obtener resultados parecidos
mediante la función echo dentro del documento: <?echo $var;?>. Sin embargo, como se verá a
continuación, el uso de la notación anterior permite a los diseñadores de las páginas Web evitar el
aprendizaje de la sintáxis de PHP. Lo único que deben conocer es la información a incluir en el
documento y dónde ubicarla. Adicionalmente la lectura del documetno HTML es más sencilla y
comprensible. He aquí la primera ventaja de Smarty, no la última y la menos importante.

Existen otro conjunto de ventajas, que se detallan a continuación:

Existencia de Modificadores
Los modificadores funcionan directamente sobre las variables, modificando su apariencia o su
contenido. Se pueden desplegar cadenas con la ayuda de letras mayúsculas, sustituir en la cadena
la palabra indicada por otra expresión, o acortarla a una longitud concreta. De esta manera, el
programador debe proporcionar únicamente los datos señalados por el diseñador, y éste se
ocupará de su formato. De este modo, se focaliza el trabajo de desarrollo en la obtención de la
información necesaria de la base de datos, del archivo o de alguna función. Al mismo tiempo, el
diseñador recibe mejores y significativas posibilidades para el formato del documento, de las que
le ofrece HTML. Además de todo esto, no tendrá problemas con usar los modificadores, dado
que son más entendibles y secillos de usar, con respecto a las funciones correspondientes de PHP.

Funciones propias
Smarty añade un conjunto de funciones que le introducen elementos de programación. mediante
estas funciones se puede leer el contenido de los arrays, crear un contador que estará numerando
las cabeceras consecutivas en el texto o rápidamente crear una lista de campos opcionales en una
sola línea de código. Por ejemplo, se puede usar el siguiente código :

{ html_radios name="revista" options=$lista_revistas separator="<br />"}

y situarlo en la plantilla, a la cual se le enviará el array asociativo $lista_revistas con los


siguientes valores:

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.12 PHP AVANZADO

$lista_revistas = array ("1" => "Programación en PHP", "2" => "Revista AJAX");

Al generar la página se creará dentro del documento HTML el siguiente trozo de código:

<input type="radio" name="revista" value="1" />Programación en PHP<br />

<input type="radio" name="revista" value="2" />Revista AJAX<br />

Conviene mencionar que todo el código creado mediante las funciones construídas en Smarty se
genera en el estándar XHTML, o al menos eso es lo que indica la documentación. Si se analiza el
ejemplo anterior se aprecia que en el interior del tag <input/> se encuentra el atributo name. Las
especificaciones de XHTML indican claramente que ese atributo debería ser sustituído por id.
Otra de las posibilidades es la creación de instrucciones if. Se pueden emplear con el objetivo de
verificar si una variable determinada que se le enviará a la plantilla contiene un valor o no. Por
ejemplo:

{if $name != ""}

¡Encantado de verte {$name}!

{else}

¿Cual es tu nombre?

{/if}

Creación de Filtros
El uso comentarios en los scripts y páginas HTML permite documentar de manera detallada el
proceso de programación y desarrollo de las aplicaciones, pero desgraciadamente dichos
comentarios se hacen visibles a los usuarios. Para evitar esto se usa el concepto de filtro, de tal
forma que se limpian las plantillas de comentarios, antes de ser generadas las páginas Web. Los
filtros también permiten agregar nuevo contenido en los archivos generados, como podría ser el
logotipo de la empresa en la parte inferior de la plantilla.

Presencia de archivos de configuración


Los archivos de configuración permiten definir ciertas variables globales, a las que se accederá
desde todas las plantillas. Creando una plantilla, tenemos la posibilidad de cargar los archivos de
configuración y las variables que en ellos se encuentran, las cuales pueden ser utilizadas y
modificadas de la misma manera que una variable común.

Plugins
Smarty es un sistema abierto, fácil de extender o modificar. Los plugins permiten crear
modificadores, funciones y filtros. También se pueden utilizar plugins construidos y
proporcionados por otros. Ya que todo está en PHP, únicamente debemos cumplir con las
especificaciones que indican los requerimientos que se refieren a la construcción de plugins en
Smarty (http://smarty.php.net/manual/es/plugins.php).

Desarrollo de Aplicaciones Web Dinámicas - UNED


PLANTILLAS DE DISEÑO SMARTY 28.13

Utilización de la caché
Cuando se crea una plantilla se genera un script php con la estructura del documento (es decir, se
convierte la plantilla Smarty a un script php) que es usada por el módulo php del servidor web
para generar la página HTML que servirá al cliente. De esta manera una vez generado el script,
todas las peticiones se resolverán con llamadas al script php generado a través de la plantilla. Si
existe un cambio en la plantilla, el sistema de manera automática vuelve a generar el script php.
El trabajo de Smarty puede acelerarse utilizando la caché (del término ingés Caching). Esta
operación consiste en almacenar el documento en formato HTML, que será enviado durante la
siguiente llamada al navegador del cliente, sin la necesidad de procesar nuevamente los scripts, o
realizar las consultas a la base de datos.

28.2.2 INSTALACIÓN Y CONFIGURACIÓN DE SMARTY


Para usar Smarty es suficiente descargar el archivo correspondiente y descomprimirlo (http://
smarty.php.net/download.php). Smarty necesita la versión 4.0.6 de PHP o superior, por lo que es
conveniente comprobar que el servidor dispone de dicha versión.

En el archivo se encuentran algunos archivos informativos además de 3 directorios: /libs, /demo


y /misc. En el primero, se incluye todo lo que es necesirio para usar Smarty y debe copiarse en el
servidor empleado en el desarrollo de las aplicaciones PHP.

Para usar plantillas, necesitaremos referenciar el archivo Smarty.class.php mediante la función


require(). Existen dos alternativas para ubicar los ficheros de Smarty:
1 Si se dispone de privilegios de administrador en el servidor de desarrollo, se debe buscar el
path dónde está intalado PHP, y en él, crear una nueva carpeta (digamos /templates), en la
que copiaremos el del directorio /libs. Para que no sea necesario invocar al archivo
Smarty.class.php, utilizando la ruta de acceso completa (por ejemplo: /usr/local/lib/php/
templates/Smarty.class.php, podemos agregar dicha ruta al campo include_path en el
archivo php.ini.
2 En caso de estar empleando un hosting con soporte PHP, es suficiente copiar el contenido
del directorio /libs en algún directorio de la cuenta proporcionada por el hosting. Una vez
que ya se ha copiado y conocemos la ruta de acceso, se puede emplear la variable
SMARTY_DIR, que se encuentra dentro del archivo Smarty.class.php.

El empleo correcto de Smarty requiere la creación de cuatro carpetas. Sus nombres por defecto
son /templates, /templates_c, /configs y /cache (a los directorios les coresponden 4 variables
dentro del archivo Smarty.class.php: $template_dir, $compile_dir, $config_dir y $cache_dir).
Para configurar Smarty simplemente hay que incluir la clase Smarty.class.php, redefinir la clase
Smarty indicando los directorios que deben usarse y luego instanciar un objeto de la nueva clase,
como muestra el siguiente ejemplo (Smarty_config.class.php):

<?php

define('SMARTY_DIR',"smarty/");

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.14 PHP AVANZADO

require_once(SMARTY_DIR.'Smarty.class.php');

class Smarty_config extends Smarty {

function Smarty_config() {

$this->teplate_dir = "templates/";

$this->compile_dir = "templates_c/";

$this->config_dir = "configs/";

$this->cache_dir = "cache/";

//$this->caching = false;

//$this->debugging = true;

//$this->debug_tpl = 'debug.tpl';

$smarty = new Smarty_config();

?>

Como se puede ver es necesario indicar los directorios para templates (smarty/templates),
templates compilados (smarty/templates_c), archivos de configuracion y cache. Obsérvese que
los directorios son relativos al directorio en donde esta Smarty (definido con SMARTY_DIR) y
no a la aplicacion. Además si se eliminan los comentarios finales tambien se indica si se desea
usar el sistema de cache o si se quiere disoponer una ventana emergente de depuración para las
plantillas. Una vez hecho esto el objeto "smarty" es el que se empleará para mostrar las plantillas.

28.2.3 EJEMPLO BÁSICO DE UTILIZACIÓN DE LAS PLANTILLAS SMARTY


Una vez que ya se ha instalado lo necesario para crear plantillas Smarty, es hora de crear la
primera aplicación Smarty. El primer ejemplo consiste en crear la típica página Hola mundo,
aunque en este caso personalizada con el nombre del usuario que accede a la página.

Paso 1 En primer lugar se debe crear el template hola.tpl que se situará en el directorio de templates (por
ejemplo smarty/templates). Su contenido es muy simple:

<h1>Hola mundo</h1>, Mi nombre es {$nombre}

Como se puede ver la plantilla es una mezcla de codigo HTML y directivas Smarty (entre llaves)
y que en este caso lo que hace es mostrar el contenido de la variable $nombre. Las variables
deben generarse y asignarse desde un script PHP.

Paso 2 Escriba un script php denominado hola.php que contenga el siguiente código:

<?php

Desarrollo de Aplicaciones Web Dinámicas - UNED


PLANTILLAS DE DISEÑO SMARTY 28.15

require_once('Smarty_config.class.php');

$smarty-> assign('nombre','Rafa');

$smarty->display('hola.tpl');

?>

El script asigna a la variable de smarty 'nombre' la cadena de texto 'Rafa' y luego muestra el
template 'hola.tpl'. El resultado es un documento html que dice: Hola mundo, Mi nombre es Rafa.

Realmente este ejemplo es bastante simple pero permite ver la forma de emplear un objeto
smarty para recopilar la información que luego se empleará en la generación de la página HTML
correspondiente. A continuación se muestra un ejemplo más completo que usa varias de las
características del sistema de plantillas Smarty.

28.2.4 UN EJEMPLO COMPLETO DE USO DE SMARTY

Para las necesidades de este ejemplo, se supone que se tiene una página sobre un conjunto
musical. Para que el trabajo resulte agradable, supongamos que es el grupo The Beatles. La parte
en la que mejor se pueden aplicar las plantillas es la discografía del conjunto. Cada disco debería
tener su propia página con el nombre del álbum, la descripción de las canciones, la fotografía de
la portada además de una breve descripción. Todos van a utilizar las plantillas preparadas , lo que
facilita añadir rápido los siguientes discos, y al mismo tiempo, las modificaciones posteriores de
cada una de las páginas.

Para eso se crea una plantilla de ejemplo, cuyo contenido se presenta en el Listado 1. Como se
puede ver ya a primera vista, es un documento común y corriente escrito en XHTML. Sin
embargo, es fácil encontrar el lugar donde aparecen las variables. En las plantillas de Smarty, el
nombre de las variables va precedido por el símbolo del dólar ($) y encerrado entre llaves.
Además, en ellas no se tienen puntos y comas, que son tan comunes en los scripts de PHP. El
archivo de la plantilla es un archivo de texto común, al cual se le asigna la extensión .tpl (del
inglés: template, es decir, plantilla). Por supuesto, nada impide darle la extensión que se desee.

Listado 1: Contenido de la plantilla album.tpl

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="content-type" content="text/html; charset=iso-8859-2" />

<meta name="description" content="Discografía del conjunto The Beatles" />

<title>{$albumName}</title>

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.16 PHP AVANZADO

</head>

<body>

<h3>{$albumName}</h3>

<table>

<tr>

<td><img src="{$albumCover}" alt="" /></td>

<td><b>Índice de canciones:</b><br />{$albumSongs}</td>

</tr>

</table>

<h4>Descripción del álbum:</h4>

<p>{$albumSynopsis}</p>

<p><a href="">Página principal</a></p>

</body>

</html>

El archivo debe almacenarse en el directorio /templates de la distribución Smarty. Una vez lista
la plantilla, se debe utilizar en el código de la aplicación. Para eso se debe crear un script PHP
cuyo contenido se muestra el Listado 2. En este script se definen los valores concretos de las
variables y la plantilla utilizada. Este archivo se coloca junto con otros documentos web.

Listado 2: Archivo title.php, el cual va a utilizar la plantilla album.tpl

<?

require ("Smarty.class.php");

$smarty = new Smarty;

$smarty->assign("albumName", "Sgt. Pepper's lonely hearts club Band");

$smarty->assign("albumCover", "grafika/sgtpep.jpg");

$smarty->assign("albumSongs", "Sgt. Pepper's Lonely Hearts Club Band;

With A Little Help From My Friends;Lucy In The Sky Of Diamonds;

Getting Better;Fixing A Hole;She's Leaving Home;

Being For The Benefit Of Mr. Kite!;Within You, Without You;

When I'm Sixty-Four;Lovely Rita ;Good Morning, Good Morning;

Sgt. Pepper's Lonely Hearts Club Band (Reprise);A Day In The Life");

Desarrollo de Aplicaciones Web Dinámicas - UNED


PLANTILLAS DE DISEÑO SMARTY 28.17

$smarty->assign("albumSynopsis", "El álbum más famoso del conjunto y uno de los


mejores álbumes en la historia de la música. Novedoso, genial -- una verdadera obra de arte.
El disco fue introducido al mercado en 1967 y se convirtió en uno de los símbolos de esa
época.");

$smarty->display("album.tpl");

?>

Una vez visto un ejemplo de script que usa Smarty es necesario comentar ciertos detalles sobre el
mecanismo de Smarty. En la primera etapa, tiene lugar la compilación de la plantilla. Pero esto
no tiene nada que ver con la compilación conocida de tales lenguajes como, por ejemplo, Java, o
la compilación de scripts PHP. Su propósito es la conversión de la plantilla a un documento php.
Esto significa que, por ejemplo, la notación {$var} será cambiada a:

<?php

echo $this->_tpl_vars['var'];

?>

El documento, de esta forma, es salvado automáticamente dentro del directorio /templates_c. En


la siguiente llamada al archivo title.php, el servidor enviará al navegador los archivos ya
convertidos, lo que permite el ahorro de tiempo y de trabajo del parser.

El código PHP de title.php es muy simple de interpretar y leer. Para empezar, se debe cargar la
librería Smarty y crear un nuevo objeto tipo smarty. Luego se emplea el método assign para crear
las variables y asignarles valores concretos. Smarty maneja los mismos tipos de variables que
PHP, así que se pueden emplear números, cadenas, arrays, etc. Finalmente el método display se
encarga de que se cargue la plantilla dada y se despliege todo el documento. Desde luego, el
archivo title.php podría contener una secuencia de funciones complicadas que permitirían la
carga de datos desde una base de datos, archivos de texto, etc. Pero se puede suponer aquí por
simplicidad que ya se dispone de ella y se pueden asignarl a variables de una vez. En este
momento, se debe prestar atención a un punto importante. Todo lo que se colocará en la plantilla
entre llaves, será tratado como una posible variable o función. Así que, si se desea introducir una
llave en el texto, debemos utilizar {ldelim} para la llave izquierda y {rdelim} para la llave
derecha. Lo mismo se refiere a colocar en el documento estilos o scripts, por ejemplo:

<style>

p {ldelim}color: #000000;

font-size: 12px{rdelim}

</style>

Es fácil convencerse de que este método resulta complejo en el caso de una gran cantidad de
llaves por lo que se puede utilizar el tag {literal} disponible en Smarty. Todo lo que se encuentra

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.18 PHP AVANZADO

entre {literal} y {/literal} no será interpretado por el mecanismo Smarty. El ejemplo anterior del
código quedaría:

{literal}

<style>

p {color: #000000;

font-size: 12px}

</style>

{/literal}

De paso se debe mencionar que Smarty tiene su propio mecanismo de comentarios, que son
eliminados durante la compilación. Los comentarios en la plantilla se inician con {* y terminan
con *}. Volviendo a la plantilla de ejemplo, se ve claramente que se pueden mejorar en ella
muchas cosas. Se puede mejorar rápidamente con algo sencillo: los modificadores.

Uso de las variables modificadas


Smarty ofrece alrededor de 20 modificadores, con ayuda de los cuales se puede cambiar la
apariencia de las variables, pero no sólo eso. Para aplicar un modificador en una variable se
utiliza el esquema:

{$variable_name|modifier_name}

Algunos de los modificadores pueden tener parámetros que deben ser proporcionados al
llamarlos. Si existiera la necesidad de añadir un parámetro a un modificador, se puede hacer
mediante el siguiente esquema:

{$variable_name|modifier_name: parameter1:parameter2}

El parámetro puede ser una cadena o un valor numérico. En el primer caso, se deben colocar
entre comillas. ¿Qué modificadores serían de utilidad para el ejemplo? Nótese que no todos los
fragmentos del título del álbum empiezan con mayúsculas. Podría ser un dato erróneo en la base
de datos, pero eso es irrelevante para un diseñador. Este valor de la variable fue transferido a la
plantilla y se debe usar tal y como viene. Para eliminar este problema, se añade el modificador
capitalize a la variable $albumTitle. Este hará que cada palabra en la variable dada empiece con
mayúscula.

Otro punto que merece la pena subrayar, es el índice de canciones. Se ha supuesto que es
porporcionado en forma de una variable escalar, donde los títulos son separados por punto y
coma. Desde luego, sería más cómodo almacenarlos en un array, pero esto lo veremos más tarde.
Ahora debemos intentar formatear la lista que llega de esta forma. Para empezar, emplearemos el
modificador replace, que busca en la variable una cadena y la cambia por otra. En este caso, el
modificador que requiere dos parámetros. El primero de ellos es la cadena a buscar y el segundo
– la cadena a introducir. Se van a cambiar los puntos y comas en la variable $albumSongs por

Desarrollo de Aplicaciones Web Dinámicas - UNED


PLANTILLAS DE DISEÑO SMARTY 28.19

tags <br/>. De este modo se obtendrá la lista de canciones, cuyos títulos serán colocados uno
debajo del otro.

El último punto será ajustar el párrafo con la descripción del disco. Para este propósito se debe
utilizar el modificador wordwrap, el cual ajusta la cadena a un ancho determinado. El
modificador posee tres parámetros. El primero de los parámetros indica el ancho al cual el texto
se debe ajustar (por defecto son 80 caracteres), el segundo, define el símbolo que servirá para
ajustar el texto (por defecto es \n), el tercer parámetro indica si el texto debe ser ajustado al final
de la palabra o si la palabra puede ser dividida en dos partes (la primera opción es la que está por
defecto).

La plantilla con cambios se presenta en el Listado 3.

Listado 3: Plantilla album.tpl después de agregar los modificadores

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="content-type" content="text/html; charset=iso-8859-2" />

<meta name="description" content="Discografía del conjunto The Beatles" />

<title>{$albumName|capitalize}</title>

</head>

<body>

<h3>{$albumName|capitalize}</h3>

<table>

<tr>

<td style="vertical-align: top"><img src="{$albumCover}" alt="" /></td>

<td><b>Índice de canciones:</b><br />{$albumSongs|replace:";":"<br />"}</td>

</tr>

</table>

<h4>Descripción del álbum:</h4>

<p>{$albumSynopsis|wordwrap:100:"<br />"}</p>

<p><a href="">Página principal</a></p>

</body>

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.20 PHP AVANZADO

</html>

Funciones especiales de Smarty


Smarty tiene muchas funciones útiles, las cuales se pueden utilizar directamente en la plantillas.
Tienen una estructura y construcción diferente a sus correspondientes de PHP. Primero, los
nombres de las funciones son colocados (así como las variables) entre claves. Segundo: los
parámetros no se colocan entre paréntesis, sino se escriben en forma idéntica como se hace con
los atributos en HTML – colocando el nombre y el valor después del signo de igualdad.

La función include() aplicada en PHP que en el script tomaría la forma:

include ("file.txt");

mientras que en la plantilla de Smarty se vería así:

{include file="file.txt"}

Además, ciertas funciones tienen etiquetas de apertura y cierre, por ejemplo, {literal} presentada
anteriormente. Como ya se conoce la información básica sobre las funciones, se pueden aplicar
en la plantilla de ejemplo.

A continuación se va a modificar la plantilla para transferir la lista de canciones en forma de


tabla, y no de cadena. El índice de canciones se ubica en un array asociativo, donde las claves
indican el título de la canción, y el valor – el tiempo de duración (esto requiere cambios dentro
del archivo title.php) Para leer los datos de un array de este tipo, se usará la función {foreach}, la
cual genera un bucle, que recorrerá consecutivamente todos los elementos del array.

Listado 4: Fragmento modificado de la plantila album.tpl

...

<table>

<tr>

<td style="vertical-align: top"><img src="{$albumCover}" alt="" /></td>

<td><b>Índice de canciones: </b><br />

{foreach key="songTitle" item="songTime" from=$albumSongs name="songs"}

{$smarty.foreach.songs.iteration}. {$songTitle} {$songTime}<br />

{/foreach}</td>

<td><b>Aporta la calificación sobre el álbum:</b><br />

<form method="get" action="vote.php">

{html_options values=$points output=$points name="points"}<br />

<input type="submit" value="Vota" />

Desarrollo de Aplicaciones Web Dinámicas - UNED


PLANTILLAS DE DISEÑO SMARTY 28.21

</form>

</tr>

</table>

...

Si se analiza el código del Listado 4, se pueden ver claramente los efectos de las modificaciones
y el uso de las funciones utilizadas en la plantilla. Para empezar, se abre la función y se definen
sus parámetros. El primero de ellos (key) define una variable a la que se asignará la clave del
elemento actual del array, mientras que el segundo (item) es una variable a la que se asignará el
valor del elemento. El siguiente atributo (from) es el nombre del array que se usará en el
recorrido. El último (name) define el nombre asignado al bucle (no es imprescindible, pero puede
ser de utilidad para ser referenciado en otras funciones). En la siguiente parte del código, se
realiza la visualización de las variables, introduciendo simplemente sus nombres a la plantilla.
Conviene prestar atención a la primera variable – {$smarty.foreach.songs.iteration}. Es una
variable de entorno que permite obtener el número de iteración actual. Al final se cierran las
etiquetas de las funciones. De esta forma sencilla se obtuvo, al mismo tiempo, el índice
numerado de canciones junto con sus tiempos de duración – todo gracias a tres líneas de código.

Se pueden añadir elementos extras a la página de ejemplo, por ejemplo una calificación del
álbum. Para este propósito se necesita definir una forma para votar, además del script
correspondiente que contará los votos y almacenará los resultados. La forma más sencilla es
insertar una combo box en la página, que ocupa menos espacio que los campos de selección.
Supongase que a cada disco se le va a asignar el rango de calificaciones del 1 al 6. Para generar la
lista y el formulario, se podría escribir un script en PHP, pero Smarty es capaz de realizar esta
acción.

La lista completa será creada con la ayuda de la función llamada {html_options}. La función
tiene tres parámetros interesantes. El primero es values, al que hay que asignarle un array con
valores que serán las opciones de la lista. El segundo es el output, que también exige un array que
contenga elementos desplegados en la lista. El último atributo es name, que define el nombre de
la lista. Todo el código que crea el formulario se presenta en el Listado 4.

Solo falta una cosa para que la combo box pueda funcionar correctamente: el array con las
calificaciones (para definir los valores y nombres de las posiciones de la lista utilizaremos los
mismos datos). Se debe definir en el archivo title.php con la ayuda del método assign.

Variables de entorno
La variable {$smarty} es una variable reservada. Gracias a ella se dispone de acceso a mucha
información sobre los temas de Smarty, por ejemplo, el nombre de la plantilla procesada
actualmente, y no sólo eso. Con su ayuda se reciben diferentes variables de entorno. Si se quiere
desplegar el valor de la variable $id, que fue transferida por el navegador por medio del método

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.22 PHP AVANZADO

POST, es suficiente escribir {$smarty.post.id}. Si se aplica este esquema de manera analóga es


sencillo tener acceso a la información sobre el servidor (por ejemplo,
{$smarty.server.SERVER_NAME}), sesión (por ejemplo, {$smarty.session.id}), etc.

Una variables muy interesante: {$smarty.now}, en la que se almacena la fecha y el tiempo actual
del sistema en formato de tiempo Unix.

Archivos de configuración
Los archivos de configuración son ideales para definir variables que serán usadas en varias
plantillas. Por ejemplo, supongase que se quiere que en el título del navegador siempre aparezca
el texto “Super página sobre The Beatles”. Para este propósito se puede crear un archivo de
configuración llamado title.conf y se almacena en el directorio /configs (por defecto, Smarty
carga de ahí los archivos de configuración). Se añade una variable en él de la siguiente manera:

pageTitle = "Super página sobre The Beatles"

El nombre de la variable no inicia con el signo de dólar, y al final no hay un punto y coma. Todo
debe estar escrito en una sola línea. La forma de llamar una variable del archivo de
configuración, dentro de una plantilla, no es muy común. Para este propósito se sitúa su nombre
entre el símbolo hash (#), por ejemplo

<title>{#pageTitle#}</title>

Pero antes de insertar la variable dentro de la plantilla, se debe cargar en ella el archivo de
configuración, con la ayuda de la función {config_load}. La función tiene el atributo file, cuyo
valor es el nombre del archivo. Recordad que es suficiente dar sólo su nombre, para que Smarty
lo busque automáticamente dentro del directorio /configs.

Conviene mencionar que en los archivos de configuración se pueden emplear los comentarios
disponibles en PHP. El otro punto importante es la forma de almacenar las variables, las que
sobrepasen la longitud de una línea. En este caso, se deben encerrar entre un triplete de comillas,
por ejemplo:

foo = """Ejemplo de una variable larga"""

Uso de filtros
En Smarty, los filtros están divididos en 3 grupos: Prefilters (cambian el contenido de la plantilla
antes de que haya sido compilada), Postfilters (modifican la plantilla después de la compilación)
y Output Filters (son ejecutados en el momento de la invocación de la llamada de la plantilla
existente, con la ayuda del metodo display). Los filtros se pueden colocar dentro de las plantillas
de dos formas: cargar un filtro ya creado o registrar uno nuevo en un archivo PHP. En primer
lugar se va a describir este segundo método.

Un filtro no es otra cosa que una función desarrollada en php que debe tener dos parámetros:
$tpl_source (en el caso de los filtros del tercer grupo es $tpl_output) y &$smarty. Como se

Desarrollo de Aplicaciones Web Dinámicas - UNED


PLANTILLAS DE DISEÑO SMARTY 28.23

pueden imaginar fácilmente, el primero de ellos es el contenido de la plantilla, y el segundo – el


objeto smarty. Exploremos el caso de postfilters, el cual quedó presentado en el Listado 6.

Listado 6: Archivo title.php después de la modificaciones

<?

require ("Smarty.class.php");

$smarty = new Smarty;

$smarty->assign("albumName", "Sgt. Pepper's lonely hearts club Band");

$smarty->assign("albumCover", "grafika/sgtpep.jpg");

$smarty->assign("albumSongs",array(

"Sgt. Pepper's Lonely Hearts Club Band" => "(2:02)",

"With A Little Help From My Friends" => "(2:44)",

"Lucy In The Sky Of Diamonds" => "(3:28)", "Getting Better" => "(2:47)",

"Fixing A Hole" => "(2:36)", "She's Leaving Home" => "(3:35)",

"Being For The Benefit Of Mr. Kite!" => "(2:37)",

"Within You, Without You" => "(5:05)", "When I'm Sixty-Four" => "(2:37)",

"Lovely Rita" => "(2:42)", "Good Morning, Good Morning" => "(2:41)",

"Sgt. Pepper's Lonely Hearts Club Band (Reprise)" => "(1:18)",

"A Day In The Life" => "(5:33)"));

$smarty->assign("albumSynopsis", "El álbum más famoso del conjunto y uno de los


mejores en la historia de la música. Novedoso, genial – una verdadera obra de arte. El disco
fue introducido al mercado en 1967 y se convirtió en uno de los símbolos de esa época.");

$smarty->assign("points", array("1", "2", "3", "4", "5", "6"));

function footer($tpl_source, &$smarty) {

return $tpl_source."\n\n<p><a href=\"\">Página principal</a></p>

\n\n</body>\n</html>";

$smarty->register_postfilter("footer");

$smarty->display("album.tpl");

?>

La función footer() se emplea para de colocar un pie de página en la plantilla. En este caso es
solamente un enlace a la página principal y las etiquetas de cierre </body> y </html>. Desde

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.24 PHP AVANZADO

luego, el pie de página es colocado después del contenido de la plantilla. Luego de definir la
función, se debe registrar como filtro mediante el método register_postfilter.

Por supuesto, sería más efectivo almacenar el filtro en un archivo separado, y después, cargarlo
directamente en la plantilla.

28.2.5 OPCIONES AVANZADAS DE SMARTY


Smarty también ofrece algunas opciones avanzadas, que pueden resultar interesantes durante la
creación de plantillas. Cada una está desactivada por defecto y se activa estableciendo el valor en
la variable adecuada del archivo Smarty.class.php a true (verdadero) ó 1. También pueden ser
definidas, una sola vez, dentro del documento con la ayuda del esquema

$smarty->variable=value,

donde variable es el nombre de la variable, y value es su valor.

Debugging Console (consola de depuración)


Es una consola, que tiene como fin ayudarnos eliminar errores los que podríamos encontrar en el
momento de la creación de plantillas con ayuda de Smarty. Después de su ejecución, durante la
visualización del documento que utiliza Smarty, debe abrirse una nueva ventana del explorador,
en la que serán enumeradas todas la plantillas, además de las variables que se hayan utilizado en
el documento junto con sus valores.

La forma más sencilla de ejecutar la consola es establecer el valor adecuado en la variable


$debugging, lo que indica que ésta será desplegada siempre al abrir el documento. Por motivos
obvios, es una buena solución sólo durante la etapa de creación de la página. Si se desea tener la
posibilidad de decidir si se quiere utilizar dicha consola siempre, es suficiente establecer el valor
de la variable $debugging_ctrl en el valor URL. En tal caso, la ventana de la consola se abrirá si
se añade la variable SMARTY_DEBUG en la dirección URL de la página a abrir, por ejemplo:
http://localhost/title.php?SMARTY_DEBUG.

Para terminar, hay que recordar que la propia consola se basa en la plantilla debug.tpl que se
encuentra en la librería de archivos Smarty. Se puede modificar para que el aspecto de la consola
concuerde con las necesidades de los probadores de código. Por otro lado, si se quisiera pasar la
plantilla de la consola a otro lugar, se debería cambiar el valor de la variable $debug_tpl.

Modo seguro
Se puede ejecutar Smarty de modo seguro o, como lo define la documentación, con la variable
$security activada. Si se modifica su valor a true (verdadero), entonces Smarty activa el modo
seguro pero con algunas limitaciones relacionadas con su funcionamiento. No se puede utilizar el
código PHP directamente en las plantillas, los archivos externos podrán ser cargados solamente
desde ciertas localizaciones, además, en modificadores e instrucciones if podrán usarse las
funciones de PHP, únicamente si han sido definidas con anterioridad. Al modo seguro se ligan

Desarrollo de Aplicaciones Web Dinámicas - UNED


PLANTILLAS DE DISEÑO SMARTY 28.25

dos variables más: la primera de ellas es $secure_dir, que representa el array que define el
conjunto de directorios seguros; la segunda es $security_settings, que define el conjunto de
funciones seguras de PHP.

Caché
Como se mencionó al principio del artículo, Smarty compila las plantillas y las almacena en
directorios separados con el fin de mejorar su funcionamiento. La segunda propiedad que acelera
el despliegue de las plantillas es el uso de la caché. Para activarlo, se puede abrir el archivo
title.php y añadir en él la siguiente línea

$smarty->caching=true;

y luego actualizar la página en el navegador. Smarty almacenará el contenido del documento


completo dentro del directorio /cache. En la siguiente llamada, éste no será creado
dinámicamente, sino que de manera automática utilizará el resultado preparado dentro del
directorio /cache. ¿Durante cuánto tiempo? Una hora, ese es el lapso de tiempo, definido en la
variable $cache_lifetime; dicho archivo debe ser almacenado en la caché. Obviamente, se puede
cambiar el valor globalmente dentro del archivo Smarty.class.php o en el documento por medio
de la declaración $smarty->cache_lifetime=seconds, donde seconds es el período en segundos,
durante el cual el archivo debe mantenerse almacenado.

¿Qué sucede en caso de que durante el lapso de tiempo definido por la variable, se realice un
cambio en la plantilla o en cualquier otro archivo que sea utilizado por el documento? Entonces
en el explorador todavía aparecerá el contenido del archivo almacenado en la caché. Para que los
cambios se reflejen enseguida se puede establecer el valor true a la variable $compile_check. En
ese caso, si Smarty descubre que la plantilla o cualquier otro archivo ha sido modificado, el
contenido de la memoria caché se crea de nuevo.

No es la solución ideal y por eso Smarty también ofrece la posibilidad de almacenar sólo una
parte de la página.

28.2.6 EJERCICIOS
Para la realización de los ejercicios es muy importante que lea la documentación disponible en
http://smarty.php.net/manual/es/

1.- Suponer que se dispone de una tienda virtual donde se venden una serie de productos que
tienen características comunes: identificador (no se mostrará) , nombre, descripción, lista de
características, imagen, unidades disponibles, días aproximados de envío del producto,
fechas inicial y final de disponibilidad. Diseñe una plantilla smarty capaz de mostrar todas
las propiedades del producto empleando las técnicas mostradas en la introducción teórica
(uso de modificadores y funciones). Suponga que el nombre y la descripción son cadenas de
texto, la lista de características un array, las unidades disponibles y los dias aproximados son
enteros y las fechas cadenas de texto con un representación de formato AÑO (4 digitos) -

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.26 PHP AVANZADO

Mes (2 dígitos) - Día (2 dígitos). El nombre se debe mostrar en mayúsculas, la descripción y


lista de características en minúsculas (excepto la primera palabra que tendrá la primera letra
en mayusculas), la imagen se mostrará en una ventana emergete (puede usar la función
popup de Smarty), las unidades y días tendrán asociados colores (si hay unidades disponi-
bles usar el verde para la fuente y en caso contrario rojo y lo mismo cuando se puede indicar
la disponibilidad del producto o no) y las fechas se mostrarán con el formato “día” de “més
“ de “año” (use el modificador date_format o alguna de las fórmulas indicadas en http://
smarty.php.net/manual/es/tips.dates.php). Deberá también escribir un script php que genere
las variables necesarias para el template en el formato indicado arriba.

2.- En una tienda virtual existen varios roles de usuarios que pueden realizar diferentes
acciones, tal y como se muestra en la Tabla 2.1. Diseñar las plantillas necesarias que depen-
diendo del tipo de rol, muestren en un menú ubicado en la parte superior las opciones dis-
ponibles para cada tipo usuario. Escriba un script php que permita seleccionar el tipo de rol
y a continuación muestre su plantilla correspondiente.
Función Administrador Comprador Vendedor Anónimo
Añadir categoría Sí No No No
Editar categoría Sí No No No
Eliminar categoría Sí No No No
Añadir Producto Sí No Sí No
Editar producto Sí No Sí No
Eliminar Producto Sí No Sí No
Añadir Producto Carrito No Sí No No
Ver Carrito No Sí No No
Eliminar Producto Carrito No Sí No No
Buscar Productos Catálogo Sí Sí Sí Sí
Listar Productos Catálogo Sí Sí Sí Sí

Tabla 28.1 Ejemplo de tabla de autorización por perfiles

3.- Si se analiza la acción “Ver un producto” de una tienda virtual se puede concluir que depen-
diendo del tipo de rol es posible asociar otros tipos de acciones. Un administrador o el vend-
edor de dicho producto podrá también Editar o Eliminar el producto y Un comprador podrá
adicionalmente Añadir el producto al carrito. Crear las plantillas necesarias que, usando la
plantilla del primer ejercicio como base, añada las acciones correspondientes al rol (selec-
cionable mediante el script del ejercicio anterior, que se debe reutilizar). Se pueden ubicar
en la parte superior de lo que sería “la ficha” del producto.

4.- Generar una estructura HTML que tenga una cabecera, un menú izquierdo, el contenido
central y un pie de página mediante plantillas Smarty (emplee la técnica de filtros mostrada
en la parte teórica). La cabecera debería mostrar la hora y fecha actual (use la función
Smarty correspondiente) y permitir seleccionar el tipo de rol empleado en la tienda virtual,
el menú izquierdo una lista de 10 productos que al ser seleccionados hace que se muestre en

Desarrollo de Aplicaciones Web Dinámicas - UNED


XML 28.27

el contenido central la ficha del producto (generada en el ejercicio 3) y el pie de página debe
mostrar el nombre de los productos mostrados.

28.3 XML

28.3.1 INTRODUCCIÓN A XML


XML (eXtended Markup Language) nació en 1998 como un proyecto del consorcio World Wide
Web y se definió como un meta-lenguaje, es decir, un lenguaje para especificar o definir otros
lenguajes, diseñado para facilitar el intercambio de documentos estructurados sobre Internet. Es
un lenguaje basado en etiquetas (tags) que se usa para describir, organizar y jerarquizar datos
mediante dichas etiquetas. Se puede entender como un lenguaje de metadatos, ya que permite
describir la estructura del documento que utiliza dicha sintaxis.

La utilización de las etiquetas en XML implica que un documento XML tenga un aspecto similar
a un documento HTML. Sin embargo este último sólo se encarga de definir cómo se va a
presentar la información del documento, mientras que XML se centra en describir la estructura
de los datos. En sentido estricto, un documento XML es simplemente un documento de texto
plano al que se le añaden etiquetas, proporcionando estas etiquetas un mecanismo muy poderoso
para definir la semántica de cualquier documento.

El origen de XML se remonta a finales de los años sesenta, cuando un grupo de investigadores se
empezó a preguntar si podría ser interesante dar usos alternativos a los documentos electrónicos.
En particular, IBM pidió a Charles Goldfarb que construyese un sistema para almacenar, buscar,
gestionar y publicar documentos. El resultado de su trabajo fue el lenguaje SGML (Standard
Generalized Markup Language).

SGML es un lenguaje de especificación de documentos “generalizado”, “estructurado” y


“etiquetado”. El término “etiquetado” se debe al empleo de etiquetas para describir la
“estructura” del documento. El término "generalizado" se refiere a que el etiquetado debe
describir la estructura de un documento y otros atributos. SGML es un estándar internacional, no
propietario y abierto, que proporciona un método para la descripción de la estructura de un
documento basándose en la relación lógica de sus partes. Además especifica una codificación
estándar para la transmisión de documentos entre sistemas computacionales diferentes: distintas
plataformas, soportes físicos, lógicos y diferentes sistemas de almacenamiento y presentación,
con independencia de su grado de complejidad. XML es un subconjunto de SGML pensado para
ser utilizado como modelo de intercambio de datos en Internet.

Del trabajo de Goldfarb y otros investigadores de IBM se extrajeron tres conclusiones


importantes:

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.28 PHP AVANZADO

1.- Para intercambiar información los programas tienen que soportar un lenguaje común. Tiene
sentido que ese lenguaje común sea algún tipo de lenguaje de marcas.

2.- La estructura de un documento se puede ver como una jerarquía de elementos. Por ejemplo,
un correo electrónico tiene, en un primer nivel, un elemento "encabezado" y un elemento
"cuerpo". El encabezado puede contener, a su vez, elementos "destinatario", "asunto", etc.
Las marcas que delimitan estos elementos se denominan marcas estructurales generalizadas
(eStructural Generalized Markup).

3.- Los documentos tienen que seguir algún tipo de reglas, es decir, el lenguaje de marcas
debería ser especificado de algún modo formal que permitiese garantizar que el documento
cumple cierta estructura. Esto facilita al dispositivo visualizador la manipulación de los
datos y la realización de cálculos a partir de ellos.

De la lectura de estas tres conclusiones se deduce que es necesario implementar algún


mecanismo que aune las tres. Una forma conveniente de hacerlo es definir el tipo del documento
recurriendo a un lenguaje de marcas que estructure la información de forma jerárquica en
elementos. En XML esto se realiza mediante un documento descriptivo del tipo de documento,
denominado DTD (Document Type Definition), y que utiliza su propio lenguaje de marcas. Una
vez que se tiene definido un tipo de documento, es necesario definir cómo se va a presentar la
información del documento en un dispositivo de visualización (por ejemplo, una pantalla de un
ordenador). Esta descripción se recoge en lo que se denomina una hoja de estilo.

De lo expuesto anteriormente se desprende que la idea central de la solución propuesta por


Goldfarb es mantener separados los tres aspectos de un documento: contenido, estructura y
presentación. Esta aproximación presenta varias ventajas importantes:

1.- Permite al dispositivo visualizador hacer el trabajo de presentación de los datos en la pan-
talla.

2.- Facilita al dispositivo visualizador la manipulación de los datos y la realización de cálculos


a partir de ellos.

3.- Posibilita realizar búsquedas de información "inteligentes".

4.- Fomenta la creación de vocabularios (marcas) específicos en diferentes dominios, como los
bancos, las telecomunicaciones, el transporte o la ingeniería de sistemas (por ejemplo
daqXML, AIML o VIML).

La característica principal del uso de documentos XML es la capacidad de definir los datos de
forma independiente a su presentación. En otros lenguajes de marcas, como por ejemplo HTML,
la propia definición de los datos en el documento lleva implícita la forma de presentar la
información. En el caso de XML es posible definir la estructura de los datos (normalmente
jerárquica) y posteriormente recurrir al modulo de transformación para obtener la presentación
adecuada al dispositivo donde se visualizará la información.

Desarrollo de Aplicaciones Web Dinámicas - UNED


XML 28.29

El uso más típico de esta característica es un tipo de transformación denominado XSLT


(eXtensible Stylesheet Language family Transformation). Consiste en la utilización de una hoja
de estilo basada en el estándar XSL (eXtensible Stylesheet Language) que especifica la
presentación de un documento XML de una clase concreta que viene determinada por su DTD.
Esta hoja de estilo describe cómo dicha instancia de la clase (el documento XML en particular)
se transforma en un documento XML que usa un vocabulario específico de formateo o
presentación (marcas), como por ejemplo HTML o XHTML. De esta manera, aplicando una
transformación XSLT a un documento XML se obtiene un documento HTML o cualquier otro
tipo de documento de presentación, como PDF o PostScript.

Los documentos XML están compuestos por caracteres del conjunto Unicode que se combinan
en cadenas de texto. La sintaxis de XML describe la forma de concatenar dichas cadenas de texto
para crear documentos XML bien formados. Las características sintácticas más significativas de
un documento XML son:

1.- Se distinguen mayúsculas y minúsculas. No es lo mismo la cadena ELEMENT que element.

2.- Las etiquetas se delimitan con '<' y ‘>’ o por '&' (al igual que ocurre en HTML).

3.- Los blancos son el espacio (ASCII 32), el tabulador (ASCII 9), el retorno de carro (ASCII
13) y el carácter de línea nueva (ASCII 10).

4.- Los literales aparecen rodeados de comillas simples o dobles. Por ejemplo, si se desea que
un atributo tenga un valor determinado el literal que define ese valor se debería escribir
como nombre_atributo=”valor”.

5.- Los nombres que se pueden utilizar para designar elementos XML deben empezar por letra,
'.' o '_', e ir seguidos de letras, dígitos, '-', '_', '.' y ':'.

Los documentos XML están divididos en dos partes principales: una cabecera y una instancia de
documento. La cabecera está compuesta de una declaración XML y una declaración de tipo de
documento, siendo ambas opcionales. En el Listado 3.3 se presenta un ejemplo de documento
XML, donde la cabecera corresponde a las líneas 1 y 2. En la primera línea se indica la versión
de la especificación XML y en la segunda que la instancia del documento declarará los datos de
acuerdo al tipo de documento holamundo definido en el fichero holamundo.dtd.

Listado 7: Archivo holamundo.dtd

1: <?xml version="1.0"?>

2: <!DOCTYPE holamundo SYSTEM "holamundo.dtd">

3: <holamundo>

4: <saludo>Hola mundo</saludo>

5: </holamundo>

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.30 PHP AVANZADO

La instancia del documento se sitúa inmediatamente después de la cabecera (líneas 3, 4 y 5) y


contiene los datos del documento. Estos datos pueden presentar restricciones estructurales en la
forma en que se definen siempre y cuando en la cabecera se haya declarado el documento de
definición de tipo.

28.3.2 MANIPULACIÓN DE DOCUMENTOS XML MEDIANTE PHP


En la sección anterior se presentaron los conceptos básicos sobre documentos XML, y una vez
conocida la estructura de dichos documentos es necesario aprender a manipularlos mediantes
técnicas de programación. Para ello es imprescindible leer el capítulo 8 del libro:

Fundamentos de PHP 5

que se envió anteriormente. En el dicho capítulo se detallan los mecanismos que posee el
lenguaje PHP (tanto en sus versiones 4.x como las 5.x) para analizar documentos XML de
acuerdo a su definición de tipos (DTD o Schema) y generar nuevos documentos con ese formato.
Es especialmente interesante el estudio de las funciones del API de procesamiento XML de PHP
5.x ya que introducen mecanismos simples de realizar las tareas más habituales con documentos
PHP.

Ejercicios

1.- Crear un script PHP capaz de leer un documento XML proporcionado por el navegador cli-
ente (use un botón de carga de fichero para enviar el documento al servidor) e indique si el
documento esta bien formado o no. Como sugerencia, defina una clase AnalizadorPHP con
las propiedades y métodos que crea necesarios.

2.- Modificar el script anterior para que sea capaz de analizar documents XML que tengan aso-
ciados DTDs o Schemas e indiquen si se cumple la especificación de estructura correspondi-
ente. En caso de ser así debe mostrar los errores de análisis encontrados durante la operación
con el formato Linea X: Tipo de error. Como sugerencia, defina una clase hija de la anterior
y añada las propiedades y métodos necesarios.

3.- Genere un script que sea capaz de representar en un formato jerarquico de tipo árbol la
estructura de un documento XML. Puede usar la extensión PEAR que se analiza en el Capí-
tulo 14 del libro Fundamentos de PHP(del que ya dispone) y que proporciona una vista vis-
ual de un árbol de datos. Este ejercicio tiene por tanto dos objetivos: crear una
representación visual de un documento XML y enseñarle que es PEAR y cómo instalar
extensiones de PHP.

4.- Cree un script que permita modificar (añadir, cambiar o eliminar) nodos y atributos de un
documento XML. Use el código desarrollado en el ejercicio anterior para disponer de la
estructura del documento en un marco situado a la izquierda y las acciones a realizar sobre
el documento (añadir, cambiar o eliminar nodos y añadir, cambiar o eliminar atributos de un
nodo) en un marco situado a la derecha.

Desarrollo de Aplicaciones Web Dinámicas - UNED


XML 28.31

5.- Cree un editor de documentos XML mediante PHP empleando el código desarrollado en los
ejericios anteriores. Es decir, el editor podrá cargar documentos XML que se podrán modi-
ficar y almacenar posteriormente en el ordenador del cliente. Además deberá poder crear
documentos XML y validar la estructura del documento respecto de un DTD o Schema
externo.

Desarrollo de Aplicaciones Web Dinámicas - UNED


28.32 PHP AVANZADO

Desarrollo de Aplicaciones Web Dinámicas - UNED

También podría gustarte