Вы находитесь на странице: 1из 296

2010 / ???

Experto en Desarrollo de Soluciones Corporativas en Software Libre

Desarrollo de Aplicaciones Web avanzadas con PHP y MySQL


Copyright (c) 2010 (Daniel Gonzlez Zaballos y David Vaquero Santiago)

Financiado por:

Impartido por:

Espacio para el logotipo del centro de formacin

LICENCIA CREATIVE COMMONS

Reconocimiento-Compartir bajo la misma licencia 3.0 Espaa

Usted es libre de: copiar, distribuir y comunicar pblicamente la obra hacer obras derivadas Bajo las condiciones siguientes:

Reconocimiento Debe reconocer los crditos de la obra de la manera especificada por el


autor o el licenciador (pero no de una manera que sugiera que tiene su apoyo o apoyan el uso que hace de su obra).

Compartir bajo la misma licencia Si transforma o modifica esta obra para crear una obra
derivada, slo puede distribuir la obra resultante bajo la misma licencia, una de similar o una de compatible.

Entendiendo que:

Renuncia Alguna de estas condiciones puede no aplicarse si se obtiene el permiso del titular
de los derechos de autor

Dominio Pblico Where the work or any of its elements is in the public domaine under
applicable law, that status is in no way affected by the license.

Otros derechos Los derechos siguientes no quedan afectados por la licencia de ninguna
manera: Los derechos derivados de usos legtimos u otras limitaciones reconocidas por ley no se ven afectados por lo anterior.

Los derecho morales del auto;


Rights other persons may have either in the work itself or in how the work is used, such as publicity or privacy rights.

Aviso Al reutilizar o distribuir la obra, tiene que dejar bien claro los trminos de la licencia de
esta obra.

INDICE

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Contenido

Pg.

1. CUESTIONES PREVIAS ....................................................................... 1 2. DESCRIPCIN DE LA ARQUITECTURA APACHE, PHP Y MYSQL... 3


2.1. Introduccin a la plataforma LAMP..................................................................3 2.1.1. Principios de la arquitectura cliente servidor................................................3 2.1.2. Tipos de Arquitectura Cliente Servidor.........................................................4 2.2. La Arquitectura LAMP........................................................................................4 2.2.1. Introduccin a LAMP ....................................................................................4 2.2.2. Glosario de Trminos ...................................................................................4 2.2.3. Elementos de la Arquitectura LAMP ............................................................5 2.2.4. Proceso de una Peticin LAMP....................................................................6 2.3. Pasos de la Instalacin de un Entorno LAMP.................................................7 2.3.1. Instalacin y configuracin o acceso a un Servidor DNS ............................7 2.3.2. Instalacin y configuracin de un SGBD: Mysql ..........................................8 2.3.3. Instalacin y configuracin de una aplicacin LAMP ...................................8

3. INTRODUCCIN A LA INSTALACIN DE LAMP................................ 9


3.1. Introduccin........................................................................................................9 3.2. Configuracin de Servicios LAMP ...................................................................9 3.2.1. Configuracin de un Servidor DNS ..............................................................9 3.2.2. Configuracin de un dominio DNS ...............................................................9 3.3. Instalacin de LAMP ........................................................................................10 3.3.1. Instalacin de *AMP en Windows con XAMPP ..........................................10 3.3.2. El panel de Control de XAMPP ..................................................................10 3.3.3. Instalacin de una LAMP en OpenSuse 10.2 ............................................11

4. HERRAMIENTAS DE DESARROLLO DE PROYECTOS PARA PHP 15


4.1. Eclipse y extensiones ......................................................................................15
IND-I

INDICE

4.1.1. Eclipse el IDE ............................................................................................. 15 4.1.2. Instalacin de Eclipse para PHP ................................................................ 15 4.1.3. Gestin de versiones: SVN ........................................................................ 16 4.2. Firefox y sus extensiones ............................................................................... 19 4.2.1. Referencias ................................................................................................ 19 4.2.2. Contenido ................................................................................................... 19 4.2.3. Mysql WorkBench....................................................................................... 21 4.2.4. Publicacin de Cdigo................................................................................ 22

5. PHP BSICO .......................................................................................25


5.1. Estructura bsica de un fichero PHP............................................................. 26 5.1.1. Inclusin de ficheros externos.................................................................... 27 5.2. Elementos del Lenguaje:................................................................................. 28 5.2.1. Variables..................................................................................................... 28 5.2.2. Constantes ................................................................................................. 29 5.2.3. Operadores................................................................................................. 30 5.3. Tipo de datos abstractos: ............................................................................... 32 5.3.1. Manejo de Cadenas de caracteres ............................................................ 32 5.3.2. Manejo de arrays de datos:........................................................................ 36 5.3.3. Variables predefinidas................................................................................ 37 5.4. Estructuras de control:.................................................................................... 38 5.4.1. Sentencias condicionales........................................................................... 38 5.4.2. Switch ......................................................................................................... 39 5.4.3. Bucles......................................................................................................... 40 5.4.4. Break y Continue ........................................................................................ 42 5.5. Funciones ......................................................................................................... 42 5.5.1. mbitos de Variables ................................................................................. 43 5.5.2. Paso de variables ....................................................................................... 45 5.5.3. Recursividad............................................................................................... 46 5.6. Salidas por pantalla ......................................................................................... 46 5.7. Actividades ....................................................................................................... 48
IND-II

INDICE

5.7.1. Tipos de datos, cadenas y arrays. .............................................................48 5.7.2. Estructuras de control.................................................................................49 5.7.3. Funciones ...................................................................................................51

6. FORMULARIOS Y SUS MTODOS .................................................... 53


6.1. GET y POST ......................................................................................................56 6.2. Otros ..................................................................................................................58 6.3. Actividad ...........................................................................................................58

7.BASES DE DATOS RELACIONALES ................................................. 61


7.1. SQL: lenguaje de definicin y manejo de datos ...........................................61 7.1.1. Lenguaje de definicin de datos (LDD) ......................................................62 7.1.2. Lenguaje de manipulacin de datos (LMD)................................................63 7.1.3. Recuperacin de clave ...............................................................................65 7.1.4. Disparadores (Triggers)..............................................................................65 7.2. Integridad referencial.......................................................................................66 7.2.1. Ejemplo: Cmo funciona ............................................................................66

8. ADMINISTRACIN .............................................................................. 69
8.1. Manejo de usuarios..........................................................................................69 8.1.1. Usuarios por defecto ..................................................................................69 8.1.2. Conectarse al servidor MySQL...................................................................70 8.1.3. Privilegios de usuarios................................................................................71 8.2. Manejo de datos ...............................................................................................72 8.2.1. Copias de seguridad...................................................................................72

9.ACCESO A DATOS .............................................................................. 75


9.1. Introduccin......................................................................................................75 9.1.1. Tipos de datos ............................................................................................75 9.2. Acceso a datos .................................................................................................77 9.2.1. Creacin de una tabla ................................................................................77 9.2.2. Eliminar una tabla.......................................................................................78 9.2.3. Modificar la estructura de una tabla ...........................................................78

IND-III

INDICE

9.2.4. ndices de una tabla ................................................................................... 78 9.2.5. Manipulacin de datos ............................................................................... 78 9.2.6. Vistas.......................................................................................................... 80 9.2.7. Sentencias preparadas .............................................................................. 82 9.2.8. Exportacin e importacin de datos ........................................................... 83 9.2.9. Rutinas almacenadas y disparadores ........................................................ 85

10. EJEMPLO Y EJERCICIOS ................................................................91


10.1. Introduccin ..................................................................................................... 91 10.2. Ejercicios .......................................................................................................... 91 10.2.1. Ejercicio 1 - Modelado de la base de datos ............................................... 91 10.2.2. Ejercicio 2 - Creacin de la base de datos en MySQL............................... 92 10.2.3. Ejercicio 3 - Poblar la base de datos en MySQL........................................ 97 10.2.4. Ejercicio 4 - Integridad referencial en MySQL............................................ 99 10.2.5. Ejercicio 5 - Acceso a Datos ...................................................................... 99 10.2.6. Ejercicio 6 - Manejo de vistas................................................................... 101 10.2.7. Ejercicio 7 - Disparadores ........................................................................ 102

11. GESTIN DE FICHEROS ................................................................105


11.1. Recepcin y manejo de ficheros .................................................................. 105 11.1.2. Actividad ................................................................................................... 109 11.2. POO en PHP.................................................................................................... 109 11.2.1. Definicin de Clases, objetos, atributos y mtodos ................................. 109 11.2.2. Manejo de objetos .................................................................................... 111 11.2.3. Actividades ............................................................................................... 112 11.2.4. Uso de la Herencia ................................................................................... 112 11.2.5. Actividades ............................................................................................... 113 11.2.6. Manejo de excepciones............................................................................ 113 11.2.7. Actividades ............................................................................................... 114 11.2.8. Diferencias entre clases abstractas e interfaces...................................... 116

12. DESARROLLO MVC CON PHP ......................................................119


12.1. Qu es MVC?................................................................................................ 119
IND-IV

INDICE

12.2. Porqu utilizar el paradigma MVC?............................................................119 12.3. Empezando a separar nuestro cdigo .........................................................120 12.4. Abstrayndonos del gestor de base de datos ............................................121 12.5. Actividades .....................................................................................................122

13. GESTOR DE PLANTILLAS: SMARTY............................................ 125


13.1.1. Instalacin.................................................................................................125 13.1.2. Bases de smarty.......................................................................................126 13.1.3. Modificadores, funciones, filtros, plugins, estructuras de control.............126 13.1.4. Como usar smarty ....................................................................................127 13.2. Generacin de CSS ........................................................................................129 13.3. Creando layouts .............................................................................................130 13.4. Creando formularios ......................................................................................131 13.4.1. Actividades ...............................................................................................131 13.5. Accesibilidad en Web ....................................................................................132

14. CAPA DE ACCESO A DATOS CON ADODB ................................. 135


14.1. Conexiones a Bases de Datos ......................................................................135 14.2. Generacin de Consultas..............................................................................136 14.2.1. Actividad ...................................................................................................136 14.3. Acceso a los Metadatos ................................................................................137 14.3.1. MetaDatabases() ......................................................................................137 14.3.2. MetaTables($ttype = false, $showSchema = false, $mask=false)...........137 14.3.3. MetaColumns($table,$toupper=true)........................................................137 14.3.4. MetaColumnNames($table)......................................................................137 14.3.5. MetaPrimaryKeys($table, $owner=false) .................................................138 14.3.6. ServerInfo($table).....................................................................................138 14.3.7. MetaForeignKeys($table, $owner=false, $upper=false) ..........................138 14.3.8. FetchField($column_number)...................................................................139 14.4. Ejecucin de Consultas.................................................................................139 14.4.1. Actividad ...................................................................................................140

15. USO DE SERVICIOS DE INTERNET CON PHP ............................. 141


IND-V

INDICE

15.1. Distintos modelos de Servicios Web ........................................................... 142 15.2. Algunos API's WEB accesibles a travs de Internet .................................. 142 15.3. Recursos......................................................................................................... 143 15.4. Actividades ..................................................................................................... 143 15.4.1. Actividad 1 ................................................................................................ 143 15.4.2. Actividad 2 ................................................................................................ 143 15.4.3. Actividad 3 ................................................................................................ 143 15.4.4. Actividad 4 ................................................................................................ 144

16. MANEJO DE USUARIOS/SEGURIDAD ..........................................145


16.1. Autenticacin y Autorizacin ....................................................................... 145 16.1.1. Actividades ............................................................................................... 147 16.2. Manejo de Sesiones....................................................................................... 148 16.2.1. Actividades ............................................................................................... 149 16.3. Manejo de Cookies......................................................................................... 149 16.3.2. Actividades ............................................................................................... 151

17. CONSTRUIR APLICACIONES PHP SEGURAS .............................153


17.1. Tratamiento de imgenes de manera dinmica.......................................... 153 17.1.1. Generacin de captcha para formularios ................................................. 153 17.1.2. Retoque de imgenes .............................................................................. 155 17.1.3. Actividades ............................................................................................... 155 17.2. Bibliotecas de seguridad: IDS ...................................................................... 156

18. OPTIMIZACIN EN PHP .................................................................159


18.1. Procesos a Optimizar .................................................................................... 159 18.2. Buenas prcticas de codificacin ................................................................ 161 18.3. Actividades ..................................................................................................... 162 18.3.1. Actividad 1 ................................................................................................ 162 18.3.2. Actividad 2 ................................................................................................ 162 18.3.3. Actividad 3 ................................................................................................ 162 18.3.4. Actividad 4 ................................................................................................ 162

IND-VI

INDICE

19. FRAMEWORKS DE DESARROLLO EN PHP................................. 163


19.1. Actividades .....................................................................................................164 19.1.1. Actividad 1 ................................................................................................164 19.1.2. Actividad 2 ................................................................................................164 19.1.3. Actividad 3 ................................................................................................164 19.1.4. Actividad 4 ................................................................................................164

20. JAVASCRIPT................................................................................... 165


20.1. Conceptos bsicos ........................................................................................165 20.2. Sintaxis y clases bsicas ..............................................................................165 20.2.1. Incluir scripts en el cdigo HTML .............................................................165 20.3. Elementos del Lenguaje:...............................................................................166 20.3.1. Tipos de datos ..........................................................................................166 20.3.2. Las variables.............................................................................................166 20.3.3. Objetos, Arrays y Funciones ....................................................................167 20.4. Operadores .....................................................................................................167 20.4.1. Operadores Aritmticos............................................................................167 20.4.2. Operadores Binarios.................................................................................168 20.4.3. Operadores Lgicos .................................................................................169 20.4.4. Operadores Varios ...................................................................................171 20.4.5. Funciones Globales..................................................................................171 20.5. Estructuras de control...................................................................................173 20.5.1. Condiciones ..............................................................................................173 20.5.2. Switch .......................................................................................................174 20.5.3. Bucles .......................................................................................................174 20.6. Ruptura de Bucles..........................................................................................175 20.7. Los Objetos de Javascript ............................................................................176 20.7.1. Objeto Object............................................................................................176 20.7.2. Objeto Function ........................................................................................177 20.7.3. Objeto Array..............................................................................................178 20.7.4. Objeto window ..........................................................................................180
IND-VII

INDICE

20.7.5. Objeto document ...................................................................................... 182 20.7.6. Objeto form............................................................................................... 184 20.7.7. Objeto Boolean......................................................................................... 185 20.7.8. Objeto Number ......................................................................................... 186 20.7.9. Objeto String............................................................................................. 186 20.7.10. 20.7.11. 20.7.12. Objeto Date ....................................................................................... 190 Objeto Math....................................................................................... 197 Objeto Regular Expession ................................................................ 199

20.8. Eventos ........................................................................................................... 203 20.8.1. Eventos en JavaScript.............................................................................. 203 20.8.2. Mtodos de evento disponibles en JavaScript......................................... 205 20.9. Actividades ..................................................................................................... 206 20.9.1. Actividad 1 ................................................................................................ 206 20.9.2. Actividad 2 ................................................................................................ 206 20.9.3. Actividad 3 ................................................................................................ 206 20.9.4. Actividad 4 ................................................................................................ 207 20.9.5. Actividad 5 ................................................................................................ 207 20.9.6. Actividad 6 ................................................................................................ 207 20.9.7. Actividad 7 ................................................................................................ 207 20.9.8. Actividad 8 ................................................................................................ 207 20.9.9. Actividad 9 ................................................................................................ 207 20.9.10. 20.9.11. 20.9.12. 20.9.13. 20.9.14. 20.9.15. 20.9.16. 20.9.17. 20.9.18. Actividad 10....................................................................................... 207 Actividad 11....................................................................................... 207 Actividad 12....................................................................................... 208 Actividad 13....................................................................................... 208 Actividad 14....................................................................................... 208 Actividad 15....................................................................................... 208 Actividad 16....................................................................................... 208 Actividad 17....................................................................................... 208 Actividad 18....................................................................................... 208

IND-VIII

INDICE

20.9.19.

Actividad 19.......................................................................................208

20.10.Introduccin a XML ........................................................................................209 20.10.1. 20.10.2. 20.10.3. 20.10.4. 20.10.5. 20.10.6. 20.10.7. 20.10.8. 20.10.9. 20.10.10. 20.10.11. 20.10.12. Historia ..............................................................................................209 Ventajas del XML ..............................................................................209 XHTML ..............................................................................................210 Estructura de un documento XML.....................................................210 Partes de un documento XML...........................................................212 Document Type Definition (DTD) ......................................................213 XML Schemas ...................................................................................215 Extended Style Language (XSL).......................................................217 Xlink, Xpath y Xpointer......................................................................220 SAX y DOM .......................................................................................222 Actividades ........................................................................................226 Referencias .......................................................................................227

21. JAVASCRIPT EN LOS DISTINTOS NAVEGADORES ................... 229


21.1. La propiedad float de CSS.........................................................................229 21.2. Estilos computados de un elemento............................................................230 21.3. Accediendo al class de un elemento........................................................230 21.4. Accediendo al atributo for de las etiquetas <label /> .............................230 21.5. Obtener la posicin del puntero del ratn...................................................230 21.6. Obtener el tamao del navegador o del rea visible ..................................231 21.7. Transparencias...............................................................................................231

22. MANEJO DEL DOM......................................................................... 233


22.1. Creando elementos y textos .........................................................................234 22.2. Usando innerHTML ........................................................................................236 22.3. Eliminando un elemento o nodo de texto....................................................236 22.4. Manipulando los estilos de los elementos ..................................................237 22.5. Actividades .....................................................................................................237 22.5.1. Actividad 1 ................................................................................................238 22.5.2. Actividad 2 ................................................................................................238
IND-IX

INDICE

23.BIBLIOTECAS JAVASCRIPT BSICAS: JQUERY Y MOOTOOLS239


23.2. Validaciones de formularios con JavaScript. ............................................. 240 23.2.1. Validacin con JQuery ............................................................................. 241 23.2.2. Validacin con MooTools ......................................................................... 242 23.3. Manejo dinmico de elementos HTML......................................................... 243 23.4. Actividades ..................................................................................................... 246

24.INTRODUCCIN A AJAX.................................................................247
24.1. Tecnologas incluidas en Ajax...................................................................... 247 24.2. Problemas e Inconvenientes ........................................................................ 248 24.3. Mtodos HTTP ................................................................................................ 248 24.4. Objeto XMLHTTPRequest.............................................................................. 249 24.5. Formatos de intercambio de Informacin ................................................... 252

25. CONSTRUCCIN DE SERVICIOS WEB EN PHP. .........................257


25.1. Introduccin a los servicios web ................................................................. 257 25.1.1. Soap ......................................................................................................... 257 25.1.2. REST ........................................................................................................ 258 25.1.3. En otras palabras ..................................................................................... 258 25.2. Actividad ......................................................................................................... 259 25.3. Desarrollo de servicios web ......................................................................... 259 25.4. Ejemplo de uso de un servicio REST: CRUDL............................................ 263 25.4.1. Listado ...................................................................................................... 273 25.4.2. Mostrado................................................................................................... 273 25.4.3. Insercin ................................................................................................... 274 25.4.4. Modificacin.............................................................................................. 274 25.4.5. Borrado..................................................................................................... 274 25.4.6. Bsqueda ................................................................................................. 275 25.5. Actividades ..................................................................................................... 275 25.5.1. Actividad 1 ................................................................................................ 275 25.5.2. Actividad 2 ................................................................................................ 275

IND-X

INDICE

26.CONSULTA DE SERVICIOS WEB EN JAVASCRIPT: JQUERY .... 277


26.1. Manejo de consultas: uso del objeto XMLHTTPRequest...........................277 26.1.1. Mtodo Open ............................................................................................278 26.2. Importacin y exportacin de datos ............................................................280 26.3. Manejo de los datos y su uso en el DOM ....................................................281 26.4. Actividad .........................................................................................................281

IND-XI

Cuestiones Previas

Cuestiones Previas
En este punto se ver desde la teora hasta la prctica de la puesta en marcha de la Arquitectura *AMP. Porqu llamarla *AMP? La A significa Apache, la M Mysql y la P PHP. Se puede encontrar definido tambin el sistema operativo substituyendo el * por una L (Linux), por una W (Windows) o por una M (Mac OS). Con las siglas completas *AMP, incluira LAMP, WAMP y MAMP. Este curso trata de explicar las cosas comunes y especficas de varias de estas arquitecturas.

Descripcin de la arquitectura Apache, PHP y MYSQL

Descripcin de la Arquitectura Apache, PHP y MYSQL

2.1. Introduccin a la plataforma LAMP


Bienvenidos a esta documentacin sobre La Teora de funcionamiento de la plataforma LAMP. Espero que os sea grata y que os ayude a entender mejor el desarrollo de aplicaciones mediante los ordenadores con GNU/Linux.

2.1.1. Principios de la arquitectura cliente servidor


A fin de poder entender correctamente el comportamiento de la arquitectura LAMP es importante describir el funcionamiento de la arquitectura de aplicaciones ClienteServidor. En Dicha arquitectura disponemos de dos tipos de agentes: Cliente: Ordenador o programa informtico que solicita informacin.

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Servidor: Ordenador o programa informtico que dispone de informacin. Dentro de este tipo de arquitectura podemos definir distintos tipos de Agentes dependiendo del tratamiento que se realice con la informacin: Activo: El Agente realiza un procesado activo de la informacin. Calculo intensivo, clculo de la presentacin grfica de la informacin, acceso a datos son algunas de las tareas tpicas de un Agente Activo. Pasivo: El agente se limita a manejar informacin en bruto o preprocesada.

2.1.2. Tipos de Arquitectura Cliente Servidor


A continuacin se detallan los distintos tipos de Arquitecturas de Cliente - Servidor: Cliente Activo, Servidor Pasivo: El cliente realiza la practica totalidad del trabajo de procesado de la informacin. Ejemplo: Google Earth. Cliente Pasivo, Servidor Pasivo: Tanto el cliente como el Servidor simplemente pasan informacin. Ejemplo: Gateways de comunicaciones VoIP. Cliente Pasivo, Servidor Activo: El Servidor realiza todo el trabajo de procesado y el cliente simplemente presenta los datos. Ejemplo: Servidores de terminales. Cliente Activo, Servidor Activo: Tanto el Servidor como el Cliente procesan la informacin. Ejemplo: Servicios de Correo Electrnico.

2.2. La Arquitectura LAMP


2.2.1. Introduccin a LAMP
Dependiendo de la aplicacin LAMP que el tipo de arquitectura puede variar, pero por simplicidad en el presente manual slo va a tratarse del Tipo Cliente Activo - Servidor Activo.

2.2.2. Glosario de Trminos


A continuacin se detallan un glosario de trminos que permiten entender mejor la arquitectura LAMP: HTML: Hyper Text Markup Language. Lenguaje que permite definir el contenido y su presentacin para que el cliente web permita visualizar la informacin que contiene. Dicho lenguaje permite la inclusin de medios (grficos, sonidos, vdeos, etc.). Etiqueta o TAG: Unidad mnima de representacin en el Lenguaje HTML. Permite definir: prrafos, tablas, enlaces, imgenes, etc... CSS: (Cascading Style Sheets) Hojas de Estilo en Cascada . Permiten generar clases de estilo que se pueden aplicar a etiquetas HTML. Dichas hojas de estilo se pueden definir dentro de los ficheros HTML o incluso referenciarlos. Los TAG permiten agrupar cambios en las propiedades de un determinando TAG. Java Script (JS): Lenguaje de programacin que permite en la parte cliente procesar y realizar cambios en la presentacin. Dichos Scripts suelen estar referenciados desde el fichero HTML.

Descripcin de la arquitectura Apache, PHP y MYSQL

Pgina Web: Unidad de contenido de un servidor web. Normalmente est compuesta de un fichero formateado en HTML y sus referencias. Sitio Web: Conjunto de reglas del Servidor Web y las pginas Web que lo componen. Servicio DNS: Servidor que entre otras funciones permite traducir nombres de mquinas en Internet a direcciones IP. Navegador Web: Cliente que permite consultar a Servidores Web y presentar la informacin HTML. Ejemplos: Firefox, Konqueror, Opera, Internet Explorer, etc. Plugin Web: Extensin de un navegador web que permite aadir una funcionalidad a un navegador web, por ejemplo la visualizacin de elementos no estndar. Ejemplos: Flash Player, JVM, etc. Apache: Servidor Web Libre. Dicho servidor es altamente flexible y actualmente el 60 % de los sitios web funcionan con Apache. Mdulo de Apache: Conjunto de funcionalidades agrupadas que permiten extender el tratamiento de la informacin por parte del servidor Web Apache. URL: Uniform Resource Locator. Definicin del acceso a un recurso. El concepto de URL ha sido incorporado dentro del ms general de URI (Uniform Resource Identifier - Identificador Uniforme de Recurso), pero el trmino URL an se utiliza ampliamente. La URL est dividida en tres partes: Nombre del Servidor Web, Recurso a acceder y Parmetros GET. Mtodo GET: Forma de paso de parmetros mediante URL. Mtodo POST: Forma de paso de parmetros mediante formulario (normalmente). PHP: PHP Hypertext Pre-processor. es un lenguaje de programacin usado generalmente para la creacin de contenido para sitios web. PHP est preparado para funcionar como un mdulo de Apache (y otros servidores Web). Direccin IP: Identificativo nico de un interfaz de red basado en el Protocolo IP. SGBD: Sistema de Gestin de Bases de Datos. Son un tipo de software muy especfico, dedicado a servir de interfaz entre la base de datos, el usuario y las aplicaciones que la utilizan. Se compone de un lenguaje de definicin de datos, de un lenguaje de manipulacin de datos y de un lenguaje de consulta. En los textos que tratan este tema, o temas relacionados, se mencionan los trminos SGBD y DBMS, siendo ambos equivalentes, y acrnimos, respectivamente, de Sistema Gestor de Bases de Datos y DataBase Management System -su expresin inglesa.SQL: Lenguaje de Consulta Estructurado (Structured Query Language). Es un lenguaje declarativo de acceso a bases de datos relacionales que permite especificar diversos tipos de operaciones sobre las mismas. Auna caractersticas del lgebra y el clculo relacional permitiendo lanzar consultas con el fin de recuperar informacin de inters de una base de datos, de una forma sencilla.

2.2.3. Elementos de la Arquitectura LAMP


A continuacin se detallarn los elementos de una arquitectura LAMP: Cliente Web/DNS: Navegador Web. Por ejemplo: Firefox. Servidor DNS: Conversor de nombres a IPs. Por ejemplo: BIND. Servidor Web: Almacn y procesador de la Informacin Web. Apache en nuestro caso. Mdulo de PHP: Mdulo para apache que permite procesar ficheros escritos en el Lenguaje PHP. Por ejemplo: PHP5 Aplicacin LAMP: Conjunto de ficheros PHP que componen una Aplicacin Web. Por ejemplo: PhpMyAdmin
5

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

SGBD: Sistema de gestin de bases de datos que permitir almacenar la informacin dinmicamente. En nuestro caso Mysql.

2.2.4. Proceso de una Peticin LAMP


A continuacin se detallarn los pasos que realizan el cliente y el servidor de una arquitectura LAMP 1. Cliente Web: Solicitud de conversin del nombre de una mquina al Servidor DNS. Por ejemplo: www.google.es 2. Servidor DNS: Recepcin y tratamiento de la solicitud. Una vez recibida la peticin realiza las consultas necesarias para resolver y obtener la direccin IP. 3. Servidor DNS: Devuelve la direccin IP que corresponde al Servidor Web al navegador Web. 4. Cliente Web: Realiza la solicitud de informacin mediante una URL(Mtodo GET) o un formulario (Mtodo POST). Dicha solicitud incluye: la direccin IP del servidor web, el puerto del servidor web, URL y parmetros POST(esta slo en el caso de formularios normalmente). 5. Servidor Web: Control de Acceso, Anlisis de la peticin y localizacin del recurso. 6. Servidor Web: Seleccin del mdulo de PHP para interpretar el fichero PHP elegido. 7. Mdulo de PHP: Ejecucin del programa PHP elegido. 8. Aplicacin PHP: Procesado de los parmetros GET o POST. 9. Aplicacin PHP: Realizacin de las llamadas SQL al Servidor de SGBD. 10. SGBD: Recogida y procesado de la peticin SQL. 11. SGBD: Retorno de los datos solicitados. 12. Aplicacin PHP: Procesado de los datos devueltos por el SGBD y Generacin del HTML resultante. 13. Modulo PHP: Paso del HTML resultante a Apache. 14. Apache: Devuelve el HTML al cliente Web. 15. Cliente Web: Presentacin del HTML resultante, CSS y elementos relacionados y ejecucin del Javascript. A continuacin se puede visualizar un grfico que resume dichos pasos:

Descripcin de la arquitectura Apache, PHP y MYSQL

2.3. Pasos de la Instalacin de un Entorno LAMP


2.3.1. Instalacin y configuracin o acceso a un Servidor DNS
Debido a que la instalacin y configuracin especficas dependen del sistema operativo y la versin escogida, se van a enumerar los pasos necesarios para su configuracin, que son los siguientes: 1. Alta de un dominio. Ejemplo: midominio.com 2. Alta de las mquinas que pertenecen al dominio. Ejemplo: servidor.midominio.com. en este paso se relaciona la direccin IP de la mquina con el nombre dentro del dominio. 3. Alta de los Alias necesarios: www, ftp, correo, etc. Se relacionan los nombre reales de las mquinas con un alias o apodo de la mquina. 4. Esperar de 24 a 48h a que se replique la informacin entre los Servidores DNS de todo el mundo. 5. Realizar una consulta de DNS para ver si ha funcionado correctamente la operacin para cada una de las mquinas y alias creados. 6. Instalacin y configuracin de Apache.

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Debido a que la instalacin y configuracin especficas dependen del sistema operativo y la versin escogida, se van a enumerar los pasos necesarios para su configuracin, que son los siguientes: 1. Configuracin de los parmetros bsicos: Directorio principal de directorio, reglas de acceso por defecto, numero de hijos, memoria ram, nmero mximo de peticiones, etc... 2. Alta y Configuracin de los mdulos bsicos necesarios: redireccin, proxy, configuracin, etc... 3. Prueba de funcionamiento del servidor web con un fichero HTML de ejemplo. 4. Instalacin y Configuracin del mdulo de PHP: inclusin del mdulo, asociacin del tipo de fichero al mdulo, configuracin de tamao mximo de upload, memoria por hilo php, acceso a datos, etc... 5. Alta de un sitio web virtual que permita manejar el sitio principal del dominio. Ejemplo: www.midominio.com relacionado con el directorio /var/www/midominio.com/ 6. Configuracin de las reglas especiales para el sitio principal del dominio: control de acceso, etc. 7. Prueba de funcionamiento de PHP con un fichero de ejemplo.

2.3.2. Instalacin y configuracin de un SGBD: Mysql


Debido a que la instalacin y configuracin especficas dependen del sistema operativo y la versin escogida, se van a enumerar los pasos necesarios para su configuracin, que son los siguientes: 1. Configuracin bsica del servidor Mysql: memoria principal disponible, tipos de tabla disponibles, memoria destinada a cache, etc... 2. Insercin de usuarios bsicos. 3. Creacin de una base de datos de ejemplo. 4. Creacin de una tabla de ejemplo. 5. Modificacin de un usuario para tener acceso a la base de datos creada. 6. Prueba de funcionamiento con un cliente de Mysql.

2.3.3. Instalacin y configuracin de una aplicacin LAMP


Debido a que la instalacin y configuracin especficas dependen del sistema operativo y la versin escogida, se van a enumerar los pasos necesarios para su configuracin, que son los siguientes: 1. Creacin de una base de datos en el servidor para la aplicacin. 2. Colocacin de las tablas principales necesarias para el funcionamiento de la aplicacin LAMP. 3. Instalacin de la aplicacin web en el sitio web principal. 4. Configuracin de la aplicacin web. 5. Prueba de la aplicacin web

INTRODUCCION A LA INSTALACIN DE LAMP

Introduccin a la Instalacin de LAMP

3.1. Introduccin
En el presente manual se van a definir a fondo aquellas tareas necesarias para poner en funcionamiento una plataforma LAMP. Por simplicidad el manual est dedicado a su instalacin y configuracin en una OpenSuse 10.2.

3.2. Configuracin de Servicios LAMP


3.2.1. Configuracin de un Servidor DNS
Debido que las distintas posibilidades a la hora de gestionar un dominio son tan variadas, en el presente manual se va a suponer que se dispone de un dominio contratado y que se sabe la direccin ip de cada una de las mquinas que van a ir dentro del dominio.

3.2.2. Configuracin de un dominio DNS

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Una vez que hayamos accedido a la herramienta de configuracin dispondremos de un interfaz a travs del cual podremos modificar las entradas del dominio. Disponemos bsicamente de tres tipo de entradas: A o entradas de maquinas (relacionan una ip con un nombre dentro del dominio), CNAME relacionan mediante un alias un nombre de mquina con otro nombre y MX que relaciona el servidor por correo por defecto con un nombre de mquina. A continuacin de puede ver una figura en el que se ve cmo configurar dichas entradas: Una vez guardados los cambios espere entre 24 y 48h a que dichos cambios surtan efecto. Despus de que haya pasado dicho plazo, pruebe a entrar mediante el navegador web para ver si funciona correctamente.

3.3. Instalacin de LAMP


A continuacin se detallarn los distintos tipos de instalaciones de un Entorno *AMP.

3.3.1. Instalacin de *AMP en Windows con XAMPP


En este punto detallaremos la instalacin de XAMPP para Windows. La versin de XAMPP para Windows est disponible en: http://www.apachefriends.org/en/xampp-windows.html Elija la versin en Formato EXE para su descarga, actualmente est disponible en: http://www.apachefriends.org/download.php?xampp-win321.7.3.exe Descargue el fichero en su ordenador y ejecute el instalador como administrador del sistema. Una vez en el instalador, seleccione el directorio de instalacin y pulse en instalar. Este proceso puede tardar unos minutos y depende de la potencia de su ordenador. Durante el proceso, tal vez le pregunte si desea activar los servicios relacionados con Apache, Mysql, etc... Inicialmente le diremos que no es necesario, ya que siempre podremos colocar los servidores como servicios en cualquier momento. Despus nos preguntar si deseamos arrancar el XAMPP Control Panel. No es necesario arrancarlo, pero aprovecharemos para hacerlo, para as explicar su funcionamiento.

3.3.2. El panel de Control de XAMPP


Hay varias maneras de arrancar y parar los servidores: Mediante los script de arranque y parada Mediante el panel de control de XAMPP

Lance el Panel de Control de XAMPP (si no lo ha hecho todava) mediante el icono en su escritorio. Cuando haya arrancado, pulse en el botn Start de Apache y Mysql. Si, por lo que sea, el arranque de apache falla, el texto Running al lado de la fila de Apache desaparecer. Esto puede ser debido a que algn programa est haciendo uso del puerto 80 de su mquina.

10

INTRODUCCION A LA INSTALACIN DE LAMP

3.3.2.1. Cree Una base de datos de prueba en Mysql


Para crear dicha base de datos puede utilizar el phpmyadmin instalado con XAMPP. Para ello siga lo siguientes pasos: Vaya desde su navegador web a la siguiente direccin: http://localhost Podr ver La pantalla principal de XAMPP, donde puede seleccionar su idioma. En el men de la derecha seleccione PhpMyAdmin Una vez que PhpMyAdmin se haya abierto en su navegador, seleccione su idioma. Introduzca los datos de acceso. Si no se han configurado usuarios, slo existir el usuario root. As que ponga en Nombre de usuario root y la contrasea djela vaca. Pulse en continuar. Una vez est dentro (logueado) en PhpMyAdmin, encontrar un formulario para crear una nueva base de datos. Introduzca el nombre de la base de datos. En el campo Collation seleccione utf8_unicode_ci. Haga clic en el botn Crear Debera ver la base de datos a su izquierda. Seleccione la nueva base de datos. Trabaje con ella :)

3.3.3. Instalacin de una LAMP en OpenSuse 10.2


En OpenSuse 10.2 esta tarea es muy sencilla, describimos ahora todos los pasos: 1. Entre en el Men de Acciones (KickOff) en el apartado de PC y pulse en el Configurador de administracin YAST. 2. Valdese como Superusuario. En cuanto intente entrar en YAST deber introducir la contrasea del SuperAdministrador (root) y pulsar en el botn Aceptar. 3. En la pestaa de Software pulse en el icono de Instalar/desinstalar Software. 4. En la pestaa de Software pulse en el icono de Instalar/desinstalar Software. 5. Una vez haya entrado en la herramienta se actualizarn los listado de Software disponibles para su manejo. 6. Cuando haya terminado de gestionar los listados, aparecer una nueva pantalla. En la parte superior derecha de la pantalla aparece una etiqueta llamada filtro y una lista desplegable. pulse en ella y seleccione Patrones. Aparecer un listado en la parte de la izquierda. 7. En dicho listado aparecen grupos de paquetes con funcionalidades acompaados de una caja de seleccin al lado izquierdo de cada uno de ellos. Para seleccionar alguno de ellos pulse con el botn izquierdo en cualquiera de las cajas de seleccin, esta caja aparecer marcada con un smbolo de visto bueno, tambin ver que en la parte de la derecha de la pantalla principal, los paquetes individuales aparecern todos seleccionados. Para de-seleccionar un patrn repita la misma operacin, ver que el smbolo de visto bueno desaparecer de la caja de seleccin. 8. Seleccione el patrn denominado Servidor Web y LAMP. 9. Pulse en el botn Aceptar. Aparecer la pantalla de descarga de paquetes desde los medios.

11

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

10. Introduzca el CD o DVD de instalacin de OpenSuse 10.2. y pulse en el botn Ok. Se iniciar la descarga de paquetes individuales. 11. A continuacin se configurarn los paquetes y servicios con YAST. 12. A continuacin pulse en el botn No en el cuadro de dilogo. 13. Se cerrar la venta de instalar y Desinstalar paquetes. 14. A continuacin pulse en el botn No en el cuadro de dilogo. 15. Se cerrar la venta de instalar y Desinstalar paquetes. 16. A continuacin necesita activar el servidor Apache y el PHP. Para lo cual debe entrar en YAST en la pestaa Servicios de red en el icono Servidor HTTP. 17. Despus aparecer la primera pantalla de configuracin de Apache. En ella debern aparecer: el puerto por el que escuchar las peticiones web (por defecto 80) y las direcciones ip por las que se permite que escuche el servidor web (127.0.0.1 por defecto). 18. Pulse en el botn Siguiente. 19. A continuacin deber marcar (si no lo est hecho ya) el cuadro de seleccin al lado de Habilitar lenguaje de guiones PHP5. 20. Pulse en Siguiente. 21. A continuacin puede ser los parmetros bsicos del servidor, tales como directorio principal, direccin de correo del administrador, etc. Pulse en Siguiente. 22. Despus podr ver los Sitios Web Virtuales que maneja el servidor, si no desea manejar ninguno ms pulse en Siguiente. Si desea configurar un nuevo Sitio Web Virtual pulse en aadir y siga los siguientes pasos. 23. A continuacin introduzca los parmetros de configuracin del nuevo servidor virtual: nombre del servidor, directorio principal del Sitio Web Virtual y el correo del administrador del sitio web virtual. Pulse en el botn Siguiente. 24. A continuacin introduzca otros parmetros de configuracin del nuevo servidor virtual: acceso a CGI, HTML pblico, etc.. 25. Pulse el botn Siguiente. 26. Despus de aadir el nuevo sitio Web Virtual. Pulse en Siguiente. 27. Despus de configurar los Sitios Web Virtuales, marque la opcin Iniciar el servidor web en el arranque. Pulse en Siguiente. 28. A continuacin se configurar el servidor web y se rearrancar si es necesario. Pulse en Finalizar. 29. A continuacin introduzca la url en el navegador web y compruebe que se visualiza correctamente. 30. Ahora es necesario comprobar si el mdulo de php funciona correctamente, para lo cual es necesario crear un fichero index.php en el directorio principal del dominio del Sitio Web Virtual. Para ello necesita abrir una terminal con permisos de sper-administrador, esto se puede conseguir si va al Men de Acciones, pestaa Aplicaciones, submen Sistema, submen Terminal, icono Programa de terminal - modo de superusuario. Le solicitar la contrasea del administratorio (root), introduzcala y pulse en el botn OK. 31. Una vez abierta la terminal ejecute los siguientes comandos:
echo "" >/srv/www/htdocs/index.php chmod 777 /srv/www/htdocs/index.php

32. Evidentemente la ruta debe coincidir con la localizacin del directorio raz del Sitio Web Virtual

12

INTRODUCCION A LA INSTALACIN DE LAMP

33. Despus abra su navegador e introduzca la url seguido de /index.php En nuestro ejemplo www.midominio.com/index.php Si se abre correctamente podr ver la informacin del mdulo php instalado en su Apache.

3.3.3.1.

Configuracin de Mysql

A fin de poder arrancar automticamente en el arranque el servidor Mysql es necesario modificar los niveles de arranque. Para lo cual entre en YAST y vaya a la pestaa Sistema y entre en el editor de niveles de ejecucin. Los pasos a seguir son los siguientes: 1. A continuacin selecciones el servicio Mysql con el botn derecho del ratn y pulse el botn Activar situado abajo a la izquierda de la pantalla. 2. Una vez activado el servicio saldr una pantalla con el resultado (debera marcar un xito en el proceso de activacin). Pulse en el botn Ok. Despus pulse en el botn finalizar. 3. Despus pulse el botn Finalizar para que se apliquen los cambios. Cuando salga la pantalla de validacin pulse en Si.

Sera conveniente recordar que el usuario por defecto de Mysql tras la instalacin es root y no dispone de una contrasea asignada. A fin de poder gestionar correctamente Mysql pasaremos al siguiente paso, Instalar la aplicacin Web PhpMyAdmin

3.3.3.2. Instalacin PhpMyAdmin

configuracin

de

Para poder gestionar de una manera sencilla Mysql, instalaremos PhpMyAdmin, una herramienta de gestin de Mysql va web. As mataremos dos pjaros de un tiro. Los pasos a seguir son los siguientes: 1. Descargarse la ltima versin de PhpMyAdmin, cuando nos pregunte el navegador qu hacer con el le diremos que queremos guardarlo en el disco duro, en el escritorio por ejemplo. 2. Una vez descargado el fichero deberemos descomprimirlo, para lo cual pulsamos sobre l para abrirlo y descomprimirlo tambin en el escritorio 3. Despus debe copiar el contenido de la carpeta que incluya el index.php al directorio /srv/www/phpmyadmin 4. Debe recordar que para hacer esto es necesario realizar esta operacin como SuperAdministrador del sistema. 5. Despus debe modificar los permisos de la carpeta para que el usuario root tenga permisos de acceso a los ficheros. 6. Despus debe comprobar mediante el navegador que tiene acceso a la url http://localhost/phpmyadmin.index.php. En nuestro ejemplo: http://www.midominio.com/phpmyadmin/index.php

13

HERRAMIENTAS DE DESARROLLO DE PROYECTOS PARA PHP

Herramientas de Desarrollo de proyectos para PHP

4.1. Eclipse y extensiones


4.1.1. Eclipse el IDE
Eclipse es una de las mejores y ms extensibles herramientas se desarrollo disponibles actualmente. Debido a a facilidad para poder generar extensiones de funcionalidad y visualizadores, dispone de distintas distribuciones adaptadas a las distintas necesidades del proceso de generacin de un proyecto. En el caso que nos ocupa, hablaremos principalmente de la distribucin especfica de J2EE.

4.1.2. Instalacin de Eclipse para PHP


Descargar e instalar el JRE para http://www.java.com/es/download/manual.jsp nuestro sistema operativo:

15

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Descargar e instalar la versin de Eclipse para desarrolladores PHP desde: http://www.eclipse.org/downloads/

4.1.3. Gestin de versiones: SVN


En la comunidad de software libre colaboran en la construccin de cdigo y documentos muchas personas. El trabajo de construccin de cdigo de manera colaborativa se puede realizar gracias a un eficiente uso de sistemas de control de versiones. Un sistema de control de versiones es fundamentalmente un software con una metodologa que permite almacenar los elementos que se vayan a gestionar (texto, imgenes) en un depsito comn y poder hacer cambios sobre los mismos. saber qu cambios se han realizado en los elementos y quin los ha realizado. Si adems son ficheros de texto podemos saber que se ha cambiado con exactitud. volver en algn punto hacia atrs el cdigo, retornar a un estado anterior. Adems se pueden gestionar ramificaciones en el cdigo para trabajar en funcionalidades nuevas sin romper la aplicacin que funciona, importar cdigo de depsitos independientes, hacer marcas de versiones que sean hitos importantes. Con todo ello podemos llegar a tener una lnea temporal (ms que una lnea es un rbol) donde podemos visualizar cual ha sido la evolucin de nuestro cdigo en cada momento. Existen muchos gestores de versiones de cdigo: Git, Mercurial, Bazaar, pero quizs uno de los ms utilizados sea Subversion http://subversion.tigris.org/. Subversion surge de replantear desde cero otro sistema ms antiguo llamado CVS de manera que el nuevo sistema no tuviera lo mismos fallos que el anterior pero si todo lo bueno que haba aportado. Tanto Subversion como CVS son sistema de control de versiones centralizados, donde hay un slo deposito que almacena el cdigo. En contra punto tenemos que Git y Mercurial son distribuidos y el depsito completo es la suma de todos los depsitos parciales de los participantes. Crear un depsito o repositorio es simplemente indicar al programa que determinado directorio va a ser el almacn de cdigo. El gestor de versiones almacenar meta-datos de cambios, fechas y autores en ficheros y carpetas no visibles dentro de este directorio. Si queremos que el repositorio sea pblico adems deberemos configurar Apache para que lo sirva mediante Webdav+svn. El depsito creado puede estar vaco, pero a partir de aqu nosotros trabajaremos en una copia desde la que nos bajaremos (update) y subiremos (commit) los cambios. Habitualmente se comienza un proyecto creando 3 directorios dentro del depsito: trunk/tronco, tags/etiquetas y branches/ramas. En trunk se almacenara el desarrollo principal del proyecto. En determinado momento puede que tengamos nuestra aplicacin funcionando como queremos (a falta de ms cosas quizs) pero nos interesa marcar que esta versin en concreto est funcionando. Estas marcas se guardan en tags/etiquetas. La mayora de los contribuidores a tu proyecto tendrn su propia carpeta en branches/ramas para hacer sus desarrollos. Cuando estn seguros de que todo va a ir bien es cuando se hace un merge/fusin con el trunk/tronco. Los branches tambin son muy utilizados para hacer experimentos o pruebas que pueden romperlo todo. En la mayora de los casos los commits, updates y merges mezclan correctamente el cdigo nuevo con el que exista, integrando solo los cambios (tambin se dice diff o delta). Pero se puede dar el caso de el sistema no pueda hacer la integracin y entonces es cuando se produce un conflicto que debe ser resuelto por el desarrollador a mano.

16

HERRAMIENTAS DE DESARROLLO DE PROYECTOS PARA PHP

4.1.3.1.

Primeros pasos con Subversion

La manera de ms rpida de ponerse a funcionar con Subversin es mediante la lnea de comandos. En todo caso existen muchos programas libres para la gestin mediante interfaz visual del repositorio y continuamente se estn lanzando plugins para programas tanto editores de cdigo como de otro mbito que permiten hacer commits, updates y diffs de esta tercera aplicacin. Puedes descargar Subversion para Ms Windows de aqu: http://www.collab.net/downloads/subversion/, pulsando en el primer botn de DOWNLOAD. Cuando termine la descarga instala la aplicacin. Si te pide reiniciar el sistema haz lo. Los usuarios de GNU/Linux, BSDs y MacOSX podrn instalar el software segn el mtodo habitual de su distribucin. Para verificar que la instalacin ha tenido xito abre la lnea de comandos y escribe svn luego pulsa intro. Si te aparece algo similar a lo siguiente es que todo ha ido bien. Type svn help for usage.

4.1.3.2.

Crear un repositorio

Vamos a crear nuestro primer repositorio. Para no complicar mucho las cosas en Ms Windows lo crearemos en la carpeta raz y en los UNIX en nuestro home: En Windows:
cd c:\ svnadmin create reposvn

En UNIX
cd svnadmin create reposvn

Ahora vamos a hacernos una copia del depsito vaco para continuar trabajando desde nuestra copia local. Lo primero es el lugar de origen y lo segundo es el destino.
svn co file:///c:/reposvn/ copiasvn svn co file:///home/usuario/reposvn copiasvn

A partir de este momento trabajamos exclusivamente desde la copia. Crearemos la estructura inicial de carpetas recomendada: Creamos las carpetas trunk, branches y tags en la carpeta copiasvn con nuestro gestor de ficheros habitual. Estas carpetas todava no estn controladas por el sistema de gestin de versiones hasta que no hagamos el siguiente comando:
cd copiasvn svn add trunk tags branches svn ci -m "subiendo estructura inicial"

Con el comando svn add estamos aadiendo estos tres directorios (podran ser ficheros de texto o imgenes o cualquier otro tipo de fichero) al control de versiones, pero todava se encuentran nicamente en nuestra copia local. Con svn ci subimos nuestros cambios de la copia local al depsito principal y mediante el parmetro -m mensaje estamos incluyendo un breve comentario entre las comillas para explicar porque hemos hecho esos cambios. Eso ayudara a otros desarrolladores, en un entorno colaborativo, a identificar tu contribucin. Para tener ms juego ahora nos haremos otra copia local: En Windows:
svn co file:///c:/reposvn/ segundacopiasvn

En Unix:
17

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

svn co file:///home/usuario/reposvn segundacopiasvn

Como veremos ahora se nos bajan los directorios estructurales. Dentro de trunk creamos un fichero de texto que llamaremos LEEME. Si le pedimos a Subversin que nos diga el estado nos dir lo siguiente: Comando:
svn status -u segundacopiasvn

Respuesta:
? trunk/LEEME

La interrogacin ? indica los ficheros que no estn bajo el sistema de control. En lugar de la interrogacin tambin nos podra aparecer:
M: el fichero o directorio ha sido modificado en local *: el fichero o directorio ha sido modificado en el depsito principal pero todava no nos hemos bajado los cambios. C: el fichero o directorio tiene un conflicto no resuelto. A: el fichero o directorio ha sido aadido pero todava no lo hemos subido al depsito principal D: el fichero o directorio va a ser borrado. I: el fichero o directorio es ignorado. !: un fichero o directorio que estaba siendo gestionado por el control de versiones a desaparecido. Si hacemos svn update se restablecer con la versin del depsito principal.

Vamos a aadir el fichero LEEME y subirlo al repositorio:


svn add LEEME svn ci -m "necesitaba un fichero para escribir la ayuda" LEEME

Ahora vamos a la primera copia local que hicimos:


svn status -u copiasvn

Veremos que est pendiente de ser actualizada.


svn update copiasvn

y ahora en copiasvn/trunk aparecer el fichero LEEME que creamos como si furamos otro usuario en otra copia. En un entorno remoto con un depsito compartido es donde todo esto cobra sentido. Subversin permite operar de la misma manera accediendo mediante URLs http://example.com/reposvn/trunk en lugar de rutas a directorios y ficheros locales. Esto es lo bsico para comprender y empezar a trabajar con Subversion, segn la metodologa elegida o nuestra forma personal de trabajo se pueden hacer muchas cosas ms y es muy recomendable leer el manual oficial del equipo de desarrollo de Subversin ya que, como decamos, no solo se ofrece una herramienta con unas funcionalidades sino tambin una metodologa de trabajo. http://svnbook.red-bean.com/

18

HERRAMIENTAS DE DESARROLLO DE PROYECTOS PARA PHP

4.1.3.3. Instalacin de la extensin de SVN para Eclipse


Comience la instalacin desde el men ayuda de eclipse, Ayuda/instalar actualizaciones/encontrar e instalar. Seleccione que quiere buscar nuevas funcionalidades para instalar. Seleccione nuevo sitio de actualizaciones e introduzca la siguiente URL: http://subclipse.tigris.org/update_1.6.x Seleccione el nuevo sitio introducido. Seleccione el meta-paquete subeclipse. Acepte la licencia. Instale. Espere a que termine de descargar e instalar la extensin. Seguramente le pida reiniciar eclipse.

4.2. Firefox y sus extensiones


4.2.1. Referencias
Web developer: tutorial Yslow Firebug

4.2.2. Contenido
De cara a poder presentar Firefox como una herramienta til para desarrolladores web. Indicaremos la principales extensiones disponibles que permiten mejorar incluso depurar aplicaciones web, tanto a nivel de funcionalidad como a nivel de estndares de calidad y accesibilidad. En esta parte del tema presentaremos 3 extensiones: Web Developer, Yslow y Firebug.

4.2.2.1.

Web Developer

Link de Descarga: https://addons.mozilla.org/es-ES/firefox/addon/60 Una de las herramientas mas potente que puede ofrecer Firefox es Web Developer. Este agregado pone a disposicin una serie de herramientas fundamentales para cualquier diseador/desarrollador web. En este tutorial vamos a desglosar generalmente todas las funciones que nos ofrece web developer, quien puede convertirse en un gran compaero de trabajo.

19

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

La primer herramienta que nos ofrece es Disable, esta permite activar y desactivar funciones dinmicas de los sitios webs como puede ser Java, Javascript en su totalidad o solo alarmas estrictas y la cache. tambin te permite desactivar el color de una pagina, pop-ups, fuentes mnimas entre otras cosas, esto vendra a ser como un depurador para comprobar funcionalidades dinmicas. Continuando con este apartado nos encontramos con Cookies, donde su palabra lo dice todo. Podemos gestionar todo tipo de pruebas, como desactivarlas, borrarlas, ver su informacin y mas. Una vez que comprobamos esto entramos en el apartado de diseo con la opcin CSS. Aqu tenis la posibilidad de desactivar las hojas de estilos por partes, ver su informacin, editar, ver por tipo de medio. Forms comprueba tus formularios mostrndote sus elementos ocultos, sus etiquetas Con Images podes deshabilitar las mismas, mostrar sus atributos ALT, ver sus dimensiones, rutas, esconderlas y mas Information te permite ver informacin especifica sobre las diferentes etiquetas en si es lo que hace. Miscellaneus te permite ver y mover lineas guas, medir zonas o imgenes con una regla, mostrar elementos ocultos, editar HTML, marcar los links como visitados y mas Outline es una de las herramientas esenciales, con este men podes ver el tamao de los diferentes elementos en tu pagina a travs de una linea. Podes ver lo que ocupa tus cabeceras, frames, elementos de bloques y mas. Resize su nombre lo dice todo, con esta opcin podes ver tus paginas en diferentes resoluciones y realizar Zoom. En Tools se encuentran Validadores, a travs de este men podes validar tus paginas en la W3C, WAI, buscar errores java y tambin validar css y html de forma local entre mas opciones. View Source te permite ver el cdigo puro y duro de la pagina en visualizacin, ver cdigo generado, de frames y mas. Por ultimo tenemos el botn Options, el cual te permite modificar muchos parmetros de este fabuloso agregado que es una herramienta fundamental para cualquier webmaster. debug Al lado derecho de Options est disponible este debugger que te avisa sobre los errores de Javascript y CSS, as como tambin el modo actual del navegador. Simplemente funcional y perfecta en su desempeo, Web Developer recorre cada rincn de tu pagina web haciendo que el anlisis y la bsqueda de errores no sea para nada estresante.

4.2.2.2.

Yslow

Link de Descarga: https://addons.mozilla.org/es-ES/firefox/addon/5369 Las opciones de Yslow son variadas pero cabe destacar las siguientes: Valoracin del grado de accesibilidad Descripcin de los elementos mostrados

20

HERRAMIENTAS DE DESARROLLO DE PROYECTOS PARA PHP

JS CSS Imgenes DOM Tiempos de carga

4.2.2.3. 4.2.2.4. Firebug

Link de Descarga: https://addons.mozilla.org/es-ES/firefox/addon/1843 Nos Permite: Inspeccionar y editar el HTML, JS y CSS Visualizacin del DOM Ver los recursos cargados Depuracin de AJAX.

4.2.3. Mysql WorkBench


4.2.3.1. Uso de Mysql WorkBench

La compra de MySQL AB por parte de Sun Microsystems y posteriormente por parte de Oracle, es sin lugar a dudas un reconocimiento al buen trabajo hecho por la comunidad de MySQL, para llevar a esta base de datos a ser una de las mejores bases de datos open source que se encuentre en el mercado, y que hoy por hoy es la base de datos predilecta por los desarrolladores, e incluso grandes empresas como Suzuki, Sagem, o la misma Adobe o sitios como Yahoo! Finance, para bases de datos transaccionales o bodegas de datos (Data Warehousing).MySQL provee entre sus herramientas, una denominada MySQL WorkBench la cual nos permite desde una ambiente grfico, disear un modelo E-R de una base de datos y luego crear la base de datos, como tal en una base de datos MySQL. Para este tutorial es necesario tener instalado: MySQL 5.x o superior MySQL WorkBench 5.x.x NOTA: En esta demo, solo se mostrar el funcionamiento de MySQL Workbench, pero no la instalacin de ste ni la de MySQL Server. El servidor Mysql puede estar instalado en cualquier equipo y/o sistema operativo soportado (Windows, Linux, Aix, etc). MySQL Workbench solo se encuentra disponible para Windows. En el ejemplo crearemos una base de datos muy sencilla, la cual no representa un ejemplo real. Simplemente es para probar las caractersticas. Primero creemos el esquema test, haciendo clic en el smbolo +. Abajo se abre una pestaa en que nos pregunta el nombre del esquema (test) y el idioma del esquema, el cual se recomienda dejar por default como se muestra

21

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

en la figura. Si la aplicacin pregunta si desean renombrar todos los objetos, seleccionen Si. Ya creado el esquema, procedemos a crear las tablas. Existen dos formas, aunque muy similares de crearlas. La primera es desde la pantalla en la que estamos, la otra es mediante la ventana visual, en la cual podremos adems, realizar las relaciones entre las tablas. Pero primero lo primero; las tablas. Verifica que ests en el esquema test y luego haz doble clic en el icono de Add Table. Al hacer clic en esta opcin, se despliega al lado un icono representando la nueva tabla, mientras que debajo se abre una nueva pestaa, en la cual podemos editar todo al respecto de las tablas haciendo (Columnas, llaves, triggers, etc) clic en cada una de las pestaas ubicadas en la parte inferior de esta nueva pestaa. Nota: los triggers solo estn disponibles a partir de MySQL 5. Cualquier tabla con triggers generada en Workbench arrojar un error cuando se corra en una versin inferior a MySQL 5.0 Agregaremos un par de columnas a la tabla: Al hacer clic en la pestaa Columns, podemos editar todas las columnas de la tabla indicada. Podemos alterar el nombre, el tipo de dato, si es nulo o no (NN) y si es Auto incremental (AI), obviamente este ltimo es slo para datos de tipo numrico, De igual forma podemos especificar un valor por default para la columna. En la parte derecha, inmediatamente podemos indicar si la columna seleccionada hace parte de la llave primaria (PRIMARY KEY), si es UNSIGNED o ZEROFILL para las variables numricas y si la variable es de tipo carcter, podemos especificar si es BINARY. Ahora pasemos a crear una tabla por medio de un diagrama E-R. En la parte superior observamos la opcin Add Diagram. Hacemos doble clic sobre ella. Luego se abre una nueva pestaa en la cual encontramos un grid. A la izquierda, encontramos una barra de herramientas, desde la cual podremos crear tablas y vistas, adems de relaciones (1:1,1:n,n:m) y a la derecha un rbol con los objetos de nuestro esquema (tablas, vistas, etc). De esa ventana, seleccionamos la tabla que creamos y la arrastramos hasta el grid. Luego hacemos clic derecho y seleccionamos Edit table, abajo nos muestra la pestaa para editar la tabla y crear columnas, llaves, etc. Buscamos a la izquierda el icono que nos permite crear una nueva tabla. Hacemos un clic en el icono y luego un clic en el grid. Editamos las segunda tabla y ahora haremos una relacin muchos a uno. Seleccionamos el icono, y luego cada una de las tablas (primero la de muchos y luego la de uno). En mi caso, la tabla de muchos es table1. Quedara algo as: Como ven el Workbench se apega a la teora relacional, donde en este caso la llave de a relacin uno pasa a la tabla de muchos. Igualmente si creamos una relacin M.N (muchos a muchos) generar una relacin entre las dos tablas. A continuacin viene la mejor parte de esta herramienta: la generacin del script SQL. Como ven, podemos exportar el diseo, incluso como una imagen en pdf, o en png, entre otros. La primera pantalla, nos muestra las opciones con las que queremos que se genere el script DDL. Luego seleccionamos la ubicacin destino del archivo que se crear. Luego nos muestra un resumen de lo que crear; usuarios, tablas, vistas, rutinas y triggers. Incluso si seleccionamos el botn Detailed Selection de cada seccin, podemos especificar an ms, por ejemplo, qu tablas deseo realmente exportar. Luego finalizar, y en la ruta que le hallamos indicado estar un archivo .sql, con nuestro script. Como se podrn dar cuenta Workbench, resuelve algunas limitantes en la comunidad open source de un buen software front-end para MySQL, y sobre todo de una herramienta que provea Forward Engineering, de una manera tan sencilla y bien ilustrada. Digamos que la nica limitante de WorkBench es su ausencia en otras plataformas.

4.2.4. Publicacin de Cdigo

22

HERRAMIENTAS DE DESARROLLO DE PROYECTOS PARA PHP

Una vez realizada toda la instalacin del Entorno *AMP, si necesitamos colocar cdigo accesible desde el servidor web, ser necesario colocar los ficheros y carpetas en un directorio que depende de la instalacin. En Linux normalmente ser /var/www , en Windows ser C:\XAMPP\htdocs

23

PHP BASICO

PHP Bsico
Lo primero de todo, que significa PHP?. En un principio, significaba Personal Home Page Tools pero ms tarde - en la versin 3 de PHP - se decidi usar un acrnimo recursivo (donde una de las letras hace referencia al propio acrnimo) cambiando el nombre a PHP Hypertext Preprocessor. Es un lenguaje orientado a crear pginas web dinmicas en las que podemos acceder a una base de datos. Es multiplataforma, esto es, puede funcionar en varios sistemas operativos, como Linux, Windows, o Mac OS. Adems es libre, por lo que se presenta como una alternativa de fcil acceso para todos (si ests interesado en conocer algo acerca del Software Libre puedes visitar este enlace de la wikipedia http://es.wikipedia.org/wiki/Software_libre). A diferencia de otros lenguajes de programacin como C, PHP es un lenguaje interpretado. Es decir, a la hora de ejecutar nuestro programa, no hace falta traducir nuestro cdigo a un lenguaje que entienda el ordenador (a este proceso de traduccin se le llama compilar), si no que hay un intrprete que es el que le dice al ordenador que es lo que queremos que haga. Esto hace que el desarrollo de aplicaciones sea ms rpido ya que no hace falta compilar cada vez que hagamos el ms mnimo cambio en nuestro cdigo. En nuestro caso, al cdigo al ser interpretado, tambin se le llama script. Como funciona el proceso de ejecucin de una web en php? 1. Pepito accede desde su navegador a nuestro documento con cdigo PHP. 2. El servidor recibe la peticin y localiza el documento.

25

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

3. El servidor arranca el interprete que traduce nuestro cdigo y lo ejecuta. 4. El interprete, tras ejecutarlo, se lo devuelve al servidor, ya traducido en html. 5. El servidor manda el cdigo html al navegador web de Pepito para que vea nuestra web. A modo de curiosidad: aunque PHP se concibi originalmente para la creacin de pginas web, existe la posibilidad de usarlo como cualquier otro lenguaje de programacin interpretado como Python o Perl, si se ejecuta con su interprete desde lnea de comandos con phpCLI (php Command Line Interpreter o Interprete en Linea de Comandos de php), esto es, sin que tenga que haber una interaccin entre el servidor y un navegador web.

5.1. Estructura bsica de un fichero PHP


Nuestro script PHP puede estar slo en un fichero, pero tambin puede estar incrustado en cdigo HTML. Para que nuestro interprete pueda diferenciar qu es cdigo PHP y cdigo HTML, usamos las etiquetas <?php y ?>. Estas etiquetas indican donde empieza y donde acaba nuestro cdigo PHP. Tambin se puede usar exclusivamente <? y ?> siempre y cuando, en nuestro servidor la directiva short_open_tag est activada. Es mas podramos prescindir de la etiqueta ?> si en nuestro fichero slo vamos a usar cdigo php. Veamos un ejemplo. Tranquilo/a si no entiendes nada de lo que hay a continuacin, ya lo veremos ms tarde.
<?php //aqu empieza nuestro cdigo php $a = "Hola mundo."; echo $a; //aqu termina nuestro cdigo php ?>

Como ves, se han colocado las etiquetas <?php y ?> y dentro nuestro script. En este caso si ejecutamos este script, el resultado al acceder por nuestro navegador seria el siguiente:
Hola mundo.

Mgicamente el texto en el que se explica donde empieza y donde termina el cdigo php no aparece. A esto se le llama comentarios (y los vas a ver mucho en este curso :D). En los lenguajes de programacin se puede (y se debe) colocar comentarios para explicar parte del cdigo, as cuando tengamos que retomar nuestro script o cuando otra persona tenga que retocar nuestro cdigo, podremos saber de forma ms rpida que es lo que estamos haciendo. Podemos poner comentarios en una sola linea o en bloque.
<?php //Este es un comentario en una linea /* Este es un comentario en bloque Este es un comentario en bloque Este es un comentario en bloque Este es un comentario en bloque*/ ?>

Casi siempre que escribamos una instruccin hay que terminar dicha instruccin con el carcter ; (hay algunas excepciones, como los comentarios, que ya las iremos viendo ms adelante)

26

PHP BASICO

Ah! Y un pequeo consejo, cuando programes, intenta indentar tu cdigo para una mayor legibilidad. En PHP se podra escribir todo un programa en una sola linea kilomtrica, pero es altamente aconsejable que separes cada cosa que hagas en lineas diferentes y con una identacin adecuada. El resto de programadores (y t mismo/a) te lo agradecern cuando tengan que revisar tu cdigo.

5.1.1. Inclusin de ficheros externos


Como dijo Julio Csar, Divide y vencers. En la cultura popular, divide y vencers hace referencia a un refrn que implica resolver un problema difcil, dividindolo en partes ms simples tantas veces como sea necesario, hasta que la resolucin de las partes se torna obvia. La solucin del problema principal se construye con las soluciones encontradas. Dicha tcnica que veremos un poco ms adelante cuando entremos a hablar de funciones tambin nos sirve como excusa para explicar la inclusin de ficheros externos. Como se ha comentado anteriormente, se en php se podra escribir todo un programa en una sola lnea, pero no debemos hacerlo por tener una mejor lectura de nuestro cdigo. Asimismo podramos dividir nuestro cdigo en diferentes ficheros para que en cada fichero tengamos algo especfico y nos sea ms fcil encontrar un cdigo en concreto si estamos buscando algn error. Pongamos un sencillo ejemplo. Imaginemos que en nuestra aplicacin web queremos acceder a una base de datos (o bbdd) y hacer complicadas operaciones matemticas. Para ello podramos crear un fichero llamado index.php donde estuviese toda la lgica principal de nuestro programa, crear otro llamado basededatos.php y otro llamado matematicas.php donde tengamos los complicados clculos. As si tenemos un problema al acceder a la bbdd, solo tendramos que revisar el archivo basededatos.php y lo mismo con los clculos matemticos. PHP nos deja incluir ficheros externos mediante los mtodos include, require, include_once y require_once. As en nuestro programa principal en el fichero index.php tendramos:
<?php include "basededatos.php"; include "matematicas.php"; //aqu empieza nuestro cdigo del programa principal ... //aqu termina nuestro cdigo del programa principal

?>

Esto nos sirve no slo para tener funcionalidades especficas que creemos nosotros en ficheros a parte, si no que adems nos permite incluir libreras y funcionalidades creadas por otras personas, que nos pueden facilitar mucho la vida. Cuales son las diferencias entre require, require_once, include e include_once? Bien, entre require e include: require buscar el fichero, si este no existe, mostrara un Fatal Error, y parar la ejecucin de nuestra aplicacin. include buscar el fichero, si este no existe mostrar un Warning y dejar que nuestra aplicacin siga su curso.

27

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

require_once e include_once siguen la misma norma que require e include acerca de los Fatal Error y de los Warning. La diferencia radica en que require_once e include_once, slo se ejecutarn una vez. Si por alguna razn el trozo de cdigo en el que estn require_once o include_once vuelve a ejecutarse, php lo ignorar.

5.2. Elementos del Lenguaje:


A continuacin veremos algunos elementos que tendremos que usar a la hora de crear nuestros programas.

5.2.1. Variables
Una variable se puede definir como porcin de memoria que ha sido creada para el almacenamiento de algn valor. Valor que puede variar a lo largo de la ejecucin de nuestro script. Por ejemplo, en una ecuacin normal del tipo 2 + x = 4, x sera nuestra variable, y en este caso almacenara el nmero 2. A la hora de programar esto es ms o menos lo mismo, solo que las variables pueden almacenar algo ms que simples nmeros. En el caso de PHP se pueden almacenar los siguientes tipos de datos: Nmeros enteros, tambin llamado int (de integer) Nmeros de coma flotante, es decir nmeros decimales, tambin llamados float (de Floating Point number) Cadenas de texto, esto es, palabras, slabas, frases. Tambin conocidos como str (de String) Arrays tambin conocidos como matrices. contienen ms de un valor y de diferentes tipos. Puede contener por ejemplo, 2 enteros, 5 decimales, 10 cadenas de texto, 3 objetos e incluso ms arrays. Booleanos, sus nicos valores pueden ser true o false (Verdadero o falso) Objetos Un Objeto, es un contenedor de uno o ms datos (variables o propiedades miembro) junto a las operaciones de manipulacin de dichos datos (funciones/mtodos). Ya los veremos ms adelante. En php para identificar una variable, se le antepone el smbolo $. As pues en el primer ejemplo que pusimos en este temario $a = Hola mundo; vemos como $a es realmente una variable que est almacenando una cadena de texto con el valor Hola mundo. Veamos algunos ejemplos de como operar con variables.
<?php $a = 1; //El valor de $a es 1 $a = 2; //El valor de $a es 2 $a + 1; //En este caso si ussemos el mtodo "echo" para escribir por pantalla, aparecera el valor 3, pero $a seguira siendo 2 $b = $a + 1; //$b valdria $a + 1 en este caso 2 + 1, es decir $b es
28

PHP BASICO

3 $c = $b - $a //$c valdra $b menos el valor de $a, en este caso 3 2, es decir $c es igual a 1 ?>

En php el tipado de las variables es dinmico. En otros lenguajes de programacin antes de usar una variable hay que crearla y decir de que tipo es. Por ejemplo en C habra que hacer
int a; a = 1;

Es ms, ni siquiera se podra asignar valores que no fuesen de ese mismo tipo. Es decir, a una variable de tipo int no se le puede asignar un valor decimal (ya que sera un tipo de dato float) En nuestro caso, en PHP, no hace falta crearla (o inicializarla), ya que se pueden hacer estas operaciones al vuelo. Adems se le puede cambiar el tipo de dato sin problemas asignndole un valor distinto. Veamos como se comportaran las variables en ficheros externos mediante el uso de require, include, require_once, e include_once. Imaginemos que tenemos 2 ficheros, fichero1.php y fichero 2.php fichero1.php:
<?php $variable = 10; ?>

fichero2.php:
<?php include fichero1.php; echo $variable; //esto mostraria por la pantalla 10 $variable = 20; include fichero1.php; echo $variable; //esto volveria a mostrar por pantalla 10 y no 20 ya que se ha //vuelto a ejecutar nuestro fichero1.php ?>

Ahora modifiquemos fichero2.php:


<?php include_once fichero1.php; echo $variable; //esto mostraria por la pantalla 10 $variable = 20; include_once fichero1.php; echo $variable; //esto ahora mostraria 20 por que php al ser un include_once ha //ignorado la ejecucin de nuestro script fichero1.php ?>

5.2.2. Constantes
A diferencia de las variables, las constantes no varan su valor a lo largo de la ejecucin de nuestra aplicacin. Adems estas no llevan el smbolo $ precedindoles Se declaran de la siguiente forma
<?php define("NOMBREVARIABLE", "valor"); define("NOMBREVARIABLE2", 27); echo NOMBREVARIABLE;

29

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

echo "<br />"; echo NOMBREVARIABLE2; ?>

Al usar el comando echo nos saldra por pantalla lo siguiente (ntese que se ha puesto un salto de carro html en el segundo echo):
valor 27

Es aconsejable utilizar maysculas para declarar el nombre de las constantes.

5.2.3. Operadores Operadores Aritmticos


Sintaxis $a + $b $a - $b $a * $b $a / $b $a % $b Nombre Suma Resta Multiplicacin Divisin Mdulo Descripcin Suma de $a y $b. Diferencia entre $a y $b Producto de $a y $b Cociente de $a entre $b Resto de la divisin de $a entre $b

Operador de Asignacin
Este operador ya lo hemos visto en la seccin de las variables el smbolo =. Bsicamente la variable de la izquierda toma el valor de la expresin que se encuentre despus del smbolo =. Se puede enrevesar un poco las asignaciones como veremos a continuacin.
<?php $a = ($b = 5) + 3; /* En este caso habramos inicializado 2 variables. $a y $b * $b tendra el valor 5, pero $a tendra el valor $b + 3, * es decir, 8. */ ?>

Es posible combinar el operador de asignacin con operadores aritmticos.


<?php $a = 2; //Inicializamos la variable $a $a += 1; // Esto equivaldra a $a = $a + 1 Es decir, a $a le asignamos su valor mas 1, en este caso, 3 ?>

Operadores de Comparacin
Los operadores de comparacin, como su nombre indica, permiten comparar dos valores. Veremos su uso un poco ms adelante, en las estructuras de control. Sintaxis $a == $b $a === $b $a != $b $a < $b Nombre Igualdad Identidad Desigualdad Menor que Descripcin Cierto si $a es igual a $b. Cierto si $a es igual a $b y si son del mismo tipo (slo PHP4) Cierto si $a no es igual a $b. Cierto si $a es estrictamente

30

PHP BASICO

menor que $b. $a > $b $a <= $b $a >= $b Mayor que Menor o igual que Mayor o igual que Cierto si $a es estrictamente mayor que $b. Cierto si $a es menor o igual que $b. Cierto si $a es mayor o igual que $b.

Ojo!, un error muy habitual es confundir = con ==. El primero es asignacin y el segundo comparacin.

Operadores de Incremento/Decremento
Sintaxis ++$a $a++ $a $a Nombre Preincremento Postincremento Predecremento Postdecremento Descripcin Incrementa $a en uno y despus devuelve $a. Devuelve $a y despus incrementa $a en uno. Decrementa $a en uno y despus devuelve $a. Devuelve $a y despus decrementa $a en uno.

Esto puede ser un poco lo, veamos un ejemplo


<?php echo "Postincremento<br />"; $a = 1; echo "Al usar el operador el usarlo es 2: ". $a."<br />"; echo "Preincremento<br />"; $a = 1; echo "Al usar el operador el usarlo es 2: ". $a."<br />"; echo "Postdecremento<br />"; $a = 2; echo "Al usar el operador el usarlo es 1: ". $a."<br />"; echo "Predecremento<br />"; $a = 2; echo "Al usar el operador el usarlo es 1: ". $a."<br />"; ?>

valor es 1: " . $a++ . ". Despus de

valor es 2: " . ++$a . ". Despus de

valor es 2: " . $a-- . ". Despus de

valor es 1: " . --$a . ". Despus de

Esto nos devolvera lo siguiente:


Postincremento Al usar el operador Preincremento Al usar el operador Postdecremento Al usar el operador Predecremento Al usar el operador el valor es 1: 1. Despus de usarlo es 2: 2 el valor es 2: 2. Despus de usarlo es 2: 2 el valor es 2: 2. Despus de usarlo es 1: 1 el valor es 1: 1. Despus de usarlo es 1: 1

Operadores Lgicos
Su uso ms habitual suele ser con tipos de datos booleanos. Los veremos tambin en ms adelante en las estructuras de control.

31

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Sintaxis $a and $b $a && $b $a or $b $a || $b $a xor $b ! $a

Nombre Y O O exclusiva Negacin

Descripcin Cierto si tanto $a como $b son ciertos. Cierto si $a o $b son ciertos. Cierto si $a es cierto o $b es cierto, pero no ambos a la vez. Cierto si $a no es cierto.

5.3. Tipo de datos abstractos:


5.3.1. Manejo de Cadenas de caracteres
Es hora de profundizar un poco en las cadenas de caracteres o strings. Hay 4 formas de delimitar una cadena de caracteres en PHP. Comillas simples Comillas dobles Documento incrustado heredoc (Desde PHP 4) Documento incrustado nowdoc (Desde PHP 5.3.0)

Comillas simples
La forma ms sencilla de especificar una cadena es acotarla mediante comillas simples (el signo '). Si se quiere poner dentro del texto una comilla simple hay que escaparla con el smbolo backslash (la barra inclinada a la izquierda \), de esta forma \'. Si se quiere poner esta barra de forma literal, hay que duplicar la barra: \\. Veamos unos ejemplos:
<?php echo 'esta es una cadena normal'; echo 'Se pueden poner varias lineas de esta forma sin ningn problema'; echo 'Para escribir el smbolo "\'" hay que usar la barra "\\"'; // Esto mostrara: Para escribir el smbolo "'" hay que usar la barra "\" ?>

Comillas dobles
Si la cadena de texto esta acotada entre comillas dobles (), PHP podr interpretar mas secuencias de escape para caracteres especiales. Secuencia de caracteres escapados \n \r Significado salto de linea (LF or 0x0A (10) in ASCII) retorno de carro (CR or 0x0D (13) in ASCII)

32

PHP BASICO

\t \v \f \\ \$ \" \[0-7]{1,3} \x[0-9A-Fa-f]{1,2}

tabulacin horizontal (HT or 0x09 (9) in ASCII) tabulacin vertical (VT or 0x0B (11) in ASCII) (desde PHP 5.2.5) form feed (FF or 0x0C (12) in ASCII) (desde PHP 5.2.5) barra signo dolar comilla doble Carcter ASCII que coincide con el numero octal Carcter ASCII que coincide con el numero hexadecimal

Si intentamos escapar cualquier otro carcter con la la barra backslash, dicha barra aparecer tambin (cosa que tambin ocurre en las comillas simples) Lo ms importante de las cadenas acotadas con comillas dobles, es el hecho de que las variables pueden ser expandidas (mostradas).
<?php $variable = "pepe"; echo "mi nombre es $variable"; //Esto mostrara: mi nombre es pepe ?>

Heredoc
Este tipo de documento incrustado incluido en PHP 4, nos permite volcar en la pantalla grandes cantidades de texto, evitando la necesidad de escapar caracteres en su interior. Su sintaxis es la siguiente. Se coloca el operador: <<< y seguido un identificativo. Acto seguido una nueva linea en la que habr el texto que queramos, y para finalizar en una nueva linea y SIEMPRE en la primera columna de la linea, de nuevo el identificativo y un punto y coma. El identificativo puede ser cualquier combinacin de letras (habitualmente se usa EOF o EOT, pero se puede usar cualquier otro que no est en el texto a introducir). Adems deber seguir las mismas reglas que cualquier etiqueta en PHP, es decir, slo caracteres alfanumricos o guiones bajos, y debe empezar con un carcter no-numrico o con un guin bajo. Este tipo de cadena nos permite usar comillas dobles sin necesidad de escape, adems como en las comillas dobles tambin interpreta (expande) las variables, lo cual es muy til a la hora de insertar gran cantidad de cdigo HTML.
<?php $variables = "variables"; $texto = <<<EOT Este es nuestro texto, con "comillas", e incluso usando $variables. EOT; echo $texto; //la salida por pantalla sera: Este es nuestro texto, con "comillas", e
33

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

incluso usando variables. ?>

En php 5.3.0 permite declarar el heredoc con el primer identificador entre comillas dobles.
<?php $texto = <<<"EOT" Nuestro texto. EOT; ?>

Nowdoc (a partir de PHP 5.3.0)


Los documentos incrustados tipo nowdocs son a las strings de comillas simples, lo que los heredocs a las strings de comillas dobles. Un Nowdoc es prcticamente lo mismo que un heredoc, pero en el cual no se parsearn las variables. Es til cuando necesitamos escribir grandes cantidades de texto que no necesiten mostrar variables etc Su sintaxis es similar al de un heredoc, solo que el primer identificador tiene que ir entre comillas simples:
<?php $texto = <<<'EOT' Nuestro texto. EOT; ?>

5.3.1.1.

Operaciones con cadenas de caracteres

Concatenacin
En php, para concatenar (unir) 2 cadenas de caracteres usaremos el smbolo punto .. Al igual que el operador de suma, permite su combinacin con el operador de asignacin.
<?php $cadena1 = "hola "; $cadena2 = "mundo!"; //Para unirlas podramos hacer lo siguiente $resultado = $cadena1.$cadena2; //Tambin se puede unir de forma literal: $resultado = "hola "."mundo!"; //o usando la mezcla del punto con el operador de asignacin $cadena1 .= "mundo!"; //en este caso el valor de $cadena1 se modificara por hola mundo! ?>

Bsqueda
A continuacin veremos algunas funciones para buscar contenidos dentro de nuestras cadenas. funcin strlen(cadena); substr_count(cadena,subcadena); descripcin Nos devuelve el tamao de la cadena (en n de caracteres) Devuelve cuantas veces aparece una subcadena en nuestra cadena

34

PHP BASICO

strstr(cadena,subcadena); stristr(cadena,subcadena); strpos(cadena,subcadena); strrpos(cadena,subcadena);

Localiza subcadena dentro de la cadena original Igual que la funcin anterior pero sin distincin entre maysculas y minsculas Primera ocurrencia de una cadena en otra Ultima ocurrencia de una cadena en otra

Extraccin
funcin strchr(cadena,carcter); substr(cadena,comienzo,longitud); descripcin Devuelve la subcadena que comienza en la primera aparicin del carcter indicado Devuelve una subcadena que empiece en la posicin y tenga la longitud que nosotros queramos

Comparacin
funcin strcmp(cadena1,cadena2); strcasecmp(cadena1,cadena2); strncmp(cadena1,cadena2,tamao); descripcin Compara dos cadenas siendo sensible a maysculas y minsculas Compara dos cadenas sin ser sensible a maysculas y minsculas Compara los N primeros caracteres de una cadena

Alteracin
funcin chop(cadena); ltrim(cadena); rtrim(cadena) ; trim(cadena); str_pad(cadena,longitud,relleno,lugar); descripcin Devuelve la cadena de caracteres sin espacios en blanco ni saltos de linea Elimina los espacios en blanco que estn a la izquierda de una cadena Igual que ltrim pero con el lado derecho Elimina espacios en blanco a ambos lados de una cadena Comprueba si la longitud de la cadena es menor que el valor indicado, si es as aade los caracteres necesarios. El lugar de aadir puede ser: STR_PAD_RIGHT para aadirlos por la derecha(opcin por defecto), STR_PAD_LEFT para la izquierda y STR_PAD_BOTH para ambos lados Repite un carcter el numero de veces indicado Convierte toda la cadena a minsculas Convierte toda la cadena a maysculas Convierte en mayscula el primer carcter de una cadena Convierte en maysculas el primer carcter de cada palabra de la cadena Sustituye una palabra por otra dentro de una cadena Traduce los caracteres que deseemos Sustituye una porcin del contenido de una

str_repeat(carcter,numero_veces); strtolower(cadena); strtoupper(cadena); ucfirst(cadena); ucwords(cadena); str_replace(subcadena1,subcadena2,cadena); strtr(cadena,originales,traducidos); substr_replace(cadena,nueva,comienzo,longitud);

35

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

cadena Veamos algunos ejemplos de uso.


$cadena = "hola mundo!!!"; $valor = strlen($cadena); //$valor valdria 13 $valor = substr_count($cadena, "!");// $valor valdria 3 $valor = strchr($cadena,"!"); //$valor valdria "!!!" $valor = chop($cadena); //$valor valdria "holamundo!!!" $valor = strtoupper($cadena); //$valor valdra "HOLA MUNDO!!!" $valor = strtr($cadena,"aou",""); //$valor valdra "hl mnd!!!"

5.3.2. Manejo de arrays de datos:


Un array (o matriz, como tambin son llamados) es un tipo de variable, con la singularidad de que no contiene un nico valor, sino un conjunto de valores referenciados con un ndice. Un array se puede crear a travs de la funcin array(). sta toma un cierto nmero de parejas clave valor separadas con coma. Y para acceder a su valor en la variable, hay que escribir el nombre de la variable y el ndice ( tambin llamado clave o key) entre corchetes.
<?php $mi_array = array( key => value , ... ); // key puede ser un entero o una cadena de texto // value puede ser cualquier valor ?>

Veamos un ejemplo:
<?php $ciudades = array( 0=>"salamanca", 1=>"valladolid", 2=>"sevilla"); echo $ciudades[0]; //mostrara: salamanca ?>

PHP tiene la ventaja de que se pueden crear arrays dinmicamente. Es decir sin usar la funcin array(), e incluso podemos aadir ms entradas a nuestro array.
<?php $ciudades[3] = "barcelona"; $nuevo_array[0] = "pepe"; $nuevo_array[1] = "jose"; ?>

5.3.2.1.

Uso asociativo de arrays

Como hemos comentado en un ejemplo, en PHP los ndices pueden ser nmeros o cadenas de texto. A los arrays cuyos ndices son cadenas de texto se les llama arrays asociativos. Estos arrays tienen la ventaja de que es ms fcil identificar cual es el contenido por el nombre de su clave. Por ejemplo:
<?php $direccion = array("calle" => "Gran va",
36

PHP BASICO

"portal" => 23, "piso" => 5, "letra" => "B", "telefono" => 91234567); ?>

5.3.2.2.

Arrays multidimensionales.

Dentro de un array se pueden almacenar todos los tipos de datos soportados por php, por lo que es posible incluir otros arrays. Imaginemos el caso anterior de la direccin, en la que podramos tener ms de un numero de telefono, el mvil y el de casa:
<?php $telefonos = array("casa" => 91234567, "mvil" => 61234567); $direccion = array("calle" => "Gran va", "portal" => 23, "piso" => 5, "letra" => "B", "telefono" => $telefonos); ?>

Hemos incluido el array $telefonos dentro de la clave telefono de nuestro array direccin. La forma de acceder sera muy sencilla:
<?php echo $direccin["telefono"]["casa"]; //Mostrara: 91234567 ?>

Para ver una forma de recorrer un array, mira el bucle foreach dentro de la seccin Bucles, en Estructuras de control.

5.3.2.3.

Funciones de manejo de arrays

Aqu veremos algunas funciones que se suelen usar bastante. Para el listado completo visitar: http://www.php.net/manual/es/ref.array.php Funcin array_key_exists array_keys array_merge array_pop array_push array_values count ia_array Descripcin Comprueba si el ndice o clave dada existe en la matriz Devuelve todas las claves de una matriz Combina dos o ms matrices Extrae el ltimo elemento de la matriz Inserta uno o ms elementos al final de la matriz Devuelve todos los valores de una matriz Cuenta los elementos de una matriz o propiedades de un objeto Nos dice si una variable es un array o no

5.3.3. Variables predefinidas


PHP tiene un buen nmero de variables predefinidas de mbito global que pueden ser accedidas en cualquier punto de nuestro script. Ms adelante veremos un punto ms centrado en explicar el mbito de las variables. Las siguientes variables tambin son conocidas como superglobales. Su contenido suelen ser arrays de datos.
37

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Variable $GLOBALS $_SERVER $_GET $_POST $_FILES $_REQUEST $_SESSION $_ENV

Definicin Hace referencia a todas las variables disponibles en mbito global Informacin del servidor y del entorno de ejecucin variables HTTP GET variables HTTP POST Variables de Carga de Archivos HTTP Variables HTTP Request (contiene por defecto las variables $_GET, $_POST y $_COOKIE) Variables de sesin Variables de entorno. Muchas son entregadas por el intrprete de comandos bajo el que PHP est corriendo y diferentes sistemas suelen tener diferentes tipos de intrpretes de comandos, el listado de variables se puede encontrar en la documentacin del intrprete de comandos que use su sistema. Cookies HTTP

$_COOKIE

5.4. Estructuras de control:


Con las estructuras de control, podremos aadir mucha ms lgica a nuestros scripts.

5.4.1. Sentencias condicionales La sentencia if


La sentencia if, sirve para ejecutar un cdigo si se cumple cierta condicin. Su estructura es la siguiente:
Si (condicin){ ejecuta este cdigo } en caso contrario { ejecuta este otro }

Vemoslo con cdigo php:


<?php $edad = 18; if($edad >= 18){ //Si $edad es mayor o igual a 18 echo "Puedes sacarte el carne de conducir"; } else { //si no echo "No puedes sacarte el carne de conducir"; } ?>

En este caso, la sentencia else significa en caso contrario. Se puede colocar una sentencia elseif que permite aadir una condicin al caso contrario. Veamos un ejemplo juntando operadores lgicos y operadores de comparacin.
<?php $edad = 18; $carnet = true; if($edad >= 18 && $carnet == true){ //si edad es mayor o igual a 18 y
38

PHP BASICO

carnet es igual a verdadero. echo "Puedes conducir"; } elseif ($edad >=18 && $carnet != true) { //si edad es mayor o igual a 18 y carnet no es igual a verdadero echo "No puedes conducir pero puedes sacarte el carnet"; } else{ echo "No puedes conducir ni sacarte el carnet"; }

Ntese que en valores booleanos hay varias expresiones que funcionan igual. Por ejemplo.
<?php $valor = true; //Si queremos que un if se ejecute si el valor es verdadero podemos hacer por ejemplo: if ($valor == true)... //si valor es igual a verdadero if ($valor) //Si valor es verdadero //aunque hay mas formas de complicarlo :) //si queremos que una sentencia if se ejecute cuando valor sea falso podemos hacer lo siguiente if ($valor == false)... //si valor es igual a falso if ($valor != true)... //si valor no es igual a verdadero if (!$valor)... //si "no valor" es verdadero (es decir si valor es falso) Recordar que una sentencia if se ejecuta si el resultado de la condicin es verdadero, por lo que para ejecutarse cuando el contenido de una variable es falso, entonces hay que "negar" esa variable. ?>

Nota: El contenido de un if deber ir siempre entre llaves. Aunque se pueden omitir si el contenido es slo y exclusivamente una accin. Por ej:
<?php //correcto if($i == 1) echo "i es igual a 1"; //incorrecto if($i == 1) echo "i es igual a 1"; $i++; //correcto if($i == 1){ echo "i es igual a 1"; $i++; } ?>

5.4.2. Switch
Con la estructura switch podremos hacer que se ejecute cierto cdigo en concreto, en funcin del valor de una variable. Es como anidar varios if.
<?php switch($variable){ case 1: echo '$variable es igual a 1'; break; case 2: echo '$variable es igual a 2'; break; case 3:

39

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

echo '$variable es igual a 3'; break; default: echo '$variable no es igual ni a 1 ni a 2 ni a 3'; break; } //esto es igual a: if($variable == 1)} '$variable es igual a 1'; }elseif($variable == 2)} '$variable es igual a 2'; }elseif($variable == 3)} '$variable es igual a 3'; }else{ '$variable no es igual ni a 1 ni a 2 ni a 3'; }else ?>

con la sentencia default podemos decir que se ejecute cdigo que no corresponda con ningn caso que propongamos.

5.4.3. Bucles
Hay 3 tipos, para valor haz, mientras valor haz y haz mientras valor, o como comentaba Coti, profesor de la Universidad de Salamanca: metralleta, John Wayne y Clint Eastwood. En php son llamados for, while y do while.

bucle for
Es el tipo para valor haz o bucle metralleta (es decir se disparara tantas veces como balas haya en el cargador). El bucle for consta de 3 partes: Inicializacin: a una variable se le da un valor Condicin: Cada vez que se inicie el bucle se valorar esta condicin, como cualquier sentencia if, se ejecutara si el resultado de la condicin es verdadero. Actualizacin: es la parte en la que se puede cambiar el valor de la variable inicializada (esta parte puede quitarse si actualizamos el valor dentro del bucle)

Veamos un ejemplo:
<?php for($i = 1; $i <10; $i++){ ... } //es lo mismo que for($i = 1; $i <10; ){ ... $i++; ... } ?>

En este caso este bucle se disparar hasta que el valor de $i sea 10.

Bucle foreach
40

PHP BASICO

PHP y algunos lenguajes de programacin tiene una especie de bucle for que se usa para recorrer arrays, el bucle foreach. Su declaracin es la siguiente:

foreach($nombre_variable_con_array $nombre_inventado_valor)

as

$nombre_inventado_indice

<? $mi_array = array( "uno" => 1, "dos" => 2, "tres" => 3, "cuatro" => cuatro ); foreach($mi_array as $indice => $valor) { print "$mi_array[$indice] => $valor. "; } //esto mostrara: 1 => 1. 2 => 2. 3 => 3. 4 => 4. //si quisiramos que la salida fuese parecida a uno => 1. dos = 2... el foreach tendra que ser as foreach($mi_array as $indice => $valor) { print "$indice => $valor. "; } ?>

Bucle While
El bucle while o bucle John Wayne (es decir primero preguntar si la el resultado de la comparacin es verdadero antes de disparar el contenido del bucle).
<?php $i = false; while($i == true){ ... if (condicionquequeramos) $i = false; ... } ?>

Bucle Do...While
El bucle dowhile o bucle Clint Eastwood (es decir primero se ejecutar una vez y despus preguntar si la el resultado de la comparacin es verdadero ). Su diferencia, como es obvio con el bucle while, es que este bucle se ejecutar SIEMPRE como mnimo una vez.
<?php $i = 1; do{ echo "este bucle se ejecutara solo una vez"; }while($i < 1); ?>

Ojo con las condiciones, ya que si las colocamos mal, podremos provocar un bucle infinito en el que no se saldra nunca. Por ejemplo:

41

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

<?php $i = 1; do{ echo "este bucle se ejecutara solo una vez"; }while($i == 1); //Al no variar el valor de $i este bucle do-while siempre se ejecutara ?>

5.4.4. Break y Continue Break


Con Break podemos parar la ejecucin de un bucle o de una sentencia switch y hacer que se salga de dicha estructura de control. por ejemplo en un switch, si al final del cdigo que se ejecuta dentro de un case, se ejecutara el siguiente case si lo hubiera. Es decir:
<?php switch ($valor){ case 1: echo "hola"; case 2: echo "adios"; break; case 3: echo "hola y adios"; break; } ?>

En este cdigo si $valor fuese igual a 1, se ejecutara el case 1 y case 2 ya que dentro de case 1 no se ha colocado el break.

Continue
Con continue podemos volver al principio del bucle desde cualquier parte del mismo.

5.5. Funciones
Durante todo el manual se ha hecho referencia a la palabra funcin. Pero que es una funcin exactamente?. Podramos definirla como un conjunto de instrucciones que nos permiten resolver una tarea especfica. Estas tareas pueden ser muy simples como sumar una serie de nmeros, o ms complejas como sacar cierta informacin de una base de datos. Antes de crear una funcin para tratar datos, es conveniente mirar la amplia referencia de funciones que tiene php http://www.php.net/manual/es/funcref.php Una funcin normal en php se escribe de la siguiente forma:
<?php function nombre_funcin($parametro_1, $parametro_2 ... $parametro_n){ instruccion_1; instruccion_2; .... instruccion_n; return $variable; //con esto podramos devolver un valor para almacenar en otra variable o para usarla en otra funcin

42

PHP BASICO

} ?>

Recuerda divide y vencers, intenta simplificar y dividir las instrucciones en funciones especificas. No es aconsejable tener diferentes funcionalidades dentro de una funcin. A la hora de revisar y mantener tu cdigo ser ms fcil. Veamos una funcin simple en la que sumamos 3 nmeros pasados como parmetros:
<?php //Declaramos la funcin function suma($valor_1, $valor_2, $valor_3){ $suma = $valor_1 + $valor_2 + $valor_3; return $suma; //con esto podramos devolver un valor para almacenar en otra variable o para usarla en otra funcin } //llamamos a la funcin echo suma(1,2,3); //el resultado por pantalla sera: 6 ?>

5.5.1. mbitos de Variables


Existen 2 tipos de mbitos, globales y locales. Las variables globales, como su nombre indica, pueden ser accedidas desde todo nuestro script, y las locales, solamente se pueden acceder desde la funcin donde estn declaradas. Las variables locales desaparecen en cuanto se termina de ejecutar la funcin. Por ejemplo:
<?php //ejemplo de variable global: $mi_variable_global = "pepe"; function mi_funcin(){ //ejemplo de variable global: $mi_variable_local = "jose"; } ?>

Para poder usar las variables globales dentro de una funcin, hay que usarla a travs de la variable superglobal $GLOBALS, o declarando la variable con el comando global. Si no, la variable que utilizaramos dentro de la funcin seria realmente una variable local. Ojo, las variables superglobales vistas en el apartado de variables predefinidas, no necesitan ser declaradas mediante el comando global Vemoslo mejor con un ejemplo:
<?php //variable global $mi_variable_global = "pepe"; function modificar_variable_global(){ //uso errneo de variable global: $mi_variable_global = "jose"; } echo $mi_variable_global; //mostramos el valor de la variable global echo "<br />"; //introducimos un salto de linea modificar_variable_global();

43

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

echo $mi_variable_global; variable global ?>

//mostramos otra vez el valor de la

El resultado en este caso sera: pepe pepe Ya que no hemos instanciado correctamente nuestra variable global. En cambio si hacemos esto: <?php //variable global $mi_variable_global = "pepe"; function modificar_variable_global(){ //uso de variable global a trabes de la variable superglobal $GLOBALS: $GLOBALS['mi_variable_global'] = "jose"; //tambin se puede hacer de esta forma: global $mi_variable_global; $mi_variable_global = "jose"; } echo $mi_variable_global; //mostramos el valor de la variable global echo "<br />"; //introducimos un salto de linea modificar_variable_global(); echo $mi_variable_global; //mostramos otra vez el valor de la variable global, ahora s modificada correctamente ?> El resultado seria: pepe jose

5.5.1.1.

Variables estticas

Como hemos comentado el las variables de mbito local se destruyen al terminar la ejecucin de nuestra funcin, pero existe una forma de hacer preservar su valor, gracias al comando static. Con l, nuestras variables locales mantendrn su valor cada vez que nuestra funcin sea ejecutada. Por ejemplo:
<?php function test(){ static $i = 0; $i++; echo $i." "; } test(); test(); test(); ?>

44

PHP BASICO

Si ejecutamos este cdigo, la salida por pantalla sera la siguiente: 1 2 3 Si nuestra variable $i no estuviese declarada como static, la salida sera 1 1 1

5.5.2. Paso de variables


Cuando se pasa una variable a una funcin (un parmetro), esto se puede hacer de 2 formas, por valor, o por referencia).

5.5.2.1.

Paso por valor

El paso por valor (por defecto en PHP), hace una copia de la variable que es la que se usa dentro de la funcin, por lo que si la variable cambia dentro de la funcin, la variable original estar intacta.
<?php function mi_funcin($parametro){ $parametro++; } $mi_variable = 1; echo "mi_variable vale: ".$mi_variable." antes de llamar a la funcin"; mi_funcin($mi_variable); echo "mi_variable vale: ".$mi_variable." despus de llamar a la funcin"; ?> Esto hara que la salida por pantalla fuese la siguiente: mi_variable vale: 1 antes de llamar a la funcin mi_variable vale: 1 despus de llamar a la funcin

5.5.2.2.

Paso por referencia

Con el paso por referencia, a diferencia del paso por valor, se modifica el valor de la original. Hay que anteponer el smbolo & al nombre del parametro en la funcin:
<?php function mi_funcin(&$parametro){ //atencin al smbolo & $parametro++; } $mi_variable = 1; echo "mi_variable vale: ".$mi_variable." antes de llamar a la funcin"; mi_funcin($mi_variable); echo "mi_variable vale: ".$mi_variable." despus de llamar a la funcin"; ?> Esto hara que la salida por pantalla fuese la siguiente: mi_variable vale: 1 antes de llamar a la funcin mi_variable vale: 2 despus de llamar a la funcin

45

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

5.5.2.3.

Parmetros por defecto

Podemos definir valores por defecto para los parmetros. Sirven para que los parmetros contengan un valor predefinido, que ser el que tomen si no se les pasa ningn valor al llamar al la funcin. Se definen asignando un valor al parmetro al declararlo en la funcin.
<?php function mi_funcin($parametro_1 = "pepe", $parametro_2 = "jose"){ .... } mi_funcin(); //al llamar a la funcin as, dentro de nuestra funcin $parametro_1 valdria "pepe" y parametro_2 valdria "jose" mi_funcin("Antonio"); //$parametro_1 valdria "Antonio" y parametro_2 valdria "jose" mi_funcin("Antonio","rosa"); //$parametro_1 valdria "Antonio" y parametro_2 valdria "rosa" ?>

5.5.3. Recursividad
PHP nos permite crear funciones recursivas. Esto es, funciones que se puedan llamar a s mismas. En otras palabras, es como hacer un bucle con la propia funcin. Mucho cuidado con hacer una funcin recursiva ya que puede ocurrirnos lo mismo que con bucles infinitos, y adems una funcin recursiva es peligrosa si tratamos datos grandes, ya que si utilizamos pasos por valor, el consumo de memoria puede ser muy grande. Ejemplo de funcin recursiva
<?php $i = 0; function suma_hasta_5(){ global $i; if ($i<5){ $i++; suma_hasta_5(); } else { echo "Ya hemos llegado a 5"; } } suma_hasta_5(); ?>

5.6. Salidas por pantalla


Como hemos visto a lo largo de este temario, se ha usado la funcin echo para mostrar texto por pantalla. Es hora de conocer otras formas como print, printf, print_r o var_dump.

5.6.1.1.

print y echo

Son prcticamente iguales pero tienen alguna diferencia, por ejemplo echo() puede tomar expresiones mltiples, como:

46

PHP BASICO

<?php echo "uno", "dos", "tres"; print "uno", "dos", "tres"; //esto dara error ?>

mientras el print() no. Sin embargo, se utiliza el print() como parte de una expresin ms compleja, donde el echo() no se podra aplicar, debido a que print() puede retornar un valor true o false y el echo() no. Otra diferencia es la velocidad donde echo es aproximadamente un 50% ms rpida.

5.6.1.2.

printf

Sirve par dar formato a un texto y mostrarlo por pantalla (hay una funcin que se llama sprintf que hace exactamente lo mismo pero sin mostrarlo por pantalla, es decir, para poder almacenar el resultado en una variable). la sintaxis seria: printf(cadena,parametro1,parametro2) En la cadena habr patrones (sealizados con un smbolo %) y el resto del texto que queramos. Los parmetros sern las variables o valores que queramos insertar en la cadena, habr tantos (y en orden) como patrones haya. Veamos un ejemplo:
<?php $nombre = "pepe"; $numero = 1; printf("este es un ejemplo de un nombre %s y este otro de un numero %d",$nombre,$numero); ?>

El significado del patrn variara segn el carcter que tenga al final: especificador b c definicin el argumento es interpretado como un nmero entero, y presentado como un nmero binario. el argumento es interpretado como un entero, y presentado como el carcter ASCII con dicho valor. el argumento es tratado como un entero y presentado con notacin decimal el argumento es tratado como un entero y presentado con notacin exponencial. el argumento es tratado como un double y presentado como un nmero de coma flotante. el argumento es tratado como un entero, y presentado como un nmero octal. el argumento es tratado como un entero y presentado como un nmero hexadecimal (con minsculas). el argumento es tratado como un entero y presentado como un nmero hexadecimal (con maysculas). el argumento es tratado como una cadena y es presentado como tal.

d e f o x

47

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

5.6.1.3.

print_r

print_r nos muestra el contenido de una variable de forma que sea legible por humanos.
<?php $mi_variable = array("uno" => 1, "dos" => 2, "tres" => 3); print_r ($mi_variable); ?>

Esto nos mostrara:


Array ( [uno] 1 [dos] 2 [tres] 3 )

5.6.1.4.

var_dump

Es similar a print_r solo que adems nos da mas informacin acerca del contenido de la variable, como cantidad (en caso de arrays) y tipos de dato. En el mismo ejemplo que antes:
<?php $mi_variable = array("uno" => 1, "dos" => 2, "tres" => 3); var_dump ($mi_variable); ?>

Esto nos mostrara: array(3) { [uno] int(1) [dos] int(2) [tres] int(3) }

5.7. Actividades
5.7.1. Tipos de datos, cadenas y arrays.
5.7.1.1. Actividad 1

Definir una variable de cada tipo: integer, double, string y boolean. Luego imprimirlas en la pgina, una por lnea.

5.7.1.2.

Actividad 2

Escribe tu nombre y tu edad por pantalla. Tu edad deber ir dentro de una variable. Haz una versin con comillas simples y otra con comillas dobles, expandiendo la variable dentro de la cadena en la versin que sea posible.

5.7.1.3.

Actividad 3

Define un array con valores del 1 al 10, con los valores desordenados e imprimelo por pantalla con print_r, despus con las funciones de arrays que proporciona php ordena el array de mayor a menor y muestralo por pantalla. http://www.php.net/manual/es/book.array.php

48

PHP BASICO

5.7.1.4.

Actividad 4

Crea 2 arrays asociativos con 5 elementos cada uno, con el contenido que tu quieras, combnalos y saca el contenido por pantalla usando print_r. Despus usa array_push y array_pop (revisa la documentacin en http://www.php.net/manual/es/book.array.php), y vuelve a sacar el contenido por pantalla.

5.7.2. Estructuras de control


5.7.2.1. Actividad 1

Genera un valor aleatorio entre 1 y 5, y escribir el nmero en castellano: (ej, si sale el numero 1, escribir uno). Para generar un numero aleatorio, usar la funcin rand http://php.net/manual/es/function.rand.php

5.7.2.2.

Actividad 2

Di si se ejecutara el if o el else en cada caso.


<?php $valor1 = 1; $valor2 = 3; if ($valor1 >= $valor2){ //script if } else { //script else } ?> <?php $valor1 = 1; $valor2 = 1.0; if ($valor1 == $valor2){ //script if } else { //script else } ?> <?php $valor1 = 1; $valor2 = "1"; if ($valor1 == $valor2){ //script if } else { //script else } ?> <?php

49

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

$valor1 = true; if ($valor1){ //script if } else { //script else } ?> <?php $valor1 = false; if (!$valor1){ //script if } else { //script else } ?> <?php $valor1 $valor2 $valor3 $valor4 = = = = true; false; 4; 10;

if (($valor1 && ($valor3 <= $valor4) && $valor1 != $valor2) || ($valor4 3 == $valor3){ //script if } else { //script else } ?>

5.7.2.3.

Actividad 3

Crea 3 bucles, uno con for, otro con while, y otro con do-while, que den 10 vueltas. Comprueba las vueltas poniendo salidas por pantalla.

5.7.2.4.

Actividad 4

Crea un bucle for, que de 5 vueltas, pero el indice deber empezar en el nmero 27 e ir en decremento.

5.7.2.5.

Actividad 5

Crea un bucle for que de 5 vueltas. Pero el ndice que uses, en vez de ir sumando de uno en uno, deber ir de 2 en 2. Adems incluye dentro del for, un switch que: En el primer caso, muestre por pantalla a suma del indice consigo mismo. En el segundo caso, muestre la resta del indice consigo mismo. En el tercer caso, muestre la multiplicacin del indice por 4 y dividido por 3 (el calculo habr que hacerlo en una sola expresin y el resultado deber aparecer en decimales).

50

PHP BASICO

En el cuarto caso, habr que crear un bucle do_while en el que se rellene un array con valores desde el 0 hasta el valor que tenga el ndice. Y mostrar dicho array con un var_dump por pantalla. En el quinto caso, comprueba si el nmero es mltiplo de 5. En caso de serlo deber aparecer en pantalla, el mensaje Es mltiplo de 5, y en caso contrario, No es mltiplo de 5.

5.7.3. Funciones
5.7.3.1. Actividad 1

Crea una funcin en la que definas un array bidimensional (2 dimensiones) en el que estn el nombre y la edad de 5 personas. La edad ser un nmero aleatorio entre 16 y 22. En otra funcin al que se le pase por referencia el array creado, recorre dicho array con un bucle while y por cada persona escribe Hola nombre, tu edad es edad. Despus de escribirlo, debers borrar el contenido de ese valor del array (http://php.net/manual/es/function.unset.php) slo en caso de que la persona sea menor de edad (edad menor o igual que 18), y se deber mostrar por pantalla que se ha procedido al borrado de dicho valor.

5.7.3.2.

Actividad 2

Implementa una funcin en la que se calcule el sumatorio de un numero dado. El resultado ser una cadena de texto con el formato El sumatorio del numero nmero es resultado (ej: El sumatorio del numero 4 es 10) que deber irse agregando a un array declarado de forma global. Para dar formato a esa cadena de texto, usa la funcin sprintf. Despus crea un bucle do_while que dar un numero aleatorio de vueltas entre 15 y 20, y donde se llamar dicha funcin con el valor que tenga el ndice en ese momento. Al salir llamara a otra funcin que recorrer el array global en sentido inverso y mostrar el contenido, con una linea por cada valor que contenga el array. El sumatorio de un numero es la suma de los n-1 enteros anteriores a n. Por ejemplo el sumatorio de 4 es 10 (4 + 3 + 2 + 1)

5.7.3.3.

Actividad 3

Escribe una funcin recursiva en la que se escribir una serie de fibonacci, que se repetir tantas veces como valga el valor pasado. Utiliza una variable esttica para ir almacenando el ndice. La serie de fibonacci es aquella en la que el siguiente termino en la sucesin, equivale a la suma de los 2 anteriores. 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 Por ejemplo, si pasramos el valor 5, en pantalla nos debera aparecer: 0, 1, 1, 2, 3. Utiliza el tratamiento de cadenas adecuado para que despus del ltimo valor aparezca un punto en vez de una coma.

51

FORMULARIOS Y SUS METODOS

Formularios y sus Mtodos


Antes de meternos con la forma de funcionar php con los formularios, vamos a pegarle un repaso a las etiquetas html que pueden componer un formulario.

form
La etiqueta FORM es la etiqueta contenedora de un formulario en HTML. Su sintaxis bsica es la siguiente:
<FORM ACTION="nuestro_script.php" METHOD="post/get"> ... formulario ... </FORM>

Con el atributo action, indicamos cual es el nombre del script que procesar el formulario, y con el atributo method, indicamos como su nombre indica, el mtodo por el cual van a ser procesados, post, o get que los veremos un poco ms adelante.

Cuadro de texto
Algunos de los componentes de un formulario (por ejemplo: campos ocultos, cuadros de texto, cuadros de texto de contrasea, botones) usan la etiqueta input y varan definiendo un valor diferente en el atributo type. vamos a centrarnos ahora en los cuadros de texto.

53

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Los cuadros de texto son los campos donde podremos introducir los datos de nuestro formulario. Se suelen usar para colocar nombres, direcciones, fechas, etc es decir, la mayora de los datos a introducir en un formulario. Su sintaxis es la siguiente:
<input type="text" namemane="nombre" value="valor por defecto">

Con el atributo type=text es con el que le decimos que es un campo de texto, el atributo name= hace que podamos identificar este cuadro cuando mandemos los datos a php, y con value podemos poner un valor por defecto si queremos (como volver a colocar los datos del formulario si al hacer una validacin desde php, se han encontrado errores)

Cuadro de texto contrasea


Los atributos son exactamente los mismos que un cuadro de texto, solo que cambia el valor type. En este caso es password. Con este tipo de campo de texto, cada vez que introduzcamos un carcter, ste se ver como un asterisco, por seguridad.
<input type="password" name="contrasenia">

Aunque tiene la posibilidad de poner un atributo value con un valor por defecto, no se suele usar, ya que por seguridad es aconsejable que el usuario siempre meta la contrasea.

Ficheros
Igual que en un cuadro de texto o en un campo de contrasea, los atributos son iguales. Pero su representacin ser muy distinta. Aparecer un cuadro de texto con un botn al lado, que al pulsarlo nos permitir elegir un fichero de nuestro equipo para mandarlo al formulario. El tamao mximo del fichero que se podr cargar, depender de la configuracin de nuestro servidor.
<input type="file" name="archivo">

Checkbox
Los checkbox se suelen usar cuando se quiere ofrecer al usuario la posibilidad de elegir varios items.
<input type="checkbox" name="nombre" value="valor_al_estar_seleccionado" checked>

Aqu, el value, no es un valor por defecto que ver el usuario, si no que es el valor que tendr cuando se seleccione el checkbox (a la hora de enviar el formulario a php). Con el atributo checked podemos decir si estar seleccionado cuando se cargue nuestro formulario.

Radiobutton
Es similar a un checkbox solo que entre un grupo de radiobuttons, solo podr haber 1 seleccionado.
<input type="radio" value="azul" checked name="color">

54

FORMULARIOS Y SUS METODOS

A diferencia de los checkbox y del resto de los input, cuando queramos dar varias opciones con un radiobutton referidos a una misma temtica, como por ejemplo: colores de carrocera: Rojo azul o negro. todos los radiobutton tendrn el mimo nombre en el atributo name. As cuando ejecutemos nuestro formulario, se mandar exclusivamente el valor del radiobutton seleccionado.

Botones
Tenemos 2 tipos principales, type=submit y type=reset Con submit ejecutaremos el formulario y haremos que se invoque a nuestro script php definido en el action de la etiqueta form. Con Reset pondremos los valores del formulario a como estuviesen originalmente.
<input type="submit" value="enviar" name="enviar">

Para botones que no tengan una lgica predefinida, se usar type=button. Estos se suelen usar si tenemos pensado dar algn tipo de lgica mediante javascript.

Campo oculto
HTML nos brinda la oportunidad de colocar campos ocultos, tiles para guardar identificativos. Ojo que no sean visibles en el navegador, no implica que sean del todo invisibles, ya que si se abre el cdigo fuente, se vern. As que no guardes informacin comprometida aqu :).
<input type="hidden" name="edad" value="55">

textareas
A diferencia de los cuadros de texto, los text areas tienen etiqueta de inicio y de cierre, y se pueden escribir varias lineas de texto (recordemos que en los cuadros de texto solo se puede escribir una)
<textarea rows="5" name="descripcion" cols="20">Es de color rojo</textarea>

Select box
<select name="dia"> <option selected value="lunes">lunes</option> <option value="martes">martes</option> <option value="miercoles">mircoles</option> </select>

Los select box son por defecto listas desplegables en las que podemos elegir un valor. Como en en el caso de los radiobutton o los checkbox el valor que se mandar es el del atributo value. Tenemos el atributo selected que har que cuando se cargue nuestra pgina, ese valor, sea el valor por defecto. Adicionalmente, este tipo de elemento html tiene la opcin de convertirse en una lista de seleccin mltiple en vez de una lista desplegable, aadindole el parametro MULTIPLE en la etiqueta select, adems hay que aadir unos corchetes al nombre para que funcione correctamente en php:

55

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

<select name="dia[]" MULTIPLE> <option selected value="lunes">lunes</option> <option value="martes">martes</option> <option value="miercoles">mircoles</option> </select>

6.1. GET y POST


Los mtodos Get y Post son 2 de los mtodos que tiene HTML para mandar informacin y son los que habitualmente se usan en PHP para gestionar formularios. Ambos mandan informacin pero la forma de hacerlo es radicalmente distinta. GET lo manda por URL (la direccin web a la vista) mientras POST de forma transparente. PHP nos permite acceder a nuestros valores mediante las variables superglobales predefinidas $_POST y $_GET. Ambas son arrays asociativos de datos en los que estarn nuestros valores. Por ejemplo si tenemos una caja de texto llamada edad podremos recoger la informacin de la siguiente forma:
<?php //si el $edad = //si el $edad = ?> mtodo elegido en nuestro formulario es GET $_GET['edad']; mtodo elegido en nuestro formulario es POST $_POST['edad'];

Ojo, si estamos intentando coger un fichero (<input type="file">), no lo encontraremos ni en $_GET ni en $_POST, si no en $_FILES. Y dispondr de ms informacin.
<?php //el array asociativo con el nombre de nuestro input tipo fichero: $_FILES['archivo']['name']; //contiene el nombre del fichero. $_FILES['archivo']['size']; //contiene el tamao del fichero en bytes ?>

$_FILES['archivo']['size'] devolver 0 si el proceso ha fallado (por ejemplo se ha sobrepasado el tamao mximo de carga) Veamos un ejemplo de un formulario completo con mtodo post (Nota: en nuestro ejemplo, nuestro script est en un fichero en la carpeta raz de nuestro dominio, y se llama index.php):
<?php //La forma habitual de saber si se ha ejecutado un formulario es viendo si esta definida la variable del botn de envo if (isset($_POST['enviar'])) { //si se ha mandado el formulario al pulsar el botn submit echo echo echo echo echo echo
56

'Tu nombre es '.$_POST['nombre']; '<br />'; 'Tu apellido es '.$_POST['apellido']; '<br />'; 'El color que has elegido es '.$_POST['color']; '<br />';

FORMULARIOS Y SUS METODOS

if (count($_POST['dia']) > 0){ echo 'Los dias que has escogido son:'; foreach ($_POST['dia'] as $valor){ echo $valor." "; } } else{ echo "No has escogido ningn valor en el select box multiple"; } echo '<br />'; if ($_POST['check']=="si"){ echo 'Has marcado el checkbox <br />'; }else{ echo 'No has marcado el checkbox <br />'; } echo 'El valor que has escogido en el primer grupo de radiobuttons es '.$_POST['radio1'].'<br />'; echo 'El valor que has escogido en el segundo grupo de radiobuttons es '.$_POST['radio2'].'<br />'; echo '<a href="index.php"> Volver al formulario</a>'; } else{//en caso de que no se haya enviado el formulario, nos muestra esto otro. ?> <html> <head><title>Formulario de ejemplo</title></head> <body> <form action="index.php" method="post"> Escribe tu nombre <input type="text" name="nombre"> <br /> Escribe tu apellido (es un campo contrase&ntilde;a, as que lo vers oculto) <input type="password" name="apellido"><br /> Elige un color. <select name ="color"> <option value="negro">negro</option> <option value="blanco">blanco</option> <option value="azul">azul</option> <option value="rojo">rojo</option> <option value="amarillo">amarillo</option> </select><br /> Elige uno o varios dias de la semana. Puedes elegir ms de uno dejando pulsada la tecla Ctrl <select name ="dia[]" multiple> <option value="lunes">lunes</option> <option value="martes">martes</option> <option value="miercoles">miercoles</option> <option value="jueves">jueves</option> <option value="viernes">viernes</option> <option value="sabado">sabado</option> <option value="domingo">domingo</option> </select> <br /> Si quieres, marca este checkbox <input type="checkbox" name="check" value="si"><br /> <hr /> Aqu un grupo de radio buttons <input type="radio" value="1" name="radio1"> 1 <br /> <input type="radio" value="2" name="radio1"> 2 <br /> <input type="radio" value="3" name="radio1"> 3 <br /> <input type="radio" value="4" name="radio1"> 4 <br /> <hr /> Aqu otro grupo de radio buttons diferente

57

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

<input <input <input <input

type="radio" type="radio" type="radio" type="radio"

value="a" value="b" value="c" value="d"

name="radio2"> name="radio2"> name="radio2"> name="radio2">

a b c d

<br <br <br <br

/> /> /> />

<input type="submit" name="enviar" value="Enviar"> </form> </body> </html> <?php } ?>

Cuando se mandan los datos por GET, como hemos dicho, los parmetros aparecern en la direccin web. La forma es: http://www.nuestrodominio.com/script.php?variable1=valor1&variable2=valor2&variablen =valorn Es decir. Tendremos la direccin a nuestro script, despus una interrogante ? que indicara que a partir de ese punto vendrn los pares de nuestras variables y sus valores, separadas por el smbolo ampersand &. En este ejemplo que hemos puesto, en php la forma de coger los datos seria:
<?php $variable1 = $_GET["variable1"]; $variable2 = $_GET["variable2"]; $variablen = $_GET["variablen"]; ?>

6.2. Otros
Aunque los veremos en un punto ms avanzado del curso, nombraremos ahora otros mtodos que tiene html. DELETE Borra el recurso especificado. PUT Sube o carga un archivo, de una forma ms eficiente que POST, pero la desventaja es que habitualmente los servidores compartidos no suelen tener activado PUT. HEAD: Pide que la respuesta idntica a la que correspondera a una peticin GET, pero sin el cuerpo de la respuesta. Esto es til para la recuperacin de meta-informacin escrita en los encabezados de respuesta, sin tener que transportar todo el contenido.

6.3. Actividad
Crea un formulario (post) tpico de registro de una pagina web, pero que valide que todos los campos y en caso de no introducir correctamente alguno (o no introducirlo), vuelva al formulario respetando los valores escritos (menos la contrasea). En caso correcto, haz una salida por pantalla con los valores. Y coloca un enlace para volver al formulario (no hace falta respetar los valores escritos por el usuario):
58

Nombre (slo texto) Apellidos (slo texto)

FORMULARIOS Y SUS METODOS

Usuario (texto y nmeros pero sin caracteres extraos ni espacios en blanco) Contrasea (texto y nmeros pero sin caracteres extraos ni espacios en blanco) Repetir contrasea (validar que ha introducido la contrasea 2 veces de forma correcta) E-mail (que por lo menos tenga una @ y un dominio con un punto despus de esta, p.ej: usuario@dominio.com) Genero (radio button masculino femenino) Comunidad autnoma en la que vive (select box normal) Elementos de ocio digital que posee: PC, mvil, PlayStation 3, Xbox 360, Wii, PSP, Nintendo DS. (Select box mltiple) Checkbox indicando si se quiere que se le mande informacin al correo.

Para tratamiento de cadenas se aconseja revisar las funciones de php dedicadas al tratamiento de cadenas. http://www.php.net/manual/es/ref.strings.php

59

Bases de datos Relacionales

Bases de Datos Relacionales

7.1. SQL: lenguaje de definicin y manejo de datos


Existen muchos tipos de bases de datos en funcin del modo en que almacenan y acceden a la informacin que guardan: relacional, jerrquica, en red, orientada a objetos, Ejemplos de gestores de bases de datos relacionales no hay muchos: MySQL, Oracle, PostGres, Informix, Microsoft SQL Server, mSQL, Un gestor de base de datos relacional almacena los datos en tablas, cada una de las cuales est formada por filas o registros, y que a su vez estn formadas por columnas o campos. El acceso a estas bases de datos se realiza mediante el lenguaje SQL (Structured Query Language). SQL es un lenguaje formal declarativo, estandarizado ISO, para manipular informacin en una base de datos. Es el lenguaje unificado para realizar consultas y dar instrucciones al gestor de base de datos. El lenguaje SQL (o ANSI SQL) sufri varias revisiones a lo largo del tiempo: Ao 1986 Nombre SQL-86 Alias SQL-87 Comentarios Primera publicacin hecha por ANSI. Confirmada por ISO en 1987.

61

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

1989

SQL-89

Revisin menor.

1992 1999

SQL-92 SQL:1999

SQL2 SQL2000

Revisin mayor. Se agregaron expresiones regulares, consultas recursivas (para relaciones jerrquicas), triggers y algunas caractersticas orientadas a objetos. Introduce algunas caractersticas de XML, cambios en las funciones, estandarizacin del objeto sequence y de las columnas autonumricas. ISO/IEC 9075-14:2006 Define las maneras en las cuales el SQL se puede utilizar conjuntamente con XML. Permite el uso de la clusula ORDER BY fuera de las definiciones de los cursores. Incluye los disparadores del tipo INSTEAD OF. Aade la sentencia TRUNCATE.

2003

SQL:2003

2006

SQL:2006

2008

SQL:2008

En la actualidad el SQL es el estndar de facto de la inmensa mayora de los SGBD comerciales. Y, aunque la diversidad de aadidos particulares que incluyen las distintas implementaciones comerciales del lenguaje es amplia, el soporte al estndar SQL-92 es general y muy amplio.

7.1.1. Lenguaje de definicin de datos (LDD)


El lenguaje de definicin de datos (Data Definition Language, o DDL), es el que se encarga de la modificacin de la estructura de los objetos de la base de datos. Existen cuatro operaciones bsicas: CREATE, ALTER, DROP y TRUNCATE.

7.1.1.1.

CREATE

Crea un objeto dentro de la base de datos. Puede ser una tabla, vista, ndice, trigger, funcin, procedimiento o cualquier otro objeto que el motor de la base de datos soporte. Ejemplo (crear una tabla)
CREATE TABLE 'TABLA_NOMBRE' ( 'CAMPO_1' INT, 'CAMPO_2' STRING )

62

Bases de datos Relacionales

7.1.1.2.

ALTER

Permite modificar la estructura de un objeto. Se pueden agregar/quitar campos a una tabla, modificar el tipo de un campo, agregar/quitar ndices a una tabla, modificar un trigger, etc. Ejemplo (agregar columna a una tabla)
ALTER TABLE 'TABLA_NOMBRE' ( ADD NUEVO_CAMPO INT UNSIGNED meel )

7.1.1.3.

DROP

Elimina un objeto de la base de datos. Puede ser una tabla, vista, ndice, trigger, funcin, procedimiento o cualquier otro objeto que el motor de la base de datos soporte. Se suele combinar con la sentencia ALTER. Ejemplo
ALTER TABLE ''TABLA_NOMBRE'' ( DROP COLUMN ''CAMPO_NOMBRE1'' )

7.1.1.4.

TRUNCATE

Trunca (borra) todo el contenido de una tabla. Ejemplo


TRUNCATE TABLE ''TABLA_NOMBRE1''

7.1.2. Lenguaje de manipulacin de datos (LMD)


7.1.2.1. Definicin

Un lenguaje de manipulacin de datos (Data Manipulation Language, o DML) es un lenguaje proporcionado por el sistema de gestin de base de datos que permite a los usuarios llevar a cabo las tareas de consulta o manipulacin de los datos, organizados por el modelo de datos adecuado.

7.1.2.2.

INSERT

Una sentencia INSERT de SQL agrega uno o ms registros a una (y slo una) tabla en una base de datos relacional.

Forma bsica
INSERT INTO ''tabla'' (''columna1'', [''columna2,... '']) VALUES (''valor1'', [''valor2,...''])

Las cantidades de columnas y valores deben ser iguales. Si una columna no se especifica, le ser asignado el valor por omisin. Los valores especificados (o implcitos) por la sentencia INSERT debern satisfacer todas las restricciones aplicables. Si ocurre

63

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

un error de sintaxis o si alguna de las restricciones no se cumple, no se agrega la fila y se devuelve un error. Ejemplo:
INSERT INTO mi_agenda (nombre, telfono) VALUES ('Juan Nadie', 987654321);

Cuando se especifican todos los valores de una tabla, se puede utilizar la sentencia acortada:
INSERT INTO ''tabla'' VALUES (''valor1'', [''valor2,...''])

Ejemplo (asumiendo que 'nombre' y 'nmero' son las nicas columnas de la tabla 'agenda_telefonica'):
INSERT INTO mi_agenda VALUES ('Juan Nadie', 987654321);

Formas avanzadas
Inserciones en mltiples filas Una caracterstica de SQL (desde SQL-92) es el uso de constructores de filas para insertar mltiples filas a la vez, con una sola sentencia SQL:
INSERT INTO ''tabla'' (''columna1'', [''columna2,... '']) VALUES (''valor1a'', [''valor1b,...'']), (''valor2a'', [''valor2b,...'']),...

Ejemplo (asumiendo que 'nombre' y 'nmero' son las nicas columnas en la tabla 'agenda_telefonica'):

INSERT INTO mi_agenda VALUES ('Juan Nadie', '987654321'), ('Luisa Amigo', '321654987');

Que poda haber sido realizado por las sentencias


INSERT INTO mi_agenda VALUES ('Juan Nadie', '987654321'); INSERT INTO mi_agenda VALUES ('Luisa Amigo', '321654987');

Copia de filas de otras tablas Un INSERT tambin puede utilizarse para recuperar datos de otros, modificarla si es necesario e insertarla directamente en la tabla. Todo esto se hace en una sola sentencia SQL que no implica ningn procesamiento intermedio en la aplicacin cliente. Un SUBSELECT se utiliza en lugar de la clusula VALUES. El SUBSELECT puede contener JOIN, llamadas a funciones, y puede incluso consultar en la misma TABLA los datos que se inserta. Lgicamente, el SELECT se evala antes que la operacin INSERT est iniciada. Un ejemplo:
INSERT INTO mi_agenda2 SELECT * FROM mi_agenda WHERE nombre IN ('Juan Nadie', 'Luisa Amigo')

64

Bases de datos Relacionales

7.1.2.3.

UPDATE

Una sentencia UPDATE de SQL es utilizada para modificar los valores de un conjunto de registros existentes en una tabla.
UPDATE ''tabla'' SET ''columna1'' = ''valor1'' ,''columna2'' = ''valor2'',... WHERE ''columnaN = ''valorN''

Ejemplo:
UPDATE mi_agenda SET telefono = '951786324' WHERE nombre = 'Juan Nadie';

7.1.2.4.

DELETE

Una sentencia DELETE de SQL borra uno o ms registros existentes en una tabla.
DELETE FROM ''tabla'' WHERE ''columna1'' = ''valor1''

Ejemplo:
DELETE FROM mi_agenda WHERE nombre = 'Juan Nadie';

7.1.3. Recuperacin de clave


Los diseadores de base de datos que usan una clave suplente como la clave principal para cada tabla, se encuentran normalmente con el problema de que es necesario recuperar automticamente la clave primaria de una sentencia SQL INSERT para su uso en otras sentencias SQL. La mayora de los sistemas no permiten sentencias SQL INSERT para retornar fila de datos. Por lo tanto, se hace necesario aplicar una solucin en tales escenarios. Las implementaciones ms frecuentes: Utilizando un procedimiento almacenado especifico para genera la clave suplente, realizar la operacin INSERT, y finalmente devolver la clave generada. Utilizando una sentencia SELECT especfica sobre una tabla temporal que contiene la ltima fila insertada. Utilizando una sentencia SELECT despus de la sentencia INSERT con funcin especfica que devuelve la clave primaria generada por el registro insertado ms recientemente. Utilizando una combinacin nica de elementos del original SQL INSERT en una sentencia SELECT posterior. Utilizando un GUID en la sentencia SQL INSERT y la recupera en una sentencia SELECT.

7.1.4. Disparadores (Triggers)

65

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Los disparadores (triggers) son definidos sobre la tabla en la que opera la sentencia INSERT, y son evaluados en el contexto de la operacin. Los disparadores BEFORE INSERT permiten la modificacin de los valores que se insertar en la tabla. Los disparadores AFTER INSERT no puede modificar los datos de ahora en adelante, pero se puede utilizar para iniciar acciones en otras tablas, por ejemplo para aplicar mecanismos de auditora.

7.2. Integridad referencial


La integridad referencial es una propiedad deseable en las bases de datos. Gracias a la integridad referencial se garantiza que una entidad (fila o registro) siempre se relaciona con otras entidades vlidas, es decir, que existen en la base de datos. Implica que en todo momento dichos datos sean correctos, sin repeticiones innecesarias, datos perdidos y relaciones mal resueltas. Todas las bases de datos relacionales gozan de esta propiedad gracias a que el software gestor de base de datos vela por su cumplimiento. En cambio, las bases de datos jerrquicas requieren que los programadores se aseguren de mantener tal propiedad en sus programas.

7.2.1. Ejemplo: Cmo funciona


Supongamos una base de datos con las entidades Persona y Factura. Toda factura corresponde a una persona y solamente una. Implica que en todo momento dichos datos sean correctos, sin repeticiones innecesarias, datos perdidos y relaciones mal resueltas. Supongamos que una persona se identifica por su atributo DNI (Documento nacional de identidad). Tambin tendr otros atributos como el nombre y la direccin. La entidad Factura debe tener un atributo DNI_cliente que identifique a quin pertenece la factura. Por sentido comn es evidente que todo valor de DNI_cliente debe corresponder con algn valor existente del atributo DNI de la entidad Persona. Esta es la idea intuitiva de la integridad referencial. Cundo se pueden producir errores en los datos? Cuando insertamos una nueva fila en la tabla secundaria y el valor de la clave fornea no existe en la tabla principal. Insertamos una nueva factura y en la columna DNI_cliente escribimos un dni que no est en la tabla de Personas (persona que no existe). Cuando modificamos el valor de la clave principal de un registro que tiene 'hijos', modificamos el DNI de una persona, sustituimos el valor que tena por un nuevo valor , si esa persona tena facturas asignadas, qu pasa con esas facturas, no pueden seguir teniendo DNI antiguo porque ese DNI ya no existe, en este caso hay dos alternativas, no dejar cambiar el DNI de la persona o bien cambiar el DNI_cliente de todas las facturas relacionadas. Cuando modificamos el valor de la clave fornea, el nuevo valor debe existir en la tabla principal. Por ejemplo cambiamos el DNI_cliente de una Factura, tena asignado el de una persona y ahora se le asigna a otra persona. El otro DNI debe existir en la tabla de personas.

66

Bases de datos Relacionales

Cuando queremos borrar una fila de la tabla principal y ese registro tiene 'hijos', por ejemplo queremos borrar Una persona si existen Facturas asignadas a esa persona, estos no se pueden quedar con el valor DNI de ese cliente, porque tendran asignado un DNI de una persona que no existe. En este caso tenemos dos alternativas, no dejar borrar la persona, o bien borrarla y poner a valor nulo el campo DNI_cliente de todos sus 'hijos'. Asociada a la integridad referencial estn los conceptos de actualizar los registros en cascada y eliminar registros en cascada.

Actualizacin y borrado en cascada El actualizar y/o eliminar registros en cascada, son opciones que se definen cuando definimos la clave fornea y que le indican al sistema gestor qu hacer en los casos comentados en el punto anterior. Actualizar registros en cascada: Esta opcin le indica al sistema gestor de la base de datos que cuando se cambie un valor del campo clave de la tabla principal, automticamente cambiar el valor de la clave fornea de los registros relacionados en la tabla secundaria. Por ejemplo, si cambiamos en la tabla de personas (la tabla principal) el valor 1 por el valor 10 en el campo DNI (la clave principal), automticamente se actualizan todos las facturas (en la tabla secundaria) que tienen el valor 1 en el campo DNI_cliente (en la clave ajena) dejando 10 en vez de 1. Si no se tiene definida esta opcin, no se puede cambiar los valores de la clave principal de la tabla principal. En este caso, si intentamos cambiar el valor 1 del DNI de la tabla de personas , no se produce el cambio y el sistema nos devuelve un error o un mensaje que los registros no se han podido modificar por infracciones de clave. Eliminar registros en cascada: Esta opcin le indica al sistema gestor de la base de datos que cuando se elimina un registro de la tabla principal automticamente se borran tambin los registros relacionados en la tabla secundaria. Por ejemplo: Si borramos una persona, automticamente todas las facturas de esa persona se borrarn de la tabla de Facturas. Si no se tiene definida esta opcin, no se pueden borrar registros de la tabla principal si estos tienen registros relacionados en la tabla secundaria. En este caso, si intentamos borrar una persona, no se produce el borrado y el sistema nos devuelve un error o un mensaje que los registros no se han podido eliminar por infracciones de clave. Por otra parte existen tres tipos de integridad referencial: Al elegir una integridad referencial completa, todas las columnas de una clave fornea deben ser nulas, o todas no nulas. Por ejemplo, en la definicin de una clave fornea de las tablas Persona (DNI) y Facturas (DNI_cliente) con este tipo de integridad referencial, le dice a nuestro sistema de gestin de bases de datos, que la clave (NULL, NULL) es aceptada, pero valores como (100, NULL) o (NULL, 100) violan la integridad referencial por que parte es nula y la otra es no nula. En el caso de parcial, permitimos parcialmente claves forneas con valores nulos, siempre y cuando el valor no nulo, corresponda con el valor de la columna correspondiente de la clave primaria. Con el mismo ejemplo, este tipo de integridad
67

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

referencial tambin admitira por ejemplo una clave (NULL, NULL) en el caso de nuestro ejemplo de 2 columnas, adems de los valores (NULL, 100) y (100, NULL) siempre y cuando una de las columnas de la clave primaria tenga (en este ejemplo) el valor 100 en alguna de los registros de la tabla. Y por ltimo con integridad referencial simple le diramos a nuestros sistema de gestin de bases de datos (siguiendo con nuestro ejemplo) que acepte claves forneas con los valores (NULL, NULL), (NULL, 100) y (100, NULL) tenga o no la clave primaria el valor 100 en la columna correspondiente de los registros de la tabla.

68

ACCESO A DATOS

Administracin

8.1. Manejo de usuarios


8.1.1. Usuarios por defecto
Siempre que queramos utilizar MySQL deberemos hacer login con un usuario autorizado y con los privilegios adecuados. MySQL permite asignar a cada usuario privilegios distintos, que determinan las tareas que podr realizar cada uno: acceder, modificar, consultar datos y realizar tareas administrativas y de control en la base de datos. El sistema de usuarios MySQL es independiente del sistema de usuarios de la plataforma Linux o Microsoft Windows en que est ejecutndose. Al instalar MySQL, por defecto se crea el usuario root, sin ninguna contrasea. Este el usuario ms importante, ya que posee total control sobre las bases de datos, por lo que lo primero que debemos hacer es proporcionarle una contrasea. De lo contrario, cualquier persona que tenga acceso local o remoto a nuestro ordenador podra acceder y realizar cualquier accin con los datos, las tablas o las bases de datos. Es aconsejable crear un nuevo usuario para acceder a las bases de datos, al que daremos solo los permisos necesarios para las tareas que debemos hacer con l, dejando a root solo para la tareas administrativas y de control. (Tambin es aconsejable borrar los usuarios que se crean por defecto).

69

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Los usuarios que MySQL crea por defecto al instalarse tienen distintos permisos segn se haya instalado sobre linux o Microsoft Windows.

8.1.1.1.

En Linux

Tras su instalacin, los privilegios de acceso por defecto se establecen ejecutando el script scripts/mysql_install_db. Este script lanza el servidor mysqld y crea los siguientes usuarios y permisos: root: es un superusuario con todos los permisos. Debe conectarse desde localhost. Carece de contrasea. usuario annimo que tiene todos los privilegios respecto de las bases de datos cuyos nombres sean test o empiecen por test_. Accede exclusivo desde localhost.

8.1.1.2.

En Microsoft Windows

En la instalacin por defecto, todos los usuarios locales (que accedan desde localhost) tienen todos los privilegios respecto de todas las bases de datos, sin necesidad de contrasea. Para asegurar la instalacin es conveniente eliminar estos usuarios annimos, y establecer unos nuevos con contrasea, as como fijar la contrasea del root o superusuario:
C:\> C:\mysql\bin\mysql mysql mysql> DELETE FROM user WHERE Host='localhost' AND User=''; mysql> QUIT C:\> C:\mysql\bin\mysqladmin reload C:\> C:\mysql\bin\mysqladmin -u root password tu_nueva_contrasea

Lo anterior solo establece contrasea para el usuario root que se conecta desde localhost. Si nuestra base de datos va a estar conectada a internet, necesitamos tambin asignar una contrasea a root cuando se conecte a travs de host (nombre de tu mquina, root@host):
C:\mysql\bin>mysqladmin u root -h tu_host password tu_password

8.1.2. Conectarse al servidor MySQL


Los programas cliente de MySQL espera por lo general que usted especifique los parmetros de conexin cuando quiere acceder a un servidor MySQL: El nombre de la mquina donde se est ejecutando el servidor MySQL. Su nombre de usuario. Su password.

Por ejemplo, el cliente mysql puede ejecutarse desde un prompt de lnea de comandos (indicado aqu por shell>) de la siguiente manera:
shell> mysql -h nombre_host -u nombre_usuario p su_clave

Las sintaxis alternativas de las opciones -h, -u, y -p son host=nombre_host, user=nombre_usuario, y password=su_clave.

70

ACCESO A DATOS

Ntese que no hay espacios entre -p o password= y la clave que le sigue. Los programas clientes de MySQL utilizan valores por defecto para cualquier parmetro que no se especifique: El nombre de servidor por defecto es localhost. El nombre de usuario por defecto es ODBC en Windows y su nombre de usuario Unix en Unix. No se aplica ninguna clave si -p no est especificado.

De esta manera, para un usuario de Unix con un nombre de usuario de jnadie, todos los siguientes comandos son equivalentes:
shell> shell> shell> shell> mysql -h localhost -u jnadie mysql -h localhost mysql -u jnadie mysql

Puede especificar valores diferentes para que se utilicen cuando se realiza una conexin de manera que no tenga que introducirlos en la lnea de comandos cada vez que invoca un programa cliente. Esto puede llevarse a cabo de diversas maneras: Puede especificar los parmetros de conexin en la seccin [client] de un archivo de opciones. La seccin relevante del archivo debera tener el siguiente aspecto:
[client] host=nombre_servidor user=nombre_usuario password=su_clave

Puede especificar algunos parmetros de conexin utilizando variables de entorno. El nombre del servidor para mysql puede ser especificado utilizando MYSQL_HOST. El nombre de usuario MySQL puede especificarse mediante USER (esto es para Windows y Netware nicamente). La clave se puede especificar utilizando MYSQL_PWD, aunque esto es inseguro.

8.1.3. Privilegios de usuarios


Se pueden asignar permisos actuando directamente sobre las tablas de la base de datos mysql, pero la forma mas cmoda y segura es, una vez hecho login como root, asignar permisos con el comando GRANT, por ejemplo:
mysql> grant select, insert on *.* to probador@'%' identified by 'mi_clave'; Query OK, 0 rows affected (0.17 sec)

Con este comando creamos un usuario llamado probador que tiene el derecho de seleccionar e insertar datos en todas las bases de datos y tablas (*.*), con la contrasea mi_clave. El signo % despus del nombre de usuario significa que el usuario puede hacer login desde cualquier mquina. Si en su lugar hubiramos escrito localhost solo podra conectarse desde local; y si queremos dar permiso al usuario desde una mquina remota, debemos escribir el nombre de dicha mquina maquina.dominio.org o su IP 198.162.1.100. El comando GRANT concede permisos, y en caso de no existir el usuario lo crea.
71

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Para retirar permisos de un usuario se usa el comando REVOKE:


mysql> REVOKE ALL ON *.* FROM probador@'%';

8.1.3.1.

Ejemplos

Permisos a probador para acceder por localhost y seleccionar, insertar datos, actualizar, crear, modificar y borrar tablas en todas las tablas de la base de datos mi_base_de_datos :

mysql> GRANT select, insert, update, create, alter, delete, drop ON mi_base_de_datos.* TO probador@localhost IDENTIFIED BY 'mi_clave';

Todos los permisos disponibles para la tabla primera dentro de la base de datos mi_base_de_datos a probador:

mysql> GRANT All ON mi_base_de_datos.primera TO probador@localhost IDENTIFIED BY 'mi_clave';

permiso exclusivo de conexin a probador a cualquier base de datos y tablas:

mysql> GRANT USAGE ON *.* TO probador@localhost IDENTIFIED BY 'mi_clave';

8.2. Manejo de datos


8.2.1. Copias de seguridad
MySQL incluye varias herramientas para la realizacin de copias de seguridad de la base de datos, mediante las que podremos poner a salvo nuestros datos y, en el eventual caso de que se pierdan, poder recuperarlos. Podemos realizar las copias de seguridad de varias formas: a travs de la sentencia SQL BACKUP TABLE. herramientas como puede ser mysqldump o mysqlhotcopy.

8.2.1.1.

Mediante BACKUP TABLE

Realiza una copia de una tabla llamada mitabla a la carpeta backups:

72

ACCESO A DATOS

BACKUP TABLE mitabla TO `/backups/

Para recuperar los datos:


RESTORE TABLE mitabla FROM '/backups/

8.2.1.2.

Comando mysqldump

Para realizar la copia de seguridad de la base de datos mibase al fichero copia_seguridad.sql:


mysqldump -opt -password=sucontrasea -user=nombreusuario mibase > archivo.sql

usuario y password para acceder a la base de datos que se esta haciendo el backup Para recuperar la informacin de un fichero y restaurar una copia de seguridad de la base de datos se utiliza el comando mysql. Otra forma mas extendida
mysql -password=sucontrasea -user=nombreusuario mibase < archivo.sql

73

ACCESO A DATOS

Acceso a datos

9.1. Introduccin
MySQL , como sistema gestor de bases de datos relacionales, est organizado a partir de tablas. Dichas tablas contienen campos. Y cada campo es capaz de contener un tipo de dato.

9.1.1. Tipos de datos


Al disear nuestras tablas tenemos que especificar el tipo de datos y tamao que podr almacenar cada campo. Una correcta eleccin debe procurar que la tabla no se quede corta en su capacidad, que destine un tamao apropiado a la longitud de los datos, y la mxima velocidad de ejecucin MySQL admite dos tipos generales de datos: nmeros y cadenas de caracteres. Y junto a estos se admiten otros tipos de datos especiales: formatos de fecha, enumerados.

9.1.1.1.

Datos numricos

En este tipo de campos solo pueden almacenarse nmeros, positivos o negativos, enteros o decimales, en notacin hexadecimal, cientfica o decimal.

75

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Tipo BIT o BOOL TINYINT

Descripcin nmero entero que puede ser 0 1 nmero entero con rango de valores vlidos desde -128 a 127. Si se configura como unsigned (sin signo), el rango de valores es de 0 a 255 nmeros enteros, con rango desde -32768 a 32767. Si se configura como unsigned, 0 a 65535. nmeros enteros; el rango de valores va desde 8.388608 a 8388607. Si se configura como unsigned, 0 a 16777215 nmeros enteros, en un rango de -2147463846 a 2147483647. Si configuramos este dato como unsigned, el rango es 0 a 4294967295 nmero entero con rango de valores desde 9223372036854775808 a 9223372036854775807. Unsigned, desde 0 a 18446744073709551615 nmeros decimales. Podemos especificar cuantos dgitos (m) pueden utilizarse (trmino tambin conocido como ancho de pantalla), y cuantos en la parte decimal (d). Mysql redondear el decimal para ajustarse a la capacidad nmero de coma flotante de precisin doble. Es un tipo de datos igual al anterior cuya nica diferencia es el rango numrico que abarca nmeros como cadenas

SMALLINT

MEDIUMINT

INT

BIGINT

FLOAT (m,d)

DOUBLE

DECIMAL

9.1.1.2.
Tipo CHAR VARCHAR

Caracteres o cadenas
Descripcin cadenas de longitud fija. Su longitud abarca desde 1 a 255 caracteres cadenas, en el mismo rango de 1 a 255 caracteres, pero en este caso, de longitud variable cadenas con un mximo de 255 caracteres. La diferencia entre la familia de datatypes text y blob es que la primera es para cadenas de texto plano (sin formato) y case-insensitive (sin distinguir maysculas o minsculas) mientras que blob se usa para objetos binarios: cualquier tipo de datos o informacin, desde un archivo de texto con todo su formato (se diferencia en esto de el tipo Text) hasta imgenes, archivos de sonido o vdeo cadenas con un rango de 255 - 65535 caracteres. La diferencia entre ambos es que TEXT permite comparar dentro de su contenido sin distinguir maysculas y minsculas, y BLOB si distingue

TINYTEXT, TINYBLOB

TEXT y BLOB

76

ACCESO A DATOS

MEDIUMTEXT, MEDIUMBLOB LONGTEXT, LONGBLOB,

textos de hasta 16777215 caracteres texto hasta mximo de 4.294.967.295 caracteres

Nota: Un campo CHAR ocupar siempre el mximo de longitud que le hallamos asignado, aunque el tamao del dato sea menor (aadiendo espacios adicionales que sean precisos). Mientras que VARCHAR solo almacena la longitud del dato, permitiendo que el tamao de la base de datos sea menor. Eso si, el acceso a los datos CHAR es mas rpido que VARCHAR. No pueden alternarse columnas CHAR y VARCHAR en la misma tabla. MySQL cambiar las columnas CHAR a VARCHAR. Tambin cambia automticamente a CHAR si usamos VARCHAR con valor de 4 o menos

9.1.1.3.
Tipo DATE DATETIME

Varios
Descripcin Fecha. El formato por defecto es YYYY MM DD desde 0000 00 00 a 9999 12 31 Combinacin de fecha y hora. El rango de valores va desde el 1 de enero del 1001 a las 0 horas, 0 minutos y 0 segundos al 31 de diciembre del 9999 a las 23 horas, 59 minutos y 59 segundos. El formato de almacenamiento es de ao-mes-dia horas:minutos:segundos Combinacin de fecha y hora. El rango va desde el 1 de enero de 1970 al ao 2037. El formato de almacenamiento depende del tamao del campo almacena una hora. El rango de horas va desde 838 horas, 59 minutos y 59 segundos a 838, 59 minutos y 59 segundos. El formato de almacenamiento es de 'HH:MM:SS' almacena un ao. El rango de valores permitidos va desde el ao 1901 al ao 2155. El campo puede tener tamao dos o tamao 4 dependiendo de si queremos almacenar el ao con dos o cuatro dgitos almacena un campo que puede contener ninguno, uno varios valores de una lista. La lista puede tener un mximo de 64 valores es igual que SET, pero solo se puede almacenar uno de los valores de la lista

TIMESTAMP

TIME

YEAR

SET

ENUM

9.2. Acceso a datos


9.2.1. Creacin de una tabla
Se usa la siguiente sintaxis:
CREATE TABLE nombre_tabla (campo1 tipo_dato NOT NULL AUTOINCREMENT, campo2 tipo_dato, PRIMARY KEY (campo1));

77

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

MySQL crear una tabla con 2 campos de los cuales campo1 es un valor nico (clave primaria que no puede ser sobreescrito.

9.2.2. Eliminar una tabla


Se usa la siguiente sintaxis:
DROP TABLE nombre_tabla;

9.2.3. Modificar la estructura de una tabla


Se usa la siguiente sintaxis:
ALTER TABLE nombre_tabla [ADD nombre_atributo definicin] nuevo campo [CHANGE antiguo_atributo nuevo_atributo definicin] campo [DROP nombre_atributo]; campo // Para aadir un // Para cambiar un // Para borrar un

9.2.4. ndices de una tabla


Los ndices son una estructura que permiten el acceso organizado a los datos contenidos de una tabla. Para crear un ndice se usa la siguiente sintaxis:
CREATE [UNIQUE] INDEX nombre_indice ON nombre_tabla (campos);

9.2.5. Manipulacin de datos


9.2.5.1. Insercin de datos

La insercin de datos en la tabla se realiza mediante el comando INSERT cuyo sintaxis es:
INSERT INTO nombre_tabla [campo_1, campo_2, ... , campo_n] VALUES (valor_1, valor_2, ..., valor_n)

9.2.5.2.

Consultas de datos

La consulta de datos se realiza con el comando SELECT y la sintaxis es la siguiente:


SELECT ([*]/[atributos]) FROM nombre_tabla/s [WHERE lista_condiciones] [GROUP BY campo/s] [HAVING listaCondiciones] [ORDER BY Campo]

Existen un conjunto de funciones dentro de las consultas de datos que nos permiten obtener informacin o realizar operaciones con respecto a los registros:

78

ACCESO A DATOS

funcin COUNT(*/DISTINCT campo) SUM(campo) AVG(campo) MAX(campo) MIN(campo)

Descripcin Cuenta el nmero de filas Suma los valores del campo indicado Obtiene la media aritmtica del campo Obtiene el valor mximo del campo Obtiene el valor mnimo del campo

Veamos un ejemplo bsico donde utilizamos WHERE y ORDER BY, aqu veremos como seleccionar de la tabla `sucursales` los campos `razon_social`, `id` y `direccion` en todos aquellos registros que el campo `razon_social` sea la cadena de texto 'mi razon social' y adems, lo ordenaremos por campo `id`
SELECT `razon_social`, `id`, `direccion` FROM `sucursales` WHERE `razon_social` = 'mi razon social' ORDER BY `id`;

9.2.5.3.

Modificacin de datos

Para modificar datos se usa la sentencia UPDATE cuya sentencia es:


UPDATE nombre_tabla SET campo_w=valor_1 [, campo_2=valor_2 ...] [WHERE condicin] [ORDER BY campo/s]

9.2.5.4.

Borrado de datos

Para borrar datos se usa la sentencia DELETE cuya sintaxis es:


DELETE FROM nombre_tabla [WHERE condicin]

9.2.5.5.

Consulta de datos usando JOIN

MySQL soporta las siguientes posibles sintaxis de JOIN (unin de dos tablas) en comandos SELECT y DELETE y UPDATE:
table_reference, table_reference table_reference [INNER | CROSS] JOIN table_reference [join_condition] table_reference STRAIGHT_JOIN table_reference table_reference LEFT [OUTER] JOIN table_reference join_condition table_reference NATURAL [LEFT [OUTER]] JOIN table_reference { ON table_reference LEFT OUTER JOIN table_reference ON conditional_expr } table_reference RIGHT [OUTER] JOIN table_reference join_condition table_reference NATURAL [RIGHT [OUTER]] JOIN table_reference

donde table_reference se define como:


tbl_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | [FORCE INDEX (key_list)]]

donde join_condition se define como:


ON conditional_expr | USING (column_list)

De entre todos los tipos posibles, los ms usados son los siguientes:

79

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

JOIN: Se obtienen todos los registros que verifican la condicin en las dos tablas, sin mostrarse los que no la cumplen. LEFT JOIN: Se obtienen todos los registros que verifican la condicin en las dos tablas, mostrando los registros que no lo cumplen correspondientes a la tabla de la izquierda (con los datos de la tabla de la derecha no informados). RIGHT JOIN: Se obtienen todos los registros que verifican la condicin en las dos tablas, mostrando los registros que no lo cumplen correspondientes a la tabla de la derecha (con los datos de la tabla de la izquierda no informados).

Veamos que el caso de JOIN se puede sustituir por una coma: Esta consulta:
mysql> SELECT * FROM personas2, telefonos2 -> WHERE personas2.id=telefonos2.id;

Sera equivalente a estas:


mysql> -> mysql> -> mysql> -> mysql> -> mysql> SELECT * FROM personas2 JOIN telefonos2 ON (personas2.id = telefonos2.id); SELECT * FROM personas2 JOIN telefonos2 WHERE (personas2.id = telefonos2.id); SELECT * FROM personas2 INNER JOIN telefonos2 ON (personas2.id = telefonos2.id); SELECT * FROM personas2 CROSS JOIN telefonos2 ON (personas2.id = telefonos2.id); SELECT * FROM personas2 JOIN telefonos2 USING(id);

9.2.6. Vistas
Una vista es un objeto de la base de datos que que agrupa una seleccin o un conjunto de datos.

9.2.6.1.

Crear Vistas

Podemos crear o modificar vistas con CREATE VIEW.


CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW nombre_vista [(columnas)] AS sentencia_select [WITH [CASCADED | LOCAL] CHECK OPTION]

Esta sentencia crea una vista nueva o reemplaza una existente si se incluye la clusula OR REPLACE. Para ver su uso consideremos que disponemos de la siguiente tabla:
mysql> desc mail_aliases; +-------------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------+----------+------+-----+---------+-------+ | alias | char(32) | NO | MUL | NULL | | | domain | char(64) | NO | | NULL | | | comments | text | NO | | NULL | | +-------------+----------+------+-----+---------+-------+ 3 rows in set (0.01 sec)

En esta tabla podemos consultar los alias de correo para todos los dominios de un servidor.

80

ACCESO A DATOS

Para acceder a datos especficos de forma repetida, podemos definir vistas. Por ejemplo, podemos crear una vista para un determinado dominio:
mysql> create view mail_alias_myhost as select alias, comments from mail_aliases where domain="myhost"; Query OK, 0 rows affected (0.04 sec)

A continuacin mediante la vista podremos acceder a los datos que se han seleccionado:
mysql> select * from mail_alias_myhost; +---------------+-----------------------------+ | alias | comments | +---------------+-----------------------------+ | helpdesk | Soporte y ayuda | | .... | .... | +---------------+-----------------------------+

Mediante la palabra clave ALGORITHM podemos indicar como deseamos que funcione: UNDEFINED: Dejamos el control a MySQL (caso por defecto). MERGE: el texto de una sentencia que haga referencia a la vista y la definicin de la vista son mezclados de forma que parte de la definicin de la vista reemplaza las partes correspondientes de la consulta. TEMPTABLE: En el momento de hacer una consulta sobre la vista se crea una tabla temporal. Este mtodo tiene una gran ventaja y una gran desventaja: o Desventaja: La vista no puede modificarse, por lo que cualquier cambio se deber hacer en la tabla original. Ventaja: Los bloqueos se liberan antes, ya que la consulta de la vista se hace a partir de la tabla temporal. Esto permite que otros threads accedan antes a la tabla que ejecutando una consulta mucho mas pesada usando el algoritmo MERGE.

9.2.6.2.

Borrar Vistas

Podemos eliminar o borrar vistas con DROP VIEW.


DROP VIEW [IF EXISTS] nombre_vista [, nombre_vista] ...

9.2.6.3.

(Meta)Informacin de Vistas

Para obtener informacin de definicin de una vista (metadatos) se utiliza SHOW CREATE VIEW.
SHOW CREATE VIEW nombre_vista

Muestra la sentencia CREATE VIEW que se utiliz para crear la vista. Por ejemplo:
mysql> SHOW CREATE VIEW mail_alias_myhost; +-------+----------------------------------------------------+ | Table | Create Table | +-------+----------------------------------------------------+ | v | create view mail_alias_myhost as | | | select alias, comments from mail_aliases | | | where domain="myhost"; | +-------+----------------------------------------------------+

81

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

9.2.6.4.

Restricciones en vistas

Presentamos las restricciones ms importantes, o qu ms a menudo se presentan. Para ms informacin, recomendamos la lectura de l punto H.4. Restricciones en vistas del manual de MySQL. El procesamiento de vistas no est optimizado: No es posible crear un ndice en una vista. Los ndices pueden utilizarse para procesar vistas usando un algoritmo de combinacin (MERGE). Sin embargo, una vista que se procesa con el algoritmo de tablas temporales (temptable) no es capaz de tomar ventaja de los ndices que hacen referencia a las tablas que contiene.

Las subconsultas no pueden utilizarse en la clusula FROM de una vista. No se puede modificar una tabla y seleccionar de la misma en una subconsulta. Se puede usar DROP TABLE o ALTER TABLE para eliminar o modificar una tabla utilizada en la definicin de una vista (lo cual invalida la vista) y no se obtendr ninguna alerta de las operaciones de eliminar o modificar. Sin embargo, se obtiene un error ms tarde, cuando se utiliza la vista.

9.2.7. Sentencias preparadas


Una sentencia o procedimiento preparado es una sentencia SQL definida y parametrizada en el servidor de modo que solo necesita para su ejecucin los valores correspondientes a los campos parametrizados. La sintaxis SQL se basa en los siguientes tres comandos SQL:
PREPARE stmt_name FROM preparable_stmt; EXECUTE stmt_name [USING @var_name [, @var_name] ...]; {DEALLOCATE | DROP} PREPARE stmt_name;

El comando PREPARE prepara un comando y le asigna un nombre, stmt_name, con el que referirse al comando posteriormente. Los nombres de comando no son sensibles a maysculas. preparable_stmt es una cadena literal o una variable de usuario que contenga el texto del comando. El texto debe representar un comando SQL nico, no varios. Dentro del comando, pueden usarse caracteres '?' como marcadores de parmetros para indicar dnde estarn los valores en la consulta posterior cuando la ejecute. Los caracteres '?' no deben delimitarse con comillas, incluso si pretende ligarlos con valores de cadenas. Tras preparar un comando, lo ejecuta con un comando EXECUTE que se refiere al nombre de comando preparado. Si el comando preparado contiene cualquier marcador de parmetro, debe aadir una clusula USING que liste las variables de usuario conteniendo los valores a ligar con los parmetros. Los valores de parmetros pueden proporcionarse slo por variables de usuario, y la clusula USING debe nombrar exactamente tantas variables como el nmero de marcadores de parmetros en el comando.

82

ACCESO A DATOS

Para eliminar un comando preparado, use el comando DEALLOCATE PREPARE . Tratar de ejecutar un comando preparado tras borrarlo provoca un error. Los siguientes comandos SQL pueden usarse en comandos preparados: CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE, y la mayora de comandos SHOW . El siguiente ejemplo muestra una sentencia preparada que calcula la hipotenusa de un tringulo dadas las longitudes de los dos catetos.
mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; mysql> SET @a = 3; mysql> SET @b = 4; mysql> EXECUTE stmt1 USING @a, @b; +------------+ | hypotenuse | +------------+ | 5 | +------------+ mysql> DEALLOCATE PREPARE stmt1;

9.2.8. Exportacin e importacin de 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 los datos de nuestras bases de datos a otras aplicaciones, o bien para importar datos desde otras fuentes a nuestras tablas. Tambin se puede usar para hacer copias de seguridad y restaurarlas posteriormente.

9.2.8.1.

Exportar a otros ficheros

Para extraer datos desde una base de datos a un fichero se usa la sentencia SELECT. Para ello, se aaden los elementos que permiten identificar el fichero de salida y el formato de los campos en dicho fichero. El resto de las clusulas de siguen siendo aplicables. El fichero de salida se identifica mediante:
[INTO OUTFILE 'file_name' export_options]

dnde file_name es el nombre del fichero de salida. Ese fichero no debe existir. Para definir el formato de salida se usa:
[FIELDS [TERMINATED BY '\t'] [[OPTIONALLY] ENCLOSED BY ''] [ESCAPED BY '\\' ] ] [LINES [STARTING BY ''] [TERMINATED BY '\n'] ]

La clusula FIELDS se refiere a las opciones de cada columna: TERMINATED BY 'carcter': nos permite elegir el carcter delimitador que se usar para sealar cada columna. El valor por defecto es el tabulador.

83

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

[OPTIONALLY] ENCLOSED BY 'carcter': sirve para elegir el carcter usado para entrecomillar cada columna. Por defecto no se entrecomilla ninguna columna. Si se aade la palabra OPTIONALLY slo se entrecomillarn las columnas de texto y fecha. ESCAPED BY 'carcter': sirve para indicar el carcter que se usar para escapar aquellos caracteres que pueden dificultar la lectura posterior del fichero. Por defecto se usa el carcter '\'.

La clusula LINES se refiere a las opciones para cada fila: STARTING BY 'carcter': permite seleccionar el carcter para comenzar cada lnea. Por defecto no se usa ningn carcter para ello. TERMINATED BY 'carcter': permite elegir el carcter para terminar cada lnea. Por defecto es el retorno de lnea.

Veamos un ejemplo. Vamos a obtener obtener un fichero de texto a partir de la tabla 'gente', con las columnas delimitadas por ';', entrecomillando las columnas de texto con '' y separando cada fila por la secuencia '\r\n':
mysql> SELECT * FROM gente -> INTO OUTFILE "gente.txt" -> FIELDS TERMINATED BY ';' -> OPTIONALLY ENCLOSED BY '\"' -> LINES TERMINATED BY '\n\r'; Query OK, 5 rows affected (0.00 sec)

El fichero de salida tendr este aspecto:


"Fulano";"1974-04-12" "Mengano";"1978-06-15" "Tulano";"2000-12-02" "Pegano";"1993-02-10" "Mengano";\N

La fecha para Mengano era NULL, para indicarlo se muestra el valor \N.

9.2.8.2.

Importar a partir de ficheros externos

Se puede recuperar el contenido de un fichero e incluirlo en una tabla. Para hacerlo disponemos de la sentencia LOAD DATA, cuya sintaxis ms simple es:
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 clusula LOCAL indica, si aparece, 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.

84

ACCESO A DATOS

Las clusulas REPLACE e IGNORE afectan al modo en que se tratan las filas ledas que contengan el mismo valor para una clave principal o nica para una fila existente en la tabla. Si se especifica REPLACE se sustituir la fila actual por la leda. Si se especifica IGNORE el valor ledo ser ignorado. La parte INTO TABLA tbl_name indica en qu tabla se insertarn los valores ledos. Las clusulas FIELDS y LINES tienen el mismo significado que vimos el exportar datos. La clusula IGNORE nmero LINES permite que las primeras nmero lneas no se interpreten como datos a importar. La ltima parte nos permite indicar la columna a la que ser asignada cada una de las columnas ledas, esto ser til si el orden de las columnas en la tabla no es el mismo que en el fichero de texto, o si el nmero de columnas es diferente en ambos. Por ejemplo, supongamos que queremos aadir el contenido de este fichero a la tabla gente:

Fichero de datos de "gente" fecha,nombre 2004-03-15,Xulana 2000-09-09,Con Clase 1998-04-15,Pingrana

Como vemos, hay dos filas al principio que no contienen datos vlidos, las columnas estn separadas con comas y, como hemos editado el fichero en MSWindows, las lneas terminan con \n\r. La sentencia adecuada para leer los datos es:
mysql> LOAD DATA INFILE "gente.txt" -> INTO TABLE gente -> FIELDS TERMINATED BY ',' -> LINES TERMINATED BY '\r\n' -> IGNORE 2 LINES -> (fecha,nombre); Query OK, 3 rows affected (0.00 sec) Records: 3 Deleted: 0 Skipped: 0 Warnings: 0

El contenido de la tabla queda entonces:


mysql> SELECT * FROM gente; +-----------+------------+ | nombre | fecha | +-----------+------------+ | Fulano | 1974-04-12 | | Mengano | 1978-06-15 | | Tulano | 2000-12-02 | | Pegano | 1993-02-10 | | Mengano | NULL | | Xulana | 2004-03-15 | | Con Clase | 2000-09-09 | | Pingrana | 1998-04-15 | +-----------+------------+ 8 rows in set (0.00 sec)

9.2.9. Rutinas almacenadas y disparadores

85

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

9.2.9.1.

Disparadores (triggers)

Un disparador es un objeto con nombre dentro de una base de datos el cual se asocia con una tabla y se activa cuando ocurre en sta un evento en particular. El soporte actual es bsico, por lo tanto hay ciertas limitaciones en lo que puede hacerse con ellos. Para crear un disparador se utiliza la sentencia CREATE TRIGGER:
CREATE TRIGGER nombre_disp momento_disp evento_disp ON nombre_tabla FOR EACH ROW sentencia_disp

Mientras que para eliminar un disparador se utiliza la sentenciaDROP TRIGGER:


DROP TRIGGER [nombre_esquema.]nombre_disp

Para entenderlo mejor planteamos un ejemplo de uso. Definimos en nuestra base de datos 2 tablas: usuarios: con los datos de nuestros usuarios. acciones: donde guardaremos las acciones realizadas sobre nuestras tablas.

Las tablas sern las siguientes:


/* Creamos la tabla de acciones*/ CREATE TABLE acciones( fecha DATE, hora TIME, accion VARCHAR(50), id_usuario integer ); /*Creamos la tabla de usuarios*/ CREATE TABLE usuarios( id_usuario integer PRIMARY KEY, nombre VARCHAR(50), apellido VARCHAR(50) );

Creamos 3 disparadores sobre la tabla de usuarios, sobre las acciones que se realicen sobre ella (insercin, modificacin o borrado). Los disparadores son:
/*Disparador para el registro de inserciones*/ DELIMITER | CREATE TRIGGER inser_usuarios BEFORE INSERT ON usuarios FOR EACH ROW BEGIN INSERT INTO acciones VALUES(CURDATE(),CURTIME(),'Registro insertado', new.id_usuario); END; | DELIMITER ; /*Disparador para el registro modificado*/ DELIMITER | CREATE TRIGGER update_usuarios BEFORE UPDATE ON usuarios FOR EACH ROW BEGIN INSERT INTO acciones VALUES(CURDATE(),CURTIME(),'Registro Modificado', old.id_usuario); END; | DELIMITER ;

86

ACCESO A DATOS

/*Disparador para el registro eliminado*/ DELIMITER | CREATE TRIGGER delete_usuarios BEFORE DELETE ON usuarios FOR EACH ROW BEGIN INSERT INTO acciones VALUES(CURDATE(),CURTIME(),'Registro eliminado', old.id_usuario); END; | DELIMITER ;

Explicamos brevemente cmo lo hemos usado en la ltima definicin: DELIMITER: los disparadores estn formados por varias instrucciones, por lo tanto, antes de comenzar su definicin, debes especificar qu carcter delimita (o separa). CREATE TRIGGER: Es la sentencia de creacin del disparador. BEFORE: Indica el momento de accin del disparador DELETE: Indica el evento que activar al disparador FOR EACH ROW: Define lo que se ejecutar cada vez que el disparador se active, lo cual ocurre una vez por cada fila afectada por la sentencia activadora. Las palabras clave OLD y NEW permiten acceder a columnas en los registros afectados por un disparador. (OLD y NEW no son sensibles a maysculas). o En un disparador para INSERT, solamente puede utilizarse NEW.nom_col; ya que no hay una versin anterior del registro. En un disparador para DELETE slo puede emplearse OLD.nom_col, porque no hay un nuevo registro. En un disparador para UPDATE se puede emplear OLD.nom_col para referirse a las columnas de un registro antes de que sea actualizado, y NEW.nom_col para referirse a las columnas del registro luego de actualizarlo.

Podemos ver su funcionamiento realizando las siguientes acciones:


INSERT INTO usuarios VALUES (1,'Pepe','Gmez'); INSERT INTO usuarios VALUES (2,'Luis','Lpez'); INSERT INTO usuarios VALUES (3,'Juan','Nadie'); /*Verificamos las inserciones*/ select * from usuarios; /*Revisamos la tabla de acciones */ select * from acciones; /*Modificamos 1 registroo*/ update usuarios set apellido = 'Hernndez' where id_usuario=1; /*Revisamos la tabla de acciones */ select * from acciones; /*Eliminamos 1registroo*/ delete from usuarios where id_usuario=3; /*Revisamos la tabla de acciones */ select * from acciones;

87

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

9.2.9.2.

Rutinas o Procedimientos almacenados

Un procedimiento almacenado es un conjunto de comandos SQL que pueden almacenarse en el servidor. Una vez que se hace, los clientes no necesitan relanzar los comandos individuales pero pueden en su lugar referirse al procedimiento almacenado. Algunas situaciones en que los procedimientos almacenados pueden ser particularmente tiles: Cuando mltiples aplicaciones cliente se escriben en distintos lenguajes o funcionan en distintas plataformas, pero necesitan realizar la misma operacin en la base de datos. Cuando la seguridad es muy importante.

Los procedimientos almacenados pueden mejorar el rendimiento ya que se necesita enviar menos informacin entre el servidor y el cliente. Pero a cambio se aumenta la carga del servidor de la base de datos ya que la mayora del trabajo se realiza en la parte del servidor y no en el cliente. Para crear un procedimiento almacenado se utiliza la sentencia CREATE PROCEDURE:
CREATE PROCEDURE sp_name ([parameter[,...]]) [characteristic ...] routine_body parameter: [ IN | OUT | INOUT ] param_name type type: Any valid MySQL data type characteristic: LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string' routine_body: procedimientos almacenados o comandos SQL vlidos

Mientras que para eliminar un procedimiento almacenado se utiliza la sentenciaDROP PROCEDURE:


DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name

Para facilitar la explicacin, planteemos un ejemplo de uso. Nuestro sistema tendr dos tablas, una con ventas y la otra con comisiones. En la primera se almacenarn cada venta que se realiza en un comercio, y en la segunda las comisiones que le corresponden a cada vendedor en el momento.
CREATE TABLE `ventas` ( `vendedor` int(11), `producto` int(11), `importe` float ) CREATE TABLE `comisiones` ( `vendedor` int(11), `comision` float )

88

ACCESO A DATOS

Las comisiones se calcula de una forma especial, le corresponde un porcentaje de las ventas segn el tipo de producto, y es importante para los vendedores el que se sepa en cada momento qu comisiones lleva ganadas. Para calcular qu comisin le corresponde a un vendedor, calcularemos los porcentajes para cada tipo de producto vendido y luego lo aadiremos/actualizaremos en la tabla de comisiones. Todo se realizar en un procedimiento almacenado.
DELIMITER | DROP PROCEDURE IF EXISTS `test`.`sp_comisiones`| CREATE PROCEDURE `test`.`sp_comisiones` (IN mivendedor INT) BEGIN DECLARE micomision INT DEFAULT 0; DECLARE suma INT; DECLARE existe BOOL; select IFNULL(sum(importe),0) into suma from ventas where producto = 1 and vendedor = mivendedor; SET micomision = micomision + (suma * 0.15); select IFNULL(sum(importe),0) into suma from ventas where producto = 2 and vendedor = mivendedor; SET micomision = micomision + (suma * 0.1); select IFNULL(sum(importe),0) into suma from ventas where producto = 3 and vendedor = mivendedor; SET micomision = micomision + (suma * 0.2); select count(1)>0 into existe from comisiones where vendedor = mivendedor; if existe then UPDATE comisiones set comision = comision+micomision where vendedor = mivendedor; else insert into comisiones (vendedor, comision) values (mivendedor, micomision); end if; END | DELIMITER ;

Ahora, para actualizar los datos de las comisiones usaremos un trigger, as cuando se haga una venta (insert en la tabla ventas), se llamar al procedimiento almacenado (sp_comisiones), que recalcular la comisin para ese vendedor.
DELIMITER $$ DROP TRIGGER `test`.`tr_ventas_insert`$$ CREATE TRIGGER `test`.`tr_ventas_insert` AFTER INSERT on `test`.`ventas` FOR EACH ROW BEGIN call sp_comisiones(new.vendedor); END$$ DELIMITER ;

9.2.9.3.

Restricciones

Presentamos las restricciones ms importantes. Para un estudio ms profundo remitimos a H.1. Restricciones en procedimientos almacenados y disparadores del manual de MySQL. Todas las restricciones para las funciones almacenadas se refieren tambin a los disparadores. Las rutinas almacenadas no pueden contener sentencias SQL arbitrarias. Las siguientes sentencias no estn permitidas dentro de una rutina almacenada: CHECK TABLES LOCK TABLES, UNLOCK TABLES

89

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

FLUSH LOAD DATA, LOAD TABLE Sentencias SQL preparadas(PREPARE, EXECUTE, DEALLOCATE).

Adems, en funciones almacenadas (pero no para procedimientos almacenados), no estn permitidas las siguientes sentencias: Sentencias que hacen commits o rollbacks explcitos o implcitos. Sentencias que devuelvan un resultado. Esto incluye sentencias SELECT que no tienen una clusula INTO y la sentencia SHOW.

90

EJEMPLOS Y EJERCICIOS

Ejemplo y ejercicios

10.1. Introduccin
El objetivo es definir una base de datos para la gestin, simple, de una o varias entidades bancarias. Consideramos que una entidad bancaria puede tener varias sucursales, que es dnde se realizan las transacciones con clientes. Los clientes abren cuentas en las sucursales para gestionar sus fondos monetarios, pudiendo disponer de una nica cuenta en diferentes sucursales de diferentes entidades bancarias. Adems, las entidades bancarias ofrecen prstamos a sus clientes, que asocian a cuentas que tienen en sus sucursales.

10.2. Ejercicios
10.2.1. Ejercicio 1 - Modelado de la base de datos
El modelo de la bb.dd. final (usando MySQL Workbench) es:

91

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

10.2.2. Ejercicio 2 - Creacin de la base de datos en MySQL


Crear la base de datos curso_ejemplo con las tablas desde MySQLWorkbench Crear la base de datos curso_ejemplo
CREATE DATABASE `curso_ejemplo` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

Crear las tablas: 1. Crear la tabla entidad_bancaria:


CREATE TABLE IF NOT EXISTS entidad bancaria ( id INT NOT NULL AUTO_INCREMENT, razon_social VARCHAR(45) NOT NULL, PRIMARY KEY (id)) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci;

2. Probar a crear la tabla cuenta sin haber creado antes la tabla sucursal: NO se puede por integridad referencial. 3. Crear la tabla sucursal:

92

EJEMPLOS Y EJERCICIOS

CREATE TABLE IF NOT EXISTS `sucursal` ( `id` INT(4) NOT NULL , `direccion` VARCHAR(45) NOT NULL , `entidad_bancaria_id` INT NOT NULL , PRIMARY KEY (`id`, `entidad_bancaria_id`) , INDEX `fk_sucursal_entidad_bancaria` (`entidad_bancaria_id` ASC) , CONSTRAINT `fk_sucursal_entidad_bancaria` FOREIGN KEY (`entidad_bancaria_id` ) REFERENCES `entidad_bancaria` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci;

4. Crear la tabla cuenta:


CREATE TABLE IF NOT EXISTS `cuenta` ( `id` INT NOT NULL AUTO_INCREMENT , `tipo` INT(1) NOT NULL DEFAULT 0 , `saldo` DOUBLE NOT NULL DEFAULT 0 , `fecha_alta` DATE NOT NULL , `sucursal_id` INT(4) NOT NULL , `sucursal_entidad_bancaria_id` INT NOT NULL , PRIMARY KEY (`id`) , INDEX `fk_cuenta_sucursal1` (`sucursal_id` ASC, `sucursal_entidad_bancaria_id` ASC) , CONSTRAINT `fk_cuenta_sucursal1` FOREIGN KEY (`sucursal_id` , `sucursal_entidad_bancaria_id` ) REFERENCES `sucursal` (`id` , `entidad_bancaria_id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci;

5. Crear la tabla cliente:


CREATE TABLE IF NOT EXISTS `cliente` ( `id` INT NOT NULL AUTO_INCREMENT , `dni` VARCHAR(10) NOT NULL , `nombre` VARCHAR(100) NOT NULL , `telefono` VARCHAR(12) NULL , PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci;

6. Crear la tabla prestamo:


CREATE TABLE IF NOT EXISTS `prestamo` ( `id` INT NOT NULL AUTO_INCREMENT , `valor` INT NOT NULL , `fecha` DATE NOT NULL , `sucursal_id` INT(4) NOT NULL , `sucursal_entidad_bancaria_id` INT NOT NULL , PRIMARY KEY (`id`) , INDEX `fk_prestamo_sucursal1` (`sucursal_id` ASC, `sucursal_entidad_bancaria_id` ASC) , CONSTRAINT `fk_prestamo_sucursal1` FOREIGN KEY (`sucursal_id` , `sucursal_entidad_bancaria_id` ) REFERENCES `sucursal` (`id` , `entidad_bancaria_id` ) ON DELETE NO ACTION
93

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci

7. Crear la tabla cliente_has_prestamo:


CREATE TABLE IF NOT EXISTS `cliente_has_prestamo` ( `cliente_id` INT NOT NULL , `prestamo_id` INT NOT NULL , PRIMARY KEY (`cliente_id`, `prestamo_id`) , INDEX `fk_cliente_has_prestamo_cliente1` (`cliente_id` ASC) , INDEX `fk_cliente_has_prestamo_prestamo1` (`prestamo_id` ASC) , CONSTRAINT `fk_cliente_has_prestamo_cliente1` FOREIGN KEY (`cliente_id` ) REFERENCES `cliente` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `fk_cliente_has_prestamo_prestamo1` FOREIGN KEY (`prestamo_id` ) REFERENCES `prestamo` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci

8. Crear la tabla cliente_has_cuenta:


CREATE TABLE IF NOT EXISTS `cliente_has_cuenta` ( `cliente_id` INT NOT NULL , `cuenta_id` INT NOT NULL , PRIMARY KEY (`cliente_id`, `cuenta_id`) , INDEX `fk_cliente_has_cuenta_cliente1` (`cliente_id` ASC) , INDEX `fk_cliente_has_cuenta_cuenta1` (`cuenta_id` ASC) , CONSTRAINT `fk_cliente_has_cuenta_cliente1` FOREIGN KEY (`cliente_id` ) REFERENCES `cliente` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `fk_cliente_has_cuenta_cuenta1` FOREIGN KEY (`cuenta_id` ) REFERENCES `cuenta` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci;

Usando un script SQL

-- ------------------------------------------------------ Table `entidad_bancaria` -- ----------------------------------------------------DROP TABLE IF EXISTS `entidad_bancaria` ; CREATE TABLE IF NOT EXISTS `entidad_bancaria` ( `id` INT NOT NULL AUTO_INCREMENT , `razon_social` VARCHAR(45) NOT NULL , PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'Datos de entidad bancaria';
94

EJEMPLOS Y EJERCICIOS

-- ------------------------------------------------------ Table `sucursal` -- ----------------------------------------------------DROP TABLE IF EXISTS `sucursal` ; CREATE TABLE IF NOT EXISTS `sucursal` ( `id` INT(4) NOT NULL , `direccion` VARCHAR(45) NOT NULL , `entidad_bancaria_id` INT NOT NULL , PRIMARY KEY (`id`, `entidad_bancaria_id`) , INDEX `fk_sucursal_entidad_bancaria` (`entidad_bancaria_id` ASC) , CONSTRAINT `fk_sucursal_entidad_bancaria` FOREIGN KEY (`entidad_bancaria_id` ) REFERENCES `entidad_bancaria` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'Sucursal de la entidad bancaria'; -- ------------------------------------------------------ Table `cuenta` -- ----------------------------------------------------DROP TABLE IF EXISTS `cuenta` ; CREATE TABLE IF NOT EXISTS `cuenta` ( `id` INT NOT NULL AUTO_INCREMENT , `tipo` INT(1) NOT NULL DEFAULT 0 , `saldo` DOUBLE NOT NULL DEFAULT 0 , `fecha_alta` DATE NOT NULL , `sucursal_id` INT(4) NOT NULL , `sucursal_entidad_bancaria_id` INT NOT NULL , PRIMARY KEY (`id`) , INDEX `fk_cuenta_sucursal1` (`sucursal_id` ASC, `sucursal_entidad_bancaria_id` ASC) , CONSTRAINT `fk_cuenta_sucursal1` FOREIGN KEY (`sucursal_id` , `sucursal_entidad_bancaria_id` ) REFERENCES `sucursal` (`id` , `entidad_bancaria_id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'Datos de cuentas bancarias'; -- ------------------------------------------------------ Table `cliente` -- ----------------------------------------------------DROP TABLE IF EXISTS `cliente` ; CREATE TABLE IF NOT EXISTS `cliente` ( `id` INT NOT NULL AUTO_INCREMENT , `dni` VARCHAR(10) NOT NULL , `nombre` VARCHAR(100) NOT NULL , `telefono` VARCHAR(12) NULL , PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'Informacin de cliente';

95

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

-- ------------------------------------------------------ Table `prestamo` -- ----------------------------------------------------DROP TABLE IF EXISTS `prestamo` ; CREATE TABLE IF NOT EXISTS `prestamo` ( `id` INT NOT NULL AUTO_INCREMENT , `valor` INT NOT NULL , `fecha` DATE NOT NULL , `sucursal_id` INT(4) NOT NULL , `sucursal_entidad_bancaria_id` INT NOT NULL , PRIMARY KEY (`id`) , INDEX `fk_prestamo_sucursal1` (`sucursal_id` ASC, `sucursal_entidad_bancaria_id` ASC) , CONSTRAINT `fk_prestamo_sucursal1` FOREIGN KEY (`sucursal_id` , `sucursal_entidad_bancaria_id` ) REFERENCES `sucursal` (`id` , `entidad_bancaria_id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'Datos de los prstamos'; -- ------------------------------------------------------ Table `cliente_has_prestamo` -- ----------------------------------------------------DROP TABLE IF EXISTS `cliente_has_prestamo` ; CREATE TABLE IF NOT EXISTS `cliente_has_prestamo` ( `cliente_id` INT NOT NULL , `prestamo_id` INT NOT NULL , PRIMARY KEY (`cliente_id`, `prestamo_id`) , INDEX `fk_cliente_has_prestamo_cliente1` (`cliente_id` ASC) , INDEX `fk_cliente_has_prestamo_prestamo1` (`prestamo_id` ASC) , CONSTRAINT `fk_cliente_has_prestamo_cliente1` FOREIGN KEY (`cliente_id` ) REFERENCES `cliente` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `fk_cliente_has_prestamo_prestamo1` FOREIGN KEY (`prestamo_id` ) REFERENCES `prestamo` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'Prestamos de clientes: tabla para resolver la relacin n a m.'; -- ------------------------------------------------------ Table `cliente_has_cuenta` -- ----------------------------------------------------DROP TABLE IF EXISTS `cliente_has_cuenta` ; CREATE TABLE IF NOT EXISTS `cliente_has_cuenta` ( `cliente_id` INT NOT NULL , `cuenta_id` INT NOT NULL , PRIMARY KEY (`cliente_id`, `cuenta_id`) , INDEX `fk_cliente_has_cuenta_cliente1` (`cliente_id` ASC) , INDEX `fk_cliente_has_cuenta_cuenta1` (`cuenta_id` ASC) , CONSTRAINT `fk_cliente_has_cuenta_cliente1`

96

EJEMPLOS Y EJERCICIOS

FOREIGN KEY (`cliente_id` ) REFERENCES `cliente` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `fk_cliente_has_cuenta_cuenta1` FOREIGN KEY (`cuenta_id` ) REFERENCES `cuenta` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci;

10.2.3. Ejercicio 3 - Poblar la base de datos en MySQL


1. Poblar datos de la tabla entidad_bancaria:
INSERT INTO `entidad_bancaria` (`id`, `razon_social`) VALUES (1, 'Caja de Ahorros'), (2, 'Banco Primero');

2. Poblar datos de la tabla cuenta SIN poblar los datos de la tabla sucursal: No se puede por integridad referencial. 3. Poblar datos de la tabla sucursal:
INSERT INTO `sucursal` (`id`, `direccion`, `entidad_bancaria_id`) VALUES (1, 'C/ HierbaBuena', 1), (1, 'C/ Naranja', 2), (2, 'C/ Tomillo', 1), (2, 'C/ Limn', 2), (3, 'C/ Menta', 1);

4. Poblar datos de la tabla cuenta:


INSERT INTO `cuenta` (`id`, `tipo`, `saldo`, `fecha_alta`, `sucursal_id`, `sucursal_entidad_bancaria_id`) VALUES (1, 0, 1345.00, '2010-04-29', 1, 1), (2, 1, 56789.00, '2010-04-07', 2, 1), (3, 1, 856.45, '2010-04-11', 2, 1), (4, 0, 1654.00, '2010-04-30', 2, 2);

5. Poblar datos de la tabla cliente:


INSERT INTO `cliente` (`id`, `dni`, `nombre`, `telefono`) VALUES (1, '123456789', 'Juan Nadie', '+34321654987'), (2, '987654321', 'Jos Lpez', '+34789456123'), (3, '678912345', 'Luisa Fernndez', '+34102938475');

6. Poblar datos de la tabla prestamo:


INSERT INTO `prestamo` (`id`, `valor`, `fecha`, `sucursal_id`, `sucursal_entidad_bancaria_id`) VALUES (1, 150000, '2010-05-18', 1, 1), (2, 8000, '2010-06-15', 2, 2);

7. Poblar datos de la tabla cliente_has_cuenta:


INSERT INTO `cliente_has_cuenta` (`cliente_id`, `cuenta_id`) VALUES (1, 1), (2, 2), (2, 3), (3, 4);

8. Poblar datos de la tabla cliente_has_prestamo:

97

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

INSERT INTO `cliente_has_prestamo` (`cliente_id`, `prestamo_id`) VALUES (1, 1), (2, 2);

SQL con los datos de todos los ejercicios:

--- Datos para la tabla `entidad_bancaria` -INSERT INTO `entidad_bancaria` (`id`, `razon_social`) VALUES (1, 'Caja de Ahorros'), (2, 'Banco Primero'); --- Datos para la tabla `sucursal` -INSERT INTO `sucursal` (`id`, `direccion`, `entidad_bancaria_id`) VALUES (1, 'C/ HierbaBuena', 1), (1, 'C/ Naranja', 2), (2, 'C/ Tomillo', 1), (2, 'C/ Limn', 2), (3, 'C/ Menta', 1); --- Datos para la tabla `cuenta` -INSERT INTO `cuenta` (`id`, `tipo`, `saldo`, `fecha_alta`, `sucursal_id`, `sucursal_entidad_bancaria_id`) VALUES (1, 0, 1345.00, '2010-04-29', 1, 1), (2, 1, 56789.00, '2010-04-07', 2, 1), (3, 1, 856.45, '2010-04-11', 2, 1), (4, 0, 1654.00, '2010-04-30', 2, 2); --- Datos para la tabla `cliente` -INSERT INTO `cliente` (`id`, `dni`, `nombre`, `telefono`) VALUES (1, '123456789', 'Juan Nadie', '+34321654987'), (2, '987654321', 'Jos Lpez', '+34789456123'), (3, '678912345', 'Luisa Fernndez', '+34102938475'); --- Datos para la tabla `prestamo` -INSERT INTO `prestamo` (`id`, `valor`, `fecha`, `sucursal_id`, `sucursal_entidad_bancaria_id`) VALUES (1, 150000, '2010-05-18', 1, 1), (2, 8000, '2010-06-15', 2, 2); --- Datos para la tabla `cliente_has_cuenta` -INSERT INTO `cliente_has_cuenta` (`cliente_id`, `cuenta_id`) VALUES (1, 1), (2, 2), (2, 3), (3, 4); --- Datos para la tabla `cliente_has_prestamo`

98

EJEMPLOS Y EJERCICIOS

-INSERT INTO `cliente_has_prestamo` (`cliente_id`, `prestamo_id`) VALUES (1, 1), (2, 2);

10.2.4. Ejercicio 4 - Integridad referencial en MySQL


1. Borrar la tabla 'entidad_bancaria':
DROP TABLE IF EXISTS `entidad_bancaria` ;

NO se puede. 2. Insertar un registro en la tabla sucursal para una entidad Bancaria inexistente:
INSERT INTO `sucursal` (`id`, `direccion`, `entidad_bancaria_id`) VALUES (1, 'C/ Arbusto', 3);

NO se puede. 3. Borrar un registro en la tabla cliente que tiene cuentas dadas de alta:
DELETE FROM `curso_ejemplo`.`cliente` WHERE `cliente`.`id` =3;

NO se puede.

10.2.5.

Ejercicio 5 - Acceso a Datos

1. Conectarse a la base de datos de ejemplo desde la consola:


mysql -u root -p curso_ejemplo

2. Comprobar las tablas de la base de datos:


mysql> show tables; +-------------------------+ | Tables_in_curso_ejemplo | +-------------------------+ | cliente | | cliente_has_cuenta | | cliente_has_prestamo | | cuenta | | entidad_bancaria | | prestamo | | sucursal | +-------------------------+

3. Obtener los datos de la tabla 'sucursal':


mysql> SELECT * from sucursal; +----+----------------+---------------------+ | id | direccion | entidad_bancaria_id | +----+----------------+---------------------+ | 1 | C/ HierbaBuena | 1 | | 1 | C/ Naranja | 2 | | 2 | C/ Tomillo | 1 | | 2 | C/ Limn | 2 | | 3 | C/ Menta | 1 | +----+----------------+---------------------+

4. Modificar un registro en la tabla sucursal y ver el resultado:

99

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

mysql> UPDATE `curso_ejemplo`.`sucursal` SET `direccion` = 'C/ Limonero' WHERE `sucursal`.`id` =2 AND `sucursal`.`entidad_bancaria_id` =2; Query OK, 1 row affected (0,00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> SELECT * from sucursal; +----+----------------+---------------------+ | id | direccion | entidad_bancaria_id | +----+----------------+---------------------+ | 1 | C/ HierbaBuena | 1 | | 1 | C/ Naranja | 2 | | 2 | C/ Tomillo | 1 | | 2 | C/ Limonero | 2 | | 3 | C/ Menta | 1 | +----+----------------+---------------------+

5. Borrar un registro en la tabla sucursal y ver el resultado:


mysql> DELETE FROM `curso_ejemplo`.`sucursal` WHERE `sucursal`.`id` = 3 AND `sucursal`.`entidad_bancaria_id` = 1; Query OK, 1 row affected (0,00 sec) mysql> SELECT * from sucursal; +----+----------------+---------------------+ | id | direccion | entidad_bancaria_id | +----+----------------+---------------------+ | 1 | C/ HierbaBuena | 1 | | 1 | C/ Naranja | 2 | | 2 | C/ Tomillo | 1 | | 2 | C/ Limonero | 2 | +----+----------------+---------------------+

6. Exportar la tabla cliente a fichero:


mysql> SELECT * FROM `cliente` INTO OUTFILE "cliente.txt" FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n\r' ; Query OK, 3 rows affected (0,00 sec)

7. Seleccionar las sucursales, mostrando la razn social de la entidad bancaria propietaria, ordenado por entidad bancaria:
mysql> SELECT b.razon_social AS name, a.id AS code, a.direccion AS address -> FROM sucursal AS a, entidad_bancaria AS b -> WHERE a.entidad_bancaria_id=b.id -> ORDER BY b.id; +-----------------+------+----------------+ | name | code | address | +-----------------+------+----------------+ | Caja de Ahorros | 1 | C/ HierbaBuena | | Caja de Ahorros | 2 | C/ Tomillo | | Banco Primero | 1 | C/ Naranja | | Banco Primero | 2 | C/ Limonero | +-----------------+------+----------------+

8. Seleccionar todos los prstamos existentes, informando el nombre y dni del prestatario:
mysql> select b.nombre, b.dni, a.valor, a.fecha from prestamo as a, cliente as b, cliente_has_prestamo as c where c.prestamo_id = a.id and c.cliente_id = b.id; +------------+-----------+--------+------------+ | nombre | dni | valor | fecha | +------------+-----------+--------+------------+ | Juan Nadie | 123456789 | 150000 | 2010-05-18 | | Jos Lpez | 987654321 | 8000 | 2010-06-15 | +------------+-----------+--------+------------+

100

EJEMPLOS Y EJERCICIOS

9. Seleccionar las cuentas existentes, mostrando la calle de la sucursal donde est asociada, mediante el uso de JOIN:
mysql> select cuenta.id, saldo, fecha_alta, direccion from cuenta left join sucursal on cuenta.sucursal_id = sucursal.id and cuenta.sucursal_entidad_bancaria_id = sucursal.entidad_bancaria_id; +----+--------+------------+----------------+ | id | saldo | fecha_alta | direccion | +----+--------+------------+----------------+ | 1 | 1345 | 2010-04-29 | C/ HierbaBuena | | 2 | 56789 | 2010-04-07 | C/ Tomillo | | 3 | 856.45 | 2010-04-11 | C/ Tomillo | | 4 | 1654 | 2010-04-30 | C/ Limonero | +----+--------+------------+----------------+

10. Mostrar, para todas las sucursales, las cuentas existentes:


mysql> select cuenta.id, saldo, fecha_alta, direccion from cuenta right join sucursal on cuenta.sucursal_id = sucursal.id and cuenta.sucursal_entidad_bancaria_id = sucursal.entidad_bancaria_id; +------+--------+------------+----------------+ | id | saldo | fecha_alta | direccion | +------+--------+------------+----------------+ | 1 | 1345 | 2010-04-29 | C/ HierbaBuena | | NULL | NULL | NULL | C/ Naranja | | 2 | 56789 | 2010-04-07 | C/ Tomillo | | 3 | 856.45 | 2010-04-11 | C/ Tomillo | | 4 | 1654 | 2010-04-30 | C/ Limonero | +------+--------+------------+----------------+

10.2.6.

Ejercicio 6 - Manejo de vistas

1. Creamos una nueva tabla en la base de datos, direccion, que contendr las direcciones de los clientes:
CREATE TABLE IF NOT EXISTS `direccion` ( `id` INT NOT NULL AUTO_INCREMENT , `calle` VARCHAR(45) NOT NULL , `poblacion` VARCHAR(45) NOT NULL , `c_postal` VARCHAR(45) NOT NULL , `cliente_id` INT NOT NULL , PRIMARY KEY (`id`) , INDEX `fk_direccion_cliente1` (`cliente_id` ASC) , CONSTRAINT `fk_direccion_cliente1` FOREIGN KEY (`cliente_id` ) REFERENCES `cliente` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci;

2. Poblamos la tabla:
INSERT INTO `direccion` (`id`, `calle`, `poblacion`, `c_postal`, `cliente_id`) VALUES (1, 'C/ Puenteduero 23', 'Miciudad', '01010', 1), (2, 'C/ Tudela 45', 'Miciudad', '01010', 1), (3, 'C/ Zamora 3, 7 A', 'Miciudad', '01010', 2);

3. Definimos la vista:
mysql> CREATE VIEW `datos_cliente` AS SELECT `cliente`.`nombre` AS `nombre`,`cliente`.`dni` AS `dni`,`cliente`.`telefono` AS `telefono`,`direccion`.`calle` AS `calle`,`direccion`.`poblacion`

101

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

AS `poblacion`,`direccion`.`c_postal` AS `c_postal` FROM (`cliente` JOIN `direccion` on((`cliente`.`id` = `direccion`.`cliente_id`)));

4. Comprobamos su estructura:
mysql> desc datos_cliente; +-----------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------+--------------+------+-----+---------+-------+ | nombre | varchar(100) | NO | | NULL | | | dni | varchar(10) | NO | | NULL | | | telefono | varchar(12) | YES | | NULL | | | calle | varchar(45) | NO | | NULL | | | poblacion | varchar(45) | NO | | NULL | | | c_postal | varchar(45) | NO | | NULL | | +-----------+--------------+------+-----+---------+-------+

5. Comprobamos el contenido:
mysql> select * from datos_cliente; +------------+-----------+--------------+-------------------+----| nombre | dni | telefono | calle | +------------+-----------+--------------+-------------------+----| Juan Nadie | 123456789 | +34321654987 | C/ Puenteduero 23 | | Juan Nadie | 123456789 | +34321654987 | C/ Tudela 45 | | Jos Lpez | 987654321 | +34789456123 | C/ Zamora 3, 7 A | +------------+-----------+--------------+------------------- --------------+----------+ poblacion | c_postal | ----------+----------+ Miciudad | 01010 | Miciudad | 01010 | Miciudad | 01010 | -----------+----------+

10.2.7.

Ejercicio 7 - Disparadores

1. Creamos una nueva tabla en la base de datos, direccion, que contendr las direcciones de los clientes:
CREATE TABLE IF NOT EXISTS `auditoria_cliente` ( `id` INT NOT NULL AUTO_INCREMENT , `dni` VARCHAR(10) NOT NULL , `nombre` VARCHAR(100) NOT NULL , `telefono` VARCHAR(12) NOT NULL , `timestamp` DATETIME NOT NULL , PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci;

2. Asociamos un disparador, de manera que cada vez que se modifique un dato en la tabla cliente quede registrado el cambio:
mysql> CREATE TRIGGER trigger_auditoria_cliente AFTER UPDATE ON cliente -> FOR EACH ROW -> INSERT INTO auditoria_cliente(dni, nombre, telefono, timestamp ) -> VALUES (OLD.dni, OLD.nombre, OLD.telefono, CURRENT_USER(), NOW() );

3. Comprobamos que el disparador funciona, para lo que modificamos un registro de la tabla y comprobamos que la tabla auditoria_cliente ha sido modificada:
mysql> UPDATE cliente SET dni = '123456786', nombre = 'Juan Nadie Nada', telefono = '+34321654988' WHERE id = 1; Query OK, 1 row
102

EJEMPLOS Y EJERCICIOS

affected (0,00 sec) Rows matched: 1 Changed: 1

Warnings: 0

mysql> select * from auditoria_cliente; +----+------------+------------+--------------+----------+-------| id | dni | nombre | telefono | usuario | +----+------------+------------+--------------+----------+-----------+------------+------------+---------------+---------+--------| 1 | 123456789A | Juan Nadie | +34321654987 | apache@% | ----+------------+------------+---------------+---------+----------------------------+ timestamp | --------------------+ 2010-04-28 16:24:49 | --------------------+ 1 row in set (0,00 sec)

103

GESTION DE FICHEROS

Gestin de ficheros
Gracias a los ficheros, podremos almacenar informacin til. Como configuraciones para nuestras aplicaciones, datos de nuestras aplicaciones (aunque a veces es mejor utilizar una base de datos para ello), logs de errores, etc

11.1. Recepcin y manejo de ficheros


PHP nos ofrece la posibilidad de gestionar ficheros de una forma sencilla. Disponemos de una amplia variedad de funciones para su manejo (disponibles en http://www.php.net/manual/es/ref.filesystem.php), pero nos centraremos en las ms bsicas. La primera funcin que utilizaremos para usar un fichero, ser fopen() que se usa para abrir dicho fichero. Dispone de varios tipos de modos de acceso al fichero (nota: llamaremos cursor a una posicin desde donde se puede interactuar con el fichero, como si de un cursor de un fichero de Word cualquiera se tratase): Modo de apertura r Descripcin Modo de solo lectura. Se abre el fichero y el cursor se coloca al principio del mismo, permitiendo leerlo hasta el final. Modo de lectura/escritura. Se abre el fichero y el cursor se coloca al principio del mismo, permitiendo leer o escribir en el fichero. Modo de slo escritura. Se crea el fichero si no
105

r+

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

existiese, y, si existe, se borra todo su contenido, se sita el cursor al principio del fichero permitindonos escribir. w+ Modo de escritura/lectura. Si el fichero no existe, se crea, y, si existiese, se borra todo su contenido, se sita el cursor al principio del fichero permitindonos escribir y leer. Modo de aadido. Abre el fichero, sita el cursor al final del mismo y permite escribir. Si el fichero no existe, lo crea, pero, en caso de existir, no borra su contenido. Modo de aadido/lectura. Sita el cursor al final del fichero y permite escribir y leer. Si el fichero no existe, lo crea, ero, si existe, no borra su contenido. Creacin y apertura para slo escritura; coloca el cursor al principio del archivo. Si el archivo ya existe, la llamada a fopen() fallar devolviendo FALSE y aparecer un Warning en pantalla. Si el archivo no existe se intenta crear. Creacin y apertura para lectura y escritura; coloca el cursor al principio del archivo. Si el archivo ya existe, la llamada a fopen() fallar devolviendo FALSE y aparecer un Warning en pantalla. Si el archivo no existe se intenta crear.

a+

x+

Su sintaxis es la siguiente:
<?php fopen("ruta_a_fichero.txt","modo"); ?>

Veamos un ejemplo abriendo un fichero que est en nuestra carpeta, y otro ejemplo en el que estamos accediendo a un fichero que se encuentra en una carpeta.
<?php //En nuestra misma carpeta $fichero = fopen("mi_fichero.txt","r");//As lo abriramos en modo de solo lectura. //En otra carpeta $fichero = fopen("carpeta/mi_fichero.txt", "w"); //As lo abriramos en modo de slo escritura ?>

Una cosa a tener en cuenta es el sistema operativo que estemos usando. Ya que si usamos un sistema bajo UNIX, las rutas se harn con una barra inclinada a la derecha /, en cambio para especificar los diferentes niveles entre carpetas en windows, necesitamos 2 barras inclinadas a la izquierda: \\
<?php //Accediendo a un fichero en una carpeta en un sistema UNIX $fichero = fopen("carpeta/mi_fichero.txt", "w"); //As lo abriramos en modo de slo escritura //Accediendo a un fichero en una carpeta en un sistema Windows $fichero = fopen("carpeta\\mi_fichero.txt", "w"); //As lo abriramos en modo de slo escritura ?>

106

GESTION DE FICHEROS

Nota: fopen, a parte de servirnos para abrir ficheros locales, nos permite abrir URLs, tipo fopen("http://www.google.com"). Para que se sepa que es una url, habr que poner el protocolo delante, es decir el http:// ya que no seria lo mismo fopen("http://www.google.com") que fopen("www.google.com"). En ese segundo caso, php intentara abrir un fichero local llamado www.google.com Al igual que abrimos un fichero, php nos da una funcin para cerrarlo. Por que hay que cerrar los ficheros?, primero, para no tener variables en memoria con posibilidad de tener gran cantidad de datos. Y otra cosa importante, es que si queremos leer el fichero despus de haber introducido datos mediante fputs por ejemplo (la funcin la veremos ms adelante), primero hay que cerrar el archivo con fclose. Este es su uso:
<?php $fichero = fopen('archivo.txt', 'r'); fclose($fichero); ?>

11.1.1.1.

Lectura de ficheros

Para leer una linea entera (siempre que el modo de apertura nos permita la lectura), podemos usar la funcin fgets(). Su sintaxis es:
<?php fgets($manejador ?> [, int $longitud ])

donde $manejador es el fichero que hayamos abierto con fopen, y donde $longitud es un numero entero en bytes que nos indica el tamao mximo de la linea a leer. $longitud es un parmetro opcional. Hasta PHP 4.3.0, al omitirlo se asuma una longitud de lnea de 1024. Si la mayora de las lineas en el archivo son todas mayores de 8KB, es ms eficiente para el script especificar la longitud mxima de lnea. Despus de leer la lnea, el cursor pasara a la linea siguiente. Veamos un ejemplo de fgets, donde adems veremos una buena forma de recorrer un fichero hasta el final del mismo:
<?php if($fh = fopen("fichero.txt","r")){ //Al colocarlo dentro de la condicin if, sabremos si no ha habido ningn problema al abrir el fichero while (!feof($fh)){ //Atencin a la funcin feof(), se usa para saber si se ha llegado al final de un fichero $F1[] = fgets($fh); } fclose($fh); } ?>

En este trozo de cdigo, vamos almacenando el contenido de nuestro fichero en un array. Gracias a la funcin feof(), sabremos si el cursor est situado en el final del fichero.

107

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

11.1.1.2.

Escritura de ficheros

Para escribir dentro de un fichero, usaremos fputs o fwrite (son idnticas, aunque fputs es un poco ms rpida que fwrite). Su sintaxis es:
<?php fwrite ( $manejador , $cadena_texto [, $longitud ] ); fputs ( $manejador , $cadena_texto [, $longitud ] ); ?>

Donde: $manejador es la variable con el contenido del fichero, abierto con fopen habitualmente, $cadena es el texto que va a ser escrito, y $longitud es un parmetro opcional, de tipo entero que determina la longitud en bytes de lo que se va a escribir. Si se da el argumento longitud, la escritura se detendr despus de hayan sido escritos tantos bytes como se indiquen o se alcance el final de $cadena, lo que suceda primero. Veamos un ejemplo:
<?php $fp = fopen('texto.txt', 'w'); fputs($fp, "1"); fputs($fp, "23"); fclose($fp); // el contenido de 'texto.txt' es 123 todo junto. $fp = fopen('texto2.txt', 'w'); fputs($fp, "1\n"); fputs($fp, "23"); fclose($fp); //en este caso el contenido de texto2.txt seria un 1 en una linea y un 23 en otra. ?>

11.1.1.3. Manejo de ficheros subidos desde un formulario con php


Lo primero es crear un formulario con un input tipo file. Ojo al tipo de codificacin que tiene que tener el formulario para subir archivos, enctype=multipart/form-data.
<form action="upload.php" method="post" enctype="multipart/formdata"> <input name="archivo" type="file" /> <input name="enviar" type="submit" value="Enviar" /> <input name="action" type="hidden" value="upload" /> </form>

Cuando se sube un fichero, se copia a una carpeta temporal, que si no es utilizado mientras funciona nuestro script, el contenido de dicha carpeta se borrar. Para saber la ruta y otras propiedades del archivo, tenemos que recurrir a la variable superglobal $_FILES. Ten en cuenta que es un array asociativo donde el ndice es el nombre del campo del formulario usado para el fichero: $_FILES['archivo']['size']: tamao en bytes $_FILES['archivo']['type']: tipo mime del archivo, por ejemplo image/jpeg

108

GESTION DE FICHEROS

$_FILES['archivo']['name']: nombre original $_FILES['archivo']['tmp_name']: nombre del archivo temporal que se utiliza para almacenar en el servidor el archivo recibido

Imaginemos que tenemos una carpeta llamada archivos_subidos donde tenemos permisos de escritura.
<?php if ($_POST["action"] == "upload") { // obtenemos los datos del archivo $tamano = $_FILES["archivo"]['size']; $tipo = $_FILES["archivo"]['type']; $archivo = $_FILES["archivo"]['name']; if ($archivo != "") { // guardamos el archivo en la carpeta archivos_subidos $destino = "archivos_subidos/".$archivo; if (copy($_FILES['archivo']['tmp_name'],$destino)) { echo = "Archivo subido: <b>".$archivo."</b>"; } else { echo "Error al subir el archivo"; } } else { echo = "Error al subir archivo"; } ?> }

Tenemos ms funciones de manejo http://es2.php.net/manual/en/ref.filesystem.php

del

sistema

de

ficheros

en

11.1.2.

Actividad
Actividad 1

11.1.2.1.

Crea un formulario que te permita subir una foto, y copiarla a un directorio de tu eleccin. Al mismo tiempo cuando se copie el fichero, crea un fichero de texto que se llame igual que la foto pero con extensin txt (pj: mifoto.jpg mifoto.txt) En el que se almacene el nombre del fichero, y la fecha en la que se ha subido. Al terminar el proceso, deber mostrar el contenido del fichero en la plantilla html

11.2. POO en PHP


La programacin orientada a objetos es un paradigma de programacin avanzado. PHP5 incorpora una nueva forma de POO respecto a versiones anteriores (PHP4 incorporaba objetos, pero lo haca de una forma algo extraa a bajo nivel), la cul contribuye a mejorar su rendimiento y aumentar sus posibilidades.

11.2.1. Definicin de Clases, objetos, atributos y mtodos

109

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Una clase es la definicin de un objeto, por decirlo de alguna forma, sera nuestro cdigo. Se compone de atributos y mtodos. Un atributo no es ms que una variable perteneciente a la clase, y que se puede acceder desde cualquier mtodo mediante una sintaxis especfica como si de una variable global se tratara. Un mtodo es una funcin perteneciente a una clase Un objeto es la instancia en tiempo de ejecucin de dicha clase.

Vemoslo con un ejemplo ms del da a da Imaginmos una persona. Con todas sus caractersticas fsicas, su gnero, altura, peso, color de pelo, extremidades etc. Persona, seria nuestra clase, donde su peso, su altura, pierna izquierda, pierna derecha etc seran sus atributos, y acciones cotidianas como andar, correr, comer, seran los mtodos de dicha clase donde se pueden usar los atributos. Por ejemplo para nuestro mtodo correr, necesitaramos usar los atributos pierna izquierda y pierna derecha. Ahora imaginemos Persona (nuestra clase), si llevamos la definicin Persona, a personas de verdad, por ejemplo Juan y Mara, estos serian los objetos. Es decir, nosotros tenemos una definicin de persona, de la cual puede haber n instancias de la misma, con los mismos atributos (aunque con valores diferentes). En este caso, nuestro objeto Juan por ejemplo tendra su atributo genero con el valor masculino, y nuestro objeto Maria tendra su atributo genero como femenino. Veamos un ejemplo en PHP de nuestra clase Persona:
<?php class Persona{ public $genero; // | public $altura; // | --- >estos seran nuestros atributos como si de variables normales se trataran. public $peso; // | public function andar(){ } como simples funciones. public function correr(){ } } ?> // | // | // | ---> as se declararan los mtodos, // | // |

Como has podido ver, se ha colocado la palabra public delante de nuestros atributos y nuestras funciones. Esto mostrar la visibilidad de nuestro atributo o de nuestro mtodo. Hay 3 tipos: public el mtodo o el atributo se puede acceder desde cualquier lado. private slo se puede acceder al mtodo o al atributo desde la misma clase pero no lo podrn ver las clases hijas (veremos que es una clase hija en el siguiente punto, la herencia). protected solo se puede acceder al mtodo o al atributo desde la misma clase o desde clases hijas.

Las clases disponen de un mtodo constructor que se ejecutar siempre que se cree el objeto. Este mtodo se llama en php5 __construct()
<?php class MiClase{

110

GESTION DE FICHEROS

} ?>

public __construct(){ //cdigo que queremos que se ejecute al crearse nuestro objeto }

11.2.2.

Manejo de objetos

Para crear un objeto a partir de una clase definida, usaremos la palabra reservada new seguido del nombre de nuestra clase:
<?php $a = new MiClase(); //Esto crear una instancia de mi clase "MiClase", dentro de $a //Si quisiramos usar los mtodos o atributos de la clase se usar una flecha $a->mi_atributo; $a->mi_mtodo(); ?>

Cuando estamos definiendo una clase si necesitamos hacer referencia al propio objeto, se usa la palabra $this. $this es una referencia al objeto que se est usando (usualmente el objeto al que el mtodo pertenece, pero puede ser otro objeto, si un mtodo es llamado estticamente desde el contexto de un objeto secundario). Veamos un ejemplo:
<?php class A { function foo() { if (isset($this)) { echo '$this esta definido ('; echo get_class($this); echo ")\n"; } else { echo "\$this no esta definido.\n"; } } } class B { function bar() { A::foo(); } } $a = new A(); $a->foo(); A::foo(); $b = new B(); $b->bar(); B::bar(); ?>

El resultado del ejemplo seria:


$this esta definido (a) $this no esta definido.

111

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

$this esta definido (b) $this no esta definido.

11.2.3.

Actividades
Actividad 1

11.2.3.1.

Crea un objeto que contenga 2 atributos numricos, e implementa 5 funciones. suma, resta, multiplicacin, divisin (decimal) y divisin entera, que muestren el resultado de la operacin por pantalla.

11.2.3.2.

Actividad 2

Modifica la clase anterior para que los atributos sean privados y solo se pueda acceder a ellos mediante los mtodos setParam1() y setParam2(). Ahora las funciones suma, resta, multiplicacin, divisin_decimal y divisin_entera, sern mtodos privados. Slo se podr acceder a ellos a travs de una funcin publica operacin() que recibir como nico parmetro una cadena de texto que ser el nombre de cada operacin.

11.2.4.

Uso de la Herencia

La herencia es uno de los mecanismos fundamentales de la programacin orientada a objetos. Gracias a la herencia, podemos definir clases, a partir de la definicin de otras clases. Las clases que hereden de otras, poseern los mismos atributos y mtodos que la clase padre, pero adems podr extender su funcionalidad aadiendo ms atributos y mtodos. Por ejemplo, imaginemos la clase mamferos. Todos los mamferos tienen cosas en comn, pero otras muy diferentes. Por ello se crearan clases que heredasen de mamferos como podran ser perros, gatos, o nuestra clase persona. Ejemplo
<?php class MiClasePadre{ public $var1; //Esta variable podr ser usada desde cualquier sitio private $var2; //esta variable solo puede ser usada en esta clase protected $var3; //esta variable solo la podrn usar esta clase y sus clases hijas. public function funcion1(){ //Esta funcin podr ser usada desde cualquier sitio } private function funcion2(){ //esta funcin solo puede ser usada en esta clase } protected function funcion3(){ //esta funcin solo la podrn usar esta clase y sus clases hijas. } } class MiClaseHija extends MiClasePadre{ public $otra_variable; public function otrafuncion(){
112

GESTION DE FICHEROS

} ?>

Al igual que vimos en el punto anterior que se puede decir la visibilidad de un mtodo o un atributo, opcionalmente podremos usar las siguientes palabras clave delante de la palabra class y que tienen mucho que ver con la herencia: abstract: clase que no puede ser crear una instancia como objeto final: no podr tener clases hijas

Las clases abstractas sirven para declarar una entidad, a la cual no se le puede implementar su cdigo en parte o al completo todava, ya que puede que su funcionalidad vare dependiendo de quien herede. Ejemplo de clase abstracta:
<?php abstract class nombre_clase{ public $x; private $y; public function __construct(){ } public abstract function nombre_mtodo(); //no se define nada de cdigo solo la declaracin del mtodo }

Como vemos, tambin se puede asignar la palabra abstract a un mtodo, el cual no implementa cdigo, es mas, ni siquiera lleva llaves para definirlo. Ese mtodo habr que implementarlo despus en las clases hijas.

11.2.5.

Actividades
Actividad 1

11.2.5.1.

Crea una clase que herede la clase del ejercicio 2 del punto anterior. Haz las modificaciones necesarias en los atributos y mtodos para que sean accesibles desde esta clase nueva, pero no desde fuera de ellas.

11.2.5.2.

Actividad 2

En esta nueva clase aade el mtodo concatenacin. Que haga una concatenacin de cadenas de texto con los 2 mtodos de la clase padre. Redefine en la clase hija la funcin getParam1 y la funcin getParam2 y haz los cambios necesarios en la clase hija para que dependiendo del mtodo devuelva un entero, un float, o una cadena. Pista: necesitaras redefinir el mtodo operacin y aadir un atributo nuevo. Para hacer una conversin de tipos utiliza las los operadores (int)(string)(float): ejemplo: $a = (int)$b;

11.2.6.

Manejo de excepciones

113

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

A partir de PHP5 se ha incluido el uso de excepciones como en otros lenguajes de programacin. El manejo de excepciones es una estructura de control de los lenguajes de programacin diseada para manejar condiciones anormales que pueden ser tratadas por el mismo programa que se desarrolla. Por ejemplo, un programa puede admitir cierto nmero de errores en el formato de los datos y continuar su proceso para producir el mejor resultado posible en lugar de producir una salida aparatosa llena de mensajes de error probablemente incomprensibles para el usuario. Muchas veces, la accin asociada a una excepcin es simplemente producir un mensaje informativo y terminar; otras veces, es slo indicacin de la necesidad de un cambio en la estrategia de resolucin del problema. Una excepcin puede ser lanzada thrown, y capturada (catched) dentro de PHP. El cdigo debe estar delimitado dentro de un bloque try, para facilitar el capturar las excepciones potenciales. Cada bloque try debe tener al menos un bloque catch. Mltiples bloques catch pueden ser usados para capturar diferentes clases de excepciones. En la ejecucin normal (cuando no hay excepciones dentro de un bloque try, o cuando el bloque catch correspondiente a la clase de la excepcin lanzada no esta presente) continuar hasta el ltimo bloque catch definido en la secuencia. Las excepciones pueden ser iniciadas o reiniciadas dentro de un bloque catch. Cuando es lanzada una excepcin, la siguiente lnea de cdigo no ser ejecutada y PHP intentar encontrar el primer bloque de captura de excepciones catch. Si una excepcin no es capturada se despliega un error fatal de PHP con un mensaje de que la excepcin no fue capturada. El objeto lanzado como excepcin, deber ser una instancia de la clase Exception o una clase heredada de la misma. Intentar lanzar (throw) un objeto que no lo sea, provocar que PHP lance un error fatal. Veamos un ejemplo de uso:
<?php function inverso($x) { if (!$x) { throw new Exception('Se ha intentado dividir por cero.'); echo "hola"; //esta linea nunca aparecer ya que se ha lanzado la excepcin. } else return 1/$x; } try { echo inverso(5) . "\n"; echo inverso(0) . "\n"; } catch (Exception $e) { echo 'Excepcin capturada: ', } // Se continua con la ejecucin. echo 'Hola mundo'; ?>

$e->getMessage(), "\n";

Al ejecutar este script este sera nuestro resultado:


0.2 Excepcin capturada: Se ha intentado dividir por cero. Hola mundo

11.2.7.

Actividades

114

GESTION DE FICHEROS

11.2.7.1.

Actividad 1

Modifica la clase hija del ejercicio anterior para que admita la posibilidad de concatenar arrays de datos. Aade un control de excepciones comprobando que los datos van a ser arrays.

11.2.7.2.

Interfaces

Las interfaces son como una declaracin de las funciones que debern tener las clases que implementen una interfaz. Es decir, si nosotros declaramos una interfaz, cuando una clase la implemente, nos aseguraremos de que esas clases tendrn dichas funciones. Cuando se defina una interfaz, se declararn exclusivamente los mtodos a implementar pero sin crear ningn tipo de cdigo dentro, de eso se tienen que encargar las clases que la implementen. Por ejemplo, imaginemos un globo tpico que llevan los nios por la calle con helio, y un avin En principio no tienen nada en comn, por lo que si hubiese que establecer una herencia sera prcticamente imposible, pero dichos objetos tienen la cualidad de que de una forma pueden ascender y descender en el aire. Ahora por ejemplo creamos un interfaz volador:
<?php interface volador{ public function ascender(); public function descender(); } ?>

Recuerda, en la interfaz no se codifican los mtodos. Ahora veamos como implementar en nuestra clase dichos mtodos.
<?php class globo implements volador{ public function ascender(){ echo "Parece que el beb se ha quedado sin su juguete"; } public function descender(){ echo "Debe estar picado..."; }

} ?>

Se podran implementar varias interfaces en la misma clase, en cuyo caso se indicaran todos los nombres de las interfaces separadas por comas. En el cdigo de la clase estamos obligados a declarar y codificar todos los mtodos de la interfaz. Nota: en concreto, PHP 5 entiende que si una clase implementa una interfaz, los mtodos de esa interfaz estarn siempre en la clase, aunque no se declaren. De modo que si no los declaramos explcitamente, PHP 5 lo har por nosotros. Esos mtodos de la interfaz sern abstractos, as que la clase tendr que definirse como abstracta. Ahora veamos el cdigo de nuestro avin:

115

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

<?php class avin implements volador{ private $piloto; private $gasolina; function __construct(){ $this->gasolina = 0; $this->piloto = false; } public function ascender(){ if (!$this->piloto){ echo "donde vas sin piloto? anda, busca uno"; } else if ($this->gasolina = 0) { echo "Deberas revisar la gasolina"; } else { echo "A volar!!..."; } } public function descender(){ if (!$this->piloto){ echo "Pero se puede saber como has arrancado esto sin piloto? Estas loco! Has visto Perdidos?... ya sabes lo que te espera"; } else { echo "Bajando..."; } } } ?>

Como se puede ver, ambas clases no tienen nada en comn salvo los mtodos, que adems por dentro son completamente diferentes. Gracias a las interfaces, podremos hacer llamadas polimrficas pasando como parmetros, los objetos que implementan una interfaz.
<?php function sube (volador $objeto){ $objeto->ascender(); } $unglobo = new globo(); $unavion = new avin(); sube($unglobo); sube($unavion); //con esto haramos que nuestro globo y nuestro avin ascendieran con la misma funcin. class ladrillo{ public $peso; } $ladrillo = new ladrillo(); sube($ladrillo); // Esto dara un Fatal Error en el que se nos indicara que hay que implementar la interfaz volador ya que nuestra clase ladrillo no lo hace ?>

11.2.8. Diferencias entre clases abstractas e interfaces

116

GESTION DE FICHEROS

Cuando hemos definido los interfaces, seguramente te hayan venido a la cabeza las clases abstractas, ya que parecen hacer lo mismo. S, y no :) Veamos unas diferencias: Caracterstica Herencia Mltiple Interfaz Una clase puede implementar tantas interfaces requiera. Clase abstracta Por lo general, una clase slo puede heredar una clase abstracta.

Implementacin por defecto

Una interfaz no puede Una clase abstracta puede proporcionar ningn cdigo de proporcionar la implementacin de algunos mtodos y dejar sin implementacin, solo la implementar exclusivamente cabecera de la funcin. aquellos que varen dependiendo de la clase hija Los interfaces carecen de atributos Una clase abstracta puede tener atributos

atributos

11.2.8.1.

Actividades

Crea una clase abstracta y una interfaz con mtodos idnticos, y haz una implementacon de cada una en dos objetos (uno en cada).

117

DESARROLLO MVC CON PHP

Desarrollo MVC con PHP

12.1. Qu es MVC?
MVC corresponde al acrnimo de Model View Controller,o en castellano, modelo vista controlador. Es un paradigma de programacin ampliamente utilizado en el desarrollo de aplicaciones web. Se encarga de separar las funcionalidades en 3 capas diferentes,como su nombre indica: modelo vista y controlador. El Modelo es la capa encargada de interactuar con la base de datos La vista es la capa que se encarga de tratar (unir la informacin recibida desde el controlador y el cdigo HTML) lo que el usuario ver. El Controlador es la capa que se encarga de la lgica general de la aplicacin,recoge las peticiones de la vista, llamar al modelo para recoger la informacin solicitada, y estos datos los devolver de nuevo a la vista para que los muestre al usuario.

12.2. Porqu utilizar el paradigma MVC?


Bsicamente por el mantenimiento y reusabilidad de nuestro cdigo. Si nuestro cdigo fallara, sera mas fcil localizar errores al tener menos lineas de cdigo. O si por ejemplo un cliente nos pide cambiar nuestro tipo de base de datos (por ejemplo de mysql a
119

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

sqlserver) slo tendramos que cambiar el modelo y no tendramos que re-escribir toda nuestra aplicacin. Veamos un ejemplo, de cmo seria una aplicacin sencilla para mostrar edad y nombre de un grupo de personas sin el paradigma MVC:
<? // abrimos conexin $cn = mysql_connect('localhost', 'usuario', 'clave'); mysql_select_db('nombre_bd', $cn); // cogemos el nombre y edad mediante una SQL $resultado=mysql_query('SELECT nombre, edad FROM personas', $cn); ?> <h1>Personas</h1> <table> <tr> <th>Nombre</th> <th>Edad</th> </tr> <?php // recorremos el array y mostramos los datos while ($fila = mysql_fetch_array($resultado, MYSQL_ASSOC)) { echo "<tr>"; echo "<td> ".$fila['nombre']." </td>"; echo "<td> ".$fila['edad']." </td>"; echo "</tr>"; } ?> </table> <?php //cerramos la conexin mysql_close($cn); ?>

Al estar todo en un solo fichero, si tuvisemos que cambiar el tipo de base de datos, habra que re-escribir prcticamente todo. Adems si se trabaja con un diseador web, mientras nosotros trabajamos en nuestro listado, l no podra trabajar en el diseo.

12.3. Empezando a separar nuestro cdigo


El ejemplo anterior los separaremos en 3 archivos, controlador.php modelo.php y vista.php. controlador.php
require('modelo.php'); $personas = cogePersonas(); require('vista.php');

modelo.php
<?php function cogePersonas() { $cn = mysql_connect('localhost', 'usuario', 'clave'); mysql_select_db('nombre_bd', $cn); $resultado = mysql_query('SELECT nombre, edad FROM personas', $cn); $personas = array();

120

DESARROLLO MVC CON PHP

while($persona = mysql_fetch_assoc($resultado)) { $personas[] = $persona; } mysql_close(); } ?>

vista.php
<h1>Personas</h1> <table> <tr> <th>Nombre</th> <th>Edad</th> </tr> <?php foreach($personas as $persona){ ?> <td><?php echo $persona['nombre'];?></td> <td><?php echo $persona['edad'];?></td> </tr> <?php } //fin del foreach ?> </table> <tr>

Con esta separacin como vemos nuestro controlador seria solo un mero programa para pasar datos de modelo a vista. Aqu es donde si queremos podemos implementar lgica adicional para hacer ms seguras nuestras aplicaciones (validaciones, control de usuarios etc).

12.4. Abstrayndonos del gestor de base de datos


En este ejemplo, hemos usado MySQL como nuestro gestor de base de datos. Si tuvisemos una aplicacin muy compleja, y tuvisemos que cambiar nuestro gestor de base de datos, nos tocara cambiar todas las funciones de acceso a mysql por las de acceso al gestor de base de datos nuevo y eso es malo. Por ello podemos dividir aun ms nuestro modelo (recuerda,divide y vencers! :D). acceso_mysql.php
function conectar($servidor, $usuario, $clave) { return mysql_connect($servidor, $usuario, $clave); } function cerrarConexion($cn) { mysql_close($cn); } function consulta($consulta, $base_datos, $cn) { mysql_select_db($base_datos, $cn); return mysql_query($consulta, $cn); } function cogerResultado($resultado, $tipo = MYSQL_ASSOC) {

121

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

return mysql_fetch_array($resultado, $tipo);

modelo.php
switch(GESTOR_BBDD){ //GESTOR_BBDD Es una constante que podramos haber definido en un fichero de configuracin de nuestra aplicacin case "MYSQL": require_once("acceso_mysql.php"); break; case "SQLSERVER": require_once("acceso_sqlserver.php"); //un fichero similar al de mysql pero con las funciones de sqlserver break; case "ORACLE": require_once("acceso_oracle.php");//lo mismo aqu pero con oracle :) break; default: require_once("acceso_mysql.php"); break; } function cogePersonas() { $cn = conectar('localhost', 'usuario', 'clave'); $resultado=consulta('SELECT nombre, edad FROM personas', 'db', $cn); $personas = array(); while ($persona = cogerResultado($resultado)) { $personas[] = $persona; } cerrarConexion($cn); return $personas; }

Ahora por cada gestor de base de datos que queramos aadir, solo tenemos que aadir un fichero ms con las funciones tpicas de ese gestor, sin cambiar nuestro modelo.

12.5. Actividades
Vamos a usar el paradigma modelo vista y controlador, pero usando objetos. Crea un fichero index.php y 3 objetos, control, modelo, y vista. En el fichero index php, se inicializara el objeto control. El objeto modelo, proveer de funciones para acceder a un fichero de texto que tendr un formato CSV (cada fila hace de registro, y los campos estn separados por el smbolo ;) Los campos correspondern a este orden: nombre, edad, direccin, telfono

Jose;39;Gran via 39;91234567 Pedro;16;Calle Mayor 1;91234567 Maria;25;Calle Antonio Machin 23;91234567

El objeto vista, tendr una funcin para recibir los datos, y los formateara con sintaxis HTML. El objeto control tendr como mnimo 2 atributos, que sern $modelo y $vista (en ellos hay que instanciar un modelo y una vista)

122

DESARROLLO MVC CON PHP

Se llamar al objeto modelo para obtener los datos del fichero CSV y se los pasara a la vista para que los muestre.

123

GESTOR DE PLANTILLAS: SMARTY

Gestor de plantillas: Smarty


Bueno, lo primero de todo, que son las plantillas?. Son ficheros que contienen la estructura completa de un documento, a la cual se le pasarn valores de determinadas variables. Por poner un ejemplo de la vida real, podran compararse a las quinielas. El papel es igual para todo el mundo, pero cada persona la rellena de forma diferente. Es decir, cada persona le pasara unos valores diferentes a la plantilla En las plantillas de Smarty podemos crear la estructura completa de un documento HTML, y en el lugar donde debe desplegarse el valor de la variable, insertamos la expresin {$variable}. Esto es lo mismo que escribir <?echo $variable;?>, pero como vemos, es ms sencillo de entender y ensucia menos nuestra plantilla, que recordemos que muchas veces es un diseador el que tiene que retocarla, y a menudo no saben de programacin. Veamos como instalar Smarty.

13.1.1.

Instalacin

Para ejecutar Smarty es suficiente descargar el archivo correspondiente y descomprimirlo, o hacer un sudo apt-get install smarty si estamos en un sistema basado en debian, como ubuntu. Si nos descargamos el fichero, tendremos que tener en cuenta que el cdigo que necesitamos, la biblioteca en s,se encuentra en el directorio /libs.

125

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Necesitaremos incluir en nuestra aplicacion el fichero Smarty.class.php con ayuda de la funcin require() (si lo hemos instalado a travs de ubuntu, es posible que la ruta donde est Smarty.class.php sea /usr/share/php/smarty/). Veamos ahora qu necesitamos para usar Smarty en nuestra aplicacin. Smarty requiere la creacin de cuatro carpetas. Sus nombres por defecto son /templates, /templates_c, /configs y /cache (Si queremos cambiarlos, habria que cambiar las 4 variables que les corresponden dentro del fichero Smaty.class.php: $template_dir, $compile_dir, $config_dir y $cache_dir). Muy importante, al menos /templates_c y /cache necesitarn tener permiso de escritura para el servidor web. Ya estamos listos para empezar a jugar con Smarty, pero antes, ya que smarty tiene mucho que ver con el diseo de nuestra aplicacin, no nos vendr mal dar un repaso rpido a la creacin de un fichero CSS.

13.1.2.

Bases de smarty filtros,

13.1.3. Modificadores, funciones, plugins, estructuras de control


13.1.3.1. Modificadores

Los modificadores funcionan como algunas funciones de tratamiento de cadenas de PHP. Por que usar modificadores de Smarty en vez de las funciones de PHP?. Si usamos los modificadores, nosotros como programadores no tendremos que preocuparnos si le tenemos que pasar el texto en maysculas al diseador, o en minsculas, por que vaya a quedar ms bonito. Es el diseador el que automticamente por medio de dichos modificadores, transformar el contenido como quiera. Adems que la sintaxis de Smarty siempre ser mucho ms fcil de usar para el diseador que la que se puede encontrar en PHP. http://www.smarty.net/manual/es/language.modifiers.php

13.1.3.2.

Funciones

Smarty nos ofrece un abanico de funciones que nos automatizan la creacin de elementos HTML a travs de arrays de datos. Pongamos un ejemplo para verlo ms claro: Si escribimos en nuestra plantilla: {html_radios name=color options=$colores separator=<br />} donde $colores es un array con los siguientes datos: $colores =
array ("1" => "azul", "2" => "amarillo", "3" => "rojo", "4" => "negro");

cuanto smarty lo procese, nos dar el siguiente resultado en nuestro cdigo HTML: <input type=radio name=magazine value=1 />azul<br /> <input type=radio name=magazine value=2 />amarillo<br /> <input type=radio name=magazine value=3 />rojo<br /> <input type=radio name=magazine value=4 />negro<br />

126

GESTOR DE PLANTILLAS: SMARTY

Y el diseador slo ha escrito una lnea :D

13.1.3.3.

Filtros

Los filtros funcionan de manera similar a los modificadores, ya que son capaces de alterar contenido. Pero en este caso, los filtros estn mas orientados a limpiar nuestras plantillas determinados elementos, como por ejemplo comentarios en documentos HTML que no queremos que se lea, o incluso agregar contenido, como firmas, por ejemplo: Esto lo he hecho con Smarty. http://www.smarty.net/manual/es/plugins.prefilters.postfilters.php

13.1.3.4.

Plugins

Si las funciones, filtros, o modificadores que tenemos a nuestra disposicin no nos sirven para la funcionalidad que necesitemos, Smarty nos permite crear nuestras propias funciones, filtros y modificadores.

13.1.3.5.

Estructuras de control

Tambin es posible la creacin de instrucciones if o foreach, por ejemplo; con el objetivo de verificar si la variable que se da a la plantilla no est vaca, esto es: {if $name != } Bienvenido! {else} Cmo te llamas? {/if} En el ejemplo citado se despliega el rtulo Bienvenido!, si la variable $name no est vaca, o Cmo te llamas? en el caso contrario. Tambin es posible utilizar bucles, en este caso el foreach, que nos permite recorrer arrays de datos:
{foreach key=key item=item from=$mi_array} {$key}: {$item}<br /> {/foreach}

13.1.4.

Como usar smarty

Para ver como usar Smarty, pongamos un ejemplo de una web de un grupo de msica, Metallica por ejemplo. Imaginemos la discografa, en la que cada disco debera tener su pgina propia. Para no escribir una pgina por cada disco, utilizaremos el sistema de plantillas. Imagina que el fichero se llama album.tpl dentro del directorio /templates.
<html> <head> <title>{$name}</title> </head> <body> <h1>{$name}</h1> <table> <tr> <td><img src="{$cover}" alt="" /></td> <td><h4>Canciones:</h4><br />{$songs}</td> </tr> </table>

127

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

<h4>Descripcin del lbum:</h4> <p>{$info}</p> <p><a href="">Pgina principal</a></p> </body> </html>

Y ahora creemos el fichero php que har uso de esta plantilla. (Para hacer ms comprensible este ejemplo, se escriben los datos tal cual, pero lo suyo es utilizar una base de datos, y usando por ejemplo, el paradigma MVC).
<?php require ("Smarty.class.php"); $smarty = new Smarty; $smarty->assign("name", "Master of Puppets"); $smarty->assign("cover", "img/masterofpuppetscover.jpg"); $smarty->assign("songs", "Battery; Master of Puppets; The Thing That Should Not Be; Welcome Home (Sanitarium); Disposable Heroes; Leper Messiah; Orion; Damage, Inc."); $smarty->assign("info", "Master of Puppets es el tercer lbum del grupo de thrash metal Metallica. Fue lanzado al mercado el 3 de marzo de 1986, y fue el ltimo lbum grabado junto al bajista Cliff Burton que morira trgicamente en septiembre de ese mismo ao en un accidente de autobs. Muchos consideran que es donde se refleja claramente la habilidad de su bajista Cliff Burton. Este disco alcanz la posicin nmero 29 de la lista del Billboard y fue uno de los primeros del thrash metal en serlo. La banda de metal progresivo Dream Theater lanz un lbum de versiones de Master of Puppets en el ao 2004 bajo el nombre "Dream Theater Oficial Bootleg: Master of Puppets" en el cual se encuentra la totalidad de las canciones del disco original producido por Metallica."); $smarty->display("album.tpl"); ?>

Como podemos observar, smarty hace uso de la funcin assign() para mandar las variables a la vista y poder ser usadas ms tarde como {$variable} y en el momento que se usa display(nombre_plantilla.tpl) nos muestra el contenido de la plantilla. A partir de aqu, Smarty compila la plantilla y empieza a sustituir las etiquetas smarty por cdigo php. Por ejemplo {$var} ser cambiado por:
<?php echo $this->_tpl_vars['var']; ?>

Cuando se haya traducido todo el documento, automticamente se copiara al directorio /templates_c, y cada vez que se llame a nuestro fichero php, el servidor coger el fichero ya traducido, por lo que no tendr que hacer la compilacin de nuevo. Si en algn momento nuestro la plantilla es modificada, smarty lo detectar automticamente, y volver a compilarla Si se quiere usar comentarios dentro de la plantilla usaremos {* y *}:
<p> cdigo de mi plantilla </p> {* esto es un comentario que no se vera ni siquiera en el cdigo html en nuestro navegador *} <p> cdigo de mi plantilla </p> ...

Ahora imaginemos que necesitamos hacer uso de los caracteres {} en nuestro documento HTML,por ejemplo si usamos javascript o css. 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:

128

GESTOR DE PLANTILLAS: SMARTY

<style> p {ldelim}color: #000000; font-size: 12px{rdelim} </style> Es obvio que si hay que usar una gran cantidad de llaves este sistema no es cmodo. Por ello Smarty nos deja las etiquetas {literal}{/literal} Y todo lo que haya entre medias, no lo interpretar. {literal} <style> p {color: #000000; font-size: 12px} </style> {/literal} De paso mencionar que Smarty tiene su propio mecanismo de comentarios, que son eliminados durante la compilacin. Los comentarios en la plantilla se inician con {* y terminan con *}. Ya que estamos viendo la etiqueta style, peguemos un repaso rpido a los CSS

13.2. Generacin de CSS


Las Hojas de Estilo (CSS: Cascading StyleSheets) son un sistema que permiten aplicar un diseo y un formato a los documentos HTML y todo esto separando el estilo visual del contenido del mismo ya que todos los estilos estn en el fichero css. Para incluir un fichero CSS en nuestro documento css hay que usar la etiqueta link dentro de nuestra etiqueta head:
<html> <head> <title>titulo</title> <link rel="stylesheet" type="text/css" href="estilos.css" /> </head> <body> </body> </html>

Tambin se puede utilizar la etiqueta style dentro del propio documento:


<style> p {color: #000000; font-size: 12px} </style>

Pero es ms recomendable utilizar la otra forma, incluyndolo con link, ya que as separamos por completo estilo y contenido. El formato bsico de una clase CSS es:
selector { atributo1: valor; atributo2: valor; ... atributo_n: valor; }

Los algunos selectores son los siguientes: SELECTOR UNIVERSAL El asterisco * hace referencia a todos los elementos HTML del documento
* { background-color: black; }

SELECTOR POR TIPO Los selectores por tipo hacen referencia a las etiquetas html en s, por ejemplo para un prrafo, etiqueta <p> sera lo siguiente:

129

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

p {

background-color: white; }

SELECTOR POR CLASE El selector por clase, hace referencia a todos los elementos que tengan el atributo class=mi_clase. En el documento css la clase se hace referencia con un punto. Puede ir solo o acompaando a la etiqueta html.
.mi_clase { background-color: yellow; }

Esto har referencia a todos los elementos html que tengan el atributo class=mi_clase.
p.mi_clase { background-color: yellow; }

Y esto har referencia a todos los prrafos <p> que tengan el atributo class=mi_clase. SELECTOR POR ID El atributo id, nico dentro del documento HTML. Por lo tanto este estilo slo se aplicar a un elemento. Se hace referencia con una almohadilla #.
#mi_clase { background-color: yellow; }

SELECTORES DESCENDENTES Para hacer referencia a elementos que estn dentro de otros, se utiliza este tipo de selectores. Bsicamente hay que definir el elemento padre y separado con un espacio el elemento al que queremos aplicarle el estilo. Por ejemplo, si nos encontramos esto:
p strong { background-color: yellow; }

Esto significa que el estilo se aplicara al contenido de todas las etiquetas strong, que estn dentro de prrafos <p>
<p> A este cdigo no se le aplicara el estilo <strong> a este si</strong> a este no </p> <strong> a este tampoco por que esta fuera de un prrafo </strong>

En cuanto a los atributos, hay una gran cantidad de ellos, podemos encontrar algunos interesantes aqu: http://www.desarrolloweb.com/articulos/186.php Por ltimo, sealar, que si aadimos ms de una hoja de estilo, y algunos selectores hagan referencia al mismo elemento, sus atributos se sumarn, y si hay algn atributo repetido en las diferentes hojas de estilo, se aplicar la ltima que haya sido leda.

13.3. Creando layouts


Lo bueno de usar un sistema de plantillas es que podemos fragmentar nuestro layout en varios ficheros e irlos referenciando dentro del layout principal. Imaginemos un index.tpl con la estructura principal.
<html> <head>titulo</head> <link rel="stylesheet" type="text/css" href="estilos.css" /> <body> {include_template file="cabecera.tpl"} {include_template file="menu.tpl"} {include_template file="contenido.tpl"} {include_template file="pie.tpl"} </body> </html>

Despus en vamos definiendo el resto de plantillas: por ejemplo cabecera.tpl:


<div class="slogan"> Eslogan de mi pagina web</div> <div class="logo"></div>

130

GESTOR DE PLANTILLAS: SMARTY

Y as sucesivamente. Podemos aadir lgica a nuestros layouts. Por ejemplo dentro de la plantilla contenido.tpl, no se mostrar lo mismo si estamos en la pgina principal, que si estamos por ejemplo (retomando el ejemplo anterior de metallica) mostrando el lbum de nuestro grupo favorito. contenido.tpl
{if $tipo == "album"} {include_template file="album.tpl"} {else} {include_template file="otro_layout.tpl"} {/if}

13.4. Creando formularios


Cuando creamos formularios, un trabajo algo tedioso es crear el cdigo html donde se pondr de nuevo los datos si ha habido algn fallo al intentar insertar, o editar un elemento, o poner listados en elementos select. Smarty nos simplifica esto al no tener que poner cdigo php en nuestra plantilla. <form method=post action=inscripcion.php>
Usuario <input type="text" name="Usuario" value="{$usuario}"><br> Nombre <input type="text" name="Nombre" value="{$nombre}"><br> Pais <select name="pais"> {html_options options=$paises} {* Esta funcin html_options equivaldra al siguiente foreach: {foreach key=key item=item from=$paises} <option value="{$key}">{$item}</option> {/foreach} *} </select> <input type="submit" value="Enviar">

</form> Aqu (http://www.smarty.net/manual/es/language.custom.functions.php) podemos ver ms funciones que nos pueden resultar muy tiles a la hora de generar formularios, ya que se pueden usar funciones para crear checkboxes, radiobuttons, etc

13.4.1.

Actividades

Vamos a seguir ampliando las funcionalidades de los 3 objetos que hemos creado anteriormente en el ejercicio del paradigma MVC

13.4.1.1.

Actividad 1

Crea un layout para una web que contenga: Cabecera o o Menu logotipo

Espacio para contenido Formulario para introducir Nombre, edad, direccin y telfono.
131

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Pie de pagina

Cuando se acceda a nuestra web, mostrar: Una cabecera que contendr un men (el men de momento solo pondr un enlace a nuestra pgina de inicio) y espacio para un logotipo o un slogan con el nombre de la aplicacion gestin de contactos En el contenido aparecer el listado de personas con sus datos personales en una tabla html y un enlace que lleve a una pgina para introducir una nueva persona. En el pie de pagina estar tu nombre y la informaron bsica sobre la web (lenguajes usados, ao etc)

13.4.1.2.

Actividad 2

Modifica el objeto vista de nuestro ejercicio del paradigma MVC para implementar toda la lgica de smarty necesaria para que funcione nuestra web. Recuerda modificar el modelo para que permita aadir ms personas al final del fichero.

13.5. Accesibilidad en Web


Segn la Wikipedia la accesibilidad web se refiere a la capacidad de acceso a la Web y a sus contenidos por todas las personas independientemente de la discapacidad (fsica, intelectual o tcnica) que presenten o de las que se deriven del contexto de uso (tecnolgicas o ambientales). Esta cualidad est ntimamente relacionada con la usabilidad. Cuando los sitios web estn diseados pensando en la accesibilidad, todos los usuarios pueden acceder en condiciones de igualdad a los contenidos. Por ejemplo, cuando un sitio tiene un cdigo XHTML semnticamente correcto, se proporciona un texto equivalente alternativo a las imgenes y a los enlaces se les da un nombre significativo, esto permite a los usuarios ciegos utilizar lectores de pantalla o lneas Braille para acceder a los contenidos. Cuando los vdeos disponen de subttulos, los usuarios con dificultades auditivas podrn entenderlos plenamente. Si los contenidos estn escritos en un lenguaje sencillo e ilustrados con diagramas y animaciones, los usuarios con dislexia o problemas de aprendizaje estn en mejores condiciones de entenderlos. Si el tamao del texto es lo suficientemente grande, los usuarios con problemas visuales puedan leerlo sin dificultad. De igual modo, el tamao de los botones o las reas activas adecuado puede facilitar su uso a los usuarios que no pueden controlar el ratn con precisin. Si se evitan las acciones que dependan de un dispositivo concreto (pulsar una tecla, hacer clic con el ratn) el usuario podr escoger el dispositivo que ms le convenga. Las limitaciones en la accesibilidad de los sitios Web pueden ser: Visuales: En sus distintos grados, desde la baja visin a la ceguera total, adems de problemas para distinguir colores (Daltonismo). Motrices: Dificultad o la imposibilidad de usar las manos, incluidos temblores, lentitud muscular, etc, debido a enfermedades como el Parkinson, distrofia muscular, parlisis cerebral, amputaciones Auditivas: Sordera o deficiencias auditivas.

132

GESTOR DE PLANTILLAS: SMARTY

Cognitivas: Dificultades de aprendizaje (dislexia, discalculia, etc) o discapacidades cognitivas que afecten a la memoria, la atencin, las habilidades lgicas, etc.

Estas pautas se pueden agrupar en 3 tipos. Pautas de Accesibilidad al Contenido en la Web (WCAG): Estn dirigidas a los webmasters e indican cmo hacer que los contenidos del sitio Web sean accesibles. Pautas de Accesibilidad para Herramientas de Autor (ATAG) Estn dirigidas a los desarrolladores del software que usan los webmasters, para que estos programas faciliten la creacin de sitios accesibles. Pautas de Accesibilidad para Agentes de Usuario (UAAG) Estn dirigidas a los desarrolladores de Agentes de usuario (navegadores y similares), para que estos programas faciliten a todos los usuarios el acceso a los sitios Web.

Normativa sobre accesibilidad en la ley espaola: Ley 51/2003 de 2 de diciembre de Igualdad de Oportunidades, No Discriminacin y Accesibilidad Universal con discapacidad. Real Decreto 366/2003 de 16 de marzo, de accesibilidad y no discriminacin de las personas con discapacidad en sus relaciones con la Administracin General del Estado. Ley 27/2007, de 23 de octubre, por la que se reconocen las lenguas de signos espaolas y se regulan los medios de apoyo a la comunicacin oral de las personas sordas, con discapacidad auditiva y sordociegas. Real Decreto 1494/2007, de 12 de noviembre, por el que se aprueba el Reglamento sobre las condiciones bsicas para el acceso de las personas con discapacidad a la sociedad de la informacin. Ley 49/2007, de 26 de diciembre, por la que se establece el rgimen de infracciones y sanciones en materia de igualdad de oportunidades, no discriminacin y accesibilidad universal de las personas con discapacidad.

Normativa UNE 139803:2004 Llamada Aplicaciones informticas para personas con discapacidad. Requisitos de accesibilidad para contenidos en la Web, proporciona soluciones accesibles para los desarrolladores Web, creando un listado de recursos que permiten definir las caractersticas que han de cumplirse en materia de los contenidos Web en Internet, Intranets y en cualquier otro tipo de redes informticas, para que stos puedan ser utilizados por el mayor nmero de personas, incluyendo las personas con discapacidad y las personas de edad avanzada. Hay una traduccin muy interesante acerca de las pautas de accesibilidad de contenido en la web (WCAG) en esta URL: http://qweos.net/blog/2009/01/28/guias-practicas-paraprofesionales-web-puntos-de-verificacion-de-las-pautas-de-accesibilidad-al-contenidoweb-wcag-20/

133

CAPA DE ACCESO A DATOS CON ADODB

Capa de acceso a datos con AdoDB


Si recuerdas, dentro del punto de MVC, se hablaba de la abstraccin de acceso a datos. Apareca una estructura switch donde hacamos un require de un fichero con el acceso a mysql, oracle, sqlserver dependiendo de la variable que se analizaba en el switch. AdoDB hace ms o menos lo mismo. Nos ofrece un api con el cual podemos acceder a diferentes tipos de bases de datos utilizando las mismas funciones.

14.1. Conexiones a Bases de Datos


Recordemos como acceder a una base de datos MySQL con el api de PHP y como recorrer los datos que nos mande php .
<?php $db = mysql_connect("localhost", "root", "password"); mysql_select_db("mydb",$db); $result = mysql_query("SELECT * FROM usuarios",$db); if ($result === false) die("failed"); while ($fields = mysql_fetch_row($result)) { for ($i=0, $max=sizeof($fields); $i < $max; $i++) { print $fields[$i].' '; } print "<br>n";
135

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

} ?>

Y esta es la forma de hacerlo con AdoDB.


<?php include("adodb.inc.php"); //incluimos nuestra libreria de adodb $db = NewADOConnection('mysql'); //creamos una conexin a base de datos almacenada en $db $db->Connect("localhost", "root", "password", "mydb"); //conectamos con nuestra base de datos llamada mydb $result = $db->Execute("SELECT * FROM usuarios"); //ejecutamos la SQL if ($result === false) die("failed"); //si el resultado,tambin llamado recordset, de la ejecucin es false, cortamos la ejecucin del script while (!$result->EOF) { //mientras que no se llegue al final de los registros for ($i=0, $max=$result->FieldCount(); $i < $max; $i++) //se recorre cada campo del registro print $result->fields[$i].' '; $result->MoveNext(); //OJO, siempre es necesario usar esta funcin para pasar al siguiente registro print "<br>n"; } $db->Close();//Cerramos la conexin. ?>

Veamos algunas funciones que se pueden usar con un recordset (el resultado de ejecutar una consulta): $recordsetMove($pos) mueve el recordset a una fila en particular. ADODB soporta avance de filas en todas las bases de datos. Algunas bases de datos no soportan retroceso en el recordset. Puede de todas maneras simular este comportamiento usando un cach. $recordsetRecordCount() retorna el total de filas obtenidas en el recordset. Algunas bases de datos no soportan esto y se devuelven un -1. $recordsetGetArray() coloca el resultado del recordset en un array.

14.2. Generacin de Consultas


Algo muy recomendable a la hora de hacer consultas a una BBDD, es tener una clase que genere consultas SQL de forma automatizada. Por ejemplo una clase, que tenga como atributos la tabla que se esta usando, un prefijo de la tabla (por si queremos tener varias instalaciones de nuestra aplicacin en una sola base de datos).

14.2.1.

Actividad

Crea una clase que genere de forma automtica consultas SQL. Ten en cuenta:

136

CAPA DE ACCESO A DATOS CON ADODB

Que se pueda usar un prefijo para la tabla Que contemple los casos de SELECT, INSERT, UPDATE y DELETE Dichos casos debern tener funciones con los mismos nombres: select insert, update, delete

14.3. Acceso a los Metadatos


Veamos funciones que nos permiten acceder a los metadatos de una base de datos, de una tabla, o de campos. En principio estos son accesibles a travs de $db, es decir, la conexin creada a la base de datos.

14.3.1.

MetaDatabases()

Devuelve un array con la lista de bases de datos disponibles en el servidor. Solo disponible para ODBC, MySQL y ADO.

14.3.2. MetaTables($ttype = $showSchema = false, $mask=false)

false,

Devuelve un array de las tablas y vistas de la base de datos actual. El array omitir en lo posible las tablas del sistema. Para nicamente mostrar tablas use dbMetaTables('TABLES'). Para nicamente mostrar vistas use $dbMetaTables('VIEWS'). Actualmente el parmetro $showSchema solo funciona para DB2, y cuando es verdadero, agrega el nombre del esquema a la tabla, ej. SCHEMA.TABLE. Se puede definir una mascara de coincidencia. Por ejemplo, con $mask = 'TMP%' solo encontrara las tablas que empiecen con 'TMP'. Por lo pronto solo mssql, oci8, odbc_mssql y postgres* manejan el parmetro $mask.

14.3.3.

MetaColumns($table,$toupper=true)

Devuelve un array de objetos de la clase ADOFieldObject, un objeto por cada columna de la tabla $table. Cada instancia tiene definidos las propiedades (name, type, max_length). Actualmente Sybase no reconoce los tipos de fecha y ADO no puede identificar el tipo adecuado de datos (por lo que se identifican como 'varchar'). El parmetro $toupper determina si hay que convertir a maysculas el nombre de la tabla (requerido por algunas bases de datos). Para el manejo de esquemas, en el parmetro $table mande $schema.$tablename. Estos solo funciona en algunas bases de datos. el valor

14.3.4.

MetaColumnNames($table)

Devuelve un array con los nombres de las columnas de la tabla $table. Desde ADOdb 4.22, es un array asociativo con las claves en maysculas

137

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Es decir, array('FIELD1'

'Field1', 'FIELD2' 'Field2')

14.3.5.

MetaPrimaryKeys($table, $owner=false)

Devuelve un array con el nombre de las columnas que forman la clave primaria de la tabla $table. Actualmente manejado por mysql, odbc (incluyendo db2, odbc_mssql, etc), mssql, postgre, interbase/firebird, oci8. Las vistas (y algunas tablas) tienen clave primaria, pero algunas veces esta informacin no esta disponible para la base de datos. Tu puedes definir una funcin ADODB_View_PrimaryKeys($databaseType, $database, $view, $owner) que devuelva el array conteniendo los campos que forman la clave primaria. Si esta funcin existe sera invocada cuando MetaPrimaryKeys() no pueda encontrar la llave primaria para tabla o vista.
<?php // En este ejemplo: dbtype = 'oci8', $db = 'mydb', $view = 'dataView', $owner = false function ADODB_View_PrimaryKeys($dbtype,$db,$view,$owner) { switch(strtoupper($view)) { case 'DATAVIEW': return array('DATAID'); default: return false; } } $db = NewADOConnection('oci8'); $db->Connect('localhost','root','','mydb'); $db->MetaPrimaryKeys('dataView'); ?>

14.3.6.

ServerInfo($table)

Devuelve un array asociativo con dos elementos 'description' y 'version'. El elemento 'description' contiene una cadena con la descripcin de la base de datos. El elemento 'version' contiene una cadena con el numero de version.

14.3.7. MetaForeignKeys($table, $upper=false)

$owner=false,

Devuelve un array asociativo con las claves forneas (foreign keys) de la tabla, o falso si no esta soportado. Por ejemplo, si la tabla 'empleados' tiene una clave fornea 'empleados.empl_dept' apunta a 'departamentos.dept_clav', y empleados.empl_puesto=organigrama.orga_puesto y empleados.empl_cat=organigrama.orga_cat, entonces $dbMetaForeignKeys('empleados') obtendr como resultado:
array( 'departamentos' => array('empl_dept=dept_clav'), 'organigrama' => array('empl_puesto=orga_puesto','empl_cat=orga_cat') )

138

CAPA DE ACCESO A DATOS CON ADODB

Opcionalmente el dueo de la tabla o vista se puede definir en $owner. Si $upper es verdadero entonces el nombre de las tablas (que sern las claves del array asociativo) se convierten a maysculas

14.3.8.

FetchField($column_number)

Ojo, a esta funcin se accede a travs del recordset, no de la conexin. Devuelve un objeto conteniendo name, type and max_length de el campo solicitado. Si max_length no se puede determinar con seguridad, tendr el valor de -1. El numero de columna esta en base a cero (la primer columna es 0). Ver el ejemplo 2.

14.4. Ejecucin de Consultas


Ya hemos visto cmo ejecutar una sentencia SELECT en ADODB. Como ejecutar sentencias como INSERT, UPDATE con ADODB: Desde la version 4.56 de ADOdb, se puede usar manejamos AutoExecute(), que simplifica las cosas proporcionando una funcin de nivel superior que encapsula las llamadas a GetInsertSQL() y GetUpdateSQL(). Por ejemplo, un INSERT puede hacerse as:
<?php $record["firstname"] = "Bob"; $record["lastname"] = "Smith"; $record["created"] = time(); $insertSQL = $db->AutoExecute($rs, $record, 'INSERT'); es un recordset ?>

//donde $rs

y un UPDATE as:
<?php $record["firstname"] = "Caroline"; $record["lastname"] = "Smith"; # Actualiza el apellido de Caroline de Miranda a Smith $insertSQL = $db->AutoExecute($rs, $record, 'UPDATE', 'id = 1'); ?>

En versiones anteriores habra que generar la SQL mediante las funciones GetInsertSQL y GetUpdateSQL().
<?php include('adodb/adodb.inc.php'); $sql = "SELECT * FROM mi_tabla WHERE id = -1"; //Creamos una SQL para que seleccione una consulta en blanco de la tabla que queremos modificar $db = NewADOConnection("mysql"); //creamos la conexin $db->Connect("localhost", "root", "contrasea", "base_de_datos"); //Se conecta a la BD $rs = $db->Execute($sql); //Ejecutamos la SQL para obtener el recordset $record = array(); //iniciamos el array que mandaremos con los valores a hacer el insert //aadimos los valores $record["campo1"] = "valor1"; $record["campo2"] = "valor2";

139

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

$record["campo3"] = "valor3"; $insertSQL = $db->GetInsertSQL($rs, $record);//Generamos la SQL mandando el recordset vaco, y los campos para hacer el insert. $db->Execute($insertSQL); //Insertamos /************************** * Ahora veremos el update **************************/ $sql = "SELECT * FROM mi_tabla WHERE id = 1"; //Hacemos una consulta en la que seleccionemos el registro a actualizar. $rs = $db->Execute($sql); //Y la obtenemos $record = array(); //iniciamos el array //colocamos los valores que queremos modificar $record["campo1"] = "otro valor1"; $record["campo2"] = "otro valor2"; $updateSQL = $db->GetUpdateSQL($rs, $record); //Generamos la SQL $db->Execute($updateSQL); //Ejecutamos $db->Close(); //Cerramos la conexin ?>

Para hacer un DELETE, solo tendremos que usar la SQL DELETE FROM mi_tabla WHERE condicin y usar un $dbExecute();

14.4.1.

Actividad

Vamos a seguir ampliando funcionalidades a nuestro gestor de contactos que llevamos haciendo desde nuestro ejercicio MVC. Coge el objeto de modelo, y modifcalo para que a partir de ahora, en vez de acceder a un fichero para coger los datos de las personas, se acceda a base de datos. Implementa tambin los mtodos de edicin y borrado. Esto implicar tambin modificar el formulario para que admita la edicin, el listado para incluir los enlaces de edicin y borrado, y el controlador para que gestione todo.

140

USO DE SERVICIOS DE INTERNET CON PHP

Uso de servicios de internet con PHP


Muchas veces nos pueden surgir situaciones en el desarrollo de una aplicacin en las que no podamos acceder directamente a las bases de datos para poder intercambiar y gestionar informacin. Diferentes polticas de comparticin de datos, as como distintos sistemas de gestin de bases de datos pueden poner trabas a la hora de manejar dichas informaciones. Para ello se han desarrollado una serie de protocolos y estndares que sirven para intercambiar datos entre aplicaciones. Distintas aplicaciones de software desarrolladas en lenguajes de programacin diferentes, y ejecutadas sobre cualquier plataforma, utilizados para intercambiar datos en redes de ordenadores como Internet. Este tipo de protocolos y estndares de intercambio de informacin son los denominados: Web Services. La interoperabilidad se consigue mediante la adopcin de estndares abiertos. Las organizaciones OASIS y W3C son los comits responsables de la arquitectura y reglamentacin de los servicios Web. Ventajas de los servicios web: Aportan interoperabilidad entre aplicaciones de software independientemente de sus propiedades o de las plataformas sobre las que se instalen.

141

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Los servicios Web fomentan los estndares y protocolos basados en texto, que hacen ms fcil acceder a su contenido y entender su funcionamiento. Al apoyarse en HTTP, los servicios Web pueden aprovecharse de los sistemas de seguridad firewall sin necesidad de cambiar las reglas de filtrado. Permiten que servicios y software de diferentes compaas ubicadas en diferentes lugares geogrficos puedan ser combinados fcilmente para proveer servicios integrados. Permiten la interoperabilidad entre plataformas de distintos fabricantes por medio de protocolos estndar y abiertos. Las especificaciones son gestionadas por una organizacin abierta, la W3C, por tanto no hay secretismos por intereses particulares de fabricantes concretos y se garantiza la plena interoperabilidad entre aplicaciones.

15.1. Distintos modelos de Servicios Web


Dentro de los protocolos y estndares abiertos y libres de la industria de los servicios web podemos destacar los siguientes: SOAP: http://es.wikipedia.org/wiki/Simple_Object_Access_Protocol REST: http://es.wikipedia.org/wiki/Representational_State_Transfer XML-RPC: http://es.wikipedia.org/wiki/XML-RPC

Estos tres sistemas de intercambio de informacin, son distintos entre s, aunque cumplen con las condiciones enumeradas anteriormente. Las diferencias principales suelen ser a nivel de protocolo y a nivel de formatos de intercambio de informacin. As como el XML-RPC fue un precursor sencillo de intercambio de informacin, SOAP su sucesor est totalmente protocolizado y estructurado, y ha dado lugar a una serie de estndares complementarios a la hora de realizar esas transacciones de informacin. Ambos sistemas estn basados en el intercambio de ficheros XML. El caso de REST o RESTful el formato de intercambio de fichero puede llegar a variar y no est tan estructurado con en el caso de SOAP. Por lo que que es ms abierto y flexible a la hora de realizar ese tipo de intercambios de informacin. El conjunto de funcionalidades ofrecidas por un determinado servicio web, suele ser denominado API WEB.

15.2. Algunos API's WEB accesibles a travs de Internet


Dichas API's son publicadas por los constructores de software para permitir acceso a caractersticas de bajo nivel o propietarias, detallando solamente la forma en que cada rutina debe ser llevada a cabo y la funcionalidad que brinda, sin otorgar informacin a cerca de como se lleva a cabo la tarea. Son utilizadas por los programadores para

142

USO DE SERVICIOS DE INTERNET CON PHP

construir sus aplicaciones sin necesidad de volver a programar funciones ya hechas por otros, reutilizando cdigo que se sabe que est probado y que funciona correctamente. En la web, las API's son publicadas por sitios para brindar la posibilidad de realizar alguna accin o acceder a alguna caracterstica o contenido que el sitio provee. Algunas de las ms conocidas son las API's de: Google API's: http://www.google.com/apis/ Flickr: http://www.flickr.com/services/api/ Amazon: https://affiliate-program.amazon.com/gp/advertising/api/detail/main.html Facebook: http://developers.facebook.com/docs/ Twitter: http://apiwiki.twitter.com/

Por otra parte podemos, llegar a encontrar determinados estndares web que permiten funcionalidades de otro mbito distinto. Por ejemplo para temas de autenticacin podemos usar: OpenID: http://es.wikipedia.org/wiki/OpenID Oauth: http://es.wikipedia.org/wiki/OAuth

15.3. Recursos
Algunos de estos API's suelen ser accesibles a travs de bibliotecas de acceso a dichos protocolos y estndares de intercambio de informacin. Una de las tareas principales a la hora de permitir la integracin de este tipo de servicios web en nuestras aplicaciones suele ser la localizacin de la informacin correspondiente a dicho API, as como la bsqueda de bibliotecas que faciliten la conexin o el intercambio de informacin. Cada protocolo y cada estndar suele tener una serie de bibliotecas de funciones asociadas.

15.4. Actividades
15.4.1. Actividad 1

Localiza una biblioteca que permita consultar servicios SOAP en PHP.

15.4.2.

Actividad 2

Localiza una biblioteca que permita manejar una autenticacin con Oauth en PHP.

15.4.3.

Actividad 3

Localiza las bibliotecas de acceso a los API's de facebook para PHP.

143

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

15.4.4.

Actividad 4

Localiza la informacin correspondiente al API Open Social.Describe para qu funciona y que recursos tienes disponibles.

144

FRAMEWORKS DE DESARROLLO EN PHP

Manejo de usuarios/seguridad

16.1. Autenticacin y Autorizacin


Aunque sean 2 palabras parecidas, cuando se habla de autenticacin y autorizacin, no hablamos de lo mismo. Por que diran los componentes de la agrupacin cmica Les Luthiers parecido no es lo mismo caballero. La autenticacin (tambin llamada autentificacin), es el proceso de intento de verificar la identidad digital del remitente de una comunicacin como una peticin para conectarse. Es decir, el tpico proceso de introducir un usuario y una contrasea. Podramos dividir los mtodos de autenticacin en 3 categoras: Sistemas basados en algo conocido. Ejemplo, una contrasea (o password) o una frase de paso (passphrase). Sistemas basados en algo posedo. Ejemplo, una tarjeta de identidad, una tarjeta inteligente, dispositivo usb. (En esta categora entraran los DNI-electronicos) Sistemas basados en una caracterstica fsica del usuario o un acto involuntario del mismo: Ejemplo, verificacin de voz, de escritura, de huellas, de patrones oculares.

Habitualmente en nuestros sistemas web utilizaremos una contrasea. Para hacer ms seguras nuestras aplicaciones, deberemos guardar de forma segura las contraseas de

145

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

nuestros usuarios para tratar de evitar que si otras personas las roban, no puedan hacer nada con ellas. Aqu es donde entran los mtodos de encriptacin. PHP nos ofrece algunas funciones para encriptar contraseas con diferentes algoritmos, por ejemplo crypt, md5 o sha1. La funcin md5 Esta funcin se encarga de aplicar el algoritmo hash md5, el primer parmetro es la cadena a encriptar, y el segundo recibe un valor booleano, si este es FALSE (por defecto) devolver el valor hexadecimal, y si el parmetro es TRUE retornara el valor binario.
<?php $md5_encripted = md5("contrasea"); //es lo mismo que $md5_encripted = md5("contrasea",false); ?>

La funcin crypt() crypt a diferencia de md5 utiliza el segundo parmetro otra cadena adicional, que se usa como semilla para generar la cadena encriptada. Si no se le pasa una, php le dar una aleatoria.
<?php $crypt_encripted = crypt("contrasea", "semilla"); ?>

La funcin sha1() Esta funcin esta desplazando al la funcin md5, utiliza encriptacion de un solo sentido usando el algoritmo de hash seguro. (http://www.faqs.org/rfcs/rfc3174.html)
<?php $sha1_encripted = sha1("contrasea"); ?>

Evidentemente podemos usar varios mtodos de encriptacin a la vez. para hacerlo ms seguro
<?php $sha1_md5_encripted = sha1(md5("contrasea")); ?>

O juntar diferentes cadenas que solo nosotros sepamos, o combinaciones con el usuario y la contrasea:
<?php $sha1_md5_encripted = sha1(crypt("contrasea"."usuario", "semilla))."holahola"); ?>

Cuando guardemos la contrasea de un usuario, lo que haremos ser guardar la cadena encriptada, y la comparacin ser entre cadenas encriptadas:
<?php $password = md5($_POST['password']); $bd_user_pass = getUserPassword($user_id); //imaginemos que getUserPassword accede a nuestra bbdd con el id del usuario y recoge la cadena encriptada con md5 if ($password == $bd_user_pass) echo "acceso concedido"; ?>

146

FRAMEWORKS DE DESARROLLO EN PHP

Evidentemente si hemos hecho alguna combinacin de cadenas extraas, cuando hagamos la comparacin deberemos hacer exactamente el mismo proceso para poder comparar ambas cadenas. La autorizacin por su parte, es el proceso de decirnos (tras estar autentificados) si se tiene acceso a un recurso. La autorizacin podramos dividirla tambin en 3 niveles: Aplicacin: el usuario tras identificarse tiene acceso la aplicacin, por ejemplo: entrar en un foro. Funcionalidad: el usuario tras identificarse tiene acceso a una funcionalidad: por ejemplo entrar a la galera de fotos del foro. Objeto: el usuario tras identificarse y poder entrar en la funcionalidad de nuestra aplicacin, puede acceder a determinado elemento: Por ejemplo, acceder a una foto en concreto de la galera de fotos, o a un post concreto en el foro.

Evidentemente, no siempre es necesario llegar a incluir una autorizacin de estos 3 niveles en nuestras aplicaciones. Si no que tendremos que evaluar nuestra aplicacin y si vemos necesario implementarlo o no. Una buena forma de establecer una autorizacin de forma genrica y no por usuario (lo que sera prcticamente imposible) es utilizando grupos, (o perfiles, o roles, aqu la terminologa nos dara igual ya que cada uno podra llamarlo de la diferentes formas para referirse a lo mismo). La idea es agrupar una serie de funcionalidades o recursos disponibles en nuestra aplicacin a un grupo. Por ejemplo, no es lo mismo la cantidad de recursos a los que puede acceder un administrador, que un usuario normal, o un usuario annimo que no est autenticado en nuestro sistema. A modo de informacin, hay un par de APIs que han surgido hace relativamente poco, y que estn intentando unificar un sistema de Autenticacin y de Autorizacin. Sus nombres son OpenID y OAuth. OpenID es un standard de identificacin digital descentralizado, con el que un usuario puede identificarse en una pgina web a travs de una URL (o un XRI en la versin actual) y puede ser verificado por cualquier servidor que soporte el protocolo. En los sitios que soporten OpenID, los usuarios no tienen que crearse una nueva cuenta de usuario para obtener acceso. En su lugar, solo necesitan disponer de un identificador creado en un servidor que verifique OpenID, llamado proveedor de identidad o IdP. OAuth por su parte es un protocolo abierto, que permite autorizacin segura de un API de modo estndar y simple para aplicaciones de escritorio, mviles, y web. Para desarrolladores de consumidores, OAuth es un mtodo de interactuar con y publicar datos protegidos. Para desarrolladores de proveedores de servicio, OAuth proporciona a los usuarios un acceso a sus datos al mismo tiempo que protege las credenciales de su cuenta. En otras palabras, OAuth permite a un usuario del sitio A compartir su informacin en el sitio A (proveedor de servicio) con el sitio B (llamado consumidor) sin compartir toda su identidad.

16.1.1.

Actividades
Actividad 1

16.1.1.1.

Crea en php un sistema autenticacin, usando las funciones de encriptacin que tu desees.
147

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

16.1.1.2.

Actividad 2

Disea un sistema de autorizacin que contemple los 3 tipos de niveles. De acceso a la aplicacin, a la funcionalidad, y a nivel de objeto.

16.2. Manejo de Sesiones


A la hora de almacenar ciertos valores durante un tiempo y que podamos acceder a ellos de forma rpida sin la necesidad de tener que guardarlos en una base de datos, podemos usar las sesiones y las cookies. Centremonos primero en las sesiones. Las sesiones, en aplicaciones web realizadas con PHP y en el desarrollo de pginas web en general, nos sirven para almacenar informacin que se memorizar durante toda la visita de un usuario a una pgina web. Dicho de otra forma, un usuario puede ver varias pginas durante su paso por un sitio web y con sesiones podemos almacenar variables que podremos acceder en cualquiera de esas pginas. Con las sesiones guardaremos informacin nica para cada usuario durante su visita. Es decir la sesin que abra un usuario en una aplicacin ser independiente de las que abran otros usuarios. Estas sesiones, tendrn un identificador nico, para identificar que sesin pertenece a cada usuario. Identificativo que para ser conservado habr que guardarlo en una cookie o propagarla a travs de la URL. Esto es configurable a travs del fichero php.ini. Veamos como usar sesiones. session_start () Funcin necesaria siempre que usemos una sesin. Inicia una sesin o contina una que pudiera estar abierta en otras pginas (de nuestra aplicacin se entiende). Al usar session_start() PHP crear el identificador nico, o si ya est creado, lo recibir por URL o de una cookie. Se puede configurar php.ini para que se inicialice la sesin sin hacer session_start() (directiva session.auto_start = 1) Muy importante, si se quiere usar sesiones, hay que usar session_start antes de escribir cualquier texto en nuestra pgina, ya que si no lo hacemos seguramente nos salte un error ya que al iniciar sesin se deben leer las cookies del usuario, algo imposible de hacer cuando las cabeceras HTTP estan enviadas. A partir de ahora podremos usar la variable global $_SESSION, que es un array asociativo. Recuerda que este curso es sobre PHP5, si usases una version anterior a PHP 4.1.0 habra que usar $HTTP_SESSION_VARS que no es de mbito global, o registrar variables por separado con session_register(). Pero centrmonos en PHP5. Cmo definir una variable de sesin:
<?php session_start(); $_SESSION["variable"] = "Valor"; ?>

Si queremos leer la variable sera de la siguiente forma (recuerda que hay que usar session_start siempre al inicio):
<?php session_start(); print $_SESSION["variable"]; ?>

148

FRAMEWORKS DE DESARROLLO EN PHP

Para obtener el id de una sesin podremos usar la funcin session_id(). Mas funciones sobre sesiones http://www.php.net/manual/en/ref.session.php en el manual de php:

16.2.1.

Actividades
Actividad 1

16.2.1.1.

Partiendo del ejercicio de crear un sistema de autenticacin en php, implementa sesiones para que el usuario permanezca logueado en tu sistema. Implementa tambin una funcin logout en la que se salga de la sesin.

16.2.1.2.

Actividad 2

Extiende el ejercicio anterior creando un contador de visitas del usuario a la web. Ten en cuenta:

16.2.1.3.

Actividad 3

Para recordar smarty, crea un formulario que est dividido en 3 pantallas diferentes. Introduccin de nombre y apellidos, introduccin de direccin, e introduccin de gustos musicales. Se deber pasar de una pantalla a otra manteniendo los datos en sesin. Cuando se haya introducido los datos en las 3 pantallas diferentes, se ir a una cuarta, donde se mostrarn los valores.

16.3. Manejo de Cookies


Cuando queremos guardar variables que perduren ms all de lo que pueda durar una sesin y no son datos crticos como contraseas, podemos usar las cookies. Estas variables se conservan durante el tiempo que nosotros necesitemos. Algunos usos de las cookies podran ser llevar un contador de visitas que haya hecho el usuario a nuestra pgina, opciones de personalizacin como el tema visual que quiere usar nuestro usuario, o el identificativo de sesin. Como crear cookies con php:

16.3.1.1.

setcookie()

Es la funcin principal para el uso de cookies. Es una funcin que admite varios parmetros de los cuales slo el primer parmetro es obligatorio. Estos son los parmetros en orden: Nombre: Cadena de caracteres con el nombre que queremos darle a la cookie.

149

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Valor: Cadena de caracteres con el valor. Caducidad Es un timestamp con el valor de la fecha en la que caducar la cookie. Lo habitual es usar es usar la funcin time(), que genera el timestamp, y despus sumarle en segundos el tiempo que queramos que dure la cookie. Por ejemplo para que la cookie dure un ao: time() + (60 * 60 * 24 * 365). Ruta La ruta donde la cookie se podr utilizar dentro del dominio. Por defecto, la cookie se podr utilizar en el directorio donde se ha creado y sus subdirectorios. Si indicamos / la cookie tendr validez dentro de todo el dominio. Dominio Es el subdominio donde se podr acceder a la cookie. Las cookies slo se pueden generar y utilizar para el dominio de la pgina donde est colocado el script, pero podemos hacerlo visible para todos los subdominios del dominio de la web por medio de .midominio.com. Seguro Es un booleano que, si es true, indica que la cookie slo puede ser transmitida por https (http seguro). Slo http Esto es otro booleano que sirve para indicar que la cookie slo puede ser accedida por medio de las cabeceras del http, lo que la hara inalcanzable para lenguajes de script en el cliente como Javascript. Este parmetro fue aadido en PHP 5.2.0 La function setcookie() de PHP genera y enva la cookie al navegador y devuelve un booleano, si es true indica que se pudo incluir en el navegador del usuario y si es false indica que no ha podido colocarla en el sistema. Ojo, que esto no indica que el usuario haya aceptado la cookie, ya que puede tener configurado el navegador para que no la acepte, y esto no lo puede detectar setcookie(). Veamos diferentes llamadas a setcookie():
<?php setcookie("cookie1", "valor"); setcookie("cookie2", "valor2", time() + 3600); setcookie("cookie3", "valor3", time() + 3600, "/", ".midominio.com"); ?>

Recordemos algo que comentbamos en la parte de sesiones. Para enviar una cookie, hay que hacerlo antes de escribir texto en la pgina, es decir, antes de mandar las cabeceras HTTP. Para recuperar las cookies, podemos usar la variable super global $_COOKIE. $_COOKIE, es un array asociativo que tendr las cookies que estn disponibles en la pgina PHP en el dominio y directorio donde est.
<?php $_COOKIE["migalleta"]; $_COOKIE["cookie2"]; ?>

150

FRAMEWORKS DE DESARROLLO EN PHP

16.3.2.

Actividades
Actividad 1

16.3.2.1.

Extiende el ejercicio del sistema de login con sesiones y contador de visitas, incluyendo un sistema con cookies para que se mantenga la sesin incluso despus de cerrar el navegador.

16.3.2.2.

Actividad 2

Haz otra version del ejercicio 3 de sesiones del formulario con 4 vistas, sustituyendo las sesiones por cookies.

16.3.2.3.

Actividad 3

Y de paso, vamos a seguir ampliando nuestro gestor de contactos :) Aade el sistema de login a la web que estamos haciendo, con un cuadro de login. No hace falta introducir el usuario y contrasea en una base de datos, puede hacerse la comprobacin directamente en el objeto controlador. Si no estamos logueados en el sistema, en vez de mostrarnos el listado de contactos, nos mostrar un formulario de login, y no nos dejar acceder a crear ni editar contactos.

151

CONSTRUIR APLICACIONES PHP SEGURAS

Construir aplicaciones PHP seguras


Tras haber visto los puntos de Autorizacin y Autenticacin, seguiremos aportando ms seguridad a nuestras aplicaciones mediante la generacin de un Captcha y mirando una libreria de IDS (Intrusion Detection System).

17.1. Tratamiento de imgenes de manera dinmica


17.1.1. Generacin de captcha para formularios

Un captcha es una imagen que crearemos en la que se incluye cdigo alfanumrico que el usuario deber introducir para validar que es quien nos est mandando la informacin en el formulario, es una persona real, y no un bot. Para generar esta imagen utilizaremos la biblioteca GD. La primero es crear una imagen con un texto aleatorio, para ello creamos un archivo llamado captcha.php el cual crear dinmicamente el texto y la imagen.
<?php session_start(); function randomText($length) { $pattern = "1234567890abcdefghijklmnopqrstuvwxyz";

153

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

for($i=0;$i<$length;$i++) { $key .= $pattern{rand(0,35)}; } return $key; } $_SESSION['captcha'] = randomText(8); // Creamos una imagen y despues aadimos el texto $im = imagecreatetruecolor(120, 20); $text_color = imagecolorallocate($im, 255, 255, 255); imagestring($im, 5, 20, 1, $_SESSION['captcha'], $text_color); // Mandamos la cabecera con el tipo de contenido, en este caso image/jpeg header('Content-type: image/jpeg'); // Mostramos la imagen imagejpeg($im); // Liberamos memoria imagedestroy($im); ?>

Crear el formulario y el cdigo php para verificar el Captcha, por ejemplo en nuestro fichero index.php. Recuerda poner el fichero captcha.php en el mismo directorio que el index.
<?php session_start(); if ($_POST['action'] == "checkdata") { if ($_SESSION['captcha'] == $_POST['captcha']) { echo "Bienvenido"; } else { echo "Intntalo de nuevo"; } exit; } ?> Ingresar el texto mostrado en la imagen <br> <form action="index.php" method="post"> <img src="captcha.php" width="100" height="20"><br> <input name="captcha" type="text"><br> <input name="btsubmit" type="submit" value="Verificar Codigo"> <input name="action" type="hidden" value="checkdata"> </form>

Ahora que ya sabemos como podemos hacer un captcha a mano, es hora de conocer otra forma. Con la el servicio reCAPTCHA. Un servicio gratuito, que ofrece un api con el que poder generar captchas para nuestras aplicaciones. Nos pide que nos demos de alta, para que nos den unas claves con las que nos identificarn a la hora de pedir el captcha. Cdigos como los de cualquier servicio online, tipo googlemaps, facebook, etc
1. Descarga la libreria reCAPTCHA Library (http://recaptcha.net), descomprmela y copia recaptchalib.php al directorio donde este tu formulario. 2. Date de alta para conseguir una clave. 3. Ahora estamos listos para empezar a modificar nuestro cdigo. Lo primero aadimos el cdigo para mostrar el CAPTCHA: <?php require_once('recaptchalib.php'); $publickey = "..."; // Esta es una de las claves que se consigue al darte de alta. echo recaptcha_get_html($publickey); ?>

154

CONSTRUIR APLICACIONES PHP SEGURAS

4. En el cdigo que procesa el formulario para validar, habra que aadir el siguiente cdigo: <?php require_once('recaptchalib.php'); $privatekey = "..."; //esta es otra clave que se consigue al darse de alta $resp = recaptcha_check_answer ($privatekey, $_SERVER["REMOTE_ADDR"], $_POST["recaptcha_challenge_field"], $_POST["recaptcha_response_field"]); if (!$resp->is_valid) { die ("The reCAPTCHA wasn't entered correctly. Go back and try it again." . "(reCAPTCHA said: " . $resp->error . ")"); }

17.1.2.

Retoque de imgenes

Ya que estamos viendo una pequea pasada por encima de la biblioteca GD, vamos a ver como hacer un thubmnail (una imagen reducida), para por ejemplo crear las miniaturas de una galeria.
<?php function createThumbnail($imageDirectory, $imageName, $thumbDirectory, $thumbWidth) { $srcImg = imagecreatefromjpeg("$imageDirectory/$imageName"); //esta funcin crea una imagen en memoria a partir de un fichero $origWidth = imagesx($srcImg); //nos da la anchura de la foto $origHeight = imagesy($srcImg); //nos da la altura de la foto $ratio = $origWidth / $thumbWidth; //calculamos el ratio a partir de la anchura para poder crear la imagen al tamao adecuado. $thumbHeight = $origHeight * $ratio; //aplicamos la reduccion $tumbilla = imagecreate($thumbWidth, $thumbHeight); //creamos una imagen en memoria imagecopyresized($thumbImg, $srcImg, 0, 0, 0, 0, $thumbWidth, $thumbHeight, imagesx($thumbImg), imagesy($thumbImg)); //y finalmente hacemos una reduccin de nuestra imagen original, a nuestra thumbnail, ojo seguimos trabajando en memoria. imagejpeg($thumbImg, "$thumbDirectory/$imageName"); //y escribimos en disco. } createThumbnail("directorioconimagenes", "fichero.jpg", "directorioparaminiaturas", 100); ?>

Para ver ms funciones sobre el api de imgenes de GD, revisa este enlace: http://php.net/manual/en/ref.image.php

17.1.3.

Actividades

155

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

17.1.3.1.

Actividad 1

Crea un formulario en el que te permita subir una fotografa (puedes reutilizar el usado en el temario de ficheros), y que adems te permita introducir un pequeo texto. Se har un thumbnail de la fotografa, y adems se le aadir como marca de agua (tanto a la fotografa como al thumbnail) el texto del formulario. La fotografa se tendr que copiar al directorio /photo, y la thumbnail al directorio /thumbs. Cuando se haya completado todo el proceso, muestra una pequea vista con las 2 fotografas.

17.1.3.2.

Actividad 2

Crea un captcha, y adelo a nuestra aplicacin de gestor de contactos, para que pida un captcha en el login, y en el aadido y edicin de contactos.

17.2. Bibliotecas de seguridad: IDS


Para hacer an mas seguras nuestras aplicaciones, en las comprobaciones bsicas que solemos hacer en formularios (numero de caracteres introducidos, que sean numricos etc), a veces no est de ms hacer algunas comprobaciones para evitar que nos inyecten cdigo malicioso que podra hacer ejecutar consultas SQL entre otras cosas. Algunos tipos de ataques pueden ser: Register_Globals Reporte de error Cross-Site Scripting (XSS) Inclusin de archivo remoto (RFI) SQL Injection

Por ello, han aparecido algunas bibliotecas de seguridad como PHP-IDS http://phpids.org (PHP- Intrussion Detection System), que lo que hacen es hacer una comprobacin del contenido que se est pasando y nos devuelve una valoracin en forma de nmero, que nos dice el riesgo que podemos correr al tratar dicho contenido. Veamos como probar IDS: Lo primero descarga la ultima versin desde http://php-ids.org Descomprime el fichero. Slo necesitaremos el contenido de libs. Por ejemplo si vamos a usar el directorio /var/www/ descomprime el contenido del directorio libs ah Debera quedar una ruta como /var/www/IDS/ Ve al fichero /var/www/IDS/Config/Config.ini.php y haz una copia en ese mismo directorio que se llame Config.ini Edtalo y configura la ruta correcta hasta IDS del parmetro base_path (si estas usando la ruta /var/www/, el valor debera ser /var/www/IDS/)

Ahora crearemos un fichero index.php (o como quieras llamarlo)

156

CONSTRUIR APLICACIONES PHP SEGURAS

<?php require_once ('IDS/Init.php'); $request = array( 'REQUEST' => $_REQUEST, 'GET' => $_GET, 'POST' => $_POST, 'COOKIE' => $_COOKIE ); $init = IDS_Init::init('IDS/Config/Config.ini'); $ids = new IDS_Monitor($request, $init); $result = $ids->run(); if (!$result->isEmpty()) { // Si hay riesgo, echaremos un vistazo al objeto de resultado echo $result; } ?> <html> <head></head> <body> <form action="index.php" method="post"> <textarea name="texto"></textarea> <input type="submit" value="enviar"> </form> </body> </html>

Y ahora es hora de probar que funciona. Escribe cualquier texto que se te ocurra y dale a enviar. Si no has escrito nada que ids considere peligroso, parecer que no ocurre nada. Pero ahora escribe lo siguiente (con comillas incluidas) "192.168.0.200",2008-06-04T17:36:08+02:00,54 Si lo ejecutamos veremos que de repente ha salido un pequeo informe, indicando que el cdigo que hemos metido tiene un riesgo catalogado con un 12. Date cuenta que est cogiendo la el valor del textarea texto desde $_POST y desde $_REQUEST. Por tanto sumara 6 y 6 desde cada uno. Adems nos indica que tipo de riesgo estamos sufriendo, en este caso sera un posible caso de SQL injection. Al utilizar PHP-IDS a parte de comprobar lo que vaya por POST, como ves tambin revisar lo que vaya por GET (en la url) o incluso via COOKIE, ya que el cracker podra intentar escribir dichos valores en las cookies de nuestro sistema.

157

OPTIMIAZACION EN PHP

Optimizacin en PHP
Uno de los procesos principales a la hora de gestionar un proyecto hecho en PHP es la mejora del rendimiento de la aplicacin web. Bien porque tenemos una misma aplicacin que debe de servir muchas peticiones en poco tiempo, o bien porque tenemos varias aplicaciones instaladas en el mismo servidor y todas ellas deben poder ejecutarse a la vez. El ltimo caso es el ms tpico, porque la mayor parte de los hosting suelen ser compartidos entre clientes, si nuestra aplicacin es lo suficientemente ligera, nos permitir que nuestra parte del servidor vaya mucho ms gil y as poder dar un mejor servicio. La siguientes mejoras propuestas deben considerarse complementarias a todos aquellos principios que rigen la Ingeniera del Software (modularidad, abstraccin, etc) y de la Algoritmia (optimizacin del algoritmos de programacin).

18.1. Procesos a Optimizar


Los procesos que se ven afectados en la resolucin de una consulta a una aplicacin PHP son aquellos de los que nos vamos a preocupar en resolver en esta parte del temario. Principalmente podemos destacar los siguientes: Parmetros por defecto de PHP: dependiendo de las configuraciones que se vayan dejando en el php.ini, pueden ser ms o menos ptimas para poder servir pginas php ms rpidas

159

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Solucin: Cambiar las configuraciones sobre PHP: Las variables de PHP que se deben usar: variables_order = GPC register_argc_argv = Off register_globals = Off (tambin til para temas de seguridad) always_populate_raw_post_data = Off magic_quotes_gpc = Off A parte de desactivar los logs de errores, consumen tiempo y recursos y a parte si tienes un error no muestras informacin que quizs no quieras.

Compilacin de Objetos: cada vez que llamas a una pgina se llama al compilador y se vuelve a procesar, aunque no haya cambiado. o Solucin: Si se cachean los objetos de PHP (parecido a lo que ocurre con JSP), la primera vez se compilara y la siguiente se usara la compilada. Existen varias herramientas que nos permiten realizar este cacheado de objetos: Alternative PHP Cache (APC): Se trata de una extensin PECL que cachea el byte-code en memoria compartida. En la versin PHP6 sera incluido en el core por defecto. http://pecl.php.net/package/APC eAccelerator: Es un proyecto derivado de del ya discontinuado Turck MMCache. Permite almacenar el byte-code tanto en memoria compartida como en disco. http://eaccelerator.net/ XCache: Al igual que APC, almacena el byte-code en memoria compartida. Este tiene muy buena fama ya que ha sido creado por uno de los desarrolladores de LigHTTPd. http://xcache.lighttpd.net/ Turck MMCache for PHP: uno de los primeros aceleradores, ya descontinuado, pero se ha dejado en el listado, para saber cual fue uno de los precursores. http://turckmmcache.sourceforge.net/index_old.html

Consultas a la BBDD: Uno de los mayores problemas a la hora de escalar correctamente una aplicacin PHP, son las consultas a la BBDD. Ya que suelen consumir tiempo (es posible que demasiado), sobre todo cuanto ms crecen los datos que debemos manejar. o Solucin 1: Implantar sistemas distribuidos de cach de objetos: se trata de tener la mayora de la BD en memoria, usando para ello memcached (http://memcached.org/). Claro, que esto realmente puede ser poco til en sitios que no tengan un elevado nmero de visitas. Solucin 2: Realizar un estudio personalizado de las consultas que ms nos consumen recursos dentro de la aplicacin. Optimizarlas para mejorar su rendimiento a nivel de Servidor de BBDD.

160

OPTIMIAZACION EN PHP

Solucin 3: Colocar el servidor de BBDD en otra mquina para as, no cargar la misma mquina con ambos procesos (PHP y BBDD).

Generacin de HTML, CSS, JS: En toda aplicacin existe una parte correspondiente a la vista que normalmente suele ser esttica. Adems, dentro del cdigo PHP se produce el proceso de generacin del cdigo HTML, CSS y JS de nuestra aplicacin. A veces, simplemente para incluirlo, a veces para calcularlo. o Solucin: Si se separa convenientemente el cdigo dinmico del esttico se puede mejorar bastante el rendimiento de nuestra aplicacin. Porque suelen existir datos estticos que se muestran ms de una vez y no se quiere que se recargue. Los sistemas de cach tambin proveen una separacin entre cdigo y HTML, que no solo mejorar el rendimiento, sino que adems har ms sencilla una futura actualizacin. La mayora de los sistemas de plantillas suelen incluir dichos cacheados de plantillas que permiten que esta generacin sea muy gil por parte del servidor.Los principales sistemas de plantillas son: Smarty Templates: http://www.smarty.net/ DWOO: http://dwoo.org/ Pear Templates: http://pear.php.net/package/HTML_Template_IT/redirected y PHP savant: http://phpsavant.com/

Cdigo generado: una vez generado todo el cdigo hay que mandarlo al cliente, este cdigo puede ser muy pesado a nivel de datos. o Solucin: Comprimir la salida: mediante PHP, comprimimos la salida usando el formato zip.

18.2. Buenas prcticas de codificacin


Una de las cuestiones principales a la hora de ponerse a codificar es principalmente la manera de programar. Establecer unas determinadas maneras ayuda a crear una serie de criterios de calidad en el uso del lenguaje. Para ello ser necesario adaptarse o crear dichas reglas del juego una vez se llegue a un nuevo equipo de trabajo en la empresa. Dichas buenas prcticas deberan incluir algunos de las siguientes cuestiones: Estructuras bsicas de carpetas: mediante este sistema una persona puede fcilmente ubicar un fichero en base a su funcin especfica. Nomenclaturas: ser necesario establecer una serie de normas a la hora de nombrar cada uno de los ficheros y cada tipo de contenido dentro de un fichero, a destacar: o o o o de ficheros de comentarios de variables de estructuras de control
161

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

o o

de funciones de clases

Uso de Sistemas de Control de Versiones: se debe establecer una poltica de cmo usar el repositorio de versiones con los proyectos. Lenguaje de modelado de datos: una vez tomados los requisitos del proyecto esta bien definir un documento estndar de modelado de datos. Informes Varios: debido a la gran cantidad de informes que se deben recoger en un determinado proyecto, est bien poder establecer una plantilla mnima por cada tipo de informe.

18.3. Actividades
18.3.1. Actividad 1

Busca comparativas de Aceleradores de PHP y haz un informe de los mismos.

18.3.2.

Actividad 2

Dwoo es un sistema de plantillas similar a Smarty. Busca parecidos y diferencias en el uso de estas dos bibliotecas de plantillas.

18.3.3.

Actividad 3

Dinmica de grupo: Discutir en un foro el listado de elementos a estandarizar en el cdigo php. Llegar a una serie de conclusiones y ponerlas por escrito.

18.3.4.

Actividad 4

Dinmica de grupo: Elegir un sistema de control de versiones, valorando los pros y los contra del mismo.

162

FRAMEWORKS DE DESARROLLO EN PHP

Frameworks de desarrollo en PHP


La palabra Framework viene a definirse, como un conjunto de herramientas y bibliotecas que facilitan el desarrollo de aplicaciones sobre una determinada tecnologa. En el caso de PHP existen varios Frameworks de desarrollo que permiten agilizar el desarrollo de aplicaciones web. Entre ellos podemos destacar los siguientes: Zend Framework: http://framework.zend.com/ Symfony: http://www.symfony-project.org/ CakePHP: http://cakephp.org/ CodeIgniter: http://codeigniter.com/

Todos ellos tienen sus pros y sus contras, a travs de la red, se pueden conseguir comparativas entre ellos (por ejemplo http://www.dinamiclearning.es/desarrolloweb/frameworks-php) que permiten comparar aquellas funcionalidades principales, tales como: Arquitectura MVC (Modelo, Vista, Controlador) Orientado a Objetos en PHP5 ActiveRecord (ORM Mapeo Objeto Relacional)
163

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

TemplateView (Vistas y algo de Plantillas) Generadores de Formularios (Ahorran trabajo y permiten el uso sencillo de grillas) Utilizacin de Scriptaculous (Prototype) para AJAX y Efectos Visuales Generacin de Reportes PDF Ficheros de configuracin Soporte de sistemas de autenticacin y autorizacin (oauth, openid, auth y authz) Soporte para la generacin de servicios web

19.1. Actividades
19.1.1. Actividad 1

Escoge uno de los frameworks listados en este tema y localiza manuales y tutoriales para l.

19.1.2.

Actividad 2

Identifica de las caractersticas indicadas en el tema, cuales de ellas soporta

19.1.3.

Actividad 3

Intenta realizar un Hola Mundo usando ese framework

19.1.4.

Actividad 4

Intenta realizar una funcionalidad (mdulo o componente) con ese Framework.

164

JAVASCRIPT

Javascript

20.1. Conceptos bsicos


Javascript, al igual que PHP es un lenguaje interpretado. No hay una compilacin de por medio. Tambin es de tipado dinmico por lo que no hay que definir el tipo de dato. Pero una de las diferencias principales con PHP por ejemplo, es que PHP se ejecuta en nuestro servidor, y javascript se ejecuta en nuestro navegador. Est pensado para darle dinamismo a las webs. Desde simples efectos visuales, hasta conectar con un servidor y descargar contenido para sustituir parte de nuestra web (esto ltimo lo veremos en la parte de AJAX).

20.2. Sintaxis y clases bsicas


20.2.1. Incluir scripts en el cdigo HTML

Para incluir el cdigo javascript en nuestra pgina HTML tenemos 2 formas de hacerlo (exactamente igual que con los CSS).

165

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

La primera es escribirlo directamente en nuestro cdigo mediante la etiqueta script:


<script type="text/javascript"> //mi cdigo javascript </script>

La otra forma es enlazar desde un fichero externo tambin mediante la etiqueta script:
<script type="text/javascript" src="ruta/hasta/mi/script.js"></script>

Algo que hay que tener en cuenta es que el cdigo javascript se ejecutar de forma lineal (tambin llamado secuencial), es decir mientras se va cargando la pgina. Para que esto no suceda, el cdigo que no queramos que se ejecute mientras se est cargando, lo meteremos en funciones, que podremos llamar nosotros cuando queramos, o que se disparen al suceder algn evento. Los eventos tienen la naturaleza de objetos, o sea, poseen mtodos y propiedades. As cuando se produce un evento podemos saber quien lo dispara, en que posicin de la pantalla se ha disparado y otras propiedades dependientes de cada evento en concreto. Y aqu viene uno de las causas para tus futuros dolores de cabeza: cada navegador maneja los eventos de manera algo diferente. Pero bueno, no nos preocupemos de esto todava :)

20.3. Elementos del Lenguaje:


20.3.1. Tipos de datos

Los tipos de datos que nos podremos encontrar en javascript son: numricos, cadenas, booleanos y punteros. Este ltimo tipo de datos que tambin se emplea a menudo en los scripts para la captura de eventos, son direcciones de memoria, usadas para asignar funciones. Si en una variable se guarda el nombre de una funcin esa variable se convierte en otro nombre para esa funcin. Raro? Esto tiene su verdadera utilidad al asignar funciones a los eventos disparados por el ratn.

20.3.2.

Las variables

Veamos un ejemplo de como declarar variables en javascript:


<script language="Javascript"> var navegador_version = 0; function verNavegador() { var version; version = document.appVersion; return version; } </script>

En este ejemplo navegador_version es una variable global mientras que version es local a la funcin verNavegador(). Observa que las variables estn creadas con la palabra clave var, el uso de esta palabra es opcional, slo es obligatorio si una variable local tienen el mismo nombre que una global. Otro detalle a tener en cuenta es que al mismo tiempo que creamos la variable podemos darle un valor, si no lo hacemos la variable contendr el valor null.

166

JAVASCRIPT

20.3.3.

Objetos, Arrays y Funciones

Estos puntos los veremos ms adelante, ya que Javascript trata a Objetos, Arrays y Funciones como si fuesen objetos.

20.4. Operadores
20.4.1. Operadores Aritmticos

En los primeros ejemplos de este tutor tan slo se han usado sentencias muy simples como asignar un valor a una variable, mediante el operador de asignacin, =, o realizar operaciones aritmticas, pero evidentemente JavaScript puede realizar mas operaciones. En esta seccin y las siguientes se presentan los operadores de que dispone este lenguaje clasificados en varios grupos, segn el contexto en el que se usen. Comenzamos con los mas conocidos, los operadores aritmticos.

20.4.1.1.

Suma +

Se trata de un operador usado para sumar dos valores numricos o para concatenar cadenas entre s o nmeros y cadenas.
var var1 = 10, var2= "Buenos", var3 = " das", var4 = 31; document.write(var1+var4) /* resultado 41 */ document.write(var2+var3) /* resultado: Buenos das */ document.write(var1+var3) /* resultando: 10 das */

20.4.1.2.

Resta -

Operador usado para restar valores numricos. Puede actuar sobre un nico operando numrico cambindole de signo.
var num1 = 10, num2 = 8, res = 0; res = num1 - num2; /*res contiene 2 */ res = -res /* ahora res contiene -2*/

20.4.1.3.

Producto ( * ) y cociente ( / )

Realizan las operaciones aritmticas de multiplicar y dividir dos valores


var op1 = 50, op2= 4, div, mul; div = op1/op2 mul = op1 * op2 Resto % /*div contiene 12.5 */ /*mul contendr 200 */

20.4.1.4.
var op1 = 50, op2= 4, resto; resto = op1 % op2;

mdulo % (resto de la divisin)


/*resto contiene 2 */

20.4.1.5.

Incremento ( ++) y decremento (--)

Estos operadores se usan para incrementar o decrementar en 1 el valor de una variable. Si el operador se antepone a la variable la operacin de incremento o decremento es prioritaria sobre cualquier otra.

167

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

var op1=5, op2 = 5, res; res = ++op1; res = op1++;

/*res adquiere el valor 6 y luego op1 el 6*/ /*res adquiere el valor 5 y luego op2 el 6*/

20.4.1.6.

Operadores compuestos

Los operadores +, -, *, / pueden asociarse con el operador de asignacin ( para cambiar el valor de una variable numrica por incrementndolo, decrementndolo, multiplicndolo o dividindolo por un valor. El operador += puede usarse igualmente con variables de cadena.
var num cad num num = 20, cad = "buena"; += 5; /*num adquiere el valor 25 (20 + 5) */ += 's' ; /*cad adquiere el valor 'buenas' */ *= 10; /*num adquiere el valor 250 (25*10) */

20.4.2.

Operadores Binarios

El ordenador, internamente, trata cualquier tipo de datos como una cadena binaria (ceros y unos). As los nmeros se representan en sistema binario de numeracin mientras que los caracteres se convierten a cdigo ASCII, que son nmeros que se almacenan por tanto codificados en binario. JavaScript ofrece los operadores tpicos para trabajar con estas cadenas a nivel de bit (cada uno de los ceros o unos de las cadenas binarias. Para trabajar con estos operadores es conveniente tener una idea previa sobre la codificacin binaria.

20.4.2.1.

Complementacin ~

Complementa una cadena binaria convirtiendo los 1 en 0 y los 0 en 1. Por ejemplo el nmero 38 escrito en sistema binario es 00100110 si le aplicamos este operador se convierte en 11011001, o sea el -39 (JavaScript usa codificacin en complemento a 2 para los nmeros negativos).

20.4.2.2.

Desplazamiento izquierda <<

Desplaza los bits a la izquierda los lugares que se le indique rellenando con ceros por la derecha y desechando los bits de mayor peso, esto equivale a multiplicar por potencias de 2. Por ejemplo si al 00011010 (26) lo desplazamos 2 a la izquierda tendremos el 01101000 (104).
var num = 26, res; res = num << 2;

/* num contendr 104 */

20.4.2.3.

Desplazamiento derecha >>

Desplaza los bits a la derecha los lugares que se le indique rellenando con ceros por la izquierda y desechando los bits de menor peso, esto equivale a una divisin entera por potencias de 2. Por ejemplo si al 00011010 (26) lo desplazamos 2 a la derecha tendremos el 00000110 (6).
var num = 26, res; res = num << 2; </Code> === AND lgico binario & === /* num contendr 104 */

168

JAVASCRIPT

Realiza un AND lgico bit a bit entre dos valores. El AND lgico da como resultado 1 slo si ambos bits son 1. Por ejemplo <code javascript> 0 1 1 0 1 1 0 1 (109) AND 0 0 1 0 0 1 1 0 (38) resultado: 0 0 1 0 0 1 0 0 (36) var op1 = 109, op2 = 38, res; res = op1 & op2;

/*res contiene 36 */

20.4.2.4.

OR lgico binario |

Realiza un OR lgico bit a bit entre dos valores. El OR lgico da como resultado 0 slo si ambos bits son 0. Por ejemplo
0 0 1 1 1 0 1 0 (58) OR 0 1 0 1 0 0 1 0 (82) 0 1 1 1 1 0 1 0 (122)

resultado:

En el ejemplo podemos ver la sintaxis del operador


var op1 = 58, op2 = 82, res; res = op1 | op2; /*res contiene 122 */

20.4.2.5.

XOR lgico binario ^

Realiza un XOR lgico bit a bit entre dos valores. El XOR lgico da como resultado 1 si uno slo de los bits es 1. Por ejemplo
0 0 1 1 1 0 1 0 (58) OR 0 1 0 1 0 0 1 0 (82) 0 0 1 0 1 0 0 0 (40)

resultado:

En el ejemplo podemos ver la sintaxis del operador


var op1 = 109, op2 = 38, res; res = op1 ^ op2; /*res contiene 40*/

20.4.3.

Operadores Lgicos

Los operadores lgicos se utilizan para realizar comparaciones entre valores, numricos o no, dando como resultado un valor booleanos (true, false). La operacin lgica negacin invierte el operando, si es true lo hace false y viceversa. Si se comparan nmeros con cadenas, JavaScript intenta convertir internamente los datos. En los operadores relacionales (>, <, >=, ) intenta convertir los datos en tipo nmero. Para los

operadores de igualdad (== ! intenta convertir los tipos de datos a cadena, nmero y booleano. Los operadores de identidad (===, != no realizan conversin de tipo.

20.4.3.1.

Mayor que >

Compara dos valores y devuelve true si el primero es mayor que el segundo. Compara tanto nmeros como cadenas.
var hoy = 4; ayer = 10, comp; comp = hoy > ayer /* comp adquiere el valor false*/

169

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

20.4.3.2.

Menor que <

Compara dos valores y devuelve true si el primero es mayor que el segundo. Compara tanto nmeros como cadenas.
var hoy = 4; ayer = 10, comp; comp = hoy < ayer /* comp adquiere el valor false*/

20.4.3.3.

Mayor o igual >=

Compara dos valores y devuelve true si el primero es mayor o es igual que el segundo. Compara tanto nmeros como cadenas.
var hoy = 4; ayer = 4, comp; comp = hoy >= ayer /* comp adquiere el valor true*/

20.4.3.4.

Menor o igual <=

Compara dos valores y devuelve true si el primero es menor o es igual que el segundo. Compara tanto nmeros como cadenas.
var hoy = 4; ayer = 4, comp; comp = hoy <= ayer /* comp adquiere el valor true*/

20.4.3.5.

Iguales ==

Compara dos valores y devuelve true si ambos son iguales. Compara tanto nmeros como cadenas.
var hoy = 4; ayer = 4, comp; comp = hoy == ayer /* comp adquiere el valor true*/

20.4.3.6.

Idnticos ===

Similar a == pero tambin compara el tipo de datos de los operandos Compara dos valores y devuelve true si el primero es mayor o es igual que el segundo. Compara tanto nmeros como cadenas.
var hoy = 4; ayer = '4', comp; comp = hoy == ayer; comp = hoy === ayer /* comp adquiere el valor true*/ /* comp adquiere el valor false*/

20.4.3.7.

No iguales != y No idnticos !==

Invierten el sentido de las comparaciones iguales == e idnticos === respectivamente.

20.4.3.8.

AND lgico &&

Este operador se utiliza para concatenar comparaciones, es decir, para comprobar varias condiciones. El resultado slo ser true si todas las comparaciones lo son.
var op1 = 2, op2 = 50, op3 = 25, comp; comp = (op1 > op2) && (op1 < op3); valor false */ /*comp adquiere el

comp es false por que op1 no es mayor que op2 aunque sea mayor que op3
170

JAVASCRIPT

20.4.3.9.

OR lgico ||

Como el anterior, sirve para realizar comparaciones compuestas y slo devolver false cuando todas las comparaciones los sean. Es decir basta que una comparacin sea true para que devuelva el valor true.
var op1 = 2, op2 = 50, op3 = 25, comp; comp = (op1 > op2) && (op1 < op3); valor true */ /*comp adquiere el

comp es true por que op1 es menor que op3, (op1 < op3 es por tanto true)

20.4.4.

Operadores Varios
delete

20.4.4.1.

Se usa para borrar propiedades de un objeto o elementos de un array. Devuelve true si la operacin se realiz con xito.
var lista = new Array(1,4,7,9,10); delete(lista,0);

El elemento lista[1] contiene ahora undefined.

20.4.4.2.

new

Se utiliza para crear instancias de un objeto


var hoy = new Date("10 /30/2000")

20.4.4.3.

typeof

Devuelve el tipo de dato al que pertenece una variable o expresin. Los tipos devueltos son number, string, boolean, object, function y undefined.
hoy = 1.2345; tipo = typeof(hoy);

La variable tipo contendr number.

20.4.5.

Funciones Globales

A s como JavaScript proporciona objetos predefinidos, tambin posee una serie de funciones predefinidas. Se trata de las funciones: eval, isNan, Number, String, parseInt, parseFloat, escape, unescape.

20.4.5.1.

eval

Se usa para evaluar una cadena con cdigo JavaScript sin referirse a un objeto concreto. La sintaxis de eval es:
eval(expr)

donde expr es la cadena a evaluar.


171

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

20.4.5.2.

isNaN(arg)

Determina si el argumento es un valor NaN (not a number)

20.4.5.3.

parseInt(str, [base])

Convierte una cadena de caracteres en un valor numrico. La funcin lleva como argumento la cadena a convertir y opcionalmente puede llevar un segundo argumento para indicar la base de numeracin en que est escrita la cadena. Si se omite se supone que la cadena representa un nmero en base 10. La cadena slo podr contener caracteres vlidos para el sistema de numeracin indicado: dgitos (0..9 para la base 10, 0 1 para nmeros binarios, 0..7 para sistema octal, 0..9, A..F para sistema hexadecimal) y signo (+, -). Si encuentra algn carcter no vlido slo interpreta desde el principio de la cadena hasta el carcter no vlido. Si comienza por un carcter ilegal devuelve NaN. Ejemplo:
var minum1 = "14"; document.write(parseInt(minum1));

Escribir 14. En el siguiente ejemplo transforma un nmero binario a decimal:


var minum1 = "11001"; document.write(parseInt(minum1,2));

Ahora escribir 25, el equivalente decimal al binario 11001.

20.4.5.4.

parseFloat(str)

Convierten una la cadena que se le pasa como argumento a un valor numrico de tipo flotante. Los caracteres vlidos de la cadena son los mismos que en parseInt mas el punto decimal y el exponente (E). No admite un segundo argumento. Por lo dems funciona exactamente igual que parseInt.
var minum1 = "14.5E2"; document.write(parseInt(minum1))

Escribir el nmero 1450, 14.5 por 10 elevado a 2.

20.4.5.5.

Number(objArg) y String(objArg)

Permiten convertir el objeto pasado como argumento a un nmero o a una cadena. Por ejemplo:
var hoy = new Date(); hoy.getDate(); document.write(string(hoy));

Escribir en pantalla la cadena Sun Sep 3 20:40:05 UTC+0200 2000 si la fecha del da es domingo 3 de Septiembre y la hora es las 20:40:05.

20.4.5.6.

escape(cadarg)

Codifica la cadena del argumento substituyendo todos los caracteres no ASCII por su cdigo en el formato %xx. Por ejemplo:
var cadena = "Buenos das"; document.write(escape(cadena));

172

JAVASCRIPT

Produce la frase "Buenos d%EDas", pues la (i acentuada) es el cdigo hexadecimal ED de ese carcter.

20.4.5.7.

unescape(cadarg)

Es inversa a la anterior, de manera que si la cadena contiene cdigos del tipo %xx son convertidos al correspondiente carcter ASCII extendido.
var cadena = "Buenos d%EDas"; document.write(escape(cadena));

Ahora se escribir Buenos das, se ha substituido %ED por su equivalente (i acentuada).

20.5. Estructuras de control


20.5.1. Condiciones

El orden en que se ejecutan las instrucciones de un programa es, por defecto, secuencial: ejecucin instruccin tras instruccin. As un programa se escribir como una sucesin de instrucciones o sentencias, utilizando un punto y coma para indicar el final de la instruccin. Pueden agruparse una serie de sentencias en un bloque encerrndolas entre llaves. A veces es necesario alterar este orden para ello se utilizan las instrucciones de control: condicionales, seleccin y bucles. Sern las sentencias condicionales las primeras que veremos. Una sentencia condicional es una instruccin en la que se hace una comparacin y segn el resultado verdadero o falso (true o false) de la misma el programa seguir ejecutando una u otra instrucciones. La condicional mas simple que podemos escribir es aquella que ejecuta u omite una serie de sentencias dependiendo de si la comprobacin da verdadero o falso. La sintaxis de esta sentencia es.
if (condicin) {bloque a ejecutar si la condicin es cierta} else {bloque a ejecutar si la condicin es false}

Si omitimos la parte del else tendremos una condicional simple. Esta sintaxis en algunos casos puede simplificarse utilizando la siguiente forma:
(condicin) ?{bloque si cierta} : {bloque si falsa}

En el siguiente ejemplo evitamos realizar una divisin por cero


if (div == 0) alert('No se puede dividir por 0'); else coc = num / div;

Otro ejemplo usando la segunda forma:


cad = (num >= 0) ? ' + ' : ' - ';

En este ejemplo cad tomar el valor + si num es positivo o cero y el - si es negativo. Las sentencias if pueden anidarse, es decir, dentro de una sentencia if pueden meterse mas sentencias if. Las condiciones pueden ser sencillas como en estos ejemplos o pueden enlazarse usando los operadores && y || (AND y OR lgicos). Veamos un ejemplo en el que comprobamos si un nmero est comprendido entre 1 y 5:

173

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

if ((num>=1) y (num < 5) { lista[indice] = 'Muy bajo'; bajos++; } indice++;

En este ejemplo si num est entre 1 y 5 (excluido) se anota en una lista la palabra 'Muy bajo' y se incrementa la variable bajos. Como vemos no se ha usado la parte de else y como se deben ejecutar mas de una sentencia las hemos encerrado entre llaves. Si num no cumple la condicin el programa se salta este bloque. En cualquier caso la siguiente instruccin que se ejecute tras el condicional ser la que incrementa el valor de indice.

20.5.2.

Switch

switch (idioma) { case 'castellano' : pagCast(); break; case 'ingles' : pagIng(); break; case 'frances' : pagFran(); break; case 'alemn' : pagAlem(); break; default : error ('Idioma no presente'); }

Durante la ejecucin se compara la variable idioma con cada uno de los posibles valores y cuando coincidan ejecuta el cdigo correspondiente. La instruccin break pone fin al bloque y hace que el programa salte a la instruccin siguiente a la sentencia switch(), si se omite el programa continuara con la siguiente comparacin. La seccin del default es opcional, su finalidad es ejecutar algn cdigo cuando ninguna de las condiciones se cumpla.

20.5.3.

Bucles
Sentencia while

20.5.3.1.

En esta estructura el programa primero comprueba la condicin: si es cierta pasa a ejecutar el cuerpo del bucle, y si es falsa pasa a la instruccin siguiente a la sentencia while. Como siempre un ejemplo lo aclarar todo:
var lista = new Array(10); var ind=0; while (ind < 10) { lista[ind] = '0'; ind++; }

En este ejemplo mientras que el valor almacenado en ind sea menor que 10 (la longitud del array ) ir almacenando en cada elemento del array lista un 0 e incrementando el valor de ind. Cuando este valor sea 10 el programa no entrar en el cuerpo del bucle. Si no se incrementara el valor de ind el bucle no acabara nunca, el programa quedara ejecutando indefinidamente el cuerpo del bucle.

174

JAVASCRIPT

20.5.3.2.

Sentencia do...while

Se trata de un bucle en el que la condicin se comprueba tras la primera iteracin, es decir que el cuerpo del bucle se ejecuta al menos una vez. El ejemplo anterior quedara como sigue:
var lista = new Array(10); var ind=0; do lista[ind] = '0'; ind++; while (ind < 10)

Como vemos aqu no son imprescindibles las llaves para encerar el cuerpo del bucle. No est contemplada en el standard ECMA 1.5.

20.5.3.3.

Sentencia for

Esta sentencia utiliza una variable de control a modo de contador para controlar la repeticin del cuerpo del bucle. La sentencia da un valor inicial a este contador y en cada iteracin lo modifica segn le indiquemos y comprueba la condicin, si se cumple ejecuta el cuerpo del bucle, si no lo salta y contina por la siguiente sentencia. Vemos el ejemplo anterior usando esta sentencia:
var lista = new Array(10); var ind; for (ind=0; ind < 10; ind++) { } lista[ind] = '0';

Como vemos el cuerpo del bucle no incrementa la variable ind, esto se indica en la cabecera de la sentencia. Este cdigo hace exactamente lo mismo que el anterior.

20.5.3.4.

Sentencia for ... in

Se trata de una variante de la sentencia for utilizada para iterar o recorrer todos los elementos de un objeto o de un array. Usa una variable de control que en cada iteracin toma el valor del elemento del objeto recorrido. Por ejemplo si pruebas este cdigo podrs ver todos los elementos del objeto document
var item; for (item in document) document.write(item+'<br>');

Con una matriz la variable de control toma el valor de los ndices de la matriz, no su contenido.

20.6. Ruptura de Bucles


Aunque procuremos usara una programacin estructura alguna vez puede ser necesario interrumpir la repeticin de un bucle o forzar una iteracin del mismo, esto puede lograrse mediante las sentencias break y continue. Son sentencias aplicables a cualquiera de las estructuras de bucle en JavaScript.

175

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

20.6.1.1.

break

La sentencia break interrumpe la iteracin actual y enva al programa a la instruccin que sigue al bucle.
var lista = new Array ('a','b','c','z','x','f'); var item ; for (item in lista) { if (lista[item] == "z") break; document.write(lista[item]+'<br>'); }

Este ejemplo escribira el contenido del array lista hasta encontrar una letra z.

20.6.1.2.

continue

La sentencia continue interrumpe la iteracin actual y enva al programa a la comprobacin de la condicin, si esta es cierta contina con la siguiente iteracin.
var lista = new Array ('a','b','c','z','x','f'); var item ; for (item in lista) { if (lista[item] == "z") continue; document.write(lista[item]+'<br>'); }

Este ejemplo escribira el contenido del array saltndose la letra z.

20.7. Los Objetos de Javascript


20.7.1. Objeto Object

Pues s: existe un objeto llamado Object del que derivan todos los objetos de JavaScript, los predefinidos y los definidos por el usuario. Esto significa que los objetos usados en JavaScript heredan las propiedades y mtodos de Object.

20.7.1.1.
toString

Mtodos

Devuelve una cadena dependiendo del objeto en que se use Objeto Array Boolean Function Number String Cadena devuelta por el mtodo Los elementos del array separados por coma Si el valor es false devuelve false si no devuelve true La cadena function nombre_de_funcin(argumentos){ [cdigo]} Representacin textual del nmero El valor de la cadena

176

JAVASCRIPT

Default
valueOf

[object nombre_del_objeto]

Devuelve el valor del objeto dependiendo del objeto en que se use Objeto Array Boolean Date Function Number String Default Valor que devuelve el mtodo Una cadena formada por los elementos separados por coma El valor booleano (true o false) La fecha como el nmero de milisegundos desde el 1/1/1970, 00:00 La propia funcin El valor numrico La cadena El propio objeto

20.7.1.2.

Propiedades

constructor

Esta propiedad contiene una referencia a la funcin que crea las instancias del objeto en particular. Por ejemplo:
x = new String("Hola"); //En este caso s.constructor contendr // function String() { [native code] } prototype

Es una propiedad utilizada para asignar nuevos mtodos o propiedades a un objeto, elementos estos que sern heredados por las diferentes instancias de ese objeto. Ejemplo:
Array.prototype.nombTipo = "matriz"; lista = new Array(9); document.write(lista.nombTipo); //Escribir la palabra matriz que es el nombTipo //que hemos dado para el objeto Array

20.7.1.3.

Como crear nuestros propios objetos?

Lo vemos en el siguiente punto :) el objeto Function.

20.7.2.

Objeto Function

Permite la creacin de funciones, ya sean con nombre o annimas. La creacin de una funcin puede realizarse por el mtodo tradicional y comn a la mayora de lenguajes de programacin:
function sumar(a, b) { return a+b; }

O bien mediante el conocido operador new:


177

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

sumar = new Function ("a", "b", "return a+b");

En cualquier caso la funcin se usar de igual forma:


document.write( sumar(90, 100) );

20.7.2.1.
Los heredados del objeto Object

Mtodos

20.7.2.2.

Propiedades

arguments

Se trata de un array que contiene los argumentos pasados a la funcin. Esta propiedad permite el uso de funciones con un nmero variable de argumentos.
caller

Contiene una referencia a la funcin que llam a la actual.


constructor

Heredada de la clase Object

20.7.2.3.

Creando funciones "objeto"

Si queremos crear un objeto javascript, lo que haremos realmente ser crear una funcin:
function pagina (titulo, color, fondo) { this.titulo = titulo; this.color = color; this.imgfondo = fondo; this.length = 3; } var miPagina = new pagina("Mi pgina", "Blue", "cruces.gif"); var nuevapag = new pagina("2a Pgina", "White", "");

Si queremos aadir mtodos a nuestro objeto, podemos hacerlo como al crear cualquier funcin:
function mi_objeto(param1, param2) { this.propiedad1 = param1; this.propiedad2 = param2; this.mi_metodo_sumar = new Function ("a", "b", "return a+b"); }

20.7.3.

Objeto Array

A diferencia de otros lenguajes, en javascript, los arrays son objetos, que tienen sus propias propiedades y mtodos (ampliables por el usuario) vemos algunas comnes a los navegadores:

178

JAVASCRIPT

20.7.3.1.
length

Propiedades

Como su nombre indica esta propiedad nos devuelve la longitud del array, es decir, el nmero de elementos que puede almacenar. Su uso es muy simple:
var lista = new Array(50); tamagno = lista.length; */ prototype /*tamagno almacenara el valor 50

Esta es una propiedad muy potente en el sentido que nos permite agregar al objeto Array las propiedades y mtodos que queramos.
Array.protoype.descriptor = null; dias = new Array ('lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes'); dias.descriptor = "Dias laborables de la semana";

En este ejemplo hemos creado una nueva propiedad para el objeto array, la propiedad descriptor que podra utilizarse para darle un ttulo a la matriz.

20.7.3.2.

Mtodos

concat(objArray)

Une el objeto Array con el array que se le pasa como argumento y devuelve el resultado en un nuevo array, sin modificar los arrays que se concatenan.
join()

Convierte los elementos de un array en una cadena separados por el carcter que se le indique. El separador por defecto es la coma.
a= new Array("Hola","Buenos","das"); document.write(a.join() +" <br>"); document.write(a.join(", ") +" <br>"); document.write(a.join(" + ") +" <br>") ;

La salida de este programa sera


Hola,Buenos,Das Hola, Buenos, Das Hola+Buenos+Das reverse()

Invierte el orden de los elementos de un Array en el propio array, sin crear uno nuevo.
slice(ini, fin)

Extrae parte de un Array devolvindolo en un nuevo objeto Array.


lista = new Array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'); sublista = lista.slice(2,6); alert(sublista.join());

En el ejemplo sublista contendr los elementos desde el ndice 2 al 5 ambos inclusive, o sea, 'c', 'd', 'e', 'f'. Si se omite el segundo argumento se extrae hasta el ltimo elemento del array y si es negativo se entiende como contando desde el final.

179

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

sort(rutord)

Ordena alfabticamente los elementos de un objeto Array. Opcionalmente podemos pasar como argumento una funcin para determinar el orden, esta funcin posee dos argumentos y devolver un valor negativo si el primer argumento es menor que el segundo, cero si son iguales y un valor positivo si el primer argumento es mayor que el segundo. En castellano esto es necesario si queremos que la y vocales acentuadas figuren en su lugar.

20.7.4.

Objeto window

Es el objeto principal en la jerarqua y contiene las propiedades y mtodos para controlar la ventana del navegador. De l dependen todos los dems objetos de la jerarqua. Vamos a ver la lista de sus propiedades y mtodos.

20.7.4.1.
Propiedad closed defaultStatus document Frame frames array history innerHeight innerWidth length location

Propiedades
Descripcin Indica la posibilidad de que se haya cerrado la ventana. (Javascript 1.1) Texto que se escribe por defecto en la barra de estado del navegador. Objeto que contiene el la pgina web que se est mostrando. Un objeto frame de una pgina web. Se accede por su nombre. El vector que contiene todos los frames de la pgina. Se accede por su ndice a partir de 0. Objeto historial de pginas visitadas. Tamao en pixels del espacio donde se visualiza la pgina, en vertical. (Javascript 1.2) Tamao en pixels del espacio donde se visualiza la pgina, en horizontal. (Javascript 1.2) Numero de frames de la ventana. La URL del documento que se est visualizando. Podemos cambiar el valor de esta propiedad para movernos a otra pgina. Ver tambin la propiedad location del objeto document. Objeto barra de direcciones de la ventana. (Javascript 1.2) Objeto barra de mens de la ventana. (Javascript 1.2) Nombre de la ventana. Lo asignamos cuando abrimos una nueva ventana. Hace referencia a la ventana de navegador que abri la ventana donde estamos trabajando. Tamao en pixels del espacio de toda la ventana, en vertical. Esto incluye las barras de desplazamiento, botones, etc. (Javascript 1.2) Tamao en pixels del espacio de toda la ventana, en horizontal. Esto incluye las barras de desplazamiento. (Javascript 1.2)

locationbar menubar name opener outherHeight

outherWidth

180

JAVASCRIPT

parent personalbar self scrollbars status statusbar toolbar top

Hace referencia a la ventana donde est situada el frame donde estamos trabajando. Objeto barra personal del navegador. (Javascript 1.2) Ventana o frame actual. Objeto de las barras de desplazamiento de la ventana. Texto de la barra de estado. Objeto barra de estado del navegador. (Javascript 1.2) Objeto barra de herramientas. (Javascript 1.2) Hace referencia a la ventana donde est situada el frame donde estamos trabajando. Como la propiedad parent. Hace referencia a la ventana actual, igual que la propiedad self.

window

20.7.4.2.
Metodo alert(texto) back()

Mtodos
Descripcin Presenta una ventana de alerta donde se puede leer el texto que recibe por parmetro Ir una pgina atrs en el historial de pginas visitadas. Funciona como el botn de volver de la barra de herramientas. (Javascript 1.2) Quitar el foco de la ventana actual. (Javascript 1.1) Captura los eventos que se indiquen por parmetro (Javascript 1.2). Elimina la ejecucin de sentencias asociadas a un intervalo indicadas con el mtodo setInterval().(Javascript 1.2) Elimina la ejecucin de sentencias asociadas a un tiempo de espera indicadas con el mtodo setTimeout(). Cierra la ventana. (Javascript 1.1) Muestra una ventana de confirmacin y permite aceptar o rechazar. Muestra una ventanita de bsqueda. (Javascript 1.2 para Netscape) Coloca el foco de la aplicacin en la ventana. (Javascript 1.1) Ir una pgina adelante en el historial de pginas visitadas. Como si pulssemos el botn de adelante del navegador. (Javascript 1.2) Ir a la pgina de inicio que haya configurada en el explorador. (Javascript 1.2) Mueve la ventana del navegador los pixels que se indican por parmetro hacia la derecha y abajo. (Javascript 1.2) Mueve la ventana del navegador a la posicin indicada en las coordenadas que recibe por parmetro. (Javascript 1.2)
181

blur() captureEvents(eventos) clearInterval()

clearTimeout()

close() confirm(texto) find() focus() forward()

home() moveBy(pixelsX, pixelsY)

moveTo(pixelsX, pixelsY)

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

open()

Abre una ventana secundaria del navegador. Se puede aprender a utilizarla en el reportaje de cmo abrir ventanas secundarias. Como si pulssemos el botn de imprimir del navegador. (Javascript 1.2)

print()

prompt(pregunta,inicializacion_de_la_respuesta) Muestra una caja de dilogo para pedir un dato. Devuelve el dato que se ha escrito. releaseEvents(eventos) resizeBy(pixelsAncho,pixelsAlto) Deja de capturar eventos del tipo que se indique por parmetro. (Javascript 1.2) Redimensiona el tamao de la ventana, aadiendo a su tamao actual los valores indicados en los parmetros. El primero para la altura y el segundo para la anchura. Admite valores negativos si se desea reducir la ventana. (Javascript 1.2) Redimensiona la ventana del navegador para que ocupe el espacio en pixels que se indica por parmetro (Javascript 1.2) Enruta un evento por la jerarqua de eventos. (Javascript 1.2) Hace un scroll de la ventana hacia la coordenada indicada por parmetro. Este mtodo est desaconsejado, pues ahora se debera utilizar scrollTo()(Javascript 1.1) Hace un scroll del contenido de la ventana relativo a la posicin actual. (Javascript 1.2) Hace un scroll de la ventana a la posicin indicada por el parmetro. Este mtodo se tiene que utilizar en lugar de scroll. (Javascript 1.2) Define un script para que sea ejecutado indefinidamente en cada intervalo de tiempo. (Javascript 1.2) Define un script para que sea ejecutado una vez despus de un tiempo de espera determinado. Como pulsar el botn de stop de la ventana del navegador. (Javascript 1.2)

resizeTo(pixelsAncho,pixelsAlto)

routeEvent() scroll(pixelsX,pixelsY)

scrollBy(pixelsX,pixelsY) scrollTo(pixelsX,pixelsY)

setInterval()

setTimeout(sentencia,milisegundos) stop()

20.7.5.

Objeto document

Con el objeto document se controla la pgina web y todos los elementos que contiene. El objeto document es la pgina actual que se est visualizando en ese momento. Depende del objeto window, pero tambin puede depender del objeto frame en caso de que la pgina se est mostrando en un frame.

20.7.5.1.

Propiedades

Veamos una lista de las propiedades del objeto document y luego veremos algn ejemplo. Propiedad alinkColor Anchor Descripcin Color de los enlaces activos Un ancla de la pgina. Se consigue con la etiqueta <A name=nombre_del_ancla>. Se accede por su nombre.

182

JAVASCRIPT

anchors (array) Applet applets (array) Area

Un array de las anclas del documento (enlaces <a>). Un applet de la pgina. Se accede por su nombre. (Javascript 1.1) Un array con todos los applets de la pgina. (Javascript 1.1) Una etiqueta <AREA>, de las que estn vinculadas a los mapas de imgenes (Etiqueta ). Se accede por su nombre. (Javascript 1.1) El color de fondo del documento. Las clases definidas en la declaracin de estilos CSS. (Javascript 1.2) Una cookie Nombre del dominio del servidor de la pgina. Un elemento de la pagina incrustado con la etiqueta <EMBED>. Se accede por su nombre. (Javascript 1.1) Todos los elementos de la pgina incrustados con <EMBED>. (Javascript 1.1) El color del texto. Para ver los cambios hay que reescribir la pgina. Un formulario de la pgina. Se accede por su nombre. Un array con todos los formularios de la pgina. Para acceder a estilos CSS. (Javascript 1.2) Una imagen de la pgina web. Se accede por su nombre. (Javascript 1.1) Cada una de las imgenes de la pgina introducidas en un array. (Javascript 1.1) La fecha de ltima modificacin del documento. El color de los enlaces. Un enlace de los de la pgina. Se accede por su nombre. Un array con cada uno de los enlaces de la pgina. La URL del documento que se est visualizando. Es de solo lectura. La pgina de la que viene el usuario. Estilos definidos a las etiquetas de HTML en la pgina web. (Javascript 1.2) El titulo de la pgina. Lo mismo que location, pero es aconsejable utilizar location ya que URL no existe en todos los navegadores. El color de los enlaces visitados.

bgColor classes cookie domain Embed

embeds (array) fgColor Form forms (array) ids Image images (array) lastModified linkColor Link links (array) location referrer tags title URL

vlinkColor

20.7.5.2.
Mtodo captureEvents()

Mtodos
Descripcin Para capturar los eventos que ocurran en la pgina web. Recibe como parmetro el evento

183

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

que se desea capturar. close() Cierra el flujo del documento. (Se ver ms adelante en este manual un artculo sobre el flujo del documento) Ofrece una lnea de control de los estilos de la pgina. En el caso que deseemos especificarlos con Javascript. Devuelve un string que contiene el texto que se ha seleccionado. En un principio slo funcionaba en Netscape. Invocas el manejador de eventos del elemento especificado. Abre el flujo del documento. Liberar los eventos capturados del tipo que se especifique, envindolos a los objetos siguientes en la jerarqua. Pasa un evento capturado a travs de la jerarqua de eventos habitual. Escribe dentro de la pgina web. Podemos escribir etiquetas HTML y texto normal. Escribe igual que el mtodo write(), aunque coloca un salto de lnea al final.

contextual()

getSelection()

handleEvent() open() releaseEvents()

routeEvent() write() writeln()

20.7.6.

Objeto form

El objeto form es un sub-objeto del objeto document y este a su vez, lo es del objeto window. As como para crear una pgina en HTML se utilizan las etiquetas <HTML> Y </HTML>, lo mismo sucede con un formulario: el formulario debe estar contenido entre las etiquetas <form> y </form> En principio la sintaxis bsica para referirnos a un formulario sera:
window.document.forms.nombre_del_formulario

En la que tranquilamente pueden prescindirse de window y forms ya que el navegador toma al formulario como un objeto en s mismo. De la misma forma, tambien puede prescindirse de document. Pero esta omisin solo se har si queremos referirnos a un formulario en particular (por ejemplo a un formulario llamado datos). Pero al momento de referirnos a todos los formularios de una pgina, solo se podr prescindir del objeto window.

20.7.6.1.

Propiedades principales del objeto form

El objeto form posee las siguientes propiedades: ^ propiedad ^ descripcin ^ name action es el nombre nico del formulario. es el lugar al cual se enva el formulario para ser procesado. El action define la URL a la cual se enva dicho formulario. mtodo de envo de los datos insertados en un

method

184

JAVASCRIPT

formulario. El method puede ser: GET = enva los datos en una cadena visible. Conveniente para enviar pocos datos. POST = enva los datos en forma invisible. Conveniente para enviar una gran cantidad de datos. target define la ventana o marco (frame) en la que se mostrarn o procesarn los resultados del formulario. El valor es el mismo que el utilizado en HTML (blank, self, top, nombre_marco, etc..)

20.7.6.2.
El objeto form posee dos mtodos: mtodo submit reset

Mtodos del objeto form

descripcin enva el formulario. restablece el formulario a los valores por defecto.

20.7.7.

Objeto Boolean

Las variables booleanas o lgicas son las que slo pueden tomar dos valores: true, verdadero, y false, falso. Este tipo de variables est implementado en JavaScript como un objeto.

20.7.7.1.
toString

Mtodos

Si el valor es false devuelve la cadena false y si es true devuelve la cadena true


valueOf

Devuelve el valor booleano (true o false)

20.7.7.2.

Propiedades

constructor

heredada del objeto genrico Object, devuelve la referencia al constructor:


function Boolean() { [native code] } prototype

Es una propiedad utilizada para asignar nuevos mtodos o propiedades, heredado del objeto genrico Object. Por ejemplo podemos traducir los valores true o false.
function valor () { return this.valueOf()?'cierto':'falso' } Boolean.prototype.valor = valor; var item = new Boolean(false); document.write(item.valor());

Con este ejemplo logramos que true se devuelva como la cadena cierto y false como la cadena falso.

185

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

20.7.8.

Objeto Number

Es el objeto destinado al manejo de datos y constantes numricas. Realmente no es habitual crear objetos de este tipo ya que JavaScript los crea automticamente cuando es necesario. No obstante la sintaxis para su creacin es la habitual para cualquier objeto:
minumero = new Number(valorinicial)

El valor inicial es optativo, si no se usa el objeto se crea con valor null

20.7.8.1.
Los heredados del objeto Object

Mtodos

20.7.8.2.

Propiedades

Adems de las heredadas del objeto Object Number posee las siguientes propiedades:
MAX_VALUE

Indica el valor mximo utilizable por JavaScript, actualmente 1.79E+308.


MIN_VALUE

Indica el valor mnimo utilizable por JavaScript, actualmente 2.22E-308.


NaN

Una constante usada para indicar que una expresin ha devuelto un valor no numrico. NaN no puede compararse usando los operadores lgicos habituales, para ver si un valor es igual a NaN se debe usar la funcin incorporada isNaN
NEGATIVE_INFINITY

Una constante para indicar infinito positivo, es decir, un valor superior al MAX_VALUE
POSITIVE_INFINITY

Una constante para indicar infinito negativo, es decir, un valor superior al MAX_VALUE con signo negativo

20.7.9.

Objeto String

El objeto String se usa para manipular cadenas de caracteres. En JavaScript todo texto encerrado entre comillas, dobles o simples, se interpreta como una cadena, as '45' no es el nmero cuarenta y cinco sino la cadena formada por los caracteres 4 y 5. El objeto String permite realizar operaciones con cadenas como concatenar o dividir cadenas, buscar texto, extraer parte de un texto, etc.. La operacin de crear una variable de este tipo se lleva a cabo como es habitual con el operador new pudindole pasar un argumento para inicializar la variable. Al usar un mtodo o referirnos a una propiedad podemos usar el nombre de la variable o una constante de cadena as el ejemplo
var mitexto = "Esta es una cadena"; var pos = mitexto.indexOf("una")

186

JAVASCRIPT

puede tambin escribirse en la siguiente forma:


var pos = "Esta es una cadena". indexOf("una");

20.7.9.1.
length:

Propiedades

devuelve la longitud de la cadena.


prototype:

permite agregar mtodos y propiedades al objeto

20.7.9.2.
anchor big blink bold charAt charCodeAt concat fixed fontcolor

Mtodos
fromCharCode indexOf italics lastindexOf link match replace search slice fontsize small split strike sub substr substring sup toLowerCase toUpperCase

Vamos algunos de los ms usados o algunos que puedan llevar a confusin por su similitud. nota: algunos mtodos como bold, o big, italics alteran el estilo visual usando etiquetas como <b></b> etc Por lo que se aconseja utilizar mejor cambios de estilos css para hacerlo lo ms genrico posible, ya que quizs dependiendo de un diseo web, usar un tipo de resaltado u otro.
charAt(atrent)

Este mtodo aplicado a una cadena devuelve el carcter que se encuentra en la posicin dada por el atributo atrent, teniendo en cuenta que el ndice del primer carcter a la izquierda de la cadena es 0 y el ltimo es una unidad menor que longitud de la cadena. Si el valor del atributo no es vlido (igual o mayor que la longitud de la cadena o negativo) el mtodo devuelve el valor undefined. Por ejemplo el siguiente cdigo devuelve la posicin del tercer carcter de la cadena nombre:
var nombre = "abcdefghij"; var car3 = nombre.charAt(2);

Devolver c, que es el tercer carcter por la izquierda (ndice igual a 2).


charCodeAt(atrent)

Este mtodo aplicado a una cadena devuelve el cdigo Unicode del carcter que se encuentra en la posicin dada por el atributo atrent, teniendo en cuenta que el ndice del primer carcter a la izquierda de la cadena es 0 y el ltimo es una unidad menor que longitud de la cadena. Si el valor del atributo no es vlido (igual o mayor que la longitud de la cadena o negativo) el mtodo devuelve el valor NAN. Por ejemplo el siguiente cdigo devuelve el Unicode del tercer carcter de la cadena nombre:
187

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

var nombre = "abcdefghij"; var car3 = nombre.charAt(2);

Devolver 99, que es el cdigo de la letra 'c', el tercer carcter por la izquierda (ndice igual a 2).
concat(atrcad)

Este mtodo aplicado a una cadena le agrega la cadena pasada como atributo, atrcad, que ser una variable o constante literal, cualquier otro tipo es convertido a cadena. Por ejemplo el siguiente cdigo concatena 'Buenos ' y 'das':
var saludo = "Buenos "; var hola = saludo.concat("das");

La variable hola contendr Buenos das, es lo mismo que si se hubiera escrito:


var hola = saludo + "das" indexOf( atrcad, desde)

Este mtodo devuelve la primera posicin dentro del objeto String donde comienza la subcadena pasada como argumento en atrcad. Admite un segundo argumento opcional que indica desde que posicin debe realizar la bsqueda, si se omite comienza a buscar por el primer carcter de la izquierda. Valores del segundo argumento negativos o mayores que la longitud de la cadena se consideran 0. Si la subcadena no se encuentra el valor devuelto es -1. Por ejemplo:
var cadena = "mi.correo@mail.com"; var arroba = cadena.indexOf('@'); var punto = cadena.indexOf('.',arroba);

Este ejemplo devuelve en arroba la posicin 9 mientras que punto contiene la 14 pues la bsqueda se hizo desde la posicin donde est el carcter arroba y encuentra el segundo punto. Recuerda que las posiciones en las cadenas se cuentan desde 0.
lastIndexOf(atrcad, desde)

Este mtodo devuelve la primera posicin dentro del objeto String donde comienza la subcadena pasada como argumento en atrcad, pero realizando la bsqueda de derecha a izquierda. Admite un segundo argumento opcional que indica desde que posicin debe realizar la bsqueda, si se omite comienza a buscar por el primer carcter de la derecha, valores negativos o mayores que la longitud de la cadena se consideran 0. Si la subcadena no se encuentra el valor devuelto es -1. Por ejemplo:
var cadena = "mi.correo@mail.com"; var arroba = cadena.lastIndexOf('@'); var punto = cadena.lastIndexOf('.',arroba);

Este ejemplo devuelve en arroba la posicin 9 mientras que punto contiene la 2 pues la bsqueda se hizo desde la posicin donde est el carcter arroba hacia el principio de la cadena encontrando el primer punto. Recuerda que las posiciones en las cadenas se cuentan desde 0.
Mtodos de String: slice ( inicio, ultimo )

Este mtodo devuelve la porcin de cadena comprendida entre las posiciones dadas por los argumentos inicio y ultimo, o el final de la cadena si se omite este segundo argumento. Si ultimo es negativo, se interpreta como nmero de posiciones contadas desde el final de la cadena. Si los argumentos no son nmeros enteros, por ejemplo cadenas, se convierten a nmeros enteros como hara el mtodo Number.parseInt().

188

JAVASCRIPT

var frase = "Autor: Pepe Almodvar"; var nombre = frase.slice(7);

La variable nombre contendr Pepe Almodvar. En este otro ejemplo usamos un segundo argumento:
var frase = "Autor: Pepe Almodvar"; var nombre = frase.slice(7, -10);

nombre contendr Pepe', es decir desde la posicin 7 hasta 10 posiciones antes del final.
split (separ)

Devuelve un array conteniendo las porciones en que queda separada la cadena por el separador indicado mediante el argumento separ, que ser una expresin regular o una cadena literal. Si este separador es una cadena vaca el texto queda desglosado en todos sus caracteres. Si se omite el separador el resultado es un array de un elemento con la cadena completa.
var linea=new String("Ttulo: El portero"); var lista = linea.split(/:\s*/);

La variable lista es un array con dos elementos Ttulo y El portero. Tambin podramos haberlo escrito como
var linea=new String("Ttulo: El portero"); lista = linea.split(":"); document.write(lista);

en este caso el primer elemento de lista es Ttulo y el segundo El portero con un espacio por delante. Por ltimo si el separador es una cadena vaca:
var linea=new String("Ttulo: El portero"); lista = linea.split(""); document.write(lista);

la variable lista contendr T,,t,u,l,o,:, ,E,l, ,p,o,r,t,e,r,o.


substr(inicio, largo)

Devuelve una subcadena extrada del objeto string comenzando por la posicin dada por el primer argumento, inicio, y con un nmero de caracteres dado por el segundo argumento, largo. Si se omite este ltimo argumento la subcadena extrada va desde inicio hasta el final de la cadena.
var linea=new String("Mi pgina es ideal); var lista = linea.substr(3);

La variable lista contendr pgina es ideal.


var linea=new String("Mi pgina es ideal); var lista = linea.substr(3, 6);

ahora la variable lista contendr pgina.

substring(ind1,ind2)

Devuelve una subcadena del objeto string que comienza en la posicin dada por el menor de los argumentos y finaliza en la posicin dada por el otro argumento. Si se omite este ltimo argumento la subcadena extrada va desde la posicin indicada por el nico argumento hasta el final de la cadena. Si los argumentos son literales se convierten a enteros como un parseInt().
var linea=new String("Mi pgina es ideal); var lista = linea.substr(3);

189

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

La variable lista contendr pgina es ideal.


var linea=new String("Mi pgina es ideal); var lista = linea.substr(3, 9);

ahora la variable lista contendr pgina, al igual que en


var linea=new String("Mi pgina es ideal); var lista = linea.substr(9, 3); toLowerCase()

Devuelve una cadena igual a la original pero con todos los caracteres en minsculas. No afecta como es lgico a caracteres no alfabticos, o sea, a los nmeros, letras acentuadas y caracteres especiales como la
var linea=new String(" Hoy es Domingo"); linea = linea.toLowerCasesubstr();

La variable lista contendr hoy es domingo.


toUpperCase()

Devuelve una cadena igual a la original pero con todos los caracteres en maysculas. No afecta como es lgico a caracteres no alfabticos, o sea, a los nmeros, letras acentuadas y caracteres especiales como la . Es muy til a la hora de comparar cadenas para asegurarse que dos cadenas no difieran slo por que algn carcter est en mayscula o minscula.
var linea=new String(" Hoy es Domingo"); linea = linea.toUpperCase();

La variable lista contendr HOY ES DOMINGO.

20.7.10.

Objeto Date

El objeto Date contiene un valor que representa fecha y hora de un instante dado. Para crear una instancia de este objeto usamos alguna de las siguientes sintaxis:
var var var var fecha= fecha= fecha= fecha= new new new new Date() date(nmero) date(cadena) date(ao, mes, da[, hora[, minutos[, seg[,ms]]]])

Los argumentos encerrados entre corchetes son opcionales. En la primera forma la variable fecha contendr la fecha del da actual. La segunda opcin almacena en fecha la fecha dada por el argumento como el nmero de milisegundos transcurridos desde la media noche del 1 de Enero de 1970. El tercer tipo se usa cuando la fecha se pasa en forma de cadena. Por ltimo la fecha puede crearse pasndole como argumento los nmeros de ao, mes, da, hora y opcionalmente, hora, minuto, segundo y milisegundo. Los aos posteriores a 1970 puede escribirse con dos dgitos, pero es aconsejable usar siempre cuatro dgitos por aquello de los efectos 2000.
var var var var var hoy = new date() /*fecha del da en hoy */ evento = new Date("November 10 1990"); otro = new Date("10 Nov 1990"); otro = new Date("10/02/2000"); //Oct, 2, 2000 instante = new Date(1990, 11, 10, 20,00);

Estas son tres posibles formas de declarar objetos de tipo fecha. Las dos ltimas almacenan el mismo da, pero en la ltima adems se guarda la hora. Donde se usen cadenas para indicar una fecha podemos aadir al final las siglas GMT (o UTC) para indicar que la hora se refiere a hora del meridiano Greenwich, si no se toma como hora local, o sea, segn la zona horaria configurada en el ordenador donde de ejecute el script.

190

JAVASCRIPT

Mtodos getDate getDay getFullYear getHours getMilliseconds getMinutes getMonth getSeconds getTime getTimezoneOffset getYear Object.toString Object.valueOf parse setDate setFullYear SetHours setMilliseconds setMinutes setMonth setSeconds setTime setYear toGMT toLocaleString toUTCString

20.7.10.1.

getDate()

Nos devuelve el da del mes del objeto fecha al que se aplica. Este mtodo controla por supuesto el nmero de das de cada mes y contempla el caso de aos bisiestos, incluida la excepcin del 2000. En el siguiente ejemplo se presenta en pantalla Hoy es da 2, suponiendo que la fecha del sistema es 2-10-200. Primero creamos la variable fecha instanciada como un objeto Date() para a continuacin escribir directamente el valor de getDate() aplicado a fecha
var fecha = new Date(); document.write("Hoy es da: "+fecha.getDate());

20.7.10.2.

getDay()

Nos devuelve el da de la semana del objeto fecha al que se aplica en forma numrica con una cifra entre 0 para el domingo y 6 para el sbado. En el siguiente ejemplo se presenta en pantalla Hoy es 1, suponiendo que la fecha del sistema es 2-Octubre-2000, o sea, lunes. Primero creamos la variable fecha instanciada como un objeto Date() para a continuacin escribir directamente el valor de getDay() aplicado a fecha
var fecha = new Date(); document.write("Hoy es "+fecha.getDay());

Si echamos manos de un array podemos mejorar un poquito este ejemplo presentando el nombre del DIA de la semana:
var fecha = new Date(); var diaSemana = new Array('domingo', 'lunes', 'martes', 'mircoles', 'jueves', 'viernes','sbado'); var dia = fecha.getDay(); document.write("Hoy es "+diaSemana[dia]);

Ahora se obtendra la ms amigable frase Hoy es lunes.

20.7.10.3.

getFullYear()

Nos devuelve el ao correspondiente del objeto fecha en formato completo es decir incluyendo el siglo. As si la fecha contiene 2-Octubre-2000, esta funcin nos dar 2000. Por ejemplo creemos la variable fecha instanciada como un objeto Date() para a continuacin se presenta directamente el valor de getFullYear() aplicado a fecha, o sea, 2000.
191

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

var fecha = new Date(); document.write("El ao actual es "+fecha.getFullYear());

Este mtodo evitaba el famoso efecto 2000 al presentar los aos siempre con cuatro dgitos.

20.7.10.4.

getHours()

Nos devuelve la seccin horas en formato 0-24 almacenada en la parte dedicada a la hora del objeto fecha al que se aplica. As si la fecha contiene 12:40:00, esta funcin nos dar 12, pero si contiene 5:40:00 nos dar 17. Igualmente el mtodo interpreta los modificadores am / pm pero siempre devuelve la hora en formato de 24 horas. Por ejemplo creemos la variable fecha instanciada como un objeto Date(), si son las 17:30:10 el valor de getHoursr() presentar 17.
var fecha = new Date(); document.write("Son las "+fecha.getHours()+" horas.");

Puedes probar que ocurre con otros valores sin necesidad de cambiar la fecha y hora del sistema de la siguiente manera:
var fecha = new Date("10-02-2000 08:20:00 pm"); document.write("Son las "+fecha.getHours()+" horas.");

Este caso presentar en pantalla Son las 20 horas

20.7.10.5.

getMilliseconds()

Nos devuelve los minutos de la seccin dedicada a la hora almacenada en el objeto fecha al que se aplica. As si la fecha contiene en su parte de hora 12:40:08:640, esta funcin nos dar 640. Por ejemplo creemos la variable fecha instanciada como un objeto Date(), si son las 17:30:08:550 el valor de getMilliseconds() presentar 550.
var fecha = new Date(); document.write("Son las "+fecha.getHours() ); document.write(":" + fecha.getMinutes() ); document.write(":" + fecha.getSeconds() ); document.write(":" + fecha.getMilliseconds());

20.7.10.6.

getMinutes()

Nos devuelve los minutos de la seccin dedicada a la hora almacenada en el objeto fecha al que se aplica. As si la fecha contiene en su parte de hora 12:40:08, esta funcin nos dar 24. Por ejemplo creemos la variable fecha instanciada como un objeto Date(), si son las 17:30:08 el valor de getMinutes() presentar 8.
var fecha = new Date(); document.write("Son las "+fecha.getHours() ); document.write(":" + fecha.getMinutes() ); document.write(":" + fecha.getSeconds() );

Si queremos que quede ms presentable podemos completar con ceros por la izquierda cuando el nmero (de horas, minutos o segundos) sea menor que 10. Esto es tan fcil como se ve en el ejemplo:
var fecha = new Date(); var horas = fecha.getHours(); var mins = fecha.getMinutes(); var segs = fecha.getSeconds(); horas = (horas < 10)?"0"+horas:horas; mins = (mins < 10)?"0"+mins:mins;

192

JAVASCRIPT

segs = (segs<10)?"0"+segs:segs; document.write("Son las "+horas); document.write(":" + mins); document.write(":" + segs);

20.7.10.7.

getMonth()

Nos devuelve en forma numrica el mes correspondiente al objeto fecha al que se aplica. As para la fecha correspondiente al 10/Oct/2000, esta funcin nos dar 10, el nmero de orden de Octubre. Por ejemplo creemos la variable fecha instanciada como un objeto Date()
var fecha = new Date(); document.write("Este mes es el "+fecha.getMonth() );

Si queremos que aparezca el nombre del mes en lugar del nmero debemos crear primero un array de doce elementos y rellenarlos con los nombres de los meses, luego usamos el resultado de getMonth() como ndice a ese array
var array = new meses(); var fecha = new Date(); var nmes = fecha.getMonth(); mes[1] = "Enero"; mes[2] = "Febrero"; mes[3] = "Marzo"; mes[4] = "Abril"; ... ... document.write("Mes actual:" + meses[nmes]);

20.7.10.8.

getSeconds()

Nos devuelve los segundos de la seccin dedicada a la hora almacenada en el objeto fecha al que se aplica. As si la fecha contiene en su parte de hora 12:40:08, esta funcin nos dar 8. Por ejemplo creemos la variable fecha instanciada como un objeto Date(), si son las 17:30:08 el valor de getSeconds() presentar 8.
var fecha = new Date(); document.write("Son las "+fecha.getHours() ); document.write(":" + fecha.getMinutes() ); document.write(":" + fecha.getSeconds() );

Si queremos que quede mas presentable podemos completar con ceros por la izquierda cuando el nmero (de horas, minutos o segundos) sea menor que 10. Esto es tan fcil como se ve en el ejemplo:
var fecha = new Date(); var horas = fecha.getHours(); var mins = fecha.getMinutes(); var segs = fecha.getSeconds(); horas = (horas < 10)?"0"+horas:horas; mins = (mins < 10)?"0"+mins:mins; segs = (segs<10)?"0"+segs:segs; document.write("Son las "+horas); document.write(":" + mins); document.write(":" + segs);

20.7.10.9.

getTime()

Nos devuelve la cantidad de milisegundos transcurridos desde el 1 de Enero de 1970 hasta la hora almacenada en el objeto fecha al que se aplica. En el ejemplo que sigue creamos un objeto Date con la fecha actual, a continuacin escribimos el nmero de milisegundos dado por este funcin, vers que este nmero habitualmente es muy grande, realmente esta funcin puede ser til para calcular el tiempo transcurrido entre dos instantes, por ejemplo en un puzzle podra ser til para calcular el tiempo que el
193

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

jugador emplea en resolver el puzzle, restando el getTime() obtenido al final del juego del getTime() obtenido al inicio.
var ahora = new Date(); document.write(ahora.getTime());

20.7.10.10.

getTimezoneOffset()

Esta funcin nos da la diferencia horaria en minutos del ordenador con respecto al meridiano de Greenwich. El valor depende por tanto de la zona o huso horario para el que est configurado el ordenador, pudiendo ser negativo o positivo segn est en la zona oriental u occidental. El ejemplo que muestra el uso de la funcin define la variable ahora con la fecha actual y devuelve en minutos la diferencia horaria con la GMT, el resultado depende de tu ordenador.
var ahora = new Date(); document.write(ahora.getTimezoneOffset());

20.7.10.11.

getYear()

Nos devuelve en forma numrica el mes correspondiente al objeto fecha al que se aplica. Por ejemplo creamos la variable fecha instanciada como un objeto Date(), y luego extraemos el ao
var fecha = new Date(); document.write("Este ao es el "+fecha.getYear());

20.7.10.12.

Object.toString() y Object.valueOf

Los casos Object.toString, y Object.valueOf, ya fueron explicados en el apartado E) Objeto Object.

20.7.10.13.

parse(fecha)

Nos devuelve la cantidad de milisegundos transcurridos desde el 1 de Enero de 1970 00:00:00 hasta la hora pasada en el argumento fecha como una cadena de caracteres. Este mtodo es un mtodo global del objeto y por tanto no es necesario crear un objeto Date para usarlo, como vemos en este ejemplo.
var transcurridos = Date.parse("1/1/2000 00:00:00"); document.write(transcurridos);

20.7.10.14.

setDate(diames)

Nos permite cambiar el da del mes del objeto fecha al que se aplica para poner el valor que se pasado en el argumento diames. Este mtodo controla por supuesto el nmero de das de cada mes y contempla el caso de aos bisiestos, incluida la excepcin del 2000, de forma que si pasamos como argumento 31 y el mes es de 30 das la funcin corrige la fecha completa pasndola al da 1 del mes siguiente. Esto lo vemos en el ejemplo que sigue: creamos una variable como un objeto Date con el ltimo da de Septiembre (mes de 30 das) e intentamos poner el da a 31, luego comprobamos la fecha almacenada:
var fecha = new Date("1 Sep 2000"); fecha.setDate(31); document.write("Hoy es da: "+fecha.toString());

Como vers si pruebas el ejemplo la fecha es corregida y pasa a 1 de Octubre.

194

JAVASCRIPT

20.7.10.15.

setFullYear()

Nos permite cambiar el ao del objeto fecha por el valor pasado como argumento, un nmero interpretado como ao completo, o sea, que para poner el ao 1995 se debe pasar 1995, no el 95. El ejemplo pone precisamente este valor en el campo ao de la variable fecha.
var fecha = new Date(); fecha.setFullYear(1995) document.write(fecha.toString());

20.7.10.16.

setHours()

Nos permite modificar la hora almacenada en el objeto fecha al que se aplica y poner la que se pasa como argumento. Lgicamente este argumento estar entre 0 y 24, aunque si se usa un valor fuera de este rango la fecha es corregida en consecuencia. Por ejemplo si intentamos poner la hora en 30 la fecha se adelanta 24 horas y se pone en las 6 horas, cambiando adems el da. Igualmente si se usa un nmero negativo en el argumento se toma como horas antes de la ltima media noche del mismo da. Observa todo esto en el ejemplo, donde al final de cada accin se presenta la fecha completa en forma de cadena:
var fecha = new Date("10 Sep 2000 00:00:00"); var nl="<br>"; fecha.setHours(20); document.write("A las 20: "+fecha.toString()+nl); fecha.setHours(30); document.write("A las 30: "+fecha.toString()+nl); fecha.setHours(-2); document.write("A las -2: "+fecha.toString()+nl);

20.7.10.17.

setMilliseconds()

Nos permite modificar el nmero de milisegundos de la hora almacenada en el objeto fecha al que se aplica, poniendo los milisegundos al valor pasado como argumento. Habitualmente el argumento estar comprendido entre 0 y 1000.
var fecha = new Date("10 Sep 2000 00:00:00"); var nl="<br>"; fecha.setMilliSeconds(900); document.write(fecha.toString()+nl);

20.7.10.18.

setMinutes(minact)

Nos permite ajustar los minutos de la seccin dedicada a la hora almacenada en el objeto fecha al que se aplica. El nuevo valor para los minutos se pasa como argumento, que habitualmente estar entre 0 y 59, aunque un valor fuera de este rango no da error sino que ajusta el resto de la hora. As 68 en el argumento adelanta el reloj una hora pone los minutos a 8, mientras que un -4 pone los minutos a 56 (60 menos 4). Puedes ver lo que ocurre en este ejemplo.
var fecha = new Date("10 Sep 2000 00:00:00"); var nl="<br>"; fecha.setMinutes(20); document.write("Minact 20: "+fecha.toString()+nl); fecha.setMinutes(68); document.write("Minact 68: "+fecha.toString()+nl); fecha.setMinutes(-4); document.write("Minact -4: "+fecha.toString()+nl);

Como ves si es necesario, se ajusta la hora cuando el nmero de minutos supera el valor 59

195

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

20.7.10.19.

setMonth(nummes)

Esta funcin se usa para modificar el mes del objeto fecha al que se aplica. El nuevo valor se pasa como un nmero en el argumento. El valor deber ser como es lgico numrico o convertible a numrico y comprendido entre 0 (Enero) y 11 (Diciembre). Si el valor est fuera del rango se toma el exceso sobre 11 y se corrige adecuadamente la fecha, y si es negativo se toma como nmero de meses antes de Enero (-1 sera Diciembre, -2 sera Noviembre, etc.). El ejemplo es muy sencillo, en este caso se cambia el mes de Septiembre por Marzo.
var fecha = new Date("10 Sep 2000 00:00:00"); fecha.setMonth(2); document.write("Minact 20: "+fecha.toString());

20.7.10.20.

setSeconds(miliseg)

Nos permite modificar el nmero de segundos de la hora almacenada en el objeto fecha al que se aplica, poniendo los segundos al valor pasado como argumento. Habitualmente el argumento estar comprendido entre 0 y 60.
var fecha = new Date("10 Sep 2000 00:00:00"); var nl="<br>"; fecha.setSeconds(90); document.write(fecha.toString()+nl);

20.7.10.21.

setTime()

Nos devuelve la cantidad de milisegundos transcurridos desde el 1 de Enero de 1970 hasta la hora almacenada en el objeto fecha al que se aplica. En el ejemplo que sigue creamos un objeto Date con la fecha actual, a continuacin escribimos el nmero de milisegundos dado por este funcin, vers que este nmero habitualmente es muy grande, realmente esta funcin puede ser til para calcular el tiempo transcurrido entre dos instantes, por ejemplo en un puzzle podra ser til para calcular el tiempo que el jugador emplea en resolver el puzzle, restando el setTime() obtenido al final del juego del setTime() obtenido al inicio.
var ahora = new Date(); document.write(ahora.setTime());

20.7.10.22.

setYear()

Nos permite cambiar el ao del objeto fecha por el valor pasado como argumento, un nmero interpretado como ao completo, o sea, que para poner el ao 1995 se debe pasar 1995, no el 95. El ejemplo pone precisamente este valor en el campo ao de la variable fecha.
var fecha = new Date(); fecha.setFullYear(1995) document.write(fecha.toString());

20.7.10.23.

toLocaleString()

Esta funcin se usa para transformar el objeto fecha al que se aplica a una cadena de caracteres segn el estndar UTC (Universal Time Coordinates), denominacin actual del GMT (Greenwich Meridian Time). La hora se ajusta segn la configuracin del ordenador. En el ejemplo que sigue la cadena devuelta ser Mon, 10 Apr 2000 02:00:00 UTC
var fecha = new Date("10 Apr 2000 02:00:00"); document.write(fecha.toUTCString());
196

JAVASCRIPT

Como ves existe una diferencia en la hora almacenada y la devuelta por la funcin, esto es debido a que la cadena devuelta es la hora correspondiente a Greenwich, no la local del ordenador. Existe una funcin similar, la toGMTString(), que es considerada como obsoleta y que se mantiene por cuestiones de compatibilidad.

20.7.10.24.

toUTCString(fecha)

Nos devuelve la cantidad de milisegundos transcurridos desde el 1 de Enero de 1970 00:00:00 hasta la hora pasada en el argumento fecha. Este argumento se pasa como una serie de nmeros separados por comas en el orden: Ao, mes, da, y opcionalmente: hora, minuto, segundos. Este mtodo es un mtodo global del objeto y por tanto no es necesario crear un objeto Date para usarlo, como vemos en este ejemplo que toma como fecha actual el 1 de Noviembre de 2000 a las 00:00:00.
var transc= Date.UTC(2000,10,1); document.write(transc);

20.7.11.

Objeto Math

Es el objeto que usa JavaScript para dotar al lenguaje de funciones matemticas avanzadas y de constantes predefinidas, como el nmero PI.
Propiedades

Son las habituales constantes como el nmero e, PI y algunos otros valores habituales en clculos matemticos. E LN10 LOG10E SQRT1_2 LN2 LOG2E PI SQRT2

Constante Logaritmo Logaritmo Raz Logaritmo Logaritmo El Raz de Euler, natural de en base 10 cuadrada natural de en base 2 conocido cuadrada de 2 de E nmero pi 2 la base 10 de E de 0.5 o para los sea la logaritmos inversa de naturales la raiz de 2

20.7.11.1.
Metodo abs cos pow acos exp random asin floor found atan log sin atan2

Mtodos
Descripcin Valor absoluto coseno Potencia de Arco coseno Exponencial Nmero al azar Arco seno Redondeo inferior Redondear Arco tangente Logaritmo natural Seno Arco tangente

197

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

max sqrt ceil min Tan Veamos algunos de los ms usados


abs(exprnum)

mximo Raz cuadrada Redondeo superior Mnimo Tangente

Devuelve el valor absoluto, o sea, sin signo, del argumento. Si el argumento fuera no entero ser convertido a numrico siguiendo las reglas de la funcin parseInt() o parseFloat(). Su sintaxis es tan simple como el ejemplo:
var numabs = Math.abs( - 45)

la variable numabs contendr el valor 45.


ceil(exprnum)

Devuelve el valor del argumento redondeado por exceso, es decir el menor nmero entero mayor o igual al argumento. Si el argumento fuera no numrico ser convertido a numrico siguiendo las reglas de la funcin parseInt() o parseFloat(). Su sintaxis es tan simple como el ejemplo:
var redexceso = Math.ceil( 4.25)

la variable redexceso contendr el valor 5.


floor(exprnum)

Devuelve el valor del argumento redondeado por defecto, es decir, el mayor nmero entero menor o igual al argumento. Si el argumento fuera no numrico ser convertido a numrico siguiendo las reglas de la funcin parseInt() o parseFloat(). Su sintaxis es tan simple como el ejemplo:
var redexceso = Math.floor( 4.75)

la variable redexceso contendr el valor 4.


max(num1, num2)

Devuelve el mayor de los dos nmeros o expresiones numricas pasadas como argumentos. Si alguno de los argumentos fuera no numrico ser convertido a numrico siguiendo las reglas de la funcin parseInt() o parseFloat(). Su sintaxis es tan simple como el ejemplo:
var mayor = Math.wax( 12, 5)

la variable mayor contendr el valor 12.


min(num1, num2)

Devuelve el menor de los dos nmeros o expresiones numricas pasadas como argumentos. Si alguno de los argumentos fuera no numrico ser convertido a numricos siguiendo las reglas de la funcin parseInt() o parseFloat(). Su sintaxis es tan simple como el ejemplo:
var menor = Math.min( 12, 5

la variable menor contendr el valor 5.


random()
198

JAVASCRIPT

Calcula un nmero aleatorio, realmente seudo-aleatorio, comprendido entre 0 y 1 ambos inclusive. Cada vez que se carga el intrprete de JavaScript se genera una semilla base para el clculo. No lleva argumentos y su sintaxis es tan simple como el ejemplo:
var azar = Math.random()*10

la variable azar contendr un nmero al azar entre 0 y 10.


round(exprnum)

Devuelve el valor entero mas prximo al nmero pasado como argumento, es decir, redondea. Si la parte decimal del argumento es 0.5 o mayor devuelve el primer entero por encima del argumento (redondeo por exceso) en caso contrario devuelve el entero anterior al argumento (redondeo por defecto). Si el argumento fuera no entero ser convertido a numrico siguiendo las reglas de la funcin parseInt() o parseFloat(). Su sintaxis es tan simple como el ejemplo:
var entero1 = Math.random(4.25) var entero2 = Math.random(4.65)

la variable entero1 contendr el valor 4 mientras entero1 que contendr 5.

20.7.12.

Objeto Regular Expession

Antes de ver este objeto, debemos saber saber algo acerca de las expresiones regulares.

20.7.12.1.

Qu son las expresiones regulares

Las expresiones regulares constituyen un mecanismo bastante potente para realizar manipulaciones de cadenas de texto. El proceso para el que se usan estas expresiones, presente en el mundo el UNIX y el lenguaje Perl, es el de buscar y/o sustituir una subcadena de texto dentro de otra cadena. En principio esto puede hacerse usando los mtodos del objeto string, pero el problema surge cuando no tenemos una subcadena fija y concreta sino que queremos buscar un texto que responda a un cierto esquema, como por ejemplo: buscar aquellas palabras que comienzan con http: y finalizan con una \, o buscar palabras que contengan una serie de nmeros consecutivos, etc.; es en estos casos cuando las expresiones regulares muestran toda su potencia. La subcadena que buscamos en el texto es lo que se llama un patrn y se construye encerrando entre dos barras inclinadas ( / ) una serie de caracteres normales y smbolos especiales llamados comodines o metacaracteres, (algo parecido a la orden dir *.bat usada en el DOS cuando queramos listar los ficheros con extensin bat). Este patrn es una descripcin del texto que se est buscando y JavaScript encontrar las subcadenas que concuerdan con ese patrn o definicin. Las expresiones regulares se usan con el objeto Regular Expresion y tambin dentro de los mtodos String.match, String.replace, String.search y String.split. En la tabla que sigue se muestran los caracteres comodn usados para crear los patrones y su significado, junto a un pequeo ejemplo de su utilizacin. Carcter \ ^ $ . Significado Marca de carcter especial Comienzo de una lnea Final de una lnea Cualquier carcter Ejemplo /\$ftp/ /^-/ /s$/ /\b.\b/ Resultado Busca la palabra $ftp Lneas que comienzan por Lneas que terminan por s Palabras de una sola

199

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

(menos salto de lnea) | () [] Indica opciones Agrupar caracteres Conjunto de caracteres opcionales /(L|l|f|)ocal/ /(vocal)/ /escrib[aoe]/

letra Busca Local, local, focal Busca vocal Vale escriba, escribo, escribe

La tabla que sigue describe los modificadores que se pueden usar con los caracteres que forman el patrn. Cada modificador acta sobre el carcter o el parntesis inmediatamente anterior. Carcter * + ? {n} {n,} {m,n} Descripcin Repetir 0 o mas veces Repetir 1 o mas veces 1 o 0 veces Exactamente n veces Al menos n veces entre m y n veces Ejemplo /l*234/ /a*mar/ /a?mar/ /p{2}sado/ /(m){2}ala/ /tal{1,3}a/ Resultado Valen 234, 1234, 11234 Valen amar, aamar, aaamar Valen amar, mar. Vale ppsado Vale mmala, mmmala. Vale tala, talla, tallla

Los siguientes son caracteres especiales o metacaracteres para indicar caracteres de texto no imprimibles, como puedan ser el fin de lnea o un tabulador, o grupos predefinidos de caracteres (alfabticos, numricos, etc) Caracteres \b \B Descripcin Principio o final de palabra Frontera entre nopalabras Un dgito Alfabtico (no dgito) Carcter nulo Caracter ASCII 9 (tabulador) Salto de pgina Salto de lnea Cualquier alfanumrico, [a-zAZ0-9_ ] Opuesto a \w ([^a-zAZ0-9_ ]) Carcter tipo espacio (como tab) Opuesto a \s Carcter de control X Carcter octal NN El hexadecimal hh /\x41/ Encuentra la A (ASCII Hex41) en letra A \c9 El tabulador /\w+/ Encuentra frase en frase., pero no el . (punto). Hallara slo el punto (.) Encuentra Si en Digo Si , pero no en Digo Sientate Ejemplo /\bver\b/ /\Bver\B/ Resultado Encuentra ver en ver de, pero no en verde Empareja ver con Valverde pero no con verde No falla en A4 Fallara en A4

\d \D \O \t \f \n \w

/[A-Z]\d/ /[A-Z]\D/

\W \s

/\W/ /\sSi\s/

\S \cX \oNN \xhh

Y despus de esta introduccin, ahora s.


200

JAVASCRIPT

20.7.12.2.

El objeto RegExp

JavaScript usa este objeto para trabajar con patrones de expresiones regulares, estos patrones se crean como cualquier otro objeto mediante su inicializacin directo o bien mediante el constructor new RegExp(), como podemos ver en el ejemplo:
var mipatron = /^[aeiou]/gi var mipatron2 = new RegExp("^[aeiou]", "gi")

Ambas formas conducen al mismo patrn, en este ejemplo define palabras que comienzan con una vocal. El patrn puede llevar modificadores o flags para matizar la forma de buscar, en el ejemplo se usan dos: g i Estos modificadores tienen los siguientes significados: flags g i m Significado Explorar la cadena completa No distinguir maysculas de minsculas Permite usar varios ^ y $ en el patrn

Estos patrones poseen en total tres mtodos exec(), test(), compile() adems de los mtodos ya citados del objeto String que tambin usan patrones como son: match(), replace(), search() y split(). La nica propiedad que funciona en estos objetos es la propiedad source que refleja el contenido del patrn. En el patrn pueden aparecer caracteres o grupos de caracteres encerrados entre parntesis, posteriormente podemos usar un ndice para referirnos individualmente al contenido de esos parntesis. Por ejemplo vamos a sustituir por un - todas los dgitos situados tras una letra en la cadena a explorar.
var cadexp = "234879x089h9y7"; var patron = /([a-z])(\d)/ig; document.write(cadexp+'<br> '); cadexp = cadexp.replace(patron, "$2-"); document.write(cadexp)

Como ves donde antes exista un dgito seguido de una letra ahora hay un dgito seguido de un guin. Las coincidencias con el primer parntesis del patrn estn en $1 y con el segundo en $2. La primera coincidencia hallada es x0, luego $1 contiene x y $2 contiene 0, sustituyo lo hallado con -$2, o sea, quito $1 y pongo un guin y me quedar -0 en lugar de x0. Como se ha usado el flag g (global) esta operacin se realiza en toda la cadena.
compile (cadpatr)

Un patrn de bsqueda puede construirse mediante una simple asignacin o mediante el constructor new RegExp y ser utilizada tal cual, pero se puede mejorar bastante la bsqueda usando este mtodo que convierte el patrn en un formato interno para optimizar su uso. Utiliza como argumento una cadena que representa la expresin regular que se quiere compilar
var patron = new RegExp(); patron.compile("\\D-"); var busq = patron.exec("1234u90t-789"); document.write('Buscando '+patron.source+'<br>'); document.write(busq[0]+' est en la posicin ' + busq.index +' de busq.input');

En este ejemplo se busca cualquier no numrico seguido de un guin en la cadena 1234u90t-789. Primero se declara la variable patron y se compila con el patrn \D- que indica cualquier carcter no numrico seguido de guin. Por ltimo muestra el patrn usado y los resultados de la bsqueda: coincidencia encontrada, posicin y cadena explorada.

201

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

exec (cadexplor)

Este mtodo busca la primera concordancia del patrn con el contenido de la cadena de texto donde se busca, que se le pasa como argumento. Si no encuentra ninguna concordancia devuelve null, pero encuentra una secuencia de caracteres que se adapte al patrn de bsqueda devuelve un array cuyo primer elemento indica la concordancia encontrada y las restantes indican los resultados de acuerdo a los parntesis que aparezcan en la expresin regular. Adems este array posee dos propiedades: index,para indicar la posicin de la subcadena encontrada, y input, que contiene la cadena de caracteres que se est explorando. Adems modifica las propiedades de una variable global RegExp con datos relativos a la bsqueda. En el ejemplo que sigue buscamos cualquier letra seguida de un nmero y de un guin, el patrn de bsqueda ser /[a..z]\d- /i, [a..z] representa todas las letras del abecedario, \d representa cualquier nmero y el modificador i se usa para no diferenciar maysculas de minsculas.
patron = /[a..z]D\d-/i; var busca = new Array() busca = patron.exec("3c491a-9d1d6-91br"); if (busca != null){ document.write("Concuerda en: "+busca.index + '<br>'); document.write("Explorando:" +busca.input + '<br>'); document.write("Hallado: " + busca[0] + '<br>'); } document.write("Resto " + RegExp.rightContext + '<br>'); test (cadexp)

Este es el mtodo ms simple del objeto expresin regular, tan slo comprueba si existe alguna coincidencia en la cadena explorada, pasada como argumento, con el patrn de bsqueda. Si existe tal coincidencia devuelve un valor booleano true y en caso contrario devuelve false. Adems afecta a las propiedades del objeto global RegExp.
var patron = new RegExp("Lunes","gi"); var cadexpl = "La reunin es el lunes o el martes."; var eslunes = patron.test(cadexpl); document.write("Es el lunes? "+eslunes+'<br>'); document.write("Hallado en "+RegExp.index);

En este sencillo ejemplo se comprueba si la cadena explorada, cadexpl, contiene la palabra lunes, sin considerar la caja (maysculas o minsculas). El resultado lo guarda en la variable eslunes.

20.7.12.3.

Variable global RegExp

Se trata de una variable global usada por JavaScript cuando realiza operaciones donde intervengan expresiones regulares. Cada vez que se realiza una de estas operaciones se modifican las propiedades de esta variable. Es una variable que puede consultarse pero que no se puede modificar directamente, es de slo lectura. No tiene ningn mtodo asociado y sus propiedades siempre hacen referencia a una operacin de bsqueda, sea con los mtodos de un objeto Regular Expresion o del objeto string. Propiedades
$1..$9:

Estos ndices contienen las partes agrupadas con parntesis en el patrn de bsqueda.
input

Cadena que se ha explorado.

202

JAVASCRIPT

lastmatch

ltima coincidencia encontrada.


multiline

Variable booleana que indica si la cadena explorada incluye saltos de lnea.


lastParen

ltima coincidencia encontrada con un patrn entre parntesis.


leftContext

Toda la cadena hasta la coincidencia hallada.


rightContext

Toda la cadena desde la coincidencia hasta el final de la cadena. Estas propiedades slo son de lectura y son actualizadas cada vez que se realiza alguna bsqueda con patrn, sea con los mtodos de una expresin regular o con los de String. En el siguiente ejemplo se puede observar estos valores tras una operacin de bsqueda.
var patron= /\D(\d)(\D)/g; var buscaren = "abde5fghj45oi"; var hallado = patron.exec(buscaren); var item; document.write("$1: "+RegExp.$1+"<br>"); document.write("$2: "+RegExp.$2+"<br> "); document.write("input: "+RegExp.input+"<br> "); document.write("index: "+RegExp.index+"<br> "); document.write("lastIndex: "+RegExp.lastIndex+"<br> ") ; document.write("multiline: "+RegExp.multiline+"<br>"); document.write("lastMatch: "+RegExp.lastMatch+"<br>"); document.write("lastParen: "+RegExp.lastParen +"<br>"); document.write("leftContext: "+RegExp.leftContext +"<br>"); document.write("rightContext:"+RegExp.rightContext+"<br>");

Es posible que no todas las propiedades sean reconocidas por todos los navegadores.

20.8. Eventos
20.8.1. Eventos en JavaScript

En JavaScript, la interaccin con el usuario se consigue mediante la captura de los eventos que ste produce. Un evento es una accin del usuario ante la cual puede realizarse algn proceso (por ejemplo, el cambio del valor de un formulario, o la pulsacin de un enlace). Los eventos se capturan mediante los manejadores de eventos. El proceso a realizar se programa mediante funciones JavaScript llamadas por los manejadores de eventos. La siguiente tabla muestra los manejadores de eventos que pueden utilizarse en JavaScript, la versin a partir de la cual estn soportados y su significado.

203

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Manejador onAbort

Versin 1.1

Se produce cuando El usuario interrumpe la carga de una imagen Un elemento de formulario, una ventana o un marco pierden el foco El valor de un campo de formulario cambia Se hace click en un objeto o formulario Se hace click doble en un objeto o formulario El usuario arrastra y suelta un objeto en la ventana La carga de un documento o imagen produce un error Una ventana, marco o elemento de formulario recibe el foco El usuario pulsa una tecla El usuario mantiene pulsada una tecla El usuario libera una tecla El navegador termina la carga de una ventana El usuario pulsa un botn del ratn El usuario mueve el puntero El puntero abando una rea o enlace El puntero entra en una rea o imagen El usuario libera un botn del ratn Se mueve una ventana o un marco El usuario limpia un formulario Se cambia el tamao de una ventana o marco Se selecciona el texto del campo texto o rea de texto de un formulario El usuario enva un formulario El usuario abandona una pgina

onBlur

1.0

onChange onClick onDblClick onDragDrop onError onFocus onKeyDown onKeyPress onKeyUp onLoad onMouseDown onMouseMove onMouseOut onMouseOver onMouseUp onMove onReset onResize onSelect

1.0 (1.1 para FileUpload) 1.0 1.2 (no en Mac) 1.2 1.1 1.1 (1.2 para Layer) 1.2 1.2 1.2 1.0 (1.1 para image) 1.2 1.2 1.1 1.0 (1.1 para area) 1.2 1.2 1.1 1.2 1.0

onSubmit onUnload Ejemplo de evento:

1.0 1.0

<INPUT TYPE="text" onChange="CompruebaCampo(this)">

En este ejemplo, CompruebaCampo() es una funcin JavaScript definida en alguna parte del documento HTML (habitualmente en la cabecera del mismo). El identificador this es una palabra propia del lenguaje, y se refiere al objeto desde el cual se efectua la llamada a la funcin (en este caso, el campo del formulario).

204

JAVASCRIPT

La siguiente tabla muestra los eventos que pueden utilizarse con los objetos del modelo de objetos JavaScript del Navigator. Manejador de evento onAbort onBlur Objetos para los que est definido Image Button, Checkbox, FileUpload, Layer, Password, Radio, Reset, Select, Submit, Text, Textarea, window FileUpload, Select, Text, Textarea Button, document, Checkbox, Link, Radio, Reset, Submit document, Link window Image, window Button, Checkbox, FileUpload, Layer, Password, Radio, Reset, Select, Submit, Text, Textarea, window document, Image, Link, Textarea document, Image, Link, Textarea document, Image, Link, Textarea Image, Layer, window Button, document, Link Ninguno (debe asociarse a uno) Layer, Link Layer, Link Button, document, Link window Form window Text, Textarea Form window

onChange onClick onDblClick onDragDrop onError onFocus

onKeyDown onKeyPress onKeyUp onLoad onMouseDown onMouseMove onMouseOut onMouseOver onMouseUp onMove onReset onResize onSelect onSubmit onUnload

20.8.2. Mtodos JavaScript

de

evento

disponibles

en

Los siguientes mtodos de evento pueden utilizarse en JavaScript: Mtodos de evento blur() click() focus() select() submit() Ejemplo: Funcin que realizan Elimina el foco del objeto desde el que se llame Simula la realizacin de un click sobre el objeto desde el que se llame Lleva el foco al objeto desde el que se llame Selecciona el rea de texto del campo desde el que se llame Realiza el envo del formulario desde el que se llame

205

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

<HTML> <HEAD><TITLE>Eventos</TITLE> <SCRIPT> <!-function Reacciona(campo) { alert("Introduzca un valor!") campo.focus() } //--> </SCRIPT></HEAD> <BODY> <FORM METHOD=POST> <INPUT TYPE=text NAME=campo onFocus="Reacciona(this)"> </FORM> </BODY> </HTML>

20.8.2.1.

Eventos onLoad y onUnload

Se usan como atributos del tag <BODY> de HTML. Ejemplo:


<BODY onLoad="Hola()" onUnload="Adios()">

La funcin Hola() se ejecutar antes de que se cargue la pgina y la funcin Adios() al abandonarla. Ejemplo:
<HTML> <HEAD> <TITLE>Ejemplo onLoad y onUnload</TITLE> </HEAD> <BODY onLoad="alert('Bienvenido a mi pgina!')" onUnload="alert('Vuelva pronto!')"> ... </BODY> </HTML>

20.9. Actividades
Con las actividades veremos tambien algunos eventos.

20.9.1.

Actividad 1

Realiza una pgina que contenga cdigo JavaScript para escribir en el documento directamente el mensaje Hola a todos. Haz que el script se ejecute al cargarse la pgina.

20.9.2.

Actividad 2

Realiza una pgina que muestre el mensaje Hola a todos en una ventana haciendo una llamada a una funcin JavaScript al pulsar un boton. Utilizar la funcin Alert().

20.9.3.

Actividad 3

206

JAVASCRIPT

Entrada y salida de pgina. Realiza una pgina que muestre el mensaje Bienvenido al entrar en la pgina y muestre el mensaje Adios al salir de la pgina mediante Alert(). (Eventos onLoad y onUnload)

20.9.4.

Actividad 4

Realiza una pgina para calcular los nmeros primos entre 1 y 100.

20.9.5.

Actividad 5

OnMouseOver(). Realiza una pgina que muestre cinco cuadrados de diferentes colores. Cuando el raton pase por encima de alguno de ellos el color de fondo ser del color de relleno del cuadrado.

20.9.6.

Actividad 6

Conversor monetario. Realiza una pgina que muestre un formulario para la conversin de Euros a Pesetas o viceversa. Los campos del formulario han de poder ser limpiados.

20.9.7.

Actividad 7

Saludo. Realiza una pgina que pregunte el nombre de entrada y muestre una pgina con un saludo. Distinguir la hora del da para saber si es por la maana, por la tarde o por la noche.

20.9.8.

Actividad 8

Arrays. Leer una cadena de texto en un formulario y generar un array con la funcin split(). Posteriormente, mostrar la siguiente informacin: Nmero de palabras, primera palabra, ltima palabra, las palabras colocadas en orden inverso, las palabras ordenadas de la a la z y las palabras ordenadas de la z a la a. Sacar toda esta informacin en una ventana nueva.

20.9.9.

Actividad 9

Coordenadas de ratn en la barra de estado. Realiza una pgina que capture las coordenadas de ratn y las muestre en la barra de estado.

20.9.10.

Actividad 10

Reloj edit box. Realiza una pgina que muestre la fecha y la hora actual en un reloj que se va actualizando.

20.9.11.

Actividad 11

207

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Verficacin formulario. Realiza una pgina que muestre un formulario y verifique la entrada de un nmero que est comprendido entre 1..100.

20.9.12.

Actividad 12

Test radio button. Realiza una pgina que efecte test de evaluacin a travs de radio button de tres opciones. La pgina prporcionar la evaluacin y las respuesta correctas a peticin del usuario.

20.9.13.

Actividad 13

Calculadora tabla formulario. Realiza una pgina implemente una calculadora aritmtica. Para ello haz uso de una tabla y un formulario.

20.9.14.

Actividad 14

Cambio de imgenes. Realiza una pgina que muestre una imagen que cambie cuando el ratn en pase por encima de la imagen y que vuelva a cambiar cuando salga de ella.

20.9.15.

Actividad 15

Dado. Hacer una pgina que simule el lanzamiento de un dado.

20.9.16.

Actividad 16

Esconder elementos. Realiza una pgina haga desaparecer elementos al paso del ratn y los muestre con un click de ratn sobre texto.

20.9.17.

Actividad 17

Formulario Select. Realizar una pgina que permita modificar (aadir, borrar, modificar) al gusto del usuario los contenidos de un elemento SELECT de un formulario.

20.9.18.

Actividad 18

Posicin y tamao. Realizar una pgina que permita controlar la posicin y tamao de otra ventana a travs de un pequeo formulario.

20.9.19.

Actividad 19

Estadstica de cadenas de texto. Realiza una pgina que contenga una funcin JavaScript para hacer estadsticas sobre una cadena de texto que se le pase, contando el nmero de veces que aparece cada letra. Utilizar un Array para almacenar la informacin estadstica.

208

JAVASCRIPT

20.10.

Introduccin a XML

XML, siglas en ingls de Extensible Markup Language (lenguaje de marcas extensible), es un metalenguaje extensible de etiquetas desarrollado por el World Wide Web Consortium (W3C). Es una simplificacin y adaptacin del SGML y permite definir la gramtica de lenguajes especficos (de la misma manera que HTML es a su vez un lenguaje definido por SGML). Por lo tanto XML no es realmente un lenguaje en particular, sino una manera de definir lenguajes para diferentes necesidades. Algunos de estos lenguajes que usan XML para su definicin son XHTML, SVG, MathML. XML no ha nacido slo para su aplicacin en Internet, sino que se propone como un estndar para el intercambio de informacin estructurada entre diferentes plataformas. Se puede usar en bases de datos, editores de texto, hojas de clculo y casi cualquier cosa imaginable. XML es una tecnologa sencilla que tiene a su alrededor otras que la complementan y la hacen mucho ms grande y con unas posibilidades mucho mayores. Tiene un papel muy importante en la actualidad ya que permite la compatibilidad entre sistemas para compartir la informacin de una manera segura, fiable y fcil.

20.10.1.

Historia

XML proviene de un lenguaje inventado por IBM en los aos setenta, llamado GML (Generalized Markup Language), que surgi por la necesidad que tena la empresa de almacenar grandes cantidades de informacin. Este lenguaje gust a la ISO, por lo que en 1986 trabajaron para normalizarlo, creando SGML (Standard Generalized Markup Language), capaz de adaptarse a un gran abanico de problemas. A partir de l se han creado otros sistemas para almacenar informacin. En el ao 1989 Tim Berners Lee cre la web, y junto con ella el lenguaje HTML. Este lenguaje se defini en el marco de SGML y fue de lejos la aplicacin ms conocida de este estndar. Los navegadores web sin embargo siempre han puesto pocas exigencias al cdigo HTML que interpretan y as las pginas web son caticas y no cumplen con la sintaxis. Estas pginas web dependen fuertemente de una forma especfica de lidiar con los errores y las ambigedades, lo que hace a las pginas ms frgiles y a los navegadores ms complejos. Se busc entonces definir un subconjunto del SGML que permitiera: Mezclar elementos de diferentes lenguajes. Es decir que los lenguajes sean extensibles. La creacin de analizadores simples, sin ninguna lgica especial para cada lenguaje. Empezar de cero y hacer hincapi en que no se acepte nunca un documento con errores de sintaxis. Para hacer esto XML deja de lado muchas caractersticas de SGML que estaban pensadas para facilitar la escritura manual de documentos. XML en cambio est orientado a hacer las cosas ms sencillas para los programas automticos que necesiten interpretar el documento.

20.10.2.

Ventajas del XML

209

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Es extensible: Despus de diseado y puesto en produccin, es posible extender XML con la adicin de nuevas etiquetas, de modo que se pueda continuar utilizando sin complicacin alguna. El analizador es un componente estndar, no es necesario crear un analizador especfico para cada versin de lenguaje XML. Esto posibilita el empleo de cualquiera de los analizadores disponibles. De esta manera se evitan bugs y se acelera el desarrollo de aplicaciones. Si un tercero decide usar un documento creado en XML, es sencillo entender su estructura y procesarla. Mejora la compatibilidad entre aplicaciones.

20.10.3.

XHTML

En el caso de HTML sucede que cada documento pertenece a un vocabulario fijo, establecido por otro fichero llamado DTD, que explicaremos ms adelante. No se pueden combinar elementos de diferentes vocabularios. Asimismo es imposible para un intrprete (por ejemplo un navegador) analizar el documento sin tener conocimiento de su gramtica (del DTD). Por ejemplo, el navegador sabe que antes de una etiqueta <div> debe haberse cerrado cualquier <p> previamente abierto. Los navegadores resolvieron esto incluyendo lgica ad hoc para el HTML, en vez de incluir un analizador genrico. Ambas opciones, de todos modos, son muy complejas para los navegadores. Para resolver estos problemas de compatibilidad entre XML y HTML, vino a la palestra, XHTML. XHTML, acrnimo en ingls de eXtensible Hypertext Markup Language (lenguaje extensible de marcado de hipertexto), es el lenguaje de marcado pensado para sustituir a HTML como estndar para las pginas web. En su versin 1.0, XHTML es solamente la versin XML de HTML, por lo que tiene, bsicamente, las mismas funcionalidades, pero cumple las especificaciones, ms estrictas, de XML. Su objetivo es avanzar en el proyecto del World Wide Web Consortium de lograr una web semntica, donde la informacin, y la forma de presentarla estn claramente separadas. La versin 1.1 es similar, pero parte a la especificacin en mdulos. En sucesivas versiones la W3C planea romper con los tags clsicos trados de HTML.

20.10.4.

Estructura de un documento XML

La tecnologa XML busca dar solucin al problema de expresar informacin estructurada de la manera ms abstracta y reutilizable posible. Que la informacin sea estructurada quiere decir que se compone de partes bien definidas, y que esas partes se componen a su vez de otras partes. Entonces se tiene un rbol de pedazos de informacin. Ejemplos son un tema musical, que se compone de compases, que estn formados a su vez por notas. Estas partes se llaman elementos, y se las seala mediante etiquetas. Una etiqueta consiste en una marca hecha en el documento, que seala una porcin de ste como un elemento. Un pedazo de informacin con un sentido claro y definido. Las etiquetas tienen la forma <nombre>, donde nombre es el nombre del elemento que se est sealando.

20.10.4.1.

Ejemplo cdigo de XML

A continuacin se muestra un ejemplo para entender la estructura de un documento XML:


<?xml version="1.0" encoding="UTF-8" ?>

210

JAVASCRIPT

<!--se utiliza UTF-8 debido a que acepta casi todo tipo de caracteres el cual es recomendado--> <!DOCTYPE Edit_Mensaje SYSTEM "Lista_datos_mensaje.dtd" [<!ELEMENT Edit_Mensaje (Mensaje)*>]> <Edit_Mensaje> <Mensaje> <Remitente> <Nombre>Nombre del remitente</Nombre> <Mail> Correo del remitente </Mail> </Remitente> <Destinatario> <Nombre>Nombre del destinatario</Nombre> <Mail>Correo del destinatario</Mail> </Destinatario> <Texto> <Asunto> Este es mi documento con no contiene atributos ni </Asunto> <Parrafo> Este es mi documento con no contiene atributos ni </Parrafo> </Texto> </Mensaje> </Edit_Mensaje>

una estructura muy sencilla entidades.... una estructura muy sencilla entidades....

Aqu est el ejemplo de cdigo del DTD del documento Edit_Mensaje:


<?xml version="1.0" encoding="ISO-8859-1" ?> <!-- Este es el DTD de Edit_Mensaje --> <!ELEMENT Mensaje (Remitente, Destinatario, Texto)*> <!ELEMENT Remitente (Nombre, Mail)> <!ELEMENT Nombre (#PCDATA)> <!ELEMENT Mail (#PCDATA)> <!ELEMENT Destinatario (Nombre, Mail)> <!ELEMENT Nombre (#PCDATA)> <!ELEMENT Mail (#PCDATA)> <!ELEMENT Texto (Asunto, Parrafo)> <!ELEMENT Asunto (#PCDATA)> <!ELEMENT Parrafo (#PCDATA)>

20.10.4.2.

Documentos XML bien formados

Los documentos denominados como bien formados (del ingls well formed) son aquellos que cumplen con todas las definiciones bsicas de formato y pueden, por lo tanto, analizarse correctamente por cualquier analizador sintctico (parser) que cumpla con la norma. Se separa esto del concepto de validez que se explica ms adelante. Los documentos han de seguir una estructura estrictamente jerrquica con lo que respecta a las etiquetas que delimitan sus elementos. Una etiqueta debe estar

211

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

correctamente incluida en otra, es decir, las etiquetas deben estar correctamente anidadas. Los elementos con contenido deben estar correctamente cerrados. Los documentos XML slo permiten un elemento raz del que todos los dems sean parte, es decir, solo pueden tener un elemento inicial. Los valores atributos en XML siempre deben estar encerrados entre comillas simples o dobles. El XML es sensible a maysculas y minsculas. Existe un conjunto de caracteres llamados espacios en blanco (espacios, tabuladores, retornos de carro, saltos de lnea) que los procesadores XML tratan de forma diferente en el marcado XML. Es necesario asignar nombres a las estructuras, tipos de elementos, entidades, elementos particulares, etc. En XML los nombres tienen alguna caracterstica en comn. Las construcciones como etiquetas, referencias de entidad y declaraciones se denominan marcas; son partes del documento que el procesador XML espera entender. El resto del documento entre marcas son los datos entendibles por las personas.

20.10.5.

Partes de un documento XML

Un documento XML est formado por el prlogo y por el cuerpo del documento as como texto de etiquetas que contiene una gran variedad de efectos positivos o negativos en la referencia opcional a la que se refiere el documento, hay que tener mucho cuidado de esa parte de la gramtica lxica para que se componga de manera uniforme. Prlogo [editar] Aunque no es obligatorio, los documentos XML pueden empezar con unas lneas que describen la versin XML, el tipo de documento y otras cosas. El prlogo de un documento XML contiene: Una declaracin XML. Es la sentencia que declara al documento como un documento XML. Una declaracin de tipo de documento. Enlaza el documento con su DTD (definicin de tipo de documento), o el DTD puede estar incluido en la propia declaracin o ambas cosas al mismo tiempo. Uno o ms comentarios e instrucciones de procesamiento.

20.10.5.1.

Cuerpo

A diferencia del prlogo, el cuerpo no es opcional en un documento XML, el cuerpo debe contener un y solo un elemento raz, caracterstica indispensable tambin para que el documento est bien formado. Sin embargo es necesaria la adquisicin de datos para su buen funcionamiento Elementos [editar] Los elementos XML pueden tener contenido (ms elementos, caracteres o ambos), o bien ser elementos vacos.

20.10.5.2.

Atributos

Los elementos pueden tener atributos, que son una manera de incorporar caractersticas o propiedades a los elementos de un documento. Deben ir entre comillas.
212

JAVASCRIPT

Por ejemplo, un elemento chiste puede tener un atributo tipo y un atributo calidad, con valores vascos y bueno respectivamente.
<chiste tipo="vascos" calidad="bueno">Esto es un da que Patxi y Josu van paseando</chiste>

20.10.5.3.

Entidades predefinidas

Entidades para representar caracteres especiales para que, de esta forma, no sean interpretados como marcado en el procesador XML. Ejemplo: Entidad Predefinida: & amp; Caracter &

20.10.5.4.

Secciones CDATA

Es una construccin en XML para especificar datos utilizando cualquier carcter sin que se interprete como marcado XML. No confundir con 2(#PCDATA) que es para los elementos. Permite que caracteres especiales no rompan la estructura. Ej:
<![CDATA[ contenido especial: &]] >

20.10.5.5.

Comentarios

Comentarios a modo informativo para el programador que han de ser ignorados por el procesador. Los comentarios en XML tienen el siguiente formato:
<!--- Esto es un comentario ---> <!-- Otro comentario -->

20.10.6.

Document Type Definition (DTD)

Una definicin de tipo de documento o DTD (siglas en ingls de document type definition) es una descripcin de estructura y sintaxis de un documento XML o SGML. Su funcin bsica es la descripcin del formato de datos, para usar un formato comn y mantener la consistencia entre todos los documentos que utilicen la misma DTD. De esta forma, dichos documentos, pueden ser validados, conocen la estructura de los elementos y la descripcin de los datos que trae consigo cada documento, y pueden adems compartir la misma descripcin y forma de validacin dentro de un grupo de trabajo que usa el mismo tipo de informacin.

20.10.6.1.

Definicin

La DTD es una definicin, en un documento SGML o XML, que especifica restricciones en la estructura y sintaxis del mismo. La DTD se puede incluir dentro del archivo del documento, pero normalmente se almacena en un fichero ASCII de texto separado. La sintaxis de las DTD para SGML y XML es similar pero no idntica. La definicin de una DTD especifica la sintaxis de una aplicacin de SGML o XML, que puede ser un estndar ampliamente utilizado como XHTML o una aplicacin local.

20.10.6.2.

Qu describe una DTD?

Las DTD se emplean generalmente para determinar la estructura de un documento mediante etiquetas (en ingls tags) XML o SGML. Una DTD describe:
213

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

* Elementos: indican qu etiquetas son permitidas y el contenido de dichas etiquetas. * Estructura: indica el orden en que van las etiquetas en el documento. * Anidamiento: indica qu etiquetas van dentro de otras.

20.10.6.3.

Ejemplos

* Un ejemplo de una DTD XML muy simple, para describir una lista de personas:
<!ELEMENT lista_de_personas (persona*)> <!ELEMENT persona (nombre, fechanacimiento?, sexo?, numeroseguridadsocial?)> <!ELEMENT nombre (#PCDATA) > <!ELEMENT fechanacimiento (#PCDATA) > <!ELEMENT sexo (#PCDATA) > <!ELEMENT numeroseguridadsocial (#PCDATA)>

Observndolo lnea a lnea nos dice: # <lista_de_personas> es un nombre de elemento vlido. El * indica que puede haber 0 o ms elementos de persona. # <persona> es un nombre de elemento vlido. ste contiene obligatoriamente el elemento nombre mientras que el resto son opcionales. Y lo son porque nos lo indica el smbolo ?. # <nombre> es un nombre de elemento vlido. Contiene caracteres. # <sexo> es un nombre de elemento vlido. Contiene caracteres. # <fechanacimiento> es un nombre de elemento vlido. # <numeroseguridadsocial> es un nombre de elemento vlido. * Un ejemplo de un fichero XML que hace uso de esta DTD:
<source lang=xml> <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE lista_de_personas SYSTEM "ejemplo.dtd"> <lista_de_personas> <persona> <nombre>Jos Garca</nombre> <fechanacimiento>25/04/1984</fechanacimiento> <sexo>Varn</sexo> </persona> </lista_de_personas> </source>

La DTD mostrada ms arriba requiere un elemento nombre dentro de cada elemento persona; el elemento lista_de_personas es tambin obligatorio, pero el resto son opcionales. Es posible renderizar este documento en un navegador habilitado para XML pegando y guardando la DTD de ms arriba en un archivo de texto llamado ejemplo.dtd y el fichero.xml a un fichero de texto denominado de forma diferente, y abriendo el archivo.xml con el navegador. Ambos ficheros deben estar guardados en el mismo directorio (o carpeta). No obstante, algunos navegadores no comprueban que un documento XML sigue las reglas de la DTD; solamente se requieren para comprobar que la DTD es sintcticamente correcta.
Limitaciones de la DTD

Un esquema basado en una DTD tiene bastantes limitaciones. Una DTD no permite definir elementos locales que slo sean vlidos dentro de otros elementos. Por ejemplo, si queremos tener un elemento <Manager> que describa al gestor de una compaa o al de una delegacin, y la definicin de Manager es diferente en cada caso, con una DTD tendramos que crear los elementos CompanyManager y DelegationManager para evitar el conflicto de nombres. Es decir, la falta de jerarqua en una DTD obliga a introducir una jerarqua a base de guiones o puntos en el espacio de nombres (Namespace). En una DTD es poco flexible la definicin de elementos con contenido mixto, es decir, que incluyan otros elementos adems de texto. Adems no es posible

214

JAVASCRIPT

indicar a qu tipo de dato (nmero, fecha, moneda) ha de corresponder un atributo o el texto de un elemento. La necesidad de superar estas limitaciones propicia la aparicin de otros lenguajes de esquema como XML Schema, herramientas ms completas de descripcin que son una alternativa a las DTD.

20.10.7.

XML Schemas

XML Schema es un lenguaje de esquema utilizado para describir la estructura y las restricciones de los contenidos de los documentos XML de una forma muy precisa, ms all de las normas sintcticas impuestas por el propio lenguaje XML. Se consigue as una percepcin del tipo de documento con un nivel alto de abstraccin. Fue desarrollado por el World Wide Web Consortium (W3C) y alcanz el nivel de recomendacin en mayo de 2001.

20.10.7.1.

Terminologa

El trmino XML Schema es utilizado con varios significados dentro del mismo contexto de descripcin de documentos, y es importante tener en cuenta las siguientes consideraciones: XML Schema (Esquema XML) es el nombre oficial otorgado a la recomendacin del W3C, que elabor el primer lenguaje de esquema separado de XML (la definicin de tipo de documentos (DTD) forma parte de XML). Es habitual referirse a los esquemas como XML schema de forma genrica, pero se recomienda utilizar el trmino documento esquema (schema document) o definicin de esquema(schema definition), y reservar XML Schema para la denominacin de este lenguaje especfico. Aunque genricamente se utilice XML schemas, XSDL (XML Schema Definition Language) es el nombre tcnico de los lenguajes de esquema de XML como: Definicin de Tipo de Documento (DTD) XML Schema RELAX NG Schematron Namespace Routing Language (NRL) Document Schema Definition Languages (DSDL) Document Definition Markup Language (DDML) Document Structure Description (DSD) SGML Schema for Object-Oriented XML (SOX)

215

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

20.10.7.2.

W3C Schema XML

El World Wide Web Consortium (W3C) empez a trabajar en XML Schema en 1998. La primera versin se convirti en una recomendacin oficial en mayo de 2001. Una segunda edicin revisada est disponible desde octubre de 2004. Esta recomendacin est desarrollada en tres partes: XML Schema Parte 0 Primer: es una introduccin no normativa al lenguaje, que proporciona una gran cantidad de ejemplos y explicaciones detalladas para una primera aproximacin a XML Schema. XML Schema Parte 1 Structures: es una extensa descripcin de los componentes del lenguaje. XML Schema Parte 2 Datatypes: complementa la Parte 1 con la definicin de los tipos de datos incorporados en XML Schema y sus restricciones.

20.10.7.3.

Componentes

XML Schema es un lenguaje de esquema escrito en XML, basado en la gramtica y pensado para proporcionar una mayor potencia expresiva que las DTD, menos capaces al describir los documentos a nivel formal. Los documentos esquema (usualmente con extensin .xsd de XML Schema Definition (XSD)) se concibieron como una alternativa a las DTD, ms complejas, intentando superar sus puntos dbiles y buscar nuevas capacidades a la hora de definir estructuras para documentos XML. El principal aporte de XML Schema es el gran nmero de tipos de datos que incorpora. De esta manera, XML Schema aumenta las posibilidades y funcionalidades de aplicaciones de procesado de datos, incluyendo tipos de datos complejos como fechas, nmeros y strings. Tipos de componentes [editar] Los esquemas XML Schema superan muchas de las limitaciones y debilidades de las DTDs. Fue diseado completamente alrededor de namespaces y soporta tipos de datos tpicos de los lenguajes de programacin, como tambin tipos personalizados simples y complejos. Un esquema se define pensando en su uso final.
Namespaces

La programacin en Schema XML se basa en Namespaces. Podemos encontrar una analoga entre stos y los llamados packages en Java. Cada Namespace contiene elementos y atributos que estn estrechamente relacionados con el Namespace. As, a la hora de definir un elemento o un atributo de un Namespace, siempre se crear una conexin entre los diferentes campos de ste. Adems, esta forma de trabajar nos permite relacionar elementos que no estn en el mismo Namespace. Despus de escribir un Schema XML se puede confirmar la correcta realizacin mediante la validacin de esquemas XML: Validacin XML.
Ejemplo

Un ejemplo de la estructura de un documento esquema vaco sera el siguiente:


<?xml version="1.0" encoding="ISO-8859-1"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="0.1" xml:lang="es"> </xsd:schema>

Un ejemplo de definicin con XML Schema sera el siguiente:

216

JAVASCRIPT

<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="Libro"> <xsd:complexType> <xsd:sequence> <xsd:element name="Ttulo" type="xsd:string"/> <xsd:element name="Autores" type="xsd:string" maxOccurs="10"/> <xsd:element name="Editorial" type="xsd:string"/> </xsd:sequence> <xsd:attribute name="precio" type="xsd:double"/> </xsd:complexType> </xsd:element> </xsd:schema>

Podemos ver como en ambos casos se inician las declaraciones indicando la versin de XML que se va a utilizar y la codificacin que se usa. Estos dos campos son necesarios para poder interpretar el esquema. Adems, en la siguiente lnea de cdigo podemos ver como se redirecciona al usuario a la pgina que ofrece las pautas de creacin de XML Schema en las que se basar la descripcin del esquema. El elemento raz se llama Libro y tiene tres hijos (elementos anidados) y un atributo. Los hijos son Titulo,Editorial que deben aparecer una vez y Autores que puede aparecer de una a diez veces. El hecho de que estn agrupados en una secuencia indica que los elementos deben aparecer en orden, es decir, primero el Titulo, luego los Autores y por ltimo la Editorial. Los tres elementos son de tipo string. El atributo de libro se llama precio y es de tipo double.

20.10.8.

Extended Style Language (XSL)

XSLT es pues, un lenguaje que se usa para convertir documentos XML en otros documentos XML; puede convertir un documento XML que obedezca a un DTD a otro que obedezca otro diferente, un documento XML bien formado a otro que siga un DTD, o, lo ms habitual, convertirlo a formatos finales, tales como WML (usado en los mviles WAP) o XHTML. Los programas XSLT estn escritos en XML, y generalmente, se necesita un procesador de hojas de estilo, o stylesheet processor para procesarlas, aplicndolas a un fichero XML. El estilo de programacin con las hojas XSLT es totalmente diferente a los otros lenguajes a los que estamos acostumbrados (tales como C++ o Perl), parecindose ms a lenguajes tales como el AWK, o a otros lenguajes funcionales, tales como ML o Scheme. En la prctica, eso significa dos cosas: No hay efectos secundarios. Una instruccin debe de hacer lo mismo cualquier que sea el camino de ejecucin que llegue hasta ella. O sea, no va a haber variables globales (Cielos!), ni bucles en los que se incremente el valor de una variable, o tenga un test de fin de bucle, ni nada por el estilo. En realidad, esto no es tan grave, y se puede simular usando recursin, como se ver. La programacin est basada en reglas: cuando ocurre algo en la entrada, se hace algo en la salida. En eso, se parece al AWK, o a cierto estilo de programacin en PERL, pero no en el resto de las cosas. Al fin y al cabo, no hay efectos secundarios. En resumen, programar con las hojas XSLT (en ingls se les llama stylesheets o logicsheets) puede ser un poco frustante, pero cuando uno aprende a usarlas, no puede vivir sin ellas. En realidad, son la nica alternativa cuando uno quiere adaptar un contenido descrito con XML a diferentes clientes (por ejemplo, mviles de diferente tamao, diferentes navegadores), y la mejor alternativa cuando uno quiere procesar

217

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

documentos XML (aunque haya otras: filtros SAX, expresiones regulares). Otra alternativa, sobre todo si se est trabajando ya con un documento XML en forma de DOM (Document object model) es trabajar directamente sobre l. En este claso, de todas formas, se pueden usar transformaciones XSL, slo que se aplicarn en memoria, en vez de leerlas desde un fichero. Lo que consiguen las hojas de estilo es separar la informacin (almacenada en un documento XML) de su presentacin, usando en cada caso las transformaciones que sean necesarias para que el contenido aparezca de la forma ms adecuada en el cliente. Es ms, se pueden usar diferentes hojas de estilo, o incluso la misma, para presentar la informacin de diferentes maneras dependiendo de los deseos o de las condiciones del usuario. Aparte del hecho habitual de procesar documentos XML, XSLT es un lenguaje de programacin, y por tanto se podra hacer cualquier cosa con ellas; incluso calcular la clebre criba de Eratstenes o ejecutar un algoritmo gentico. Pero a nosotros nos va a interesar ms como simple herramienta de transformacin de XML. Actualmente hay varias versiones del estndar XSLT: la versin 1.0, que es la que implementan la mayora de los procesadores, y se denomina recomendacin, es decir, para el consorcio W3, lo equivalente a un estndar, y la versin 2.0 , que, a fecha de 4 de noviembre del 2004, es un working draft, o borrador de trabajo, que es el paso previo a un estndar. Algunos procesadores, tales como el Saxon, implementan ya esta ltima versin. Hay algunas diferencias importantes: el tratamiento uniforme de los rboles (tcnicamente, se pueden convertir fragmentos de rboles de resultados en nodesets), uso de mltiples documentos de salida, y funciones definidas por el usuario que se pueden definir en XSLT, y no slo en Java u otro lenguaje, como suceda en estndares anteriores. Para Windows, en sus diferentes versiones, hay dos herramientas que permiten editar XML y hojas de estilo XSLT, y aplicar directamente la una a la otra. Una de ellas es XMLSpy, que tiene un IDE muy bonito, pero que casca con relativa frecuencia. De hecho, he sido incapaz de aplicar una hoja de estilo a un documento XML. Otra opcin es usar eXcelon Stylus, un buen de programa, pero que slo est disponible para WindowsNT/2000 (y no s si XP); la versin 3.0 beta es gratuita para desarrolladores. En realidad, para editar XML y XSLT no hace falta ningn editor especial, pero viene bien un editor de XML o incluso un entorno integrado que te ayude a indentar bien el cdigo, e incluso a cerrar las etiquetas en el orden correcto, o te saque la etiqueta y atributos admisibles en cada momento en funcin del DTD. En ese sentido, si se trabaja en Windows, el mejor es el eXcelon Stylus; en Linux, se puede uno apaar bien con el XEmacs (que te valida usando un DTD, si es necesario).

20.10.8.1.

Cmo se usan las hojas de estilo

Hay muchas formas de usar las hojas de estilo. Lo ms normal es usarlas dentro de un entorno de publicacin tal como el Cocoon, o el IBM Transcoding Publisher, AxKit u otros por el estilo. Un entorno de publicacin de XML permite mantener sitios completos basados en XML, y generar pginas en diferentes formatos a partir de ellos. En general, recomendamos Cocoon, que es una herramienta gratuita y Open Source basada en Java, y adems una de las ms avanzadas en el sector. Para una solucin profesional, es mejor el IBM TP, pues forma parte del servidor de aplicaciones WebSphere, y cuenta con interfaz grfico avanzado; el problema es el coste. La principal diferencia entre la versin 2 de Xalan y las anteriores es que implementa el llamado TrAX, una API para poder aplicar transformaciones a rboles XML; probablemente incorpore tambin la versin 1.1 de XSLT En muchos casos, lo que se necesita es aplicar hojas de estilo dentro de una aplicacin, o usarlas desde lnea de comandos a partir de otra aplicacin o otro lenguaje de
218

JAVASCRIPT

programacin. En ese caso, lo ms til es usar un procesador de hojas de estilo, que habitualmente se encuentra en conjuncin con un parser XML, con o sin validacin. De estos, hay los siguientes: Xalan, que ser el que ms usemos en este tutorial, y que adems es gratuito. La versin actual es la 2.6. Es una herramienta escrita en Java, y lo nico que se necesita para hacerla funcionar es una mquina virtual Java (JVM), tal como la de Microsoft, Sun o IBM. Xalan necesita un parser XML para funcionar, tal como el Xerces, aunque el fichero correspondiente (xerces.jar) viene incluido en la distribucin. Saxon, un procesador bastante rpido, tambin escrito en Java, con su propio parser incluido, aunque se puede usar uno externo. Hay una versin denominada Instant Saxon, un procesador rpido, y fcil de usar, slo para Windows. Por lo pronto, es el nico que implementa la versin 2.0 de XSLT. Hay otros muchos procesadores, tales como el XT de James Clark, xsltproc o el Sablotron. Todos ellos y muchos ms se pueden encontrar en la pgina de procesadores XSLT de XMLSoftware.com. En Linux recomiendo el xsltproc, basado en la librera XML/XSL de gnome; es muy rpido, es un ejecutable y no hace falta instalar Java para usarlo. A su vez, los procesadores de hojas de estilo se pueden usar como libreras de clases, o desde otros lenguajes. Por ejemplo, el mdulo XML::XSLT para Perl. Estos mdulos se pueden usar para poder trabajar con XSLT fuera de entornos de publicacin, como por ejemplo un servidor web normal. xalan es en realidad una librera que se puede usar tambin desde programas en Java. Algunos navegadores tambin lo implementan, o lo harn en el futuro. En concreto, el Mozilla debera incluirlo a partir de la versin 0.9; desde la versin 0.7 se poda incluir un plugin llamado TransforMiiX, que tericamente aplica XSLT. En realidad, casi todos los navegadores modernos, con mayor o menor fortuna, lo incluyen. Firefox, por ejemplo, lo toma sin problemas. Finalmente, para este curso, se puede usar un formulario simple que aplica hojas de estilo XSLT a documentos XML usando Perl: aplicador de hojas de estilo.

20.10.8.2.

Hojas de estilo bsicas

Para empezar, vamos a tratar de presentar una hoja XML de lo ms simple (tienda0.xml):
<?xml version="1.0" encoding='ISO-8859-1'?> <?xml-stylesheet href="tienda0.xsl" type="text/xsl"?> <tienda> <nombre>La tiendecilla </nombre> <telefono>953 87 12 23 </telefono> </tienda>

Este ejemplo lo iremos extendiendo hasta que contenga un catlogo de una tienda virtual. Por lo pronto incluimos solamente datos bsicos sobre la tienda. Para convertirlo en HTML, usaremos la siguiente hoja de estilo (tienda-html.xsl): 1
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match='/'> <html> <head> <title>Generado con tienda-html.xsl</title> </head> <body>
219

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

<h1> <xsl:apply-templates /> </h1> </body> </html> </xsl:template> </xsl:stylesheet>

Tal como est, se puede cargar directamente con Firefox, que mostrar algo similar a la imagen. Asimismo se puede usar cualquier entorno integrado que incluya la posibilidad de hacer transformaciones, como el XMLShell o XMLSpy mencionados anteriormente.

20.10.9.

Xlink, Xpath y Xpointer

XPath identifica partes de un documento XML concreto, como pueden ser sus atributos, elementos, etc. XLink por su lado, describe un camino estndar para aadir hiperenlaces en un archivo XML. Es decir, es un mecanismo de vinculacin a otros documentos XML. Funciona de forma similar a un enlace en una pgina Web, es decir, funciona como lo hara <a href=>, slo que a href es un enlace unidireccional. Sin embargo, XLink permite crear vnculos bidireccionales, lo que implica la posibilidad de moverse en dos direcciones. Esto facilita la obtencin de informacin remota como recursos en lugar de simplemente como pginas Web. XPointer funciona como una sintaxis que apunta a ciertas partes de un documento XML, es como una extensin de XPath. Se utiliza para llegar a ciertas partes de un documento XML. Primero, XLink permite establece el enlace con el recurso XML y luego es XPointer el que va a un punto especfico del documento. Su funcionamiento es muy similar al de los identificadores de fragmentos en un documento HTML ya que se aade al final de una URI y despus lo que hace es encontrar el lugar especificado en el documento XML. Al ser XPointer una extensin de XPath, XPointer tiene todas las ventajas de XPath y adems permite establecer un rango en un documento XML, es decir, con XPointer es posible establecer un punto final y un punto de inicio, lo que incluye todos los elementos XML dentro de esos dos puntos. Finalmente, XQL, lenguaje de consultas, se basa en operadores de bsqueda de un modelo de datos para documentos XML que puede realizar consultas en infinidad de tipos de documentos como son documentos estructurados, colecciones de documentos, bases de datos, estructuras DOM, catlogos, etc.

20.10.9.1.
Ejemplo de documento XML:

Ejemplos de uso

<?xml version="1.0" encoding="ISO-8859-1"?> <libro> <titulo></titulo> <capitulo> <titulo></titulo> <seccion> <titulo></titulo> </seccion> </capitulo> </libro>

Ejemplo de transformacin XSL:


<!-- Transforma el documento XML anterior en un documento XHTML --> <xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:strip-space elements="libro capitulo titulo"/> <xsl:output

220

JAVASCRIPT

method="xml" indent="yes" encoding="iso-8859-1" doctype-public="-//W3C//DTD XHTML 1.1//EN" doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"/> <!-- Utiliza el ttulo del libro como ttulo del documento XHTML --> <xsl:template match="libro"> <html> <head> <title> <xsl:value-of select="titulo"/> </title> </head> <body> <xsl:apply-templates/> </body> </html> </xsl:template> <!-- Y tambin como ttulo de nivel H1 --> <xsl:template match="libro/titulo"> <h1> <xsl:apply-templates/> </h1> </xsl:template> <!-- Los ttulos de los captulos aparecern como H2 --> <xsl:template match="capitulo/titulo"> <h2> <xsl:apply-templates/> </h2> </xsl:template> <!-- Los ttulos de las secciones aparecern como H3 --> <xsl:template match="seccion/titulo"> <h3> <xsl:apply-templates/> </h3> </xsl:template> </xsl:stylesheet>

Ejemplo de cdigo XPath:


<!-- Toma todos los elementos titulo dentro del elemento captulo y los elementos autor dentro del elemento capitulo --> /doc/capitulo/titulo | /doc/capitulo/autor

Ejemplo de cdigo XLink:


<my:crossReference xlink:href="libro.xml" xlink:role="http://www.example.com/linkprops/listalibros" xlink:title="Lista de libros"> Lista actual de libros </my:crossReference>

Ejemplo de cdigo XPointer:


documento.xml#xpointer( /libro/capitulo[@public])xpointer(/libro/capitulo[@num="1"])

Ejemplo de cdigo de XQuery:


<!-- Libros escritos por Vargas Llosa despus de 1991 --> <bib> { for $b in doc("http://libro.example.com/bib.xml")/bib/libro where $b/autor = "Vargas Llosa" and $b/@anio > 1991

221

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

return <libro anio="{ $b/@anio }"> { $b/titulo } </libro> } </bib>

20.10.10.

SAX y DOM

Las herramientas o programas que leen el lenguaje XML y comprueban si el documento es vlido sintcticamente, se denominan analizadores o parsers. Un parser XML es un mdulo, biblioteca o programa que se ocupa de transformar un archivo de texto en una representacin interna. En el caso de XML, como el formato siempre es el mismo, no necesitamos crear un parser cada vez que hacemos un programa, sino que existen un gran nmero de parsers o analizadores sintcticos disponibles que pueden averiguar si un documento XML cumple con una determinada gramtica. Entre esos analizadores o parsers cabe destacar DOM y SAX. DOM y SAX, son pues dos herramientas que sirven para analizar el lenguaje XML y definir la estructura de un documento, aunque existen otras muchas. Podemos hacer una distincin entre las herramientas que son validantes y las que son No validantes. Las primeras verifican que el documento, adems de estar bien formado de acuerdo a las reglas de XML, responda a una estructura definida en una Definicin del Tipo de Documento (DTD). Los parsers DOM y SAX son independientes del lenguaje de programacin y existen versiones particulares para Java, VisualBasic, C, Java, PHP, etc.

20.10.10.1.

DOM

El Modelo de Objetos del Documento parser Document Object Model (DOM) es un modelo de objetos estandarizado para documentos HTML y XML. DOM es un conjunto de interfaces para describir una estructura abstracta para un documento XML. Los programas que acceden a la estructura de un documento a travs de la interfaz de DOM pueden insertarse arbitrariamente, borrarse y reordenar los nodos de un documento XML, esto es, con DOM se puede modificar el contenido, la estructura y el estilo o presentacin de los documentos. Todas estas funciones se realizan mediante llamadas a funciones y procedimientos que permiten acceder, cambiar, borrar o aadir nodos de informacin (datos o metadatos) de los documentos XML. DOM es una una interfaz de programacin de aplicaciones (API) para documentos HTML y XML. Define la estructura lgica de los documentos y el modo en que se accede y manipula un documento. El trmino documento en DOM se entiende de una forma amplia, pues XML se utiliza cada vez ms como un medio para representar muchas clases diferentes de informacin que puede ser almacenada en sistemas diversos, y mucha de esta informacin se vera, en trminos tradicionales, ms como datos que como documentos. Sin embargo, XML presenta estos datos como documentos, y se puede usar el DOM para manipular estos datos. Con el Modelo de Objetos del Documento los programadores pueden construir documentos, navegar por su estructura, y aadir, modificar o eliminar elementos y contenido. Se puede acceder a cualquier cosa que se encuentre en un documento HTML o XML, y se puede modificar, eliminar o aadir usando el Modelo de Objetos del Documento, salvo algunas excepciones. Siendo una especificacin del W3C, uno de los objetivos importantes del Modelo de Objetos del Documento es proporcionar una interfaz estndar de programacin que pueda utilizarse en una amplia variedad de entornos y aplicaciones. El DOM se ha

222

JAVASCRIPT

diseado para utilizarse en cualquier lenguaje de programacin como Java o ECMAScript (un lenguaje de scripts industrial basado en JavaScript y JScript. Cuando nos referimos a interfaz al hablar de DOM (o de SAX), no nos estamos refiriendo a interfaz grfica, sino a interfaz de aplicaciones. Una interfaz es un dispositivo que permite comunicar dos sistemas que no hablan el mismo lenguaje. Una Interfaz de Programacin de Aplicaciones Niveles o interfaceso API (Application Programming interface) es un conjunto de funciones o mtodos usados para acceder a cierta funcionalidad. La interfaz se encarga de mantener el dilogo con los datos para poder tener acceso a ellos y manipularlos. La utilizacin de APIs es muy comn cuando tenemos un conjunto de datos que queremos tratar o manipular y se aplica, sobre todo, para acceder a bases de datos y realizar tareas que estn a caballo entre las aplicaciones y las bases de datos. Estas tareas se realizan bien a travs del servidor de base de datos, o bien a travs del cliente. Esto quiere decir, que puede darse el caso de que el cliente conste de las tres primeras interfaces o niveles, o que se encuentren las dos ltimas en el servidor (ver imagen adjunta). La interfaz correspondiente a la base de datos, es donde se encontrar el servidor y toda la informacin depositada en l. El DOM es, pues, un API o interfaz de programacin para documentos. DOM guarda una gran similitud con la estructura del documento al que modeliza y muestra los documentos con una estructura lgica que es muy parecida a un rbol. Sin embargo, el DOM no especifica que los documentos deban ser desarrollados como un rbol o un bosque, ni tampoco especifica cmo deben implementarse las relaciones entre objetos. El DOM es un modelo lgico que puede desarrollarse de la manera que sea ms conveniente, por eso se debe hablar de un modelo de estructura en general, y no de estructura en forma de rbol, en particular. Una propiedad importante de los modelos de estructura del DOM es su isomorfismo estructural: si dos desarrollos cualesquiera del Modelo de Objetos del Documento se usan para crear una representacin del mismo documento, ambos crearn el mismo modelo de estructura, con exactamente los mismos objetos y relaciones. El nombre de DOM o Modelo de Objetos del Documento se adopt porque se trata de un modelo de objetos en el sentido tradicional del diseo orientado a objetos: los documentos se modelizan usando objetos, y el modelo comprende no solamente la estructura de un documento, sino tambin su comportamiento y el de los objetos de los cuales se compone. Esto significa que los nodos del diagrama obtenido mediante DOM no representan una estructura de datos, sino que representan objetos, los cuales pueden tener funciones e identidad. Como modelo de objetos, el DOM identifica: las interfaces y objetos usados para representar y manipular un documento la semntica de estas interfaces y objetos, incluyendo comportamiento y atributos las relaciones y colaboraciones entre estas interfaces y objetos Tradicionalmente, la estructura de los documentos SGML se ha representado mediante un modelo de datos abstractos, no con un modelo de objetos. En un modelo de datos abstractos, el modelo se centra en los datos. En los lenguajes de programacin orientados a objetos, los datos se encapsulan en objetos que ocultan los datos, protegindolos de su manipulacin directa desde el exterior. Las funciones asociadas con estos objetos determinan cmo pueden manipularse los objetos, y son parte del modelo de objetos. El Modelo de Objetos del Documento no es un conjunto de estructuras de datos, sino un modelo de objetos que especifica interfaces. Aunque la especificacin del W3C contiene diagramas que muestran relaciones padre/hijo, stas son relaciones lgicas definidas
223

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

por las interfaces de programacin, no representaciones de ninguna estructura interna de datos particular. El Modelo de Objetos del Documento no define la semntica interna real de los lenguajes XML o de HTML. El DOM es un modelo de programacin diseado para respetar las semnticas establecidas por el W3C en otras especificaciones. El DOM no tiene ninguna consecuencia en el modo en que se escriben los documentos XML y HTML; cualquier documento que pueda escribirse con estos lenguajes puede ser representado en el DOM. As pues, DOM es un conjunto de interfaces y objetos diseado para manipular documentos HTML y XML que se puede desarrollar usando otros sistemas y lenguajes especficos. Las especificaciones del W3C que regulan el Modelo de Objetos del Documento son las siguientes: Document Object Model (DOM) Level 1Specification. http://www.w3.org/TR/REC-DOMLevel-1/ (trad. al castellano: POZO, Juan R. Especificacin del Modelo de Objetos del Documento (DOM). Nivel 1. http://html.conclase.net/w3c/dom1-es/cover.html En esta especificacin se define el Nivel 1 del Modelo de Objetos del Documento, una interfaz independiente de la plataforma y del lenguaje que permite a programas y scripts acceder y actualizar dinmicamente los contenidos, la estructura y el estilo de los documentos. El Modelo de Objetos del Documento proporciona un conjunto estndar de objetos para representar documentos HTML y XML, un modelo estndar de cmo pueden combinarse estos objetos y una interfaz estndar para acceder a ellos y manipularlos. Las compaas pueden dar soporte al DOM como interfaz para sus estructuras de datos y APIs propietarias, y los autores de contenido pueden escribir para las interfaces estndar del DOM en lugar de para las APIs especficas de cada producto, lo cual incrementa la interoperabilidad en la Web. El objetivo de la especificacin DOM es definir una interfaz programable para HTML y XML. La especificacin del Nivel 1 del DOM se divide en dos partes: Ncleo y HTML. El ncleo proporciona un conjunto de interfaces fundamentales de bajo de nivel que pueden representar cualquier documento estructurado, al mismo tiempo que define interfaces extendidas para representar documentos XML. La seccin de HTML proporciona interfaces adicionales de alto nivel que se utilizan con las interfaces fundamentales definidas en la seccin sobre el Ncleo del Nivel 1 para proporcionar una visin ms conveniente de los documentos HTML. Document Object Model (DOM) Level 2 agrupa las siguientes especificaciones: Core Specification http://www.w3.org/TR/DOM-Level-2-Core/ Views Specification http://www.w3.org/TR/DOM-Level-2-Views/ Events Specification http://www.w3.org/TR/DOM-Level-2-Events/ Style Specification http://www.w3.org/TR/DOM-Level-2-Style/ Traversal and Range Specification http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ HTML Specification http://www.w3.org/TR/DOM-Level-2-HTML/ Estas Recomendaciones definen el Document Object Model Nivel 2 que se construye sobre el Document Object Model Nivel, pero aadiendo un conjunto de interfaces especializadas para crear y manipular la estructura y el contenido del documento. Document Object Model (DOM) Level 3 agrupa las siguientes especificaciones:
224

JAVASCRIPT

Core Specification. http://www.w3.org/TR/DOM-Level-3-Core/ Validation Specification. http://www.w3.org/TR/DOM-Level-3-Val/ El Document Object Model Core Level 3 se construye sobre el Document Object Model Level 2, completa el mapeado entre DOM y el conjunto de informacin XML [XML Information Set: http://www.w3.org/TR/xml-infoset/] , incluyendo soporte para XML Base [http://www.w3.org/TR/xmlbase/], aade la posibilidad de adjuntar informacin del usuario a los nodos DOM, ofreciendo mecanismos para resolver los prefijos de los espacios de nombre o para manipular atributos ID para tipificar la informacin, etc. Otros informes tcnicos de inters elaborados por el W3C en relacin a DOM son: Document Object Model FAQ. http://www.w3.org/DOM/faq.html What does your user agent claim to support? http://www.w3.org/2003/02/06-domsupport.html (trad. al castellano: GUTIRREZ FERRERAS, Fernando.Qu afirma soportar su Agente de Usuario? http://ferguweb.tx.com.ru/w3/06-dom-support.html)

20.10.10.2.

SAX

El Simple API for XML (SAX) es una interfaz simple para aplicaciones XML. Fcil e intuitiva, muchos programadores de Java la utilizan, ya que se usa especialmente en situaciones en los que los archivos XML ya estn en una forma que es estructuralmente similar a la que deseamos obtener. Por lo general, se usa SAX cuando la informacin almacenada en los documentos XML, es decir, los datos, han sido generados por mquina o son legible por mquina. En este caso, SAX es la forma ms directa de API para que los programas tengan acceso a esa informacin. Los datos generados y legibles por mquina incluyen algunos elementos como los siguientes: Propiedades de objetos Java almacenados en formato XML Consultas (queries) formuladas usando alguna clase de texto basada en lenguajes de interrogacin (SQL, XQL, OQL, etc.) El conjunto resultante se genera basndose en conjunto de resultados que se generan basndose en consultas (queries) (ste debera incluir datos en tablas de bases de datos relacionales codificadas en XML). As, los datos generados por la mquina son informacin que normalmente tenemos creada en estructuras de datos y clases para Java. Un ejemplo simple de este tipo, puede ser una libreta de direcciones. La libreta en un archivo XML contiene puramente datos que pueden ser codificados como texto usando XML, no se trata, pues de algo similar a un documento creado con un procesador de textos, sino a datos en s mismos. Cuanto los datos son de este tipo, lo corriente es crear una estructura de datos y clases, es decir, un modelo de objetos (object models) para poder ordenar, manipular y almacenar estos datos. SAX permite crear rpidamente una herramienta u operador de clase que puede crear instancias de los modelos de objetos basados en el almacenamiento de datos de los documentos. Por ejemplo, un operador de documentos SAX que lee un documento XML que contiene una Libreta de direcciones y crea una clase Libreta de direcciones que puede usarse para acceder a esta informacin. El documento XML Libreta de direcciones contiene elementos Persona, los cuales contienen, por ejemplo, los elementos nombre y correo electrnico. El modelo de objeto Libreta de direcciones contendra las siguientes clases: Clases Libreta de Direcciones, que es un contenedor para objetos Persona.
225

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Clase Persona, que es un contenedor para la cadena de objetos nombre y correo electrnico. As el operador del documento Libreta de direcciones SAX, es el responsable de colocar los elementos persona dentro de los objetos Persona, y almacena todo en un objeto: Libreta de Direcciones. Este documento coloca los elementos nombre y correo electrnico dentro de una cadena de objetos.

20.10.10.3.

Comparacin entre SAX y DOM

Un analizador (parser) SAX es una herramienta ms verstil, ms veloz y menos potente que un analizador (parser) DOM. SAX requiere una mayor programacin, pero puede ser muy til si lo que interesa es rescatar un fragmento de un documento o buscar slo un elemento en particular. En contraste, un DOM es menos verstil, ms lento, pero una vez usado no hay que desarrollar nada ms. Con DOM se obtiene el rbol ya construido y listo para poder funcionar. Los parsers DOM y SAX trabajan de diferente manera. SAX necesita menos cdigo y menos memoria, aunque tiene menos capacidad que DOM. El funcionamiento es el siguiente: primero se comienza a leer el documento, luego se detectan los eventos de parsing (como por ejemplo comienzos o finales de un elemento), la aplicacin procesa esa parte leda y, por ltimo, se reutiliza la memoria y se vuelve a leer hasta un nuevo evento. As pues, el parser SAX procesa el documento XML analizando la corriente de entrada XML, pasando los eventos SAX a un mtodo para operar con una programacin definida. Un parser DOM, por el contrario, opera con la corriente completa de entrada XML, es decir, lee todo el documento completo y devuelve un Document Object. Document, esto es, construye un rbol en memoria que refleja toda la estructura del documento. La aplicacin recorre el rbol realizando su procesamiento ya que el documento devuelto por el parser DOM tiene un API que permite manipular el rbol (virtual) de Node objects. ste representa la estructura de la entrada XML. La principal diferencia entre DOM y SAX es que mientras el primero tiene acceso al documento completo, esto es, que todos los elementos y atributos estn disponibles a la vez, en SAX slo est disponible el elemento actual.

20.10.10.4.

Cundo usar DOM y cundo usar SAX

Si los documentos XML contienen documentos de datos almacenados en un formato XML, entonces lo natural es usar DOM. Si por ejemplo, se est creando alguna clase de sistema de gestin de la informacin y se tiene un gran nmero de documentos de datos de diferentes tipo (como archivos de Word o Excel) y esos documentos pueden organizarse e indexarse desde toda clase de documentos fuente, DOM permitir acceder a los programas que almacenan la informacin en esos documentos. En DOM, se pueden generar consultas (queries) usando XPAth. Con este lenguaje, se pueden expresar cosas tales como: dame todos los nodos que se llaman x y que tienen un nodo hijo llamado y con el conjunto de atributos z para un valor cierto. Sin embargo, si se est tratando principalmente con estructuras de datos, DOM no es la mejor eleccin. En ese caso es mejor usar SAX.

20.10.11.
226

Actividades

JAVASCRIPT

Responde a las siguientes preguntas: Describe XML con tus propias palabras Qu es XHTML respecto a XML? Para que sirven las XSLT? Cmo se pueden enlazar dos archivos XML? Cmo se puede localizar un recurso dentro de un fichero XML? Si un fichero XML est cargado en memoria, Que tipo de parser utilizaras?

20.10.12.

Referencias

XML: http://es.wikipedia.org/wiki/Extensible_Markup_Language XHTML: http://es.wikipedia.org/wiki/XHTML DTD: http://es.wikipedia.org/wiki/Definici%C3%B3n_de_tipo_de_documento XML Schema: http://es.wikipedia.org/wiki/XML_Schema XSL y XSLT: http://geneura.ugr.es/~jmerelo/XSLT/ Xlink: http://geneura.ugr.es/~victor/cursillos/xml/XLink/ W3c: http://www.w3c.es/divulgacion/guiasbreves/tecnologiasxml Guia sax y dom: http://www.hipertexto.info/documentos/dom.htm

227

JAVASCRIPT EN LOS DISTINTOS NAVEGADORES

Javascript en los distintos navegadores


Desgraciadamente, la implementacin de Javascript en los diferentes navegadores no es igual, y nos podemos encontrar con scripts que no funcionen correctamente en todos los navegadores (incluso que solo lleguen a funcionar en uno). En http://www.quirksmode.org/dom/w3c_html.html tenemos un listado de propiedades y mtodos de javascript y sus compatibilidades en los diferentes navegadores. La gente de ImpressiveWeb hizo un listado con 7 diferencias entre los 2 navegadores ms conocidos: Internet Explorer y Firefox que deberamos tener en cuenta a la hora de hacer nuestros scripts.

21.1. La propiedad float de CSS


Generalmente cuando accedemos a una propiedad relacionada al estilo de un elemento solemos usar element.style.propiedad, pero para la propiedad float usar el sistema element.style.float no nos va a ser posible.
// IE document.getElementById("elem").style.styleFloat = "left"; // right // FF document.getElementById("elem").style.cssFloat = "left"; // right

229

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

21.2. Estilos computados de un elemento


Si queremos acceder a los estilos procesados ya por el navegador nos encontramos con una diferencia significante en el sintaxis para ambos navegadores.
// IE var myObject = document.getElementById("header"); var myStyle = myObject.currentStyle.backgroundColor; // FF var myObject = document.getElementById("header"); var myComputedStyle = document.defaultView.getComputedStyle(myObject, null); var myStyle = myComputedStyle.backgroundColor; // MIX var myObject = document.getElementById("header"); var myStyle = myObject.currentStyle ? myObject.currentStyle.backgroundColor : document.defaultView.getComputedStyle(myObject, null).backgroundColor;

21.3. Accediendo al class de un elemento


Debido a la especificacin de Internet Explorer, cuando queremos acceder al class de un elemento usando getAttribute() debemos modificar el nombre que solicitamos.
// IE var myObject = document.getElementById("header"); var myAttribute = myObject.getAttribute("className"); // FF var myObject = document.getElementById("header"); var myAttribute = myObject.getAttribute("class");

21.4. Accediendo al atributo for de las etiquetas <label />


Exactamente lo mismo ocurre con el atributo for de las etiquetas <label /> que en Internet Explorer para solicitar esta informacin, debemos reemplazar el nombre que pedimos.
// IE var myObject = document.getElementById("myLabel"); var myAttribute = myObject.getAttribute("htmlFor"); // FF var myObject = document.getElementById("myLabel"); var myAttribute = myObject.getAttribute("for");

21.5. Obtener la posicin del puntero del ratn

230

JAVASCRIPT EN LOS DISTINTOS NAVEGADORES

Otra diferencia y que mucho nos hace agrandar nuestro cdigo es la localizacin del puntero.
// IE var myCursorPosition = [0, 0]; myCursorPosition[0] = event.clientX; myCursorPosition[1] = event.clientY; // FF var myCursorPosition = [0, 0]; myCursorPosition[0] = event.page; myCursorPosition[1] = event.pageY; // MIX var myCursorPosition = [0, 0]; myCursorPosition[0] = event.clientX || event.page; myCursorPosition[1] = event.clientY ||event.pageY;

21.6. Obtener el tamao del navegador o del rea visible


Al obtener el tamao de la pantalla y del area visible nos encontramos con el mismo problema. Parece que no se ponen de acuerdo en que nombre ponerle a las propiedades comunes.
// IE var myBrowserSize = [0, 0]; myBrowserSize[0] = document.documentElement.clientWidth; myBrowserSize[1] = document.documentElement.clientHeight; // FF var myBrowserSize = [0, 0]; myBrowserSize[0] = window.innerWidth; myBrowserSize[1] = window.innerHeight;

Aqu hay que hacer una pequea aclaracin: window.innerWidth/innerHeight y document.documentElement.clientWidth/Height representan exactamente lo mismo: no

window.innerWidth/innerHeight estn implementadas en Firefox, Opera y Safari (pero no en IE) y nos proporcionan las dimensiones del viewport incluyendo el tamao de las barras de scroll si las hubiese. document.documentElement.clientWidth/Height estn implementadas en todos y contienen las dimensiones del viewport (sin incluir barras de scroll).

21.7. Transparencias
Si las transparencias en CSS ya eran un desastre donde nos veamos obligados a usar hacks dependiendo del navegador, en javascript nos encontramos el mismo problema.
// CSS #myElement { filter: alpha(opacity=50); opacity: 0.5; // FF }

// IE

// IE var myObject = document.getElementById("myElement");

231

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

myObject.style.filter = "alpha(opacity=80)"; // FF var myObject = document.getElementById("myElement"); myObject.style.opacity = "0.5";

232

MANEJO DEL DOM

Manejo del DOM


Javascript permite acceder a cada uno de los elementos de una pgina utilizando tan slo algunos mtodos y propiedades. La forma bsica de acceder a un elemento es mediante el atributo id, gracias al mtodo getElementById.
<p> <a id="contacto" href="contactos.html">Contctenos</a> </p>

Puede usarse el atributo id del elemento a para acceder al mismo:


var elementoContacto = document.getElementById("contacto");

Ahora el valor de la variable elementoContacto est referida al elemento [a] y cualquier operacin sobre la misma afectar el hiperenlace. El mtodo getElementById es adecuado para operar sobre un elemento en especfico, sin embargo, en ocasiones se necesita trabajar sobre un grupo de elementos por lo que en este caso puede utilizarse el mtodo getElementsByTagName. Este retorna todos los elementos de un mismo tipo. Asumiendo la siguiente lista desordenada:
<ul> <li><a <li><a <li><a <li><a </ul> href="editorial.html">Editorial</a></li> href="semblanza.html">Autores</a></li> href="noticias.html">Noticias</a></li> href="contactos.html">Contctenos</a></li>

233

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Puede obtenerse todos los hipervnculos de la siguiente manera:


var hipervinculos= document.getElementsByTagName("a");

El valor de la variable hipervinculos es una coleccin de elementos [a]. Las colecciones son arreglos pudindose acceder a cada elemento a travs de la ya conocida notacin con corchetes. Los elementos devueltos por getElementsByTagName sern ordenado segn el orden que aparezcan en el cdigo fuente. Por tanto para el caso anterior quedara as: hipervinculos[0] el elemento [a] para Editorial hipervinculos[1] el elemento [a] para Autores hipervinculos[2] el elemento [a] para Noticias hipervinculos[3] el elemento [a] para Contctenos Otra maneras de acceder a un elemento usando su id es document.all[id] la cual fue introducida en Internet Explorer 4 y document.layers[id] introducida por Netscape 5 por que el W3C todava no haba estandarizado la manera de acceder a los elementos mediante su id. Sin embargo, no se recomienda su uso porque al estar fuera de los estndares actuales hay navegadores que no soportan estos mtodos. Por otro lado existen varios elementos en un documento HTML que pueden ser accedidos de otras maneras. El elemento body de un documento puede accederse a travs de la forma document.body, mientras que el conjunto de todos los formularios en un documento puede encontrase en document.forms, as mismo el conjunto de todas las imgenes sera mediante document.images. Actualmente la mayora de los navegadores soportan esto mtodos an as es recomendable el uso del mtodo getElementsByTagName, vase el siguiente ejemplo para acceder al elemento body:
var body = document.getElementsByTagName("body")[0];

22.1. Creando elementos y textos


La creacin de nodos es posible mediante el uso de dos mtodos disponibles en el objeto document. Dichos mtodos son: createElement(Tipo cadena): Crea un nuevo elemento del tipo especificado y devuelve un referencia a dicho elemento. createTextNode(Cadena de texto): Crea un nuevo nodo de texto con el contenido especificado en la cadena de texto. El siguiente ejemplo muestra cmo se crea un nuevo elemento de prrafo vaco:
var nuevoEnlace = document.createElement("a");

La variable nuevoEnlace ahora referencia un nuevo enlace listo para ser insertado en el documento. El texto que va dentro del elemento [a] es un nodo de texto hijo, por lo que debe ser creado por separado.
var nodoTexto = document.createTextNode("Semblanza");

234

MANEJO DEL DOM

Luego si desea modificar el nodo de texto ya existente, puede utilizarse la propiedad nodeValue, esta permite coger y poner el nodo de texto:
var textoViejo = nodoTexto.nodeValue; nodoTexto.nodeValue = "Novedades";

El valor de la variable textoViejo es ahora Semblanza y el nuevo texto Novedades. Se puede insertar un elemento o texto (nodo) como ltimo hijo de un nodo ya existente usando el mtodo appendChild. Este mtodo coloca el nuevo nodo despus de todos los hijos del nodo.
NuevoEnlace.appendChild(nodoTexto);

Ahora todo lo que se necesita es insertar el enlace en el cuerpo del documento. Para hacer esto, se necesita una referencia al elemento body del documento, teniendo como gua los estndares siguientes:
var cuerpoRef = document.getElementsByTagName("body")[0]; cuerpoRef.appendChild(nuevoEnlace);

Otra manera sera utilizando el mtodo getElementById. Para ello se asume que la etiqueta <body> tiene asignado un valor para el atributo id.
<body id=cuerpo> <script> var cuerpoRef = document.getElementById("cuerpo"); cuerpoRef.appendChild(nuevoEnlace); </script>

Existen bsicamente tres maneras mediante las cuales un nuevo elemento o nodo de texto puede ser insertado en una pgina Web. Todo ello depende del punto en el cual se desee insertar el nuevo nodo: como ltimo hijo de un elemento, antes de otro nodo o reemplazo para un nodo. El caso de apertura de un nuevo hijo ya fue visto en el ejemplo anterior, luego para insertar el nodo antes de otro nodo se realiza utilizando el mtodo insertBefore de su elemento padre, mientras que el reemplazo de nodo se utiliza el mtodo replaceChild de su elemento padre. Al usar insertBefore, se necesita tener referencias al nodo que va ser insertado y donde va a ser insertado, considrese el siguiente cdigo HTML:
<p id="mwEnlaces"> <a id="editor" href="editorial.html">Editorial</a> </p>

Luego el nuevo enlace ser insertado antes de enlace ya existente llamando el mtodo insertBefore desde el nodo padre (prrafo):
var anclaTexto = document.createTextNode("Actualidad"); var nuevoAncla = document.createElement("a"); nuevoAncla.appendChild(anclaTexto); var anclaExistente = document.getElementById("editor"); var padre = anclaExistente.parentNode; var nuevoHijo = padre.insertBefore(nuevoAncla, anclaExistente);

Si se hiciera una traduccin del DOM hacia HTML despus de esta operacin el resultado sera el siguiente:
<p id="mwEnlaces"> <a> Actualidad </a><a id="editor" href="editorial.html">Editorial</a> </p>

235

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

En el caso de reemplazar el enlace usando replaceChild:


var nuevoHijo = padre.replaceChild(nuevoAncla, anclaExistente);

El DOM lucir as:


<p id="mwEnlaces"> <a> Actualidad </a> </p>

22.2. Usando innerHTML


En aplicaciones complejas donde es necesario crear varios elementos a la vez, el cdigo JavaScript generado puede ser extenso recurrindose a la propiedad innerHTML. Dicha propiedad fue introducida por Microsoft permitiendo leer y escribir el contenido HTML de un elemento. Por ejemplo, puede crearse fcilmente una tabla con mltiples celdas e insertarla luego en la pgina con innerHTML:
var tabla = '<table border="0">'; tabla += '<tr><td>Celda 1</td><td>Celda 2</td><td> Celda 3</td></tr>'; tabla += '</table>'; document.getElementById("datos").innerHTML = tabla;

22.3. Eliminando un elemento o nodo de texto


Se pueden eliminar nodos existentes y nuevos. El mtodo removeChild permite eliminar nodos hijos a cualquier nodo con tan slo pasarle las referencias del nodo hijo [a] eliminar y su correspondiente padre. Para mejor compresin volvamos al ejemplo anterior:
<p id="mwEnlaces"> <a id="editor" href="editorial.html">Editorial</a> </p>

El mtodo removeChild ser usado para eliminar el hipervnculo del elemento padre prrafo:
var ancla = document.getElementById("editor"); var padre = ancla.parentNode; var hijoRemovido = padre.removeChild(ancla);

La variable hijoRemovido todava hace referencia al elemento, de manera que fue removido pero no destruido, no pudindose localizar en ninguna parte del DOM. Este se encuentra disponible en memoria como si fuera creado usando el mtodo createElement. Esto permite posicionarlo en cualquier otra parte de la pgina. Lectura y escritura de los atributos de un elemento Las partes ms frecuentemente usadas de un elemento HTML son sus atributos, tales como: id, class, href., title, estilos CSS, entre muchas otras piezas de informacin que pueden se incluidas en una etiqueta HTML. Los atributos de una etiqueta son traducidos por el navegador en propiedades de un objeto. Dos mtodos existen para leer y escribir los atributos de un elemento, getAttribute permite leer el valor de un atributo mientras que setAttribute permite su escritura. En ocasiones se hace necesario ver las propiedades y mtodos de un determinado elemento, esto puede realizarse mediante la siguiente funcin utilitaria:

236

MANEJO DEL DOM

function inspector(el) { var str =; for (var i in el){ str+=I + : + el.getAttribute(i) + \n; } alert(str); }

Para usar la funcin inspector() tan slo debe pasarle la referencia al elemento, continuando con el ejemplo anterior resulta:
var ancla = document.getElementById("editor"); inspector(ancla);

Para modificar el atributo title del hipervnculo, elemento referenciado por la variable ancla, se usar el setAttribute, pasndole el nombre del atributo y el valor:
var ancla = document.getElementById("editor"); ancla.setAttribute("title", "Artculos de programacin"); var nuevoTitulo = ancla.getAttribute("title"); //El valor de la variable nuevoTitulo es ahora Artculos de programacin.

22.4. Manipulando los estilos de los elementos


Como se ha visto, los atributos que le son asignados a las etiquetas HTML estn disponibles como propiedades de sus correspondientes nodos en el DOM. Las propiedades de estilo pueden ser aplicadas a travs del DOM. Cada atributo CSS posee una propiedad del DOM equivalente, formndose con el mismo nombre del atributo CSS pero sin los guiones y llevando la primera letra de las palabras a maysculas. Vase el siguiente ejemplo para mayor entendimiento donde se utiliza un atributo CSS modelo: algun-atributo-css Tendr como equivalente la siguiente propiedad o mtodo en Javascript: algunAtributoCss Por tanto, para cambiar el atributo CSS font-family de un elemento, podra realizarse de lo siguiente:
ancla.style.fontFamily = 'sans-serif';

Los valores CSS en Javascript sern en su mayora del tipo cadena; por ejemplo: fontsize, pues posee dimensiones tales como px, %. Slo los atributos completamente numricos, tales como z-index sern del tipo entero. En muchos casos es necesario aparecer y desaparecer un determinado elemento, para ellos se utiliza el atributo CSS display, por ejemplo, para desaparecer:
ancla.style.display = 'none';

Luego para volverlo a mostrar se le asigna otro valor:


ancla.style.display = 'inline';

22.5. Actividades

237

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

22.5.1.

Actividad 1

Crea un formulario, con el que se puedan subir ficheros. Con javascript, aade la posibilidad que despus de pulsar un botn (evento onclick), se aada un campo ms para subir ficheros. Ten en cuenta de que los campos de los ficheros debern tener el atributo name diferente, para que se pueda coger despus con PHP.

22.5.2.

Actividad 2

Crea un cronmetro con Javascript, que tenga los botones de Inicio/Pausa (Cuando se inicie, botn pasar a ser pausa y viceversa), y Parada (Vuelta a 0). Deber contemplar milisegundos, segundos, minutos y horas.

238

BIBLIOTECAS JAVASCRIPT BASICAS: JCUERY Y MOOTOOLS

Bibliotecas Javascript bsicas: Jquery y Mootools


Al igual que podemos encontrarnos bibliotecas y frameworks en PHP con los que tenemos mucho cdigo resuelto, en javascript nos pasa lo mismo. Dos de las bibliotecas que ms destacan hoy dia son JQuery (http://jquery.com) y MooTools (http://mootools.net). Pasemos a pegar un breve vistazo sobre JQuery y MooTools.

23.1.1.1.

JQuery

jQuery consiste en un nico fichero JavaScript que contiene las funcionalidades comunes de DOM, eventos, efectos y AJAX. La caracterstica principal de la biblioteca es que permite cambiar el contenido de una pgina web sin necesidad de recargarla, mediante la manipulacin del rbol DOM y peticiones AJAX. Para ello utiliza las funciones $() o jQuery(). A partir de este fichero Javascript, nos podemos encontrar ms bibliotecas que va creando la comunidad del software libre que usen JQuery, como para crear pequeos calendarios, o funcionalidades enteras como para simular por ejemplo el comportamiento de las cajas de iGoogle. Funcin $()

239

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

La forma de interactuar con la pgina es mediante la funcin $() (un alias de jQuery()) que recibe como parmetro una expresin CSS o el nombre de una etiqueta HTML y devuelve todos los nodos (elementos) que concuerden con la expresin.
$("#tablaAlumnos") $(".activo") estilo "activo" //Devolver el elemento con id="tablaAlumnos" //Devolver una matriz de elementos que contenga el

Una vez obtenidos los nodos, se les puede aplicar cualquiera de las funciones que facilita la biblioteca.
// Una vez obtenidos todos los nodos que contenga el estilo "activo" // se les elimina ese estilo (removeClass()) y se les aplica uno nuevo (addClass()) $(".activo").removeClass("activo").addClass("inactivo");

23.1.1.2.

MooTools

A diferencia de JQuery, donde el framework al completo se encuentra en un solo fichero, mootools, se divide en varios ficheros donde se encuentran diferentes funcionalidades. De hecho, al descargar mootools desde su web, es posible descargar slo las partes que tiene pensado utilizar y sus dependencias necesarias: Core: coleccin de funciones de apoyo de las que hace uso el resto de components. Class: es la biblioteca base de MooTools para la instanciacin de objetos Natives: Coleccin de mejoras al objeto nativo JavaScript, aadiendo funcionalidades, compatibilidad y nuevos mtodos que simplifican el cdigo. Element: multitud de mejoras y compatibilidades al objeto HTML Effects: API avanzada para animar Elements Remote: proporciona una interfaz para peticiones XHR, Cookie y herramientas para JSON Window: Proporciona una interfaz, vlida para cualquier navegador, para obtener informacin del cliente, por ejemplo el tamao de la ventana Las funciones $() y $$() Al igual que JQuery en MooTools existe $(), pero su diferencia radica en que en MooTools con $() solo podremos hacer referencia a un elemento con un identificativo en concreto, es decir, ni clases CSS ni elementos HTML. con $$() podremos seleccionar varios elementos a la vez, como por ejemplo todos los elementos a y elementos h1
//Seleccionamos todos los enlaces y h1. var misElementos = $$('a', 'h1');

23.2. Validaciones de formularios con JavaScript.


Ahora que ya hemos visto como acceder a elementos del DOM a mano, veremos como hacer una validacin de formularios gracias a JQuery y MooTools. Pero antes de hacerlo, solo recordar algo importante. JavaScript, puede estar desactivado por el usuario, as que para aumentar nuestra seguridad, deberamos hacer tambien una validacin en nuestro cdigo PHP, para evitar posibles errores. Que adelantaramos entonces poniendo una comprobacin en javascript adems de la que hagamos en
240

BIBLIOTECAS JAVASCRIPT BASICAS: JCUERY Y MOOTOOLS

PHP? Pues por ejemplo que el usuario no tenga que recargar la pgina. Lo que se podra traducir en ahorro de ancho de banda si tuvisemos una cantidad crtica de usuarios y formularios, por poner un ejemplo: Facebook tiene a dia de hoy ms de 300 millones de usuarios poniendo comentarios donde se comprueba continuamente el mximo de caracteres Al hacer una comprobacin previa, nos podramos evitar muchas recargas de la web y por tanto, mucho ancho de banda.

23.2.1.

Validacin con JQuery


el plugin validate

Para este ejemplo usaremos (http://docs.jquery.com/Plugins/Validation#Example)

Primero en el head, incluiremos los ficheros de JQuery necesarios, y pondremos unos estilos bsicos.
<head> <script type="text/javascript" src="jquery-1.2.6.pack.js"></script> <script type="text/javascript" src="jquery.validate.min.js"></script> <script type="text/javascript" src="jquery.metadata.js"></script> <style> form {width:700px;height:520px;display:inline;float:left;margin:20px 0 0 0} label { color: #000; font-size: 1em; line-height: 140%; margin: 10px 0 .2em 90px; display: block; } input.textField { width: 350px; color: #000; font-size: 1.1em; padding: 4px; background: #fff; border: 1px solid #999; margin: 0 0 20px 0; display: inline;margin: 0 0 .2em 90px; } textarea.textArea { width: 500px; height: 150px; color: #000; fontfamily: Tahoma,tahoma,sans-serif,Arial,Tahoma,Verdana;fontsize: 1em; padding: 4px; background: #fff; border: 1px solid #999; margin: 0 0 .2em 90px; overflow: auto; } .error-message, label.error { color: #a10052; margin: 0 0 .5em 90px; display: block; font-size: 1em !important;font-weight:bold; } </style> </head>

Acto seguido, crearemos nuestro formulario de ejemplo (si vas a incluir esto como ejemplo, no olvides poner las etiquietas <body> y </body>)
<form id="frmContact" method="post"> <fieldset style="display:none;"> <input type="hidden" name="_method" value="POST" /> </fieldset> <label for="ContactName">NOMBRE</label> <input name="data[Contact][name]" type="text" class="textField" maxlength="255" value="" id="ContactName" /> <label for="ContactRecipient">CORREO ELECTRNICO</label> <input name="data[Contact][recipient]" type="text" class="textField " value="" id="ContactRecipient" /> <label for="ContactPhone">TELFONO</label> <input name="data[Contact][phone]" type="text" class="textField" maxlength="255" value="" id="ContactPhone" /> <label for="ContactMessage">MENSAJE / CONSULTA</label> <textarea name="data[Contact][message]" cols="5" rows="3" class="textArea" id="ContactMessage" ></textarea> <input type="submit" name="Enviar" value="Enviar" /> </form>

Y finalmente, implementamos nuestra validacin al final del fichero html o enlazndolo (pero en este caso, siempre al final del fichero):
$(document).ready(function(){ $("#frmContact").validate({ event: "blur", rules: {
241

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

'data[Contact][name]': "required", 'data[Contact][recipient]': { required: true, email: true }, 'data[Contact][message]': "required" }, messages: { 'data[Contact][name]': "Por favor ingrese su nombre", 'data[Contact][recipient]': "Ingrese una direccin de email vlida", 'data[Contact][message]': "Por favor, ingrese su mensaje o consulta" }, debug: true, errorElement: "label", errorContainer: $("#errores"), submitHandler: function(form){ $.ajax({ type: "POST", url: "contacto.asp", data: "nombre="+$('#ContactName').val()+"&email="+$('#ContactRecipient').val()+ "&telefono="+$('#ContactPhone').val()+"&comentario="+$('#ContactMessage') .val(), success: function(msg){ if(msg==1){ $("#mensaje").html("El mensaje se ha enviado correctamente"); } } }); } }); });

23.2.2.

Validacin con MooTools

Al igual que en JQuery, enlazaremos temas y bibliotecas necesarias. En este caso usaremos el plugin FormCheck http://mootools.floor.ch/en/demos/formcheck/
<script type="text/javascript" src="/js/mootools/core.js"></script> <script type="text/javascript" src="/js/mootools/more.js"></script> <script type="text/javascript" src="/js/formcheck/lang/es.js"> </script> <script type="text/javascript" src="/js/formcheck/formcheck.js"> </script> <link rel="stylesheet" href="/js/formcheck/theme/classic/formcheck.css" type="text/css" media="screen" />

este sera el cdigo que usaramos para activar la validacin en nuestro formulario llamado myform. Notar que se puede poner antes de <body> ya que usa el evento domready, es decir, cuando se han terminado de cargar los elementos del DOM
<script type="text/javascript"> window.addEvent('domready', function(){ new FormCheck('myform'); }); </script>

y despus usaramos construiramos nuestro formulario. Veamos algunos ejemplos de inputs


<form name="myform" method="post" action="mi_url"> URL <input class="validate['required','url']" /><BR /> TELEFONO <input class="validate['required','phone']" /><BR /> Contrasea <input type="password" class="validate['required']" name="password" id="password" /><BR /> Confirma contrasea <input type="text"

242

BIBLIOTECAS JAVASCRIPT BASICAS: JCUERY Y MOOTOOLS

class="validate['confirm[password]']" name="confirm" /> <input type="submit" value="Enviar" name="submit"> </form>

23.3. Manejo dinmico de elementos HTML


23.3.1.1. JQuery

En http://api.jquery.com/category/manipulation/ tenemos todo el listado de funciones para manipular el DOM. Vamos a ver un pequeo listado de las ms habituales. Crear nuevo elementos html utilizar $() (funcin factora). Veremos como usarla justo en el siguiente ejemplo. Insertar un nuevo/s elemento/s, dentro de cada elemento/s correspondiente/s: .append() .appendTo() .prepend() .prependTo() La diferencia entre metodo y metodoTo, radica en que en el primero, el selector precede al contenido insertado, y en el segundo es al revs, el contenido precede al selector. Veamoslo mejor con un ejemplo.
<h2>Saludos</h2> <div class="container"> <div class="inner">Hola</div> <div class="inner">Adios</div> </div> <script type="text/javascript"> $('.inner').append('<p>Test</p>'); //como se ve, primero aparece el selector, y se le dice cual es el contenido que va a ir dentro. $('<p>Test</p>').appendTo('.inner'); //En este otro caso, primero se crea el contenido con la funcin factoria $() y //se le dice que ese contenido, ir dentro del selector </script>

Y el cdigo resultante sera en el caso de append:


<h2>Saludos</h2> <div class="container"> <div class="inner"> Hola <p>Test</p> </div> <div class="inner"> Adios <p>Test</p> </div> </div>

En el caso de prepend, el bloque p con la palabra test, iran antes de de Hola y Adios. Insertar nuevo/s elemento/s adyacentes al elemento/s correspondiente/s:

243

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

.after() .insertAfter() .before() .insertBefore() Exactamente el mismo caso:


<h2>Saludos</h2> <div class="container"> <div class="inner">Hola</div> <div class="inner">Adios</div> </div> <script type="text/javascript"> $('.inner').after('<p>Test</p>'); //como se ve, primero aparece el selector, y se le dice cual es el contenido que va a ir dentro. $('<p>Test</p>').insertAfter('.inner'); //En este otro caso, primero se crea el contenido con la funcin factoria $() y //se le dice que ese contenido, ir dentro del selector </script> <!-- cdigo resultante con after/insertAfter --> <div class="container"> <h2>Saludos</h2> <div class="inner">Hola</div> <p>Test</p> <div class="inner">Adios</div> <p>Test</p> </div> <!-- si ussemos before insertBefore, se encontraran antes de los divs con la clase inner.

Con after/before/insertAfter/insertBefore podemos hacer otras cosas como esto:


$('h2').insertAfter($('.container'));

Con lo cual moveramos el titulo h2 de la siguiente forma:


<div class="container"> <div class="inner">Hola</div> <div class="inner">Adios</div> </div> <h2>Saludos</h2>

Reemplazar cada elemento/s correspondiente/s con un nuevo/s elemento/s: .html() Con .html podremos coger el contenido de un elemento si lo usamos como getter o incluirlo si lo usamos como setter. Veamos un ejemplo: Imaginemos el siguiente div:
<div class="demo-container"><p>hola</p></div> var myhtml = $('div.demo-container').html(); //aqui estariamos usandolo como "getter". la variable myhtml tendria el valor <p>hola</p> //en este otro caso $('div.demo-container').html("<p>adios</p>); //estamos usandolo como "setter" y cambiando el contenido del div a <p>adios</p> borrando el contenido <p>hola</p>

244

BIBLIOTECAS JAVASCRIPT BASICAS: JCUERY Y MOOTOOLS

Eliminar elemento/s para cada correspondiente/s elemento/s: .empty() Eliminar para cada correspondiente/s elemento/s y sus descendientes, pero sin borrarlos del DOM: .remove() La diferencia bsica entre empty y remove, es que empty elimina el contenido del elemento del dom, mientras que remove elimina el elemento en s:
<h2>Saludos</h2> <div class="container"> <div class="hola">Hola</div> <div class="adios">Adios</div> </div> <script type="text/javascript"> $('.hola').empty(); </script> <!-- codigo resultante con empty --> <h2>Saludos</h2> <div class="container"> <div class="hola"></div> <!--notese que falta el contenido--> <div class="adios">Adios</div> </div> <script type="text/javascript"> $('.hola').remove(); </script> <!-- codigo resultante con remove --> <h2>Saludos</h2> <div class="container"> <div class="adios">Adios</div><!-- Ahora falta el elemento por completo--> </div>

23.3.1.2.
Creando un Elemento

MooTools

var miElemento = new Element(tipoElemento, {opciones});

Donde tipo elemento le tenemos que indicar que elemento del dom queremos crear, y en opciones pondremos los parmetros. Veamoslo con un ancla (<a>)
var miEnlace = new Element('a', { 'class': 'mi-clase', 'id': 'mi-id', 'href': 'http://sitio.com' });

injectBefore / injectAfter / injectInside: Con esto conseguiremos insertar antes, despus o dentro de otro elemento respectivamente. Por ejemplo:
<div id="otroElemento"></div>

Y usamos
var elemento = new Element('div', {'id':'MiElemento'}); elemento.injectBefore('otroElemento');

Nos quedara:

245

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

<div id="MiElemento"></div> <!-- se ha insertado justo antes (before) del otro elemento --> <div id="otroElemento"></div>

Si hiciramos lo mismo con After, se insertara inmediatamente despus, y con Inside, dentro. Si quisiramos introducir texto dentro de un elemento, usaramos appendText(texto). Recuerda que si quieres insertar html hay que usar injectInside, ya que appendText traducira los caracteres especiales a cdigo html.
<div id="elemento"></div> <script type="text/javascript"> $('elemento').appendText('Mi textoooooo'); </script> <!-- codigo resultante --> <div id="elemento">Mi textoooooo</div>

Para borrar un elemento, en MooTools tambien existe el metodo .remove:


<div id="miElemento"> <div id="aborrar"></div> </div> <script type="text/javascript"> $('aborrar').remove() </script> <!-- codigo resultante --> <div id="miElemento"> </div>

En http://www.jourmoly.com.ar/ hay una buena recopilacin con ms mtodos en castellano de como modificar el DOM con MooTools, aunque si quieres una documentacin mas amplia, es mejor ir a la propia documentacin de Mootools (en este caso, para el DOM) http://mootools.net/docs/core/Element/Element

23.4. Actividades
23.4.1.1. Actividad 1

Busca ms ejemplos de JQuery y MooTools de funcionalidades parecidas, y compara como lo hacen cada uno.

23.4.1.2.

Actividad 2

Despus de tu experiencia con JQuery y Mootools Con cual te quedaras?. Participa en un debate con el resto de tus compaeros y compaeras, defendiendo tu eleccin.

246

INTRODUCCION A AJAX

Introduccin a Ajax
Ajax, acrnimo de Asynchronous JavaScript And XML (JavaScript asncrono y XML), es una tcnica de desarrollo web para crear aplicaciones interactivas o RIA (Rich Internet Applications). Estas aplicaciones se ejecutan en el cliente, es decir, en el navegador web de los usuarios mientras se mantiene la comunicacin asncrona con el servidor en segundo plano. De esta forma es posible realizar cambios sobre las pginas sin necesidad de recargarlas, lo que significa aumentar la interactividad, velocidad y usabilidad en las aplicaciones. Ajax es una tecnologa asncrona, en el sentido de que los datos adicionales se requieren al servidor y se cargan en segundo plano sin interferir con la visualizacin ni el comportamiento de la pgina. JavaScript es el lenguaje interpretado (scripting language) en el que normalmente se efectan las funciones de llamada de Ajax mientras que el acceso a los datos se realiza mediante XMLHttpRequest, objeto disponible en los navegadores actuales. En cualquier caso, no es necesario que el contenido asncrono est formateado en XML. Ajax es una tcnica vlida para mltiples plataformas y utilizable en muchos sistemas operativos y navegadores dado que est basado en estndares abiertos como JavaScript y Document Object Model (DOM).

24.1. Tecnologas incluidas en Ajax


Ajax es una combinacin de cuatro tecnologas ya existentes:

247

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

XHTML o HTML y CSS para el diseo que acompaa a la informacin. DOM accedido con un lenguaje de scripting por parte del usuario, especialmente implementaciones ECMAScript como JavaScript y JScript, para mostrar e interactuar dinmicamente con la informacin presentada. El objeto XMLHttpRequest para intercambiar datos de forma asncrona con el servidor web. En algunos frameworks y en algunas situaciones concretas, se usa un objeto iframe en lugar del XMLHttpRequest para realizar dichos intercambios. XML es el formato usado generalmente para la transferencia de datos solicitados al servidor, aunque cualquier formato puede funcionar, incluyendo HTML preformateado, texto plano, JSON, YAML. Como el DHTML, o LAMP, Ajax no constituye una tecnologa en s, sino que es un trmino que engloba a un grupo de stas que trabajan conjuntamente.

24.2. Problemas e Inconvenientes


Las pginas con AJAX son mas difciles de desarrollar que las pginas estticas. Las pginas creadas dinmicamente mediante peticiones sucesivas AJAX, no son registradas de forma automtica en el historial del navegador, as que haciendo clic en el botn de volver del navegador, el usuario no sera devuelto a un estado anterior de la pgina, en cambio puede volver a la ltima pgina que visit. Soluciones incluyen el uso de IFrames invisible para desencadenar cambios en el historial del navegador y el cambio de la porcin de anclaje de la direccin (despus de un #). Los motores de bsquedas no entienden JavaScript. La informacin en la pgina dinmica no se almacena en los registros del buscador. Hay problemas usando Ajax entre nombres de dominios. Eso es una funcin de seguridad. El sitio con Ajax usa ms recursos en el servidor. Es posible que pginas con Ajax no puedan funcionar en telfonos mviles, PDA u otros aparatos. Ajax no es compatible con todos los software para ciegos u otras discapacidades.

24.3. Mtodos HTTP


Un mensaje http consiste en una peticin de un cliente al servidor y en la respuesta del servidor al cliente.

24.3.1.1.

Mtodo OPTIONS

Este mtodo representa un peticin de informacin sobre las opciones de comunicacin disponibles en la cadena peticin-respuesta identificada por la URI de la peticin.

248

INTRODUCCION A AJAX

24.3.1.2.

Mtodo GET

El mtodo GET requiere la devolucin de informacin al cliente identificada por la URI.

24.3.1.3.

Mtodo HEAD

El mtodo HEAD es igual que el mtodo GET, salvo que el servidor no tiene que devolver el contenido, slo las cabeceras.

24.3.1.4.

Mtodo POST

El mtodo POST se usa para hacer peticiones en las que el servidor destino acepta el contenido de la peticin como un nuevo subordinado del recurso pedido.

24.3.1.5.

Mtodo PUT

El mtodo PUT permite guardar el contenido de la peticin en el servidor bajo la URI de la peticin.

24.3.1.6.

Mtodo DELETE

Este mtodo se usa para que el servidor borre el recurso indicado por la URI de la peticin.

24.3.1.7.

Mtodo TRACE

Este mtodo se usa para saber si existe el receptor del mensaje y usar la informacin para hacer un diagnstico.

24.4. Objeto XMLHTTPRequest


*XMLHttpRequest*, es una API empleada para realizar peticiones HTTP y HTTPS a servidores Web. Para los datos transferidos se usa cualquier codificacin basada en texto, incluyendo: texto plano, XML, JSON, HTML y codificaciones particulares especficas. La interfaz se presenta como una clase de la que una aplicacin cliente puede generar tantas instancias como necesite para manejar el dilogo con el servidor. El uso ms popular, si bien no el nico, de esta interfaz es proporcionar contenido dinmico y actualizaciones asncronas en pginas WEB mediante tecnologas construidas sobre ella como por ejemplo AJAX.
Historia

La primera versin de la interfaz XMLHttpRequest fue desarrollada por Microsoft que la introdujo en la versin 5.0 de Internet Explorer. Esta primera versin se public utilizando un objeto ActiveX, lo que significa que puede ser utilizada desde cualquier entorno de desarrollo de software con soporte para esta tecnologa, es decir, la prctica totalidad de plataformas generalistas de desarrollo para Microsoft Windows. Microsoft ha seguido manteniendo y actualizando esta tecnologa incluyendo la funcionalidad dentro del *Microsoft XML Parser (MSXML)* en sus sucesivas versiones. A partir de la versin 7 de Internet Explorer la interfaz se ofrece de manera integrada. Al ser integrada, el acceso a
249

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

la interfaz se realiza enteramente con objetos (JScript o VBScript) proporcionados por el navegador y no mediante bibliotecas externas. El proyecto Mozilla incorpor la primera implementacin integrada de XMLHttpRequest en la versin 1.0 de la Suite Mozilla en 2002. Esta implementacin sera seguida por Apple a partir de Safari 1.2, Konqueror, Opera Software a partir del Opera 8.0 e iCab desde la versin 3.0b352. El W3C (World Wide Web Consortium) present el 27 de septiembre de 2006 el primer borrador de una especificacin estndar de la interfaz. La versin actual de 15 de abril de 2008, etiquetada como borrador final, es el resultado de varias revisiones. Mientras no se alcance una versin definitiva, los desarrolladores de aplicaciones WEB debern tener en cuenta las diferencias entre implementaciones o bien utilizar paquetes o frameworks que realicen esta funcin.
Evolucin de la interfaz

El 25 de febrero de 2008 se public la primera versin de la especificacin *XMLHttpRequest Level 2*. Esta nueva especificacin, que se inicia antes de haber publicado la versin definitiva de la interfaz, pretende aadir nuevas funciones como: peticiones entre dominios (*cross-site*), eventos de progreso y manejo de flujos de bytes (*streams*) tanto para el envo como para la recepcin.
Implementacin y uso de la interfaz

La interfaz se presenta encapsulada en una clase. Para utilizarlo, la aplicacin cliente debe crear una nueva instancia mediante el constructor adecuado. Es posible realizar peticiones sncronas y asncronas al servidor; en una llamada asncrona el flujo de proceso no se detiene a esperar la respuesta como se hara en una llamada sncrona, si no que se define una funcin que se ejecutar cuando se complete la peticin: un manejador de evento. XMLHttpRequest es una interfaz para realizar llamadas mediante HTTP, por lo que es recomendable un buen conocimiento de este protocolo. Es importante el manejo correcto de la cache en el servidor HTTP, en los proxy cache intermedios y en el navegador WEB. Otro elemento importante es el manejo de juegos de caracteres, la codificacin y decodificacin de texto y su identificacin mediante cabeceras HTTP y MIME. El estndar XMLHttpRequest recomienda UTF-8 para la codificacin de cadenas de texto. La codificacin particular de los datos transmitidos se determina segn el siguiente algoritmo, utilizando la primera opcin que corresponda. Si los datos transmitidos son XML o HTML, y as se identifica mediante la correspondiente cabecera Content-Type de HTTP, la codificacin se detectar basndose en las reglas estndar de XML o HTML segn corresponda. Si la cabecera HTTP especifica un tipo MIME mediante Content-Type e identifica un charset se utiliza dicho charset. Si los datos enviados especifican un BOM (byte order mark) vlido, se utilizar la variante UTF determinada por dicho BOM. (Es decir UTF-8, UTF-16 o UTF-32). Utilizar UTF-8. Es importante tener esto en cuenta en entornos dnde se mezclen varias codificaciones, por ejemplo, pueden producirse errores de visualizacin de caracteres al incorporar funcionalidad AJAX a una pgina WEB codificada con ISO 8859-1.

250

INTRODUCCION A AJAX

24.4.1.1.
Atributo readyState

Atributos
Descripcin Devuelve el estado del objeto como sigue: 0 = sin inicializar, 1 = abierto, 2 = cabeceras recibidas, 3 = cargando y 4 = completado. (Level 2) Devuelve la respuesta como un array de bytes Devuelve la respuesta como una cadena Devuelve la respuesta como XML. Esta propiedad devuelve un objeto documento XML, que puede ser examinado usando las propiedades y mtodos del rbol del DOM. Devuelve el estado como un nmero (p. ej. 404 para Not Found y 200 para OK). Devuelve el estado como una cadena (p. ej. Not Found o OK).

responseBody responseText responseXML

status statusText

24.4.1.2.
Mtodo abort() getAllResponseHeaders()

Mtodos
Descripcin Cancela la peticin en curso Devuelve el conjunto de cabeceras HTTP como una cadena. Devuelve el valor de la cabecera HTTP especificada. Especifica el mtodo, URL y otros atributos opcionales de una peticin. El parmetro de mtodo puede tomar los valores GET, POST, o PUT (GET y POST son dos formas para solicitar datos, con GET los parmetros de la peticin se codifican en la URL y con POST en las cabeceras de HTTP). El parmetro URL puede ser una URL relativa o completa. El parmetro asncrono especifica si la peticin ser gestionada asncronamente o no. Un valor true indica que el proceso del script contina despus del mtodo send(), sin esperar a la respuesta, y false indica que el script se detiene hasta que se complete la operacin, tras lo cual se reanuda la ejecucin. En el caso asncrono se especifican manejadores de eventos, que se ejecutan ante cada cambio de estado y permiten tratar los resultados de la consulta una vez que se reciben, o bien gestionar eventuales errores. Enva la peticin Aade un par etiqueta/valor a la cabecera HTTP a enviar.

getResponseHeader( nombreCabecera ) open( mtodo, URL [, asncrono[, nombreUsuario [, clave]]] )

send([datos]) setRequestHeader( etiqueta, valor )

24.4.1.3.
Propiedad onreadystatechange

Eventos
Descripcin Evento que se dispara con cada cambio de estado.

251

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

onabort onload onloadstart onprogress

(Level 2) Evento que se dispara al abortar la operacin. (Level 2) Evento que se dispara al completar la carga. (Level 2) Evento que se dispara al iniciar la carga. (Level 2) Evento que se dispara peridicamente con informacin de estado.

La propuesta inicial de W3C no incluye propiedades y eventos presentes en implementaciones reales, como por ejemplo los eventos onload, onerror, onprogress, onabort y ontimeout. Algunos de ellos s son recogidos por la nueva especificacin Level 2, como puede verse en el cuadro anterior.
Instanciacin del objeto

A continuacin se muestra un posible cdigo JavaScript que permite crear el objeto teniendo en cuenta las diferencias entre los navegadores ms populares.
var httpRequest; if (window.XMLHttpRequest) { //El explorador implementa la interfaz de forma nativa httpRequest = new XMLHttpRequest(); } else if (window.ActiveXObject) { //El explorador permite crear objetos ActiveX try { httpRequest = new ActiveXObject("MSXML2.XMLHTTP"); } catch (e) { try { httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } if (!httpRequest) { alert("No ha sido posible crear una instancia de XMLHttpRequest"); }

24.5. Formatos de intercambio de Informacin


Para poder cambiar informacin en servicios web, lo ms normal es usar un formato marcado para dicho intercambio. Como son XML, JSON y YAML. XML ya lo hemos visto anteriormente en el curso, y JSON y YAML siguen ms o menos la misma finalidad. Aunque YAML no es del todo utilizado a la hora de desarrollar aplicaciones AJAX ya que se utiliza mejor JSON para este tipo de menesteres (o XML), si es ms normal verlo por otros servicios web realizados por ejemplo con SOAP. Veremos ahora la misma informacin parseada con los diferentes formatos, y en el caso de JSON y YAML un poco ms de informacin debido a que no lo hemos visto anteriormente en el curso.
XML <menu id="file" value="File"> <popup> <menuitem value="New" onclick="CreateNewDoc()" />

252

INTRODUCCION A AJAX

<menuitem value="Open" onclick="OpenDoc()" /> <menuitem value="Close" onclick="CloseDoc()" /> </popup> </menu> JSON {"menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ] } }}

JSON, acrnimo de JavaScript Object Notation, es un formato ligero para el intercambio de datos. JSON es un subconjunto de la notacin literal de objetos de JavaScript que no requiere el uso de XML. La simplicidad de JSON ha dado lugar a la generalizacin de su uso, especialmente como alternativa a XML en AJAX. Una de las supuestas ventajas de JSON sobre XML como formato de intercambio de datos en este contexto es que es mucho ms sencillo escribir un analizador semntico de JSON. En JavaScript, un texto JSON se puede analizar fcilmente usando el procedimiento eval(), lo cual ha sido fundamental para que JSON haya sido aceptado por parte de la comunidad de desarrolladores AJAX, debido a la ubicuidad de JavaScript en casi cualquier navegador web. En la prctica, los argumentos a favor de la facilidad de desarrollo de analizadores o del rendimiento de los mismos son poco relevantes, debido a las cuestiones de seguridad que plantea el uso de eval() y el auge del procesamiento nativo de XML incorporado en los navegadores modernos. Por esa razn, JSON se emplea habitualmente en entornos donde el tamao del flujo de datos entre cliente y servidor es de vital importancia (de aqu su uso por Yahoo, Google, etc, que atienden a millones de usuarios) cuando la fuente de datos es explcitamente de fiar y donde no es importante el no disponer de procesamiento XSLT para manipular los datos en el cliente. Si bien es frecuente ver JSON posicionado contra XML, tambin es frecuente el uso de JSON y XML en la misma aplicacin. Por ejemplo, una aplicacin de cliente que integra datos de Google Maps con datos meteorolgicos en SOAP hacen necesario soportar ambos formatos. Cada vez hay ms soporte de JSON mediante el uso de paquetes escritos por terceras partes. La lista de lenguajes soportados incluye ActionScript, C, C++, C#, ColdFusion, Common Lisp, Delphi, E, Eiffel, Java, JavaScript, ML, Objective CAML, Perl, PHP, Python, Rebol, Ruby, y Lua. En diciembre de 2005 Yahoo! comenz a dar soporte opcional de JSON en algunos de sus servicios web. El trmino JSON est altamente difundido en los medios de programacin, sin embargo, es un trmino mal descrito ya que en realidad es solo una parte de la definicin del estndar ECMA-262 en que est basado Javascript. De ah que ni Yahoo, ni Google emplean JSON, sino LJS. Una de las cualidades intrnsecas de Javascript denominada LJS (Literal Javascript) facilita el flujo de datos e incluso de funciones, para la cual no requiere la funcin eval() si son datos los que se transfieren como en el caso de xml. Todo lo referente a transferencia de datos en todos sus tipos, incluyendo arrays, booleans, integers, etc. no requieren de la funcin eval(), y es precisamente en eso en donde supera por mucho JavaScript al XML, si se utiliza el LJS y no la incorrecta definicin de JSON.
253

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

YAML 'menu': 'id': 'file' 'popup': 'menuitem': - {'onclick': 'CreateNewDoc()', 'value': 'New'} - {'onclick': 'OpenDoc()', 'value': 'Open'} - {'onclick': 'CloseDoc()', 'value': 'Close'} 'value': 'File'

YAML fue creado bajo la creencia de que todos los datos pueden ser representados adecuadamente como combinaciones de listas, hashes (mapeos) y datos escalares (valores simples). La sintaxis es relativamente sencilla y fue diseada teniendo en cuenta que fuera muy legible pero que a la vez fuese fcilmente mapeable a los tipos de datos ms comunes en la mayora de los lenguajes de alto nivel. Adems, YAML utiliza una notacin basada en el indentacin y/o un conjunto de caracteres Sigil distintos de los que se usan en XML, haciendo que sea fcil componer ambos lenguajes. Los contenidos en YAML se describen utilizando el conjunto de caracteres imprimibles de Unicode, bien en UTF-8 o UTF-16. La estructura del documento se denota indentando con espacios en blanco; sin embargo no se permite el uso de caracteres de tabulacin para indentar. Los miembros de las listas se denotan encabezados por un guin ( - ) con un miembro por cada lnea, o bien entre corchetes ( [ &nbsp; ] ) y separados por coma espacio ( , &nbsp; ). Los arrays asociativos se representan usando los dos puntos seguidos por un espacio. en la forma clave: valor, bien uno por lnea o entre llaves ( { &nbsp; } ) y separados por coma seguida de espacio ( , &nbsp; ). Un valor de un array asociativo viene precedida por un signo de interrogacin ( ? ), lo que permite que se construyan claves complejas sin ambigedad. Los valores sencillos (o escalares) por lo general aparecen sin entrecomillar, pero pueden incluirse entre comillas dobles ( ), o comillas simples ( ' ). En las comillas dobles, los caracteres espaciales se pueden representar con secuencias de escape similares a las del lenguaje de programacin C, que comienzan con una barra invertida ( \ ). Se pueden incluir mtliples documentos dentro de un nico flujo, separndolos por tres guiones ( ); los tres puntos ( ) indican el fin de un documento dentro de un flujo. Los nodos repetidos se pueden denotar con un ampersand ( &amp; ) y ser referidos posteriormente usando el asterisco ( * ) Los comentarios vienen encabezados por la almohadilla ( # ) y continan hasta el final de la lnea. Los nodos pueden etiquetarse con un tipo o etiqueta utilizando el signo de exclamacin( ! ) seguido de una cadena que puede ser expandida en una URL. Los documentos YAML pueden ser precedidos por directivas compuestas por un signo de porcentaje ( % ) seguidos de un nombre y parmetros delimitados por espacios.. Hay definidas dos directivas en YAML 1.1: La directiva %YAML se utiliza para identificar la versin de YAML en un documento dado.

254

INTRODUCCION A AJAX

La directiva %TAG se utiliza como atajo para los prefijos de URIs. Estos atajos pueden ser usados en las etiquetas de tipos de nodos. YAML requiere que las comas y puntos y comas que se utilicen como separadores en las listas sean seguidos por un espacio, de forma que los valores escalares que contengan signos de puntuacin (como 5,280 o http://www.url.com) se puedan representar sin necesidad de utilizar comillas. Hay dos caracteres adicionales que estn reservados en YAML para su posible estandarizacin en un futuro: la arroba ( @ ) y el acento grave ( ` ).

255

CONSTRUCCION DE SERVICIOS WEB EN PHP

Construccin de servicios web en PHP.

25.1. Introduccin a los servicios web


Un Web Service o servicio web es un conjunto de protocolos y estndares que sirven para intercambiar datos entre aplicaciones. Distintas aplicaciones de software desarrolladas en lenguajes de programacin diferentes, y ejecutadas sobre cualquier plataforma, pueden utilizar los servicios web para intercambiar datos tanto en red como a traves de Internet. La interoperabilidad se consigue mediante la adopcin de estndares abiertos. Las organizaciones OASIS y W3C son los comits responsables de la arquitectura y reglamentacin de los servicios Web. Para mejorar la interoperabilidad entre distintas implementaciones de servicios Web se ha creado el organismo WS-I, encargado de desarrollar diversos perfiles para definir de manera ms exhaustiva estos estndares.

25.1.1.

Soap

SOAP (siglas de Simple Object Access Protocol) es un protocolo estndar que define cmo dos objetos en diferentes procesos pueden comunicarse por medio de intercambio de datos XML. Este protocolo deriva de un protocolo creado por David Winer en 1998, llamado XML-RPC. SOAP fue creado por Microsoft, IBM y otros y est actualmente bajo el auspicio de la W3C. Es uno de los protocolos utilizados en los servicios Web.

257

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Desde PHP5 el soporte para SOAP es nativo, por lo que al programador se le facilita mucho ms la vida gracias a las clases SoapServer y SoapClient. La documentacin la podemos encontrar aqu: http://www.php.net/manual/es/book.soap.php

25.1.2.

REST

REST o Transferencia de Estado Representacional (Representational State Transfer) es una tcnica de arquitectura software para sistemas hipermedia distribuidos como la World Wide Web. El trmino se origin en el ao 2000, en una tesis doctoral sobre la web escrita por Roy Fielding, uno de los principales autores de la especificacin del protocolo HTTP y ha pasado a ser ampliamente utilizado por la comunidad de desarrollo. Si bien el trmino REST se refera originalmente a un conjunto de principios de arquitectura descritos ms abajo, en la actualidad se usa en el sentido ms amplio para describir cualquier interfaz web simple que utiliza XML y HTTP, sin las abstracciones adicionales de los protocolos basados en patrones de intercambio de mensajes como el protocolo de SOAP. Es posible disear sistemas de servicios web de acuerdo con el estilo arquitectural REST de Fielding y tambin es posible disear interfaces XMLHttpRequest de acuerdo con el estilo de llamada a procedimiento remoto (tambin conocido como RPC) pero sin usar SOAP. Estos dos usos diferentes del trmino REST causan cierta confusin en las discusiones tcnicas, aunque RPC no es un ejemplo de REST. Los sistemas que siguen los principios REST se llaman con frecuencia RESTful; los defensores ms acrrimos de REST se llaman a s mismos RESTafaris. REST afirma que la web ha disfrutado de escalabilidad como resultado de una serie de diseos fundamentales clave: Un protocolo cliente/servidor sin estado: cada mensaje HTTP contiene toda la informacin necesaria para comprender la peticin. Como resultado, ni el cliente ni el servidor necesitan recordar ningn estado de las comunicaciones entre mensajes. Sin embargo, en la prctica, muchas aplicaciones basadas en HTTP utilizan cookies y otros mecanismos para mantener el estado de la sesin (algunas de estas prcticas, como la reescritura de URLs, no son permitidas por REST) Un conjunto de operaciones bien definidas que se aplican a todos los recursos de informacin: HTTP en s define un conjunto pequeo de operaciones, las ms importantes son POST, GET, PUT y DELETE. Con frecuencia estas operaciones se equiparan a las operaciones CRUD que se requieren para la persistencia de datos, aunque POST no encaja exactamente en este esquema. Una sintaxis universal para identificar los recursos. En un sistema REST, cada recurso es direccionable nicamente a travs de su Uniform Resource Identifier (URI). El uso de hipermedios, tanto para la informacin de la aplicacin como para las transiciones de estado de la aplicacin: la representacin de este estado en un sistema REST son tpicamente HTML o XML. Como resultado de esto, es posible navegar de un recurso REST a muchos otros, simplemente siguiendo enlaces sin requerir el uso de registros u otra infraestructura adicional.

25.1.3.

En otras palabras

Para diferenciar SOAP y REST, vamos a verlo de la siguiente forma. Nota: Es una explicacin muy a grosso modo, que la veremos ms a fondo en los ejemplos que pongamos en los siguientes puntos.

258

CONSTRUCCION DE SERVICIOS WEB EN PHP

Con SOAP, imaginemos que tenemos una aplicacin servidor en la que se nos ofrece una serie de mtodos definidos en un fichero xml (llamado wsdl), como pueden ser por ejemplo:
getUsers(); getUser($id); ...

Y nosotros desde nuestra aplicacin cliente, lo que hacemos es utilizar dichas funciones (utilizando como referencia el fichero wsdl). Mientras que desde REST, lo que hacemos es uso de los mtodos HTTP antes nombrados (GET, POST, PUT, DELETE) y dependiendo de la ruta de acceso haremos unas cosas u otras. Por ejemplo a travs de miaplicacion.com/users/ con un metodo GET accederemos al listado de usuarios a traves de miaplicacion.com/users/1 con un metodo GET accederemos a la descripcin del usuario con identificativo 1 a traves de miaplicacion.com/users/1 con un metodo PUT accederemos a la modificacin del usuario con identificativo 1 Como observamos, la estructura de la URL es muy especfica, y no se usa el formato tpico de ?variable=valor&variable2=valor2 si no que se utiliza una estructura de Pretty URL. Que gracias a ella, es mucho ms sencillo de entender para los humanos. Si queremos usar pretty urls en nuestro servidor, habr que habilitarlo mediante la directiva mod_rewrite. Mientras que desde REST

25.2. Actividad
Busca webs que ofrezcan APIs de acceso a sus datos via web service, ya sea por SOAP o por REST

25.3. Desarrollo de servicios web


Para poder comprender a la perfeccin un servicio web, veamos un ejemplo hecho con SOAP. (Nota: Si se quiere usar estos ejemplos, es necesario instalar la extensin de PHP5 adecuada, en nuestro caso php-soap. En ubuntu con hacer un sudo aptitude install php-soap valdria). Fichero WSDL inventory.wsdl
<?xml version='1.0' encoding='UTF-8' ?> <definitions name='Inventory' targetNamespace='urn:TestInventario' xmlns:tns='urn:TestInventario' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:xsd='http://www.w3.org/2001/XMLSchema'

259

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/' xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/' xmlns='http://schemas.xmlsoap.org/wsdl/'>

<message name='getItemCountRequest'> <part name='upc' type='xsd:string'/> </message> <message name='getItemCountResponse'> <part name='Result' type='xsd:integer'/> </message>

<portType name='InventoryPortType'> <operation name='getItemCount'> <input message='tns:getItemCountRequest'/> <output message='tns:getItemCountResponse'/> </operation> </portType>

<binding name='InventoryBinding' type='tns:InventoryPortType'> <soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http'/> <operation name='getItemCount'> <soap:operation soapAction='urn:xmethods-delayedquotes#getItemCount'/> <input> <soap:body use='encoded' namespace='urn:xmethods-delayed-quotes' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/> </input> <output> <soap:body use='encoded' namespace='urn:xmethods-delayed-quotes' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/> </output> </operation> </binding>

260

CONSTRUCCION DE SERVICIOS WEB EN PHP

<service name='InventoryService'> <port name='InventoryPort' binding='InventoryBinding'> <soap:address location='http://direccion_de_mi_servidor/server.php'/> </port> </service> </definitions>

Fichero server.php
<?php require 'inventory_functions.php';

ini_set("soap.wsdl_cache_enabled", "0"); // Para nuestro ejemplo no necesitamos el cacheado del WSDL, asi que lo desactivamos $server = new SoapServer("inventory.wsdl"); $server->addFunction("getItemCount"); $server->handle(); ?>

Nota: En este ejemplo se usan solamente funciones mediante el mtodo addFunction(), pero es posible incluir clases enteras gracias a la mtodo addClass(). Nuestro fichero con las funciones necesarias inventory_functions.php.
<?php function getItemCount($upc){ //in reality, this data would be coming from a database $items = array('12345'=>5,'19283'=>100,'23489'=>'234'); return $items[$upc]; } ?>

Y por ltimo nuestra aplicacin cliente.


<?php ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache $client = new SoapClient("http://ruta_a_servidor_con_fichero_wsdl/inventory.wsdl"); $return = $client->getItemCount('12345'); print_r($return); ?>

261

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Todo servicio web necesita de 3 pasos: Captura de parmetros, Tratamiento de datos y Exportacin de datos. Tanto en la captura de parmetros como en la exportacin de datos, necesitamos saber que tipo de dato estamos pasando, as como las reglas de intercambio (si vamos a pasarlo como texto plano,un JSON, un XML) En SOAP y gracias a el soporte nativo de PHP5 de este protocolo, todo esto es muy sencillo como se ha podido ver. En nuestro ejemplo, para hacer la captura de parmetros y la exportacin de datos, (entre otras cosas), usamos el fichero WSDL. Que no es ms que un fichero en XML que detalla toda la lgica de negocio de dnde est nuestro servidor, que funciones disponibles hay, y qu parmetros se pueden usar (tipo de dato del parmetro) y qu nos van a devolver las funciones.
Captura de parmetros y exportacin de datos

Por ejemplo:
<service name='InventoryService'> <port name='InventoryPort' binding='InventoryBinding'> <soap:address location='http://direccion_de_mi_servidor/server.php'/> </port> </service>

En esta parte diramos donde est nuestro servidor. En esta otra parte:
<message name='getItemCountRequest'> <part name='upc' type='xsd:string'/> </message> <message name='getItemCountResponse'> <part name='Result' type='xsd:integer'/> </message>

<portType name='InventoryPortType'> <operation name='getItemCount'> <input message='tns:getItemCountRequest'/> <output message='tns:getItemCountResponse'/> </operation> </portType>

Definimos los mtodos disponibles, y qu parmetros y valores acepta y devuelve respectivamente. Donde se ve, que tenemos disponible la operacin getItemCount, y en el Request(captura de parmetros) necesitamos una cadena de texto (string) y nos devuelve en el Response (parmetros devueltos) un entero (integer) En el resto del fichero, la parte de los bindings, es la parte en la que le decimos la codificacin que vamos a usar en dicha comunicacin, en este caso usaremos un XML

262

CONSTRUCCION DE SERVICIOS WEB EN PHP

genrico disponible en schemas.xmlsoap.org, y que la comunicacin ser tipo RPC (no olvidemos que SOAP est basada en RPC):

<binding name='InventoryBinding' type='tns:InventoryPortType'> <soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http'/> <operation name='getItemCount'> <soap:operation soapAction='urn:xmethods-delayedquotes#getItemCount'/> <input> <soap:body use='encoded' namespace='urn:xmethods-delayed-quotes' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/> </input> <output> <soap:body use='encoded' namespace='urn:xmethods-delayed-quotes' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/> </output> </operation> </binding> Tratamiento de datos

El tratamiento de datos es la lgica que nosotros queramos darle a nuestro servicio. Acceder a BBDD, tratar cadenas, etc En nuestro ejemplo SOAP, las funciones estaran en el fichero inventory_functions.php. donde en este caso slo devolvemos un valor de un array.
<?php function getItemCount($upc){ //estos datos deberian venir desde BBDD $items = array('12345'=>5,'19283'=>100,'23489'=>'234'); return $items[$upc]; } ?>

25.4. Ejemplo de uso de un servicio REST: CRUDL


Para este ejemplo usaremos una aplicacin servidor escrita en php, y una aplicacin cliente que sera la consumidora. Adems tomaremos json como formato por defecto. En el caso de la aplicacin consumidora, tendremos un cliente REST genrico.

263

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Adems tenemos que tener en cuenta que vamos a usar prettyurls por lo que el servidor apache tendr que estar correctamente configurado. Script de configuracin de apache
Alias /rest /var/www/REST <Directory "/var/www/REST"> Options Indexes FollowSymLinks AllowOverride All Order allow,deny Allow from all </Directory> <Location /rest> #Para activar la reescritura RewriteEngine On RewriteCond %{REQUEST_FILENAME} RewriteCond %{REQUEST_FILENAME} RewriteRule ^(.*)$ index.php/$1 </Location>

MultiViews

!-f !-d [L]

Segn este Script, tendremos nuestro cdigo en la carpeta /var/www/REST, y accederemos a el, a traves de nuestro navegador en la ruta http://localhost/rest/ Veamos ahora el cdigo de nuestro servidor REST: Nota: este servidor esta hecho de forma que sea fcil entender REST, pero no es la forma ms ptima de implementarlo, ya que podra estar perfectamente integrado en un sistema MVC y con ms comprobaciones de seguridad para que no nos pasen ms o menos parmetros que los que necesitamos etc Adems toda la parte de modelo, se est haciendo con un array asociativo, y lo suyo es que fuese una aplicacin con bases de datos. index.php
<?php class RestUtils { public static function processRequest() { // cogemos el metodo $request_method = strtolower($_SERVER['REQUEST_METHOD']); $return_obj = new RestRequest(); // aqui almacenaremos los datos $data = array(); switch ($request_method) { // para get y post esto sera sencillo case 'get': $data = $_GET; break; case 'post': $data = $_POST; break; // Aqui esta lo "complicado" case 'put': //para put y delete usamos una cadena desde una localizacion de input especial de PHP y la parseamos con parse_str. parse_str(file_get_contents('php://input'), $put_vars); $data = $put_vars; break; case 'delete': $data=''; //delete no acepta parametros
264

CONSTRUCCION DE SERVICIOS WEB EN PHP

break; } // almacenamos el metodo $return_obj->setMethod($request_method); // Almacenamos los parametros pasados en crudo, por si necesitamos acceder a ellos $return_obj->setRequestVars($data); if(isset($data['data'])) { // asumimos que los datos estan pasados en forjato JSON $return_obj->setData(json_decode($data['data'])); } else if($request_method == "get"){ $return_obj->setData($data); } return $return_obj; } public static function sendResponse($status = 200, $body = '', $content_type = 'text/html') { $status_header = 'HTTP/1.1 ' . $status . ' ' . RestUtils::getStatusCodeMessage($status); // establecemos status header($status_header); // el tipo de contenido header('Content-type: ' . $content_type); // mostramos exclusivamente el cuerpo si est creado if($body != '') { echo $body; exit; } // en caso de que el cuerpo del mensaje sea vacio, necesitaremos construirlo else { // creamos la variable $message = ''; // Esta parte es opcional pero quedara mas presentable a los usuarios switch($status) { case 401: $message = 'Debes estar autorizado para ver esta pagina.'; break; case 404: $message = 'La URL solicitada ' . $_SERVER['REQUEST_URI'] . ' no existe.'; break; case 500: $message = 'Se ha encontrado un error al procesar la peticion.'; break; case 501: $message = 'El metodo solicitado no esta implementado.'; break; } // A veces la firma del servidor no esta activa (es la directiva apache

265

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

"ServerSignature On") $signature = ($_SERVER['SERVER_SIGNATURE'] == '') ? $_SERVER['SERVER_SOFTWARE'] . ' Server at ' . $_SERVER['SERVER_NAME'] . ' Port ' . $_SERVER['SERVER_PORT'] : $_SERVER['SERVER_SIGNATURE']; // Lo suyo es que esta parte este en una plantilla $body = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title>' . $status . ' ' . RestUtils::getStatusCodeMessage($status) . '</title> </head> <body> <h1>' . RestUtils::getStatusCodeMessage($status) . '</h1> <p>' . $message . '</p> <hr /> <address>' . $signature . '</address> </body> </html>'; echo $body; exit; } } public static function getStatusCodeMessage($status) { // Esto podria estar en un fichero de texto y parseado mas tarde pero por ahora nos vale $codes = Array( 100 => 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => '(Unused)', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type',

266

CONSTRUCCION DE SERVICIOS WEB EN PHP

416 417 500 501 502 503 504 505 );

=> => => => => => => =>

'Requested Range Not Satisfiable', 'Expectation Failed', 'Internal Server Error', 'Not Implemented', 'Bad Gateway', 'Service Unavailable', 'Gateway Timeout', 'HTTP Version Not Supported'

return (isset($codes[$status])) ? $codes[$status] : ''; } } class RestRequest { private $request_vars; private $data; private $http_accept; private $method; public function __construct() { $this->request_vars = array(); $this->data = ''; $this->http_accept = (strpos($_SERVER['HTTP_ACCEPT'], 'json')) ? 'json' : 'xml'; $this->method = 'get'; } public function setData($data) { $this->data = $data; } public function setMethod($method) { $this->method = $method; } public function setRequestVars($request_vars) { $this->request_vars = $request_vars; } public function getData() { return $this->data; } public function getMethod() { return $this->method; } public function getHttpAccept() { return $this->http_accept; } public function getRequestVars() { return $this->request_vars; } }

267

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

function send($data, $send_data){ //dependiendo de si nuestro cliente quiere json o xml se lo enviaremos de una forma u otra. if($data->getHttpAccept() == 'json') { RestUtils::sendResponse(200, json_encode($send_data), 'application/json'); } else if ($data->getHttpAccept() == 'xml') { // Usamos el serializador de xml de PEAR $options = array ( 'indent' => ' ', 'addDecl' => false, 'rootName' => $fc->getAction(), XML_SERIALIZER_OPTION_RETURN_RESULT => true ); $serializer = new XML_Serializer($options); RestUtils::sendResponse(200, $serializer->serialize($send_data), 'application/xml'); } } $data = RestUtils::processRequest(); require 'users.inc.php'; switch($data->getMethod()) { // this is a request for all users, not one in particular case 'get': $user_data = processGet($data); send($data, $user_data); break; // creamos un usuario case 'post': $user_data = processPost($data); send($data, $user_data); break; case 'put': $user_data = processPut($data); send($data, $user_data); break; case 'delete': $user_data = processDelete($data); send($data, $user_data); break; } function processGet($data){ $exploded = explode ("/", $_SERVER['REQUEST_URI']); //en nuestro caso si el 3 elemento es numerico, es que estamos pasando el identificativo $mydata = $data->getData(); if(strpos($_SERVER['REQUEST_URI'], 'user') && is_numeric($exploded[3])) return getUser($exploded[3]); if(strpos($_SERVER['REQUEST_URI'], 'user') && isset($mydata["name"])) //busqueda de usuario return getUserSearch($mydata["name"]); if(strpos($_SERVER['REQUEST_URI'], 'user'))//listado de usuarios return getUserList(); } function processPost($data){

268

CONSTRUCCION DE SERVICIOS WEB EN PHP

return addUser($data->getData()->username, $data->getData()->password); } function processPut($data){ $exploded = explode ("/", $_SERVER['REQUEST_URI']); return modifyUser($exploded[3], $data->getData()->username, $data>getData()->password); } function processDelete($data){ $exploded = explode ("/", $_SERVER['REQUEST_URI']); return deleteUser($exploded[3]); }

Las funciones de acceso a datos, fichero users.inc.php:


<?php $users = array('1' => array("user" => "juan", "password" => "nauj" ), '2' => array("user" => "pepe", "password" => "epep" ), '3' => array("user" => "antonio", "password" => "tonitoni" )); function getUserList(){ global $users; return $users; } function getUser($userid){ global $users; return $users[$userid]; } function getUserSearch($cond){ global $users; for ($i=1; $i<=count($users); $i++){ if ($users[$i]["user"] == $cond) return $users[$i]; } return null; } function addUser($name, $password){ global $users; $users[count($users)+1]["name"] = $name; $users[count($users)]["password"] = $password; //aqui solo usamos count a secas ya que se ha creado al asignar el name return $users; } function modifyUser($id, $name, $password){ global $users; $users[$id]["user"] = $name; $users[$id]["password"] = $password; return $users; } function deleteUser($userid){ global $users; unset($users[$userid]); return $users; }

Ahora veamos el cdigo de nuestro cliente genrico de REST. Para desarrollarlo hemos usado la libreria cURL http://php.net/manual/en/book.curl.php

269

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Fichero RestRequest.inc.php
<?php class RestRequest { protected $url; protected $verb; protected $requestBody; protected $requestLength; protected $acceptType; protected $responseBody; protected $responseInfo; public function __construct ($url = null, $verb = 'GET', $requestBody = null) { $this->url = $url; $this->verb = $verb; $this->requestBody = $requestBody; $this->requestLength = 0; $this->acceptType = 'application/json'; $this->responseBody = null; $this->responseInfo = null; if ($this->requestBody !== null) { $this->buildPostBody(); } } public function flush () { $this->requestBody = null; $this->requestLength = 0; $this->verb = 'GET'; $this->responseBody = null; $this->responseInfo = null; } public function execute () { $ch = curl_init(); try { switch (strtoupper($this->verb)) { case 'GET': $this->executeGet($ch); break; case 'POST': $this->executePost($ch); break; case 'PUT': $this->executePut($ch); break; case 'DELETE': $this->executeDelete($ch); break; default: throw new InvalidArgumentException('Current verb (' . $this->verb . ') is an invalid REST verb.'); } } catch (InvalidArgumentException $e)
270

CONSTRUCCION DE SERVICIOS WEB EN PHP

{ curl_close($ch); throw $e; } catch (Exception $e) { curl_close($ch); throw $e; } } public function buildPostBody ($data = null) { $data = ($data !== null) ? $data : $this->requestBody; if (!is_array($data)) { throw new InvalidArgumentException('Invalid data input for postBody. Array expected'); } $data = http_build_query($data, '', '&'); $this->requestBody = $data; } protected function executeGet ($ch) { $this->doExecute($ch); } protected function executePost ($ch) { if (!is_string($this->requestBody)) { $this->buildPostBody(); } curl_setopt($ch, CURLOPT_POSTFIELDS, $this->requestBody); curl_setopt($ch, CURLOPT_POST, 1); $this->doExecute($ch); } protected function executePut ($ch) { if (!is_string($this->requestBody)) { $this->buildPostBody(); } $this->requestLength = strlen($this->requestBody); $fh = fopen('php://memory', 'rw'); fwrite($fh, $this->requestBody); rewind($fh); curl_setopt($ch, CURLOPT_INFILE, $fh); curl_setopt($ch, CURLOPT_INFILESIZE, $this->requestLength); curl_setopt($ch, CURLOPT_PUT, true); $this->doExecute($ch); fclose($fh); }

271

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

protected function executeDelete ($ch) { curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); $this->doExecute($ch); } protected function doExecute (&$curlHandle) { $this->setCurlOpts($curlHandle); $this->responseBody = curl_exec($curlHandle); $this->responseInfo = curl_getinfo($curlHandle); curl_close($curlHandle); } protected function setCurlOpts (&$curlHandle) { curl_setopt($curlHandle, CURLOPT_TIMEOUT, 10); curl_setopt($curlHandle, CURLOPT_URL, $this->url); curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true); curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array ('Accept: ' . $this>acceptType)); }

public function getAcceptType () { return $this->acceptType; } public function setAcceptType ($acceptType) { $this->acceptType = $acceptType; } public function getResponseBody () { return $this->responseBody; } public function getResponseInfo () { return $this->responseInfo; } public function getUrl () { return $this->url; } public function setUrl ($url) { $this->url = $url; } public function getVerb () { return $this->verb; } public function setVerb ($verb) { $this->verb = $verb;

272

CONSTRUCCION DE SERVICIOS WEB EN PHP

} }

Y antes de empezar con las funcionalidades, vamos a dejar claro como vamos a acceder a nuestro api. listado con todos los usuarios metodo GET a la url http://localhost/rest/user/ aadir un usuario. metodo POST a la url http://localhost/rest/user/ modificar un usuario. metodo PUT a la url http://localhost/rest/user/id_del_usuario por ejemplo para el usuario con id = 1 sera: http://localhost/rest/user/1 ver un usuario. metodo GET a la url http://localhost/rest/user/id_del_usuario igual que con modificar. borrar un usuario. metodo DELETE a la url http://localhost/rest/user/id_del_usuario igual que con modificar busqueda de usuario. metodo GET a la url http://localhost/rest/user/ pero pasndole ms parametros en la URL En estos ejemplos, usaremos la clase cliente, y mostraremos el resultado en json. Evidentemente en una aplicacin final, los datos debern ser tratados para mostrar un html con sus estilos CSS.

25.4.1.

Listado

Gracias a nuestra clase genrica vamos a tener una forma muy sencilla de hacer todas estas funcionalidades. Despues de ejecutar la consulta REST, dispondremos de 2 mtodos. getResponseInfo() y getResponseBody(). getResponseBody() tiene todo el contenido de nuestro servicio, mientras que getResponseInfo() nos da informacin adicional no relevante para el usuario final, pero que a nosotros, los programadores nos puede ser muy util como tamao de las cabeceras, tiempo total que ha llevado la consulta etc Y ahora s, empecemos por el listado:
<?php require 'RestRequest.inc.php'; $MyRequest = new RestRequest('http://localhost/rest/user/', "GET"); $MyRequest->execute(); print "Response info: <br />"; print_r ($MyRequest->getResponseInfo()); print "<br />Response body: <br />"; print ($MyRequest->getResponseBody());

Como decamos getResponseBody() tiene nuestro cuerpo. Por lo que este mtodo debera mostrarnos
Response body: {"1":{"user":"juan","password":"nauj"},"2":{"user":"pepe","password":"epe p"},"3":{"user":"antonio","password":"tonitoni"}}

25.4.2.
<?php

Mostrado

273

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

require 'RestRequest.inc.php'; $MyRequest = new RestRequest('http://localhost/rest/user/3', "GET"); $MyRequest->execute(); print "Response info: <br />"; print_r ($MyRequest->getResponseInfo()); print "<br />Response body: <br />"; print ($MyRequest->getResponseBody());

Resultado:
{"user":"antonio","password":"tonitoni"}

25.4.3.
<?php

Insercin

require 'RestRequest.inc.php'; $request["data"]='{"username": "miguel", "password": "miki"}'; $MyRequest = new RestRequest('http://localhost/rest/user/', "POST", $request); $MyRequest->execute(); print "Response info: <br />"; print_r ($MyRequest->getResponseInfo()); print "<br />Response body: <br />"; print ($MyRequest->getResponseBody());

Resultado:
{"1":{"user":"juan","password":"nauj"},"2":{"user":"pepe","password":"epe p"},"3":{"user":"antonio","password":"tonitoni"},"4":{"name":"miguel","pa ssword":"miki"}}

25.4.4.
<?php

Modificacin

require 'RestRequest.inc.php'; $request["data"]='{"username": "miguel", "password": "miki"}'; $MyRequest = new RestRequest('http://localhost/rest/user/2/', "PUT", $request); $MyRequest->execute(); print "Response info: <br />"; print_r ($MyRequest->getResponseInfo()); print "<br />Response body: <br />"; print ($MyRequest->getResponseBody());

Resultado:
{"1":{"user":"juan","password":"nauj"},"2":{"user":"miguel","password":"m iki"},"3":{"user":"antonio","password":"tonitoni"}}

25.4.5.
<?php

Borrado

require 'RestRequest.inc.php';

274

CONSTRUCCION DE SERVICIOS WEB EN PHP

$MyRequest = new RestRequest('http://localhost/rest/user/2/', "DELETE"); $MyRequest->execute(); print "Response info: <br />"; print_r ($MyRequest->getResponseInfo()); print "<br />Response body: <br />"; print ($MyRequest->getResponseBody());

Resultado:
{"1":{"user":"juan","password":"nauj"},"3":{"user":"antonio","password":" tonitoni"}}

25.4.6.
<?php

Bsqueda

require 'RestRequest.inc.php'; $MyRequest = new RestRequest('http://localhost/rest/user/?name=pepe', "GET"); $MyRequest->execute(); print "Response info: <br />"; print_r ($MyRequest->getResponseInfo()); print "<br />Response body: <br />"; print ($MyRequest->getResponseBody());

Resultado:
{"user":"pepe","password":"epep"}

25.5. Actividades
25.5.1. Actividad 1

Implementa el ejemplo CRUDL REST con un paradigma MVC. Tanto cliente como servidor. Puedes usar este ejemplo como base.

25.5.2.

Actividad 2

De los servicios web en REST que has encontrado en el primer ejercicio del punto anterior, elige uno, y haz que el cliente rest php conecte contra el. Es posible que necesites algn tipo de autenticacin, ya que REST permite hacer una autenticacon. cURL tambien ofrece la posibilidad de aadir autenticacin. Si lo necesitas, solo tienes que aadir lo siguiente al cliente rest del ejemplo anterior: En la declaracin de variables
protected $username; protected $password;

En el constructor

275

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

$this->username = null; $this->password = null;

En la funcin execute
public function execute () { $ch = curl_init(); $this->setAuth($ch); /// <<<<<<---- ESTA LINEA

Y aadir estas funciones:


protected function setAuth (&$curlHandle) { if ($this->username !== null && $this->password !== null) { curl_setopt($curlHandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); curl_setopt($curlHandle, CURLOPT_USERPWD, $this->username . ':' . $this>password); } } public function getPassword () { return $this->password; } public function setPassword ($password) { $this->password = $password; } public function getUsername () { return $this->username; } public function setUsername ($username) { $this->username = $username; }

276

CONSULTAS DE SERVICIOS WEB EN JAVASCRIPT:JQUERY

Consulta de servicios web en JavaScript: Jquery


Antes de ver como hacer unas consultas con JQuery, veamos como hacerlas a mano directamente con el objeto XMLHttpRequest.

26.1. Manejo de consultas: XMLHTTPRequest

uso

del

objeto

Antes de seguir con el objeto XMLHTTPRequest, debemos tener una cosa en cuenta. No todos los navegadores web tienen implementado los mtodos PUT y DELETE, aunque los navegadores web ms modernos empiezan a hacerlo. En el caso de que nuestro navegador no lo soporte, podramos implementar PUT y DELETE a travs de POST mandando algn parmetro extra, y haciendo el control extra en nuestro script PHP. En primer lugar crearemos nuestro objeto ActiveX en IExplorer y un objeto nativo en el resto de navegadores que lo soportan, y es por ello que tendremos que ver qu objeto creamos, controlndolo con diferentes condiciones, con esto conseguimos que el navegador cree una instancia del objeto apropiado, dependiendo del navegador usado por el usuario.
function nuevoAjax(){ var xmlhttp=false; try {

277

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

xmlhttp = new ActiveXObject(Msxml2.XMLHTTP); } catch (e) { try { xmlhttp = new ActiveXObject(Microsoft.XMLHTTP); } catch (E) { xmlhttp = false; } } if (!xmlhttp && typeof XMLHttpRequest!=undefined) { xmlhttp = new XMLHttpRequest(); } return xmlhttp; }

Ahora repasemos los mtodos y propiedades del objeto XMLHttpRequest que hemos visto al principio del mdulo. Mtodos abort() Detiene la peticin en curso. getAllResponseHeaders() Devuelve todas las cabeceras de la respuesta (etiquetas y valores) como una cadena. getResponseHeader(etiqueta) Devuelve el valor de la etiqueta en las cabecerasde la respuesta. open(mtodo,URL,asncrona,nombre,password) Abre una conexin con esa URL mediante ese metodo (GET o POST) send(contenido) Enva el contenido al servidor. setRequestHeader(etiqueta,valor) Establece el valor de una etiqueta de las cabeceras de peticin. De est lista nos detendremos en el mtodo open que es uno de los ms utilizados y el que nos permitir utilizar la mejor caracterstica de Ajax que es la carga de datos externos a la pgina sin necesidad de recargar la misma.

26.1.1.

Mtodo Open

El mtodo open prepara una conexin HTTP a travs del objeto XMLHttpRequest con un mtodo y una URL especificados.
XMLHttpRequest.open ( string Metodo, string URL [, boolean Sincronia [, string Usuario [, string Contrasea ] ] ] );

Metodo es la cadena que nos indicara el tipo de conexin (GET o POST) URL es la url a la que realizamos la peticin Sincronia es un campo booleano con el que podemos utilizar modo asncrono o sncrono, si lo fijamos en false modo sncrono perderiamos las mejores caractersticas de AJAX, los datos Usuario y Pwd son opcionales por si queremos dotar de una autenticacin. Al llamar a open el atributo readyState a 1, resetea los headers de envo y devuelve los atributos responseText, responseXML, status y statusText a sus valores iniciales Propiedades onreadystatechange Contiene el nombre de la funcin que se ejecuta cada vez que el estado de la conexin cambie.
278

CONSULTAS DE SERVICIOS WEB EN JAVASCRIPT:JQUERY

readyState Estado de la conexin, puede valer desde 0 (no iniciada) hasta 4 (completado). responseText Datos devueltos por el servidor en formato cadena. responseXML Datos devueltos por el servidor en forma de documento XML que puede ser recorrido mediante las funciones del DOM (getEementsByTagName, etc). status Cdigo enviado por el servidor, del tipo 404 (documento no encotrado) o (OK), 401 (No autorizado), 405 (Metodo no implementado) statusText Mensaje de texto enviado por el servidor junto al cdigo (status), para el caso de cdigo 200 contendr OK. Y ahora pasemos a coger informacin con GET
function cargarContenido(){ var module, userid, contenedor; contenedor = document.getElementById(contenedor); module = document.getElementById(module ).value; userid = document.getElementById(userid ).value; ajax=nuevoAjax(); ajax.open(GET, module+"/"+userid,true); ajax.onreadystatechange=function() { if (ajax.readyState==4) { contenedor.innerHTML = ajax.responseText } } ajax.send(null) }

26.1.1.1.

Ejemplo de envo de datos POST

Unicamente debemos cambiar algunas cosas en nuestra funcin: Adiccin de una lnea adicional: setRequestHeader que especifica qu tipo de datos llegarn al servidor. Cambio del parametro que especifica el mtodo a POST y por ltimo utilizaremos parametros para el send.
function cargarContenido(){ var t1, t2, contenedor; contenedor = document.getElementById(contenedor); t1 = document.getElementById(texto1 ).value; t2 = document.getElementById(texto2 ).value; ajax=nuevoAjax(); ajax.open(POST, ejemploajax2.php,true); ajax.onreadystatechange=function() { if (ajax.readyState==4) { contenedor.innerHTML = ajax.responseText } } ajax.setRequestHeader(Content-Type, application/x-www-formurlencoded); ajax.send(t1=+t1+&t2=+t2) }

Al mandar por post la informacin, podemos mandarla con el formato variable=valor&variable2=valor2, o incluso podemos mandar contenido en formato json y por supuesto, en el caso del GET, usar la funcin eval() para leer el contenido. Para los metodos PUT y DELETE, el cdigo seria prcticamente el mismo que en POST y en GET respectivamente. Poniendo parametros en el send() en el caso de PUT, y poniendo null en el send() en el caso del DELETE.

279

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

26.2. Importacin y exportacin de datos


Veamos como recibir y mandar datos con JQuery. Uso de la funcin load.
$(document).ready(function(){ $("#enlaceajax").click(function(evento){ evento.preventDefault(); $("#destino").load("recibe-parametros.php", {nombre: "Pepe", edad: 45}, function(){ alert("recibidos los datos por ajax"); }); }); })

esta funcin tiene el formato: .load(string URL, parametros, callback) Donde en: URL ponemos una string con la direccin de nuestro servidor REST. parametros, si ponemos null o una cadena de texto, la peticin se mandar va GET, y si mandamos en notacin de objeto, como en el ejemplo, se mandara por POST aqu definimos una funcin que se ejecutar a modo de callback. Ojo, si el contenido de nuestro servicio REST nos devuelve html en s, podremos usar load para GET sin ningn tipo de problema, ya que esa funcin introduce dentro del contenido de nuestro elemento HTML (un div por ejemplo) los datos del servidor, como si usaramos innerHTML(). Si nuestro servicio REST nos va a mandar otro tipo de contenido (un json por ejemplo), debermos usar la funcion $().get(). Tambin tenemos la posibilidad de usar $().post() en vez de .load() Por ejemplo
//Con get podemos usar esta notacion, $.get("servidor.php", { name: "John", time: "2pm" }, function(data){ alert("Data Loaded: " + data); }); //o esta otra, si no queremos mandar parametros $.get("servidor.php", function(data){ alert("Data Loaded: " + data); });

load() solo implementa GET y POST por la razn que comentbamos antes, de que PUT y DELETE no estn implementados en varios navegadores, pero podemos extender JQuery y crearnos nuestras propias funciones para el caso de PUT y DELETE.
function _ajax_request(url, data, callback, type, method) { if (jQuery.isFunction(data)) { callback = data; data = {}; } return jQuery.ajax({ type: method,

280

CONSULTAS DE SERVICIOS WEB EN JAVASCRIPT:JQUERY

url: url, data: data, success: callback, dataType: type }); } jQuery.extend({ put: function(url, data, callback, type) { return _ajax_request(url, data, callback, type, 'PUT'); }, delete_: function(url, data, callback, type) { return _ajax_request(url, data, callback, type, 'DELETE'); } });

Y de esta forma lo tendramos listo para usar JQuery.put() o JQuery.delete()

26.3. Manejo de los datos y su uso en el DOM


Como hemos comentado, a la hora de recibir datos, podriamos recibirlos de varias formas. Un html ya formado, u otro contenido por ejemplo json. Con JQuery, si recibimos en un GET, unos datos ya formados en html, con utilizar la funcin load nos valdra, ya que con usarlo sobre el identificativo, todo se hace de forma automtica.
$(document).ready(function(){ $("#enlaceajax").click(function(evento){ evento.preventDefault(); $("#destino").load("recibe-parametros.php", {nombre: "Pepe", edad: 45}, function(){ alert("recibidos los datos por ajax"); }); }); })

En este caso el contenido de nuestro elemento HTML con identificativo #destino se ver modificado automticamente. Por el contrario si recibisemos un JSON mediante la funcin $.get(), la forma de convertirlo en un objeto javascript, es la siguiente:
var myObject = eval('(' + myJSONtext + ')');

Por ejemplo:
var myObject = null; $.get("servidor.php", function(data){ myObject = eval('(' + data + ')'); });

Nota: Para mandar datos en formato json, con mandar un objeto javascript es suficiente. A partir de que tengamos nuestros datos JSON, para modificar el DOM solo tendremos que usar las funciones tpicas de JQuery para crear nuevos elementos con el contenido que nosotros queramos.

26.4. Actividad

281

EXPERTO EN DESARROLLO DE SOLUCIONES CORPORATIVAS EN SOFTWARE LIBRE

Implementa con javascript la posibilidad de ejecutar desde el navegador las funciones ofrecidas por nuestro servidor de REST. Si quieres usar la funcion load directamente recuerda que todo tiene que ir ya creado en html. Aade Smarty a nuestro paradigma MVC si no lo habas hecho y busca la funcin en su API que nos devuelve una template ya compilada

282