384
Manual Imprescindible de PHP5 Luis Miguel Cabezas Granado Prólogo de Zeev Suraski y Andi Gutmans ANAYA MULTIMEDIA

Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo

Manual Imprescindible de

PHP5

Luis Miguel Cabezas Granado

Proacutelogo de Zeev Suraski y Andi Gutmans

ANAYA MULTIMEDIA

MANUAL IMPRESCINDIBLE

RESPONSABLE EDITORIAL

Eugenio Tuya Feijooacute

ILUSTRACIOacuteN DE CUBIERTA

Cecilia Poza Melero

REALIZACIOacuteN DE CUBIERTA

Gracia Fernaacutendez-Pacheco

Todos los nombres propios de programas sistemas operativos equipos hardware etc que aparecen en este libro son marcas registradas de sus respectivas compantildeiacuteas u organizaciones

Reservados todos los derechos El contenido de esta obra estaacute protegido por la ley que estashyblece penas de prisioacuten y o multas ademaacutes de las correspondientes indemnizaciones por dantildeos y perjuicios para quienes reprodujeren plagiaren distribuyeren o comunicasen puacuteblishycamente en todo o en parte una obra literaria artiacutestica o cientiacutefica o su transformacioacuten interpretacioacuten o ejecucioacuten artiacutestica fijada en cualquier tipo de soporte o comunicada a traveacutes de cualquier medio sin la preceptiva autorizacioacuten

copy EDICIONES ANA YA MULTIMEDIA (GRUPO ANAYA SA) 2004 Juan Ignacio Luca de Tena 15 28027 Madrid Depoacutesito legal M-44920-2004 ISBN 84-415-1785-1 Printed in Spain Imprime Artes Graacuteficas Guemo SL Febrero 32 Madrid 28022

A mi mujer Mariacutea Fernanda por creer en nuestro Proyecto de vida

Agradecimientos

Finalizar este libro ha sido una odisea donde han intervenido muchas personas y factores mudanza incluida Para empezar me gustariacutea agradecer a Marta Camarero y a Eugenio Tuya su fe en miacute como escritor Me dieron aacutenimos desde el principio y un poquito de prisa A Zeev Suraski y Andi Gutmans creadores de PHP 5 por crear el lenguashyje y tratarme como a uno de los suyos en los iquestseminar de wwwzendcom Ademaacutes tengo que agradecerles la rapidez con la que escribieron el proacuteshylogo del libro A Marco Tabini director de la revista canadiense PHParchitect por enshyviarme el manual de Certificacioacuten PHP en papel y no en PDF A Tim Converse y Joyce Park por escribir PHP5 and MySQL Bible cuyos conocimientos me bebiacute en apenas 3 diacuteas A Harry Fuecks por escribir el mejor libro de PHP de todos los tiempos The PHP Anthology que me hizo reorientar todos los esfuerzos a la innoshyvacioacuten

A la Asociacioacuten Regional de Universidades Populares de Extremadura (AUPEX) por probar todos mis programas escritos en PHP (libros de visita foros nccproject newton etceacutetera) Espero dar alguacuten diacutea con la tecla A mis compantildeeros de trabajo Pako Palomo Javi y Pedro por las largas horas de discusioacuten en torno a Delphi Java C y por supuesto PHP A Justo Cabezas porque todo lo que me regaloacute fueron libros de informaacuteshytica y encima escritos por eacutel Sigo tus pasos A los grupos de usuario de gnuLinux de Extremadura wwwsinuhorg y wwwgulexorg por ser una fuente inagotable de conocimientos Por uacuteltimo A mi padre Ramoacuten que ya no estaacute a mi madre Felisa y a mi hermano Felipe porque nunca entendieron nada de informaacutetica pero me animashyron a seguir adelante con todo lo que me propuse Al resto de la familia porque cada uno de ellos ha tenido algo que ver en miacute vida y forman parte de lo que soy

iacutendice

Coacutemo usar este libro 19 Destinatarios de este libro 20 Organizacioacuten del libro 20 Convenios que emplea este libro 25 Los ejemplos en la Web de Anaya 26

Proacutelogo 27

Introduccioacuten 29 Historia de PHP 30 Nuevas Caracteriacutesticas de PHP 5 31

Faacutecil de usar 31 Embebido en HTML 32 Multiplataforma 33 Licencia Open Source 34 Multitud de Extensiones 34 Velocidad e incorporacioacuten de objetos 34 Popularidad 35 Gran Comunidad de apoyo 35

Objetivos del libro 36

1 Introduccioacuten a PHP 5 39 Introduccioacuten 40

8 iacutendice

HTML estaacutetico 40 Tecnologiacuteas del lado del cliente 42 Tecnologiacuteas del lado del servidor 43 Etiquetas de PHP 45 Nuestro primer programa en PHP 5 46 Repaso de HTML 47

Cabecera y cuerpo de una paacutegina Web 47 Cabecera 48 Cuerpo del documento 48 Paacuterrafos y saltos de liacuteneas 49 Estilo de texto 49 Enlaces de texto 51 Listas 51 Imaacutegenes 52 Tablas 53

Resumen 54

2 Variables constantes y tipos de datos 55 Variables en PHP 5 56

Tipos de Variables 56 Asignacioacuten de variables 57

Tipos simples 57 Enteros (integer) 58 Nuacutemeros de coma flotante (double) 59 Cadena de caracteres (string) 59 Boolean 61 NULL 62

Variables de variables 62 Constantes 63

defined() 63 Constantes predefinidas 64

Funciones relacionadas con variables 65 isset() 65 unsetQ 66 gettype() 66 settype() 67 empty() 67 is_integer() is_double() is_string() 67 intvalQ doublevalQ strvalQ 68

Resumen 68

iacutendice 9

3 Operadores 69

Introduccioacuten 70 Operador de asignacioacuten 70 Operador Unario 71 Operadores Aritmeacuteticos 71 Operadores de comparacioacuten 71 Operadores Loacutegicos 73 Operador Ternario 74 Operadores bit a bit 74 Operadores de asignacioacuten combinados 75 Operador de ejecucioacuten 76 Operador de supresioacuten de errores 77 Precedencia de Operadores 78 Resumen 80

4 Estructuras de control 81

Introduccioacuten 82 Estructuras de eleccioacuten 82

if-else 82 elseif 83 switch 84

Bucles 86 while 86 do-while 89 for 89

break y continueacute 92 Finalizar la ejecucioacuten de un programa 93 Sintaxis alternativa 93 Resumen 94

5 Funciones 95 Introduccioacuten 96 Valores de las funciones 96 Funcioacuten de ejemplo Obtencioacuten de la fecha actual 97 Documentacioacuten sobre funciones 98 Funciones de usuario 99

Definicioacuten de funciones 99 Paraacutemetros insuficientes 101 Paraacutemetros en exceso 102

10 iacutendice

Aacutembito de las variables 102 Variables estaacuteticas 104

Include() y require() 105 Recursividad 105 Funciones con nuacutemero de argumentos variables 106

Argumentos por defecto 106 Argumentos mediante un array 107 Muacuteltiples argumentos con func_num_args() 109

Llamadas por valor 110 Llamadas por referencia 111

Referencia a variables 112 Funciones variables 113 Resumen 114

6 Cadenas de caracteres y expresiones regulares 115 Introduccioacuten 116 Propiedades de las cadenas 116

iacutendices de string 116 Operadores 118 Sintaxis para muacuteltiples liacuteneas 118

Funciones de string 119 Tamantildeo de la cadena 120 Posicioacuten de los caracteres 120 Comparacioacuten 121 Buacutesqueda de caracteres 122 Seleccioacuten de subcadenas 122 Funciones de limpieza de cadenas 124 Sustitucioacuten de cadenas 126 Funciones de mayuacutescula y minuacutescula 126

Expresiones regulares 127 Comprobar expresiones regulares 129 Reemplazar patrones 131

Resumen 131

7 Conjuntos de datos del tipo array 133

Introduccioacuten 134 Creacioacuten de arrays 134

Asignacioacuten directa 134 array() 135 Funciones que devuelven arrays 136

iacutendice 11

Arrays multidimensionales 136 Propiedades de arrays 137

count() 1 3 7

in_array() 137 Borrar ocurrencias 138 Interactuar con arrays 138

Funciones para avanzar en un array 140 Funciones para retroceder en un array 142 Intercambio de valores 143 Inversioacuten del contenido 144 Mezcla de los valores 145

Pilas 145 Ordenacioacuten de los valores 146 Resumen 148

amp Paso de informacioacuten entre formularios 149

Introduccioacuten 150 Argumentos GET 150

Formularios con GET 151 Paso de informacioacuten con GET 155

Argumentos POST 157 Variables suacuteper-globales 158 Resumen 159

9 Programacioacuten orientada a objetos bull bull 1 6 1

Introduccioacuten 162 Definicioacuten de clases 163

Instancia de clase 164 Funcioacuten constructor 165

Herencia 165 Meacutetodos o funciones de objeto 166 Herencia encadenada 168 Valores y alcance de variables 168

Miembros puacuteblicos privados y protegidos 170 Meacutetodos privados 170 Meacutetodos protegidos 171 Meacutetodos puacuteblicos 171

Interfaces 172 Clases abstractas 172 Clases con meacutetodos estaacuteticos 173

12 iacutendice

Llamadas a funciones padre 174 Sobrecarga de meacutetodos 176 Sentildealizacioacuten 176 Funciones de manejo de clases 177 Resumen 179

10 Ficheros y almacenamiento de datos 181 Introduccioacuten 182 Funciones de lectura y escritura de ficheros 182

Abrir el fichero 182 Lectura de ficheros 183 Escritura de ficheros 185

Sistema de ficheros y directorios 188 Copiar borrar y renombrar 188 Funciones de comprobacioacuten 189 Directorios 190

Ficheros de configuracioacuten 191 Manejo de ficheros en el servidor 193

Subida de ficheros 193 Descarga de ficheros 195

Resumen 197

11 Bases de datos con SQL y SQLite 199 Introduccioacuten 200 SQL 200

SELECT 202 Uniones 203

INSERT 205 UPDATE 206 DELETE 207

Definicioacuten de tablas 207 SQLite 208

Creacioacuten de bases de datos 209 Uacuteltimos cambios en una tabla 211 Seleccioacuten de datos 212

SQLite orientado a objetos 213 Seleccioacuten de registros 214 Funciones de Array para recuperar datos 215 Nuacutemero de filas 216 Moverse entre registros 216

Resumen 218

iacutendice 13

12 PHP 5 y MySQL 219 Introduccioacuten 220 Administracioacuten de usuarios 220 Conexioacuten a MySQL 220

Seleccionar datos 222 Manipulacioacuten de datos 224

Insertar una fila 224 Actualizar una fila 225 Borrar una fila 225

Errores con las comillas 226 Contando filas 228

Contar filas con PHP 228 Contar filas con MySQL 229

Contar filas afectadas 230 Uacuteltimo nuacutemero insertado 230 Buacutesquedas dentro de una tabla 231 Definicioacuten de bases de datos 231

Creacioacuten de bases de datos 231 Creacioacuten de tablas 231

Resumen 233

13 Sesiones y Cookies 235 Introduccioacuten 236 Sesiones en PHP 5 237

Instanciando sesiones 237 Variables de sesioacuten 239 Problemas con los navegadores 240 Funciones para el manejo de sesiones 241

Cookies 243 setcookie() 243 Borrar una cookie 244

Cabeceras HTTP laquo 245 Resumen 246

14 Lectura y escritura de archivos XML 247 Introduccioacuten 248 SAXDOMySimpleXML 250 SAX 250 DOM 254

14 iacutendice

Usar DOM para leer archivos 255 Todo es un objeto 255 Atributos 256 Buacutesquedas muacuteltiples 257

Escribir archivos XML con DOM 257 Modificar archivos XML 259

SimpleXML 259 Resumen 261

15 Aplicaciones praacutecticas de XML 263 Introduccioacuten 264 Compartir informacioacuten con RSS 264

Distintos formatos 264 Leer un archivo RSS 268 Escribir archivos RSS 269

Servicios Web XML-RPC 272 Clase IXR 273 Cliente XML-RPC 274 Servidor XML-RPC 275 Usos de XML-RPC 277

Resumen 277

16 Generacioacuten de graacuteficos con PHP 5 279 Introduccioacuten 280 Graacuteficos HTML 280

Graacuteficos de barras 284 Libreriacutea GD 285

Tipos MIME 285 Mostrar una imagen en pantalla 286 Crear imaacutegenes en miniatura 288 Generar una marca de agua 290

Graacuteficos estadiacutesticos profesionales con JpGraph 292 Graacuteficos de barras 292 Graacuteficos en 3D 295

Resumen 297

17 Gestioacuten de errores en PHP 5 299 Introduccioacuten 300 Errores y Excepciones 300

iacutendice 15

La clase Exception 301 Bloque Try Catch 303 Heredar de la clase Exception 304 Limitaciones de PHP 5 305

Control de errores sin excepciones 306 Errores nativos de PHP 306 Controladores de error 307 Errores de usuario con trigger_error() 308

Depuracioacuten de errores 308 Resumen 309

18 Conexiones desde PHP 5 311

Introduccioacuten 312 FTP 312

Mostrar los archivos remotos 314 Descargar y Enviar ficheros 315 Otras funciones de FTP 316

Correo electroacutenico 317 Enviar correo desde PHP 318

PHPMailer 319 Antildeadir un fichero adjunto 320

Resumen 322

19 Creacioacuten de archivos PDF 325

Introduccioacuten 326 Libreriacutea FPDF 326

Nuestro primer documento 327 Funciones de texto 328

Meacutetodo Write() 328 Meacutetodo Cell() 329

Desplazamiento de los cursores 330 Salto de paacutegina automaacutetico 330

Sobrescribir los meacutetodos 331 Cabecera 331 Imagen de cabecera 332 Pie de paacutegina 333

Tablas 334 Enlaces 337 Resumen 338

16 iacutendice

20 Plantillas con Smarty 339

Introduccioacuten 340 Instalacioacuten de Smarty 341 Utilizacioacuten baacutesica de Smarty 341

Cuidado con los estilos CSS 345 Llamada a varias plantillas 346 Variables 346 Modificadores 347

Funciones 350 foreach 350 if elseif else 351 php incluido en plantillas 351 assign 352 counter 352 cycle 352

Opciones avanzadas de Smarty 353 Plugins 353 Filtros 354

Resumen 355

Apeacutendice A Instalacioacuten de PHP 5 y MySQL 357

Antes de comenzar 358 Instalacioacuten en MacOSX 358

Apache 358 PHP 5 360 MySQL 4 360 Comprobacioacuten final 361

Instalacioacuten en Windows 362 Instalacioacuten en gnuLinux 363 Recomendacioacuten final 364

Apeacutendice B Configuracioacuten de phpini 367 Introduccioacuten 368

short_open_tag 368 disable_functions 368 max_execution_time 368 error_reporting 368 register_globals 368 magic_quotes_runtime 369

iacutendice 17

include_path 369

Resumen 369

Apeacutendice C Bibliografiacutea 371 Bibliografiacutea 372

Libros de PHP 5 372 Revistas profesionales 372 Paacuteginas Web 373

Glosario 375

iacutendice alfabeacutetico 381

Coacutemo usar este libro

20 Coacutemo usar este libro

Destinatarios de este libro

Este libro estaacute dirigido a usuarios noveles que no sepan programar en ninshyguacuten lenguaje de desarrollo y a usuarios que ya conocen PHP pero desean tener una base soacutelida sobre la nueva versioacuten

PHP 5 estaacute ligado a Internet por lo tanto todas las aplicaciones praacutecticas del lenguaje estaacuten orientadas a realizar contenidos dinaacutemicos para paacutegishynas Por eso el lector debe conocer los aspectos baacutesicos de disentildeo en HTML

El libro puede dividirse en dos partes Una primera en la que se detallan los conceptos principales del lenguaje como las variables estructuras de control manejo de cadenas de caracteres creacioacuten de objetos y conectivi-dad con bases de datos que daraacute al lector novel una visioacuten general de PHP 5 y le permitiraacute comenzar a desarrollar sus primeras aplicaciones La segundaparte algo maacutes compleja haraacute las delicias del usuario novel y del medio Esta cuenta con teacutecnicas avanzadas para la lectura escritura de archivos XML creacioacuten de imaacutegenes en tiempo de ejecucioacuten conexioshynes de FTP y correo electroacutenico o disentildeo de plantillas con Smarty

El Software Libre estaacute presente en el aacutembito de la programacioacuten Por eso podemos utilizar algunos programas libres como base para construir aplishycaciones maacutes complejas El disentildeo de plantillas o la creacioacuten de llamadas a procedimientos remotos no seriacutea posible sin las libreriacuteas Smarty o IXR para XML-RPC desarrolladas por la comunidad de PHP para su uso libre

Por tanto el libro va dirigido a usuarios noveles que no saben nada de PHP Pero tambieacuten a usuarios medios o avanzados que desean conocer las nuevas caracteriacutesticas de PHP 5 y manejar teacutecnicas avanzadas de coshymunicacioacuten y disentildeo

Organizacioacuten del libro

Este libro estaacute dividido en 20 capiacutetulos con los siguientes contenidos

bull Capiacutetulo 1 Introduccioacuten a PHP 5 La introduccioacuten a PHP hace un reshycorrido por las nociones baacutesicas de HTML Ademaacutes aprenderaacute coacutemo crear su primera paacutegina en PHP y coacutemo mezclar el coacutedigo HTML con PHP

bull Capiacutetulo 2 Variables constantes y tipos de datos Los valores que manejamos en los programas deben ser almacenados en zonas de me-

PHP 5 21

moria reservadas por PHP Estas zonas reciben el nombre de variables y pueden ser tratadas de diferentes forma dependiendo de los valores que guarden (nuacutemeros enteros cadenas de caracteres valores boolea-nos) Este capiacutetulo contiene todo lo necesario para comprender coacutemo maneja PHP 5 las variables y las constantes estableciendo una diferenshycia con otros lenguajes fuertemente tipados como Java o C

bull Capiacutetulo 3 Operadores Otro aspecto de los lenguajes de programashycioacuten tiene que ver con los siacutembolos que se utilizan para realizar operashyciones aritmeacuteticas loacutegicas o de asignacioacuten Cada uno de los siacutembolos recibe el nombre de operador Este capiacutetulo muestra por grupos todos los operadores con los que se puede encontrar en PHP 5 Asiacute podraacute ver operadores especializados en sumas restas multiplicaciones o dishyvisiones (aritmeacuteticos) operadores de igualdad desigualdad o asignashycioacuten (de comparacioacuten) incluso operadores de manejo a nivel de bits (binarios)

bull Capiacutetulo 4 Estructuras de control El flujo de los programas viene deshyterminado siempre por las estructuras de control Estas indican en cada momento el rumbo que debe llevar el coacutedigo y lo que debe mostrar nuesshytra paacutegina basaacutendose en el valor contenido en las variables Las estrucshyturas de control y los operadores estaacuten iacutentimamente relacionados y su unioacuten permite desviar a evolucioacuten del programa en uno u otro sentido Las estructuras de control que veraacute en este capiacutetulo le daraacuten la potencia suficiente para crear sus primeros programas funcionales

bull Capiacutetulo 5 Funciones Si su coacutedigo se hace muy extenso a medida que avanza en la comprensioacuten del libro en este capiacutetulo aprenderaacute a remeshydiarlo Las funciones permitiraacuten al lector agrupar fragmentos de coacutedishygo repetitivo y aislarlo en ficheros independientes Este capiacutetulo no soacutelo cubre los aspectos teoacutericos para la creacioacuten de funciones sino que adeshymaacutes es un compendio de buenas praacutecticas a tener en cuenta para que sus proyectos se desarrollen ordenadamente Los aspectos baacutesicos a trashytar son la creacioacuten de funciones propias y el paso de paraacutemetros entre funciones de varias formas diferentes

bull Capiacutetulo 6 Cadenas de caracteres y expresiones regulares La mayor parte de la informacioacuten que puede encontrar en las paacuteginas es texto Conocer todas las teacutecnicas para concatenar medir cortar y buscar texshytos es baacutesico para crear un proyecto basado en contenido dinaacutemico Un perioacutedico digital un Log o incluso su propio CMS ya no tendraacuten seshycretos despueacutes de leer este capiacutetulo Ademaacutes la gran potencia de buacutesshyqueda de patrones viene de la mano de las expresiones regulares Eacutestas

22 Coacutemo usar este libro

permiten encontrar palabras frases y patrones dentro de un texto deshyterminado para manipularlo a nuestro antojo

bull Capiacutetulo 7 Conjuntos de datos del tipo array Este capiacutetulo trata a fonshydo las colecciones de datos PHP 5 maneja los conjuntos de datos como arrays asociativos Es posible acceder a los valores de un array de forma simple utilizando un iacutendice como en C y de forma asociativa asocianshydo una palabra a un valor determinado dentro del array Los arrays tieshynen un incalculable valor en los posteriores capiacutetulos usaacutendose como valor de retorno de muchas funciones de conectividad de bases de dashytos lectura de archivos XML o creacioacuten de plantillas

bull Capiacutetulo 8 Paso de informacioacuten entre formularios Si en el capiacutetulo 1 pudo ver los conceptos baacutesicos de la creacioacuten de paacuteginas en este podraacute conocer las teacutecnicas para enviar informacioacuten a traveacutes de formularios La mayoriacutea de las paacuteginas utilizan formularios para interactuar con los usuashyrios Aprenderaacute a pasar variables y arrays entre dos paacuteginas y coacutemo recoshyger desde PHP 5 los valores que se enviacutean Ademaacutes podraacute saber la diferencia entre los meacutetodos GET y POST y las variables suacuteper-globales

bull Capiacutetulo 9 Programacioacuten orientada a objetos El gran avance queacute ha sufrido PHP 5 desde su versioacuten anterior ha sido la total incorporacioacuten de la sintaxis y teacutecnica orientada a objetos Esto permite desarrollar proshygramas reutilizables en varios proyectos Una de las ventajas de la proshygramacioacuten orientada a objetos es que nos permite utilizar software de otras personas simplemente conociendo los meacutetodos que implementa no es necesario conocer coacutemo funciona el objeto para utilizarlo En este capiacutetulo el usuario novel y medio aprenderaacute las nuevas caracteriacutesticas de la programacioacuten orientada a objetos de PHP 5 A partir del capiacutetulo 9 casi todos los ejemplos estaraacuten basados en esta metodologiacutea de trabajo

bull Capiacutetulo 10 Ficheros y almacenamiento de datos La forma maacutes natushyral de almacenar datos persistentes es guardarlos en un fichero de dashytos Es una tarea muy sencilla y no dependemos de la instalacioacuten de alguacuten programa externo como una base de datos El capiacutetulo 10 mueacutes- tra coacutemo almacenar variables y textos dentro de un archivo para desshypueacutes recuperarlo en nuestra paacutegina Ademaacutes aprenderaacute una serie de teacutecnicas para recuperar ficheros enviados a traveacutes de un formulario y para poner en descarga archivos del servidor

bull Capiacutetulo 11 Bases de datos con SQL y SQLite Sin duda la mejor forma de almacenar datos masivos es utilizar una base de datos PHP 5 incorshypora una API de gestioacuten de bases de datos SQLite que permite almaceshynar millones de registros de diferentes tipos en un archivo binario Lo

PHP 5 23

mejor de utilizar SQLite es que no necesita instalacioacuten de una base de datos ni su administracioacuten todo estaacute contenido dentro de la API Aunshyque este libro no estaacute dedicado a la programacioacuten con bases de datos se da una referencia de los usos maacutes comunes del lenguaje de consultas estructurado (SQL) para que se pueda iniciar en este complejo mundo

bull Capiacutetulo 12 PHP 5 y MySQL MySQL ha sido siempre la panacea del desarrollo en el aacutembito profesional Es una base de datos robusta que permite administracioacuten de usuarios y seguridad a nivel de tablas y celshydas Es algo compleja de administrar pero muy sencilla de manejar desde PHP 5 Su utilizacioacuten ha sido tal que en el mundo de desarrollo se habla de las paacuteginas LAMP (Linux + Apache + MySQL + PHP) En este capiacutetulo aprenderaacute a manejar las funciones maacutes caracteriacutesticas de MySQL y a utilizarlas por medio de objetos en sus aplicaciones La proacutexima aparicioacuten de MySQL 5 hace prever que la combinacioacuten con PHP seraacute perfecta (MySQL 5 + PHP 5 = 10)

bull Capiacutetulo 13 Sesiones y Cookies En este capiacutetulo se detallan las teacutecnishycas necesarias para grabar informacioacuten en el equipo de los usuarios Estas pequentildeas variables (Cookies) permiten crear un pequentildeo control de asistencia de sus usuarios o guardar configuraciones especiales En cuanto a las sesiones son muy necesarias a la hora de crear espacios de venta de productos Las sesiones identifican a un usuario en concreto dentro de una paacutegina y permiten asociar variables concretas a ese usuashyrio aunque la paacutegina esteacute siendo visitada por muchas personas a la vez

bull Capiacutetulo 14 Lectura y escritura de archivos XML Frente a una inmenshysa cantidad de tipos de archivos propietarios como los documentos DOC o XLS nos encontramos a una serie de archivos basados en el lenguaje XML Este tipo de archivos como SXW (Openoffice) o SVG (graacuteficos vectoriales) estaacuten creados para ser entendidos por las personas y por los ordenadores Por lo tanto crear programas que interpreten estos archivos no es nada complejo El capiacutetulo 14 muestra tres caminos disshytintos para leer archivos XML Dos de ellos que vienen funcionando desde versiones anteriores SAX y DOM Y uno nuevo implementado en PHP 5 para facilitar esta tarea al programados Ademaacutes se incluyen las pautas necesarias para que cree sus propios archivos XML con la metodologiacutea DOM

bull Capiacutetulo 15 Aplicaciones praacutecticas de XML Si en el capiacutetulo anterior sentaacutebamos las bases para la lectura de informacioacuten desde archivos XML en este capiacutetulo crearemos objetos que implementen aplicacioshynes reales y actuales para compartir informacioacuten Es muy habitual hoy

24 Coacutemo usar este libro

en diacutea que las paacuteginas lleven asociados un panel de noticias que se generan en portales diferentes Esta informacioacuten se puede mostrar grashycias a teacutecnicas como RSS

Ademaacutes de crear sus propios objetos de generacioacuten de contenido RSS y su lectura haremos hincapieacute en lo que actualmente se llaman servicios Los servicios son pequentildeos programas almacenados en alguacuten servidor que informan acerca de algo concreto Aquiacute aprenderaacute a crear sus sershyvicios con las teacutecnicas ya adquiridas en el capiacutetulo 14

bull Capiacutetulo 16 Generacioacuten de graacuteficos con PHP 5 La generacioacuten de graacuteshyficos desde PHP 5 es posible gracias a la utilizacioacuten de libreriacuteas extershynas como GD Esto le permite manipular archivos graacuteficos que sus usuarios puedan subir a traveacutes de un formulario Con esta libreriacutea pueshyde generar graacuteficos en miniatura para despueacutes de hacer clic en eacutel antildeashydir una marca de agua a todas las imaacutegenes antildeadiendo el logo de su empresa o asociacioacuten

Otra gran libreriacutea es JpGraph que permite crear todo tipo de graacuteficos estadiacutesticos Esto le serviraacute para conocer el nuacutemero de visitas por diacutea mes o antildeo comparativas anuales de ventas de productos y todo un abanico de posibilidades

bull Capiacutetulo 17 Gestioacuten de errores en PHP 5 Una vez terminada la aplishycacioacuten tendraacute que tener en cuenta las partes del coacutedigo donde puede tener problemas Algunos usuarios pueden introducir caracteres no permitidos o nuacutemeros donde se esperaban letras La gestioacuten de errores permite mostrar al desarrollador y al usuario doacutende aparece el error y el tipo de fallo que se ha producido Una buena gestioacuten de errores haraacute que su programa sea maacutes fiable

bull Capiacutetulo 18 Conexiones desde PHP 5 La conectividad de PHP con otras aplicaciones o servicios ha sido siempre una preocupacioacuten de sus desarrolladores Asiacute desde anteriores versiones puede encontrar coshynectividad con servicios LDAP POP3 SMTP o FTP

Este capiacutetulo trata de abarcar dos servicios muy utilizados por la coshymunidad de usuarios El FTP en primer lugar para enviar y recuperar informacioacuten de otros servidores desde un programa escrito en PHP Y en segundo lugar el manejo de las funciones necesarias para enviar informacioacuten por correo electroacutenico

bull Capiacutetulo 19 Creacioacuten de archivos PDF El formato de texto maacutes difundishydo en Internet es el PDF Tanto se ha extendido este formato que la mayoshyriacutea de las paacuteginas profesionales contienen archivos PDF con diferentes contenidos Desde paacuteginas de contenido tecnoloacutegico hasta las de cocina

PHP 5 25

exportan sus contenidos en PDF para que sus usuarios puedan disfrutar desde su ordenador del manual del video o la receta de la semana

En este capiacutetulo veraacute paso a paso coacutemo generar un archivo PDF comshypleto desde la cabecera hasta el pie de paacutegina pasando por todo tipo de textos e imaacutegenes

bull Capiacutetulo 20 Plantillas con Smarty La uacuteltima aportacioacuten de este libro tiene que ver con la tendencia de separar el coacutedigo PHP de la presentashycioacuten en HTML Smarty provee unos sencillos mecanismos desde PHP que permiten realizar sencillamente esta separacioacuten Ademaacutes de las caracteriacutesticas baacutesicas de las plantillas la potencia de Smarty reside en la compilacioacuten del disentildeo cada vez que cambian los datos hecho que otorga a Smarty el puesto nuacutemero 1 en velocidad en el ranking de sisteshymas de plantillas En este capiacutetulo aprenderaacute a crear plantillas con Smarty que permitiraacuten cambiar el aspecto graacutefico de su aplicacioacuten sin tocar el coacutedigo escrito en PHP 5

bull Apeacutendice A Instalacioacuten de Apache y PHP 5 en distintos Sistemas Opeshyrativos La instalacioacuten de PHP 5 es muy sencilla en gnuLinux MacOSX y Windows El Apeacutendice muestra los pasos necesarios para instalar un servidor Apache con el parse de PHP 5 listo para ser utilizado con los ejemplos En cada caso la instalacioacuten se hace de una forma distinta Hemos buscado para cada Sistema Operativo la opcioacuten maacutes sencilla que es utilizando alguacuten paquete compacto que se instale y deje listo el sistema Puesto que es un libro para principiantes hemos huido de crear PHP 5 desde el coacutedigo fuente compilando el programa

bull Apeacutendice B Configuracioacuten baacutesica de phpini El archivo de configurashycioacuten php i n i contiene aspectos de funcionamiento de PHP 5 que pueshyden cambiarse sin necesidad de compilar el programa Este Apeacutendice contiene algunos paraacutemetros de configuracioacuten que pueden ser uacutetiles

bull Apeacutendice C Bibliografiacutea Este libro estaacute basado en el conocimiento adquirido tras la lectura de numerosos libros sobre la temaacutetica paacutegishynas Web y revistas profesionales del sector Este Apeacutendice cubre todas las posibilidades dando al lector un camino a seguir despueacutes de termishynar el presente libro

Convenios que emplea este libro

El nombre de los comandos funciones meacutetodos u objetos aparecen resalshytados en el libro de la siguiente forma ob j e t o

26 Coacutemo usar este libro

Algunas palabras teacutecnicas que no tienen una traduccioacuten faacutecil al castellano o simplemente estaacute fuertemente asentada en el idioma teacutecnico aparecen de la siguiente forma array true ofalse

En el libro aparecen resaltados una serie de temas circunstancias o aconshytecimientos extraordinarios de la siguiente forma array true ofalse

Nota

Anotaciones sobre el texto

Advertencia

Informacioacuten importante a tener en cuenta a la hora de desarrollar un programa Explican de alguna manera posibles equivocacioshynes o ayudas para no caer en errores frecuentes

Truco

Consejo o informacioacuten importante que puede facilitar el trabajo

Los ejemplos en la Web de Anaya

La mayoriacutea de los ejemplos del libro se pueden obtener en la Web de Anashyya Multimedia en la direccioacuten siguiente

httpwwwanayamultimediaes Seleccionando los menuacutes Atencioacuten a clientegtComplementosgtManuales lmprescindiblesgtManual Imprescindible de PHP 5 Ademaacutes de los ejemplos puede encontrar las aplicaciones externas o enshylaces a las mismas que utilizamos para desarrollar algunos ejemplos como Smarty FPDF JpGraph o la libreriacutea IXR

Todos los ejemplos han sido probados en el servidor Apache para MacOSX con el paquete de PHP 501 y en un servidor Apache sobre gnuLinEx Todas las capturas de pantalla se han realizado con el navegador Grulla (Mozilla Firefox) de gnuLinEx 2004

Proacutelogo

28 Proacutelogo

Una de las preguntas maacutes interesantes que nos hacen es queacute hace que PHP tenga tanto eacutexito Distintas personas nos han dado respuesta a esta preshygunta Algunos sostienen que es su excelente conexioacuten con bases de dashytos otros que se debe al coacutedigo abierto por el contrario otros mantienen que es su funcionamiento Sin embargo nuestra opinioacuten difiere PHP pershymite que cualquier usuario obtenga raacutepidamente resultados de forma senshycilla incluso aquellos que no posean experiencia en programacioacuten Al mismo tiempo a diferencia de las herramientas RAD PHP permite el deshysarrollo de proyectos tan complejos como se desee En nuestra opinioacuten esta combinacioacuten ausente en la mayoriacutea de las plataformas Web actuales es lo que hace que PHP sea especial

Lograr el equilibrio entre estas dos liacuteneas (la potencia y la sencillez) no ha sido faacutecil pero siacute imprescindible para el eacutexito de PHP como tambieacuten lo son las nuevas caracteriacutesticas que permiten al desarrollador aprovechar la uacuteltima tecnologiacutea

PHP 5 es el producto de este importante equilibrio Aunque dotado de muchas funciones nuevas esta versioacuten es tan accesible como lo fueron PHP 3 y PHP 4 con lo que permite un raacutepido aprendizaje para aquellos que se inicien De hecho algunas de las novedades basadas en la interfaz de Zend Engine II como SimpleXML SQLite y SOAP hacen maacutes sencillo el uso de PHP al tiempo que incrementa el potencial de aquellos usuarios noveles pues les permite trabajar con XML SQL y Web Services sin esfuerzo

La nueva generacioacuten PHP tambieacuten supone una buena noticia para desashybolladores experimentados En primer lugar por simplificar todas aqueshyllas funciones que ya se han indicado (al contrario de lo que normalmente se piensa ni siquiera a los desabolladores avanzados les gusta trabajar a menos que sea imprescindible) y en segundo lugar por poner a su disposhysicioacuten funciones mejoradas Las nuevas opciones orientadas a objetos de Zend Engine II son un regalo para el desarrollo de aplicaciones de media y gran escala como la nueva extensioacuten mysqli y el nuevo moacutedulo de inteshygracioacuten NET que permite la creacioacuten de aplicaciones hiacutebridas de PHP que emplean la estructura NET

Este libro es una gran introduccioacuten a PHP en general y de PHP 5 en partishycular Si no tiene experiencia previa con PHP e incluso si no tiene ningushyna experiencia en programacioacuten en breve podraacute trabajar con eacutel

Zeev Suraski Tel A v i v

Andi Gutmans Cupertino

Introduccioacuten

30 Introduccioacuten

Historia de PHP

Rasmus Lerdorf miembro del equipo de desarrollo de Apache creoacute PHP (Personal Home Page) en 1994 Su uacutenica intencioacuten fue la de crear un pequeshyntildeo sistema de control para verificar el nuacutemero de personas que leiacutean su curriculum vitae en la Web

En los meses siguientes a su creacioacuten PHP se desarrolloacute en torno a un grushypo de programadores que comprobaban el coacutedigo y sus revisiones Para dar maacutes potencia al sistema Rasmus creoacute funciones en lenguaje C para permitir conexioacuten a bases de datos Este fue el comienzo de la potencia real del leguaje

En 1995 aparecioacute un conjunto de herramientas sobre PHP Esta biblioteca se llamoacute Herramientas para paacuteginas personales y conteniacutean un analizashydor de coacutedigo muy sencillo un libro de visitas un contador y algunas macros que facilitaban el trabajo de los disentildeadores

A mediados de 1995 aparecioacute una revisioacuten puacuteblica llamada PHPFI 20 Esta nueva versioacuten contaba con un analizador sintaacutectico reescrito desde 0 ademaacutes de unas herramientas escritas para el tratamiento de datos desshyde un formulario (de ahiacute el nombre aacuteeFI Form iacutenterpreter) y conectividad con mSQL (Gestor de bases de datos)

Hacia 1997 PHPFI se estaba usando en maacutes de 50000 paacuteginas en todo el mundo En este periacuteodo de tiempo Zeev Suraski y Andi Gutmans decishydieron crear una nueva versioacuten de PHPFI para solventar unos probleshymas con una aplicacioacuten de comercio electroacutenico que estaban desarrollando PHP 30 nacioacute con suculentas innovaciones como la conectividad con vashyrios gestores de bases de datos protocolos y una API ampliada La vershysioacuten oficial de PHP 30 vio la luz en junio de 1998 donde se contemplaba ya la programacioacuten orientada a objetos

En 1999 se realizoacute la primera revisioacuten del motor Zend (Zend Engine) que aportaba modularidad claridad y herramientas de optimizacioacuten para paacuteshyginas de gran escala Zend viene de la unioacuten de Zeev y Andi

PHP 40 vio la luz en mayo de 2000 dividida en 3 partes El motor Zend la API de servidor y los moacutedulos de funcionas El motor Zend es el responshysable de analizar el coacutedigo PHP definir la sintaxis y del lenguaje de proshygramacioacuten La API permite la comunicacioacuten con el servidor Con esta API es posible utilizar PHP desde varios servidores Los moacutedulos contienen funciones para el manejo de cadenas archivos XML o tratamiento de imaacuteshygenes

PHP 5 31

La orientacioacuten a objetos no estaacute muy lograda en PHP 40 Los objetos tieshynen un tratamiento muy pobre e iloacutegico La definicioacuten de las variables miembro (propiedades) y los meacutetodos son siempre puacuteblicos por lo que la encapsulacioacuten es nula Todos los objetos se pasan por valor por defecto cuando deberiacutean pasarse por referencia

Todas estas propuestas realizadas por el equipo de desarrollo de PHP han desembocado en la creacioacuten del motor Zend 20 y su consecuencia PHP 5

PHP 5 incorpora una verdadera orientacioacuten a objetos Antildeadiendo las pashylabras reservadas public protected y priacutevate a la definicioacuten de las propiedashydes y meacutetodos de los objetos se permite una verdadera encapsulacioacuten Ademaacutes del considerable avance con respecto a los objetos PHP 5 incorshypora un control de errores muy mejorado al estilo de los lenguajes de proshygramacioacuten maacutes avanzados

Nota

Despueacutes de una encuesta entre desarrolladores y usuarios de PHP se decidioacute cambiar el significado de PHP a PHP Hypertext Pre-processor Este cambio sigue los pasos de Richard Stallman al nombrar a su sistema operativo GNU (GNU is not Unix) doshytando a la palabra PHP de recursividad Es un juego de palabras muy utilizado en el ambiente hacker

Nuevas Caracteriacutesticas de PHP 5

Existen muchas razones para elegir PHP 5

Faacutecil de usar

PHP 5 es un lenguaje muy faacutecil de aprender con respecto a otros lenguashyjes utilizados para el mismo propoacutesito como JAVA o ASP Debido a esto no es necesario hacer un estudio muy concienzudo de sus funciones para realizar programas sencillos que nos resuelvan la mayoriacutea de los probleshymas diarios

La mayoriacutea de las funciones maacutes usuales estaacuten disponibles por defecto como la conexioacuten a bases de datos o la utilizacioacuten de servidores IMAP Existe una gran cantidad de paacuteginas con documentacioacuten y programas heshychos por desarrolladores que se pueden leer y modificar libremente

32 Introduccioacuten

Embebido en HTML

Las paacuteginas escritas en PHP son simples paacuteginas en HTML que contieshynen ademaacutes de las etiquetas normales el programa que queremos ejecushytar Por ejemplo

ltHTMLgt ltBODYgt ltHEADgt ltTITLEgtEjemplo de PHP5 embebidoltTITLEgt ltHEADgt ltBODY ltPgtEsto es HTML del buenoltPgt ltphp Aquiacute comienza el coacutedigo PHP Lo siguiente es una simple asignacioacuten de variables y su salida por pantalla $nombre=Luis Miguel $apellidos=Cabezas Granado $fecha_hoy=date(d-ra-Y1) gt ltPgtEste paacuterrafo contiene HTML y PHP El autor del script es ltphp echo ($nombre $apellidosgt gtlt Pgt ltPgtLa fecha de ejecucioacuten del script es ltphp echo($fecha_hoy)gtltPgt ltBODYgt ltHTMLgt

Cuando un cliente solicita esta paacutegina el servidor preprocesa los datos y ejecuta las instrucciones de PHP En este caso las variables (las palabras que tienen el signo $ delante) se llenan con los valores que hay a la dereshycha del signo igual Una vez resuelto todo el proceso el servidor le enviacutea al cliente una paacutegina soacutelo con etiquetas de HTML La figura 11 muestra este proceso

Si inspeccionamos ahora el coacutedigo que tenemos en el navegador nos dareshymos cuenta de que las etiquetas de PHP han desaparecido

ltHEAD ltTITLEgtEjemplo de PHP5 embebido-TITLEgt ltHEADgt ltBODYgt ltPgtEsto es HTML del buenoltPgt ltPgtEste paacuterrafo contiene HTML y PHP El autor del script es Luis Miguel Cabezas GranadoltPgt ltPgtLa fecha de ejecucioacuten del script es 05-07-2004ltPgt ltBODYgt ltHTMLgt

higura ii Kesuitaao ae ejecutar un scnpi sencillo

La consecuencia maacutes inmediata es que no es necesario compilar el prograshyma en coacutedigo binario antes de poder testar si funciona o no PHP es un lenshyguaje interpretado como otros muchos en el mercado (ASP Python o JSP)

Multiplataforma

PHP 5 se ejecuta en multitud de plataformas Sistemas Operativos y Sershyvidores existentes Es compatible con los tres servidores liacutederes del mershycado Apache Microsoft Internet Information Server y Netscape Enterprise Server

Tabla 11 Sistemas Operativos y Servidores para PHP 5

Basados en UNIX Windows

Sistema Operativo AIX AUX BSDI Digital UNIXTru64 FreeBSD HP-UX IacuteRIX MacOS X gnuLinux gnuLinEx NetBSD OpenBSD SCO UnixWare Solaris SunOS Ultrix Xenix y muchos maacutes Windows 98Me Windows NT 2000XP2003

Servidores Apache fhttpd Netscape US PWS Netscape Apashyche Omni

Puesto que PHP se ejecuta en todos los Sistemas Operativos indicados en la tabla 11 y en la mayoriacutea de las plataformas hardware existentes (Intel

PHP 5 33

34 Introduccioacuten

A M D PowerPc SPARC etceacutetera) nos seraacute muy sencillo conseguir un lashyboratorio de pruebas para nuestros script

Licencia Open Source

La licencia de Coacutedigo Abierto implica que el coacutedigo fuente de PHP 5 es libre de ser descargado e inspeccionado por nosotros La consecuencia principal es que el coste del producto en la mayoriacutea de los casos es de 0 Euros Tener el coacutedigo fuente de PHP 5 sirve entre otras cosas para poshyder hacer nuestro servidor a medida es decir podemos compilar el proshygrama con las opciones que realmente utilicemos (base de datos LDAP)

Si acompantildeamos Apache el servidor maacutes popular a la instalacioacuten de PHP 5 y antildeadimos alguna base de datos Open Source como PostgreSQL tendreshymos un sistema completo de script de servidor cuyo coste es nulo frente a otras opciones en las que es necesario el uso de licencias

Multitud de Extensiones

PHP 5 se desarrolla para dar la mayor versatilidad y flexibilidad a los usuashyrios que lo utilizan Es por esto por lo que existen muchas extensiones del lenguaje que permiten utilizar nuevas bases de datos protocolos enlaces a libreriacuteas etceacutetera

El acceso a bases de datos tiene una gran potencia implementando soporshyte nativo para 15 Sistemas Gestores de Bases de Datos muy populares En cuanto a los protocolos podemos contar con extensiones que controlan el acceso a LDAP IMAP o POP3 Tambieacuten se ha cuidado el soporte para crear imaacutegenes en tiempo de ejecucioacuten gracias a la libreriacutea GD

Dada la importancia del desarrollo del lenguaje XML en los uacuteltimos antildeos PHP 5 incorpora tres meacutetodos de acceso a este tipo de archivos SAX D O M y simpleXML Ademaacutes se incorpora a PHP 5 la gestioacuten de errores mediante el manejo de excepciones

En esta versioacuten se han antildeadido facilidades para utilizar los repositorios de coacutedigo de PEAR

Velocidad e incorporacioacuten de objetos

El nuevo motor Zend 20 acelera los procesos de ejecucioacuten del coacutedigo Ademaacutes incorpora un nuevo modelo de objetos que permite crear ciacutea-

Figura 12 Uso de PHP desde el antildeo 2000

Gran Comunidad de apoyo

PHP 5 se ha escrito bajo el auspicio del Coacutedigo Abierto Por lo tanto exisshyte una comunidad que apoya su desarrollo en colaboracioacuten La ventaja principal es que existen multitud de paacuteginas listas de correo y foros de debate cuyo tema de conversacioacuten es el manejo de este lenguaje de proshygramacioacuten

Esta comunidad sirve de apoyo para todos los que necesitamos conocer desde los aspectos maacutes baacutesicos hasta las implementaciones maacutes complishycadas Tan pronto como hagamos uso de esta ayuda nos sentiremos oblishygados a prestar la nuestra a usuarios principiantes y asiacute la Comunidad se

PHP 5 35

ses y meacutetodos privados protegidos y puacuteblicos clases abstractas e inter-faces

Popularidad

El uso de PHP se ha disparado desde el antildeo 1999 como puede verse en la figura 12

36 Introduccioacuten

iraacute ampliando Si nuestros conocimientos llegan a superar alguacuten diacutea los objetivos de este libro podemos pensar en contribuir enviando fallos en el lenguaje respondiendo a mensajes de las listas de correo participando en foros de debate o escribiendo extensiones en lenguaje C

Objetivos del libro

A la hora de seleccionar este libro o cualquier otro sobre PHP 5 creo que es esencial que conozca los objetivos que marcan sus capiacutetulos Este libro en concreto estaacute pensado para

bull Tener una visioacuten general de los lenguajes de script para desarrollo

bull Conocer las ventajas de PHP 5 frente a otros lenguajes similares Tener una visioacuten general de las nuevas caracteriacutesticas que ofrece PHP 5

bull Aprender los conceptos baacutesicos para empezar a desarrollar aplicacioshynes sencillas que muestren contenido dinaacutemico

bull Identificar claramente todas las caracteriacutesticas de la orientacioacuten a objeshytos y aprender a desarrollar aplicaciones divididas en partes con moacuteshydulos reutilizables en distintos proyectos

bull Sacar partido de la API SQLite y del gestor de bases de datos MySQL para crear aplicaciones maacutes profesionales que nutran de contenido las paacuteginas

bull Crear formularios que enviacuteen informacioacuten y ficheros entre varias paacuteshyginas de distinta forma

bull Aprender a generar archivos para Internet de distintos formatos Los archivos XML o PDF se han vuelto indispensables en esta era y muy uacutetiles para exportar informacioacuten a los usuarios

bull Conocer las funciones baacutesicas para la creacioacuten de paacuteginas que controshylen y manipulen imaacutegenes Ademaacutes conoceraacute herramientas para geshynerar en el momento graacuteficos estadiacutesticos de diferentes formas

bull Controlar todos los errores que puedan producir los programas evishytando mostrar en el navegador mensajes de error geneacutericos para mosshytrar errores controlados por nosotros

bull Generar plantillas con libreriacuteas para separar el coacutedigo escrito en PHP de la presentacioacuten creada con HTML o alguacuten programa de disentildeo

El libro crea una base muy fuerte para comenzar a realizar aplicaciones profesionales Es evidente que la creacioacuten de archivos XML PDF genera-

PHP 5 37

cioacuten de graacuteficos o plantillas Smarty necesitan un libro entero para cubrir todas las caracteriacutesticas que ofrecen Este libro da una visioacuten general a los lectores y permite conocer las herramientas que actualmente se utilizan para que cada uno pueda investigar por su cuenta las que maacutes le interese

Capiacutetulo 1

Introduccioacuten aPHP5

En este capiacutetulo aprenderaacute a

bull Diferenciar entre scripts de cliente y servidor bull Utilizar diferentes tipos de etiquetas de inicio de PHP bull Escribir su primer programa en PHP bull Conocer las etiquetas HTML

40 Capiacutetulo 1

Introduccioacuten

El mundo de los desarrolladores de paacuteginas ha cambiado de forma vertishyginosa en los uacuteltimos antildeos En poco tiempo han surgido tecnologiacuteas y reshyvisiones de esas tecnologiacuteas que hacen que los programadores tengamos que reciclarnos continuamente

Hace unos antildeos el desarrollo de grandes paacuteginas era complicado de manshytener El lenguaje existente era uacutenicamente HTML y solo permitiacutea crear las paacuteginas y subirlas a un servidor El problema de esto es que modificar alguacuten dato de una de las paacuteginas implicaba un trabajo extra que incluiacutea descargarla modificarla maquetarla de nuevo y subirla al servidor

Actualmente existe un conjunto de lenguajes que permiten desarrollar paacutegishynas Web dinaacutemicas es decir que el contenido puede variar muy raacutepidamente sin ninguacuten esfuerzo por parte de los desarrolladores Eacutestos se denominan lenguajes de script de servidor porque la ejecucioacuten del programa se realiza en el servidor Web donde se encuentra alojada la paacutegina Existe un largo compendio de lenguajes que se pueden utilizar para la creacioacuten de paacuteginas Web dinaacutemicas ASP de Microsoft Java y JSP de Sun Perl Python PHP

HTML estaacutetico

El tipo maacutes baacutesico de paacutegina Web es completamente estaacutetico basado en texto plano y completamente escrito en HTML La paacutegina siguiente es un ejemplo de Web estaacutetica

ltHTMLgt ltHEADgt

ltTITLEbLibros sobre PHP 5 y gnuLinuxltTITLEgt ltHEADgt ltBODYgt ltTABLE BORDER-lgt ltTRgt

ltTDgtTiacutetulo de libros americanos sobre PHP 5ltTDgt ltTRgt ltTABLEgt ltulgt ltlixbgt Advanced PHP Programmingltbxbrxligt ltlixbgtPHP5 and MySQL bibleltbxbrxligt ltlixbgtLearning PHP 5ltbgtltbrxligt ltlixbgtUpgrading to PHP 5ltbxbrxligt ltlixbgtBeginning PHP 5 and MySQLltbxbrxligt

Introduccioacuten a PHP 5 41

ltlixbgtPHP 5 Power Programmingltfcgtgtltbrgtltligt lt u lgt ltTABLE border=lgt ltTRgt ltTDgtTiacutetulo de libros americanos sobre gnuLinuxltTDgt ltTRgt ltTABLEgt ltulgt ltlixbgtRunning Linuxltbxbrxligt ltlixbgtLinux in a Nutshellltbxbrxligt ltlixbgtHow Linux Worksltbxbrxligt ltlixbgtLinux for Non-Geeksltbxbrxligt ltulgt ltBODYgt ltHTHLgt

Figura 11 Ejemplo de paacutegina Web estaacutetica

La figura 11 muestra el ejemplo de una Web estaacutetica El funcionamiento de Internet es algo complejo para explicarlo en este capiacutetulo pero vamos a dar vinas nociones baacutesicas sobre lo que pasa tras la peticioacuten de una paacutegina Web por un cliente Los pasos que sigue nuestro navegador de Internet son

bull Nuestro ordenador solicita al servidor una paacutegina Web a traveacutes de Inshyternet

bull El servidor enviacutea los datos solicitados en formato de texto

42 Capiacutetulo 1

bull El navegador recibe estos datos interpreta la paacutegina Web enviada y la muestra en la pantalla de acuerdo con la resolucioacuten del monitor las preferencias del usuario y alguacuten otro factor

En la figura 12 podemos ver todo el proceso

Figura 12 Esquema de peticioacuten de una Web estaacutetica

Las paacuteginas Web estaacuteticas no permiten apenas una interactividad con el usuario final Por eso han aparecido numerosas tecnologiacuteas que hacen maacutes usable las paacuteginas y eliminan algunas restricciones o limitaciones Los lenshyguajes Javascript Vbscript CSS o los ap-plet de Java ofrecen una mayor interactividad pero son dependientes del navegador que utilicemos o de programas externos

Tecnologiacuteas del lado del cliente

Muchas de las mejoras antildeadidas al lenguaje HTML pertenecen a tecnoloshygiacuteas del lado del cliente es decir que se descargan junto con la paacutegina Web solicitada al servidor y se ejecutan en nuestro ordenador local La tabla 11 todas las tecnologiacuteas aparecidas hasta ahora del lado del cliente Estas tecnologiacuteas aunque son maacutes llamativas y permiten desarrollar la imashyginacioacuten en pro del disentildeo dependen totalmente de las caracteriacutesticas del navegador Por ejemplo si tiene un ordenador ibook de Apple con un Sisshytema Operativo gnuLinux Debiacutean (como el autor) le seraacute complicado obshytener una maacutequina virtual de Java y un inteacuterprete de Flash Las tecnologiacuteas de cliente no pueden rescatar datos de servidores porque su ejecucioacuten es uacutenicamente en local Eacutesto los imposibilita para recuperar informacioacuten de bases de datos o servicios

introduccioacuten a PHP 5 43

Tabla 11 Tecnologiacuteas del lado del cliente

[Tecnologiacutea Descripcioacuten Efecto de ejemplo

CSS HTML Sirve para dar formato a las Enlaces con movi-Dinaacutemico paacuteginas color tamantildeo capas efectos miento Javascript Manejo de eventos del navegador Imaacutegenes que Vbscript cambian cuando

se aproxima el ratoacuten Applets Aplicaciones pequentildeas Puzzles conectivi-de Java dad con bases de

datos Animaciones Animaciones graacuteficas Peliacuteculas iexclnteracti-Flash vas

Tecnologiacuteas del lado del servidor

Los lenguajes del lado del servidor son invisibles para los clientes Las paacuteginas que utilicen scripts de este tipo contienen el coacutedigo entre etique-fas parecidas a las de HTML pero eacutestas desaparecen cuando el cliente reshycibe la paacutegina

Los pasos que debe seguir nuestro navegador de Internet son

bull Nuestro ordenador solicita al servidor una paacutegina Web a traveacutes de Inshyternet

bull El servidor comprueba si la paacutegina solicitada contiene scrvpt del lado del servidor (PHP ASP JSP etceacutetera)

bull Ejecuta los posibles scripiacutes y antildeade el resultado final a la paacutegina Web resultante

bull El navegador recibe estos datos interpreta la paacutegina Web enviada y la muestra en la pantalla de acuerdo con la resolucioacuten del monitor las preferencias del usuario y alguacuten otro factor

La figura 13 muestra el proceso Los lenguajes del lado del servidor necesitan un motor (un programa) que interprete el coacutedigo Este programa puede formar parte o no del servidor Web En nuestro caso utilizaremos el motor Zend Engine 20 para parsear (interpretar) los proshygramas escritos en PHP 5

Figura 14 Zend Studio 351 para MacOSX

Suponiendo que ya tiene un servidor para probar los programas o ha leiacuteshydo el Apeacutendice A para instalar su propio servidor Web con PHP 5 vamos a crear nuestro primer programa del lado del servidor Para escribir los programas puede utilizar cualquier editor de texto plano

44 Capiacutetulo 1

Introduccioacuten a PHP 5 45

En gnuLinux tiene algunos editores libres que funcionan muy bien Sus nombres son Bluefish o Anjuta En entornos propietarios como Windows o MacO^X existen editores proshyfesionales que ademaacutes de disentildear paacuteginas Web permiten antildeadir todo tipo de coacutedigo PHP eso siacute los programas no son gratuitos y hay que pagar una elevada licencia por su uso Para los tres sistemas operativos tenemos una impresionante herramienta de edicioacuten y depuracioacuten creada por los programa^ores de PHP 5 La herramienta Zend Studio tiene dos versiones una de pago bajo licenshycia con muacuteltiples opciones de depuracioacuten y otra gratuita con opciones de desarrollo tan interesantes como el auto completado de funciones y variables

Etiquetas de PHP

Lo primero que debe saber es que todo prograrr1^ escrito en PHP debe empezar por unas etiquetas determinadas

ltphp gt

Ademaacutes aacutee esta iacuteoxma oacutee iacutemciax xm programa pu^dt ^urf^cam -iquesti -hiti iquesti-vo php i n i para que sus programas puedan empezar entre

lt gt

Nota

El archivo php i n i contiene la configuracioacuten de PHP en ese moshymento Cambiando algunos paraacutemetros podraacute cambiar la forma de funcionar del parser

El paraacutemetro s h o r t - o p e n - t a g puede igualarse a off o a on Si contiene el valor on PHP permitiraacute el uso de la etiqueta cofta Otra forma posible de empezar un programa escrito en PHP es utilizando las etiquetas de ASP Mucha gente que desarrolla con programas de Microsoft como Fron-tPage para generar paacuteginas Web utiliza esta forma de empezar el coacuteshydigo

lt gt

46 Capiacutetulo 1

Nuestro primer programa en PHP 5

Despueacutes de estas pequentildeas nociones ya estaacute preparado para crear su prishymer programa Eacuteste le va a permitir tener una visioacuten de la configuracioacuten global de PHP 5

Puede escribir el programa siguiente en cualquier editor de texto como vimos anteriormente

ltHTMLgt

ltHEADgt ltTITLEgtMi primer programa en PHP 5ltTITLEgt ltHEADgt ltBODYgt ltphp echo Este es el tiacutepico Hola Mundo ltbrxbrgt phpinfo() gt ltBODYgt ltHTMLgt

Como puede ver el programa contiene la estructura normal de una paacutegishyna Web La etiqueta ltHTMLgt define el comienzo y el final de la paacutegina Esta puede dividirse en dos partes La primera estaacute separada por la etishyqueta ltHEADgt y contiene informacioacuten sobre el autor tiacutetulo y meta datos que pueden servir para antildeadir coacutedigo Javascript o CSS La segunda parte es el cuerpo de la paacutegina Web es decir contiene todos los datos que veraacute el usuario en el navegador Estaacute separada entre etiquetas ltBODYgt

Dentro del BODY puede ver que empleamos las etiquetas de inicio y fin de programa PHP Dentro de estas etiquetas hay dos funciones que hacen cosas distintas Las funciones son programas ya creados y funcionales que pueden utilizarse en el transcurso de nuestro programa Existen en PHP 5 una infinidad de funciones uacutetiles para el manejo de cadenas de caracteshyres funciones aritmeacuteticas o funciones para mostrar texto en pantalla La funcioacuten echo ) se encarga de mostrar los datos en pantalla en este caso se encargaraacute de mostrar la frase Este es el tiacutepico Hola Mundo Ademaacutes imprime dos etiquetas ltbr gt que no se muestran porque tienen sentido dentro de HTML La etiqueta ltbrgt antildeade un salto de liacutenea a la paacutegina Web

La funcioacuten phpinf o () enviacutea al navegador la configuracioacuten de PHP que estamos utilizando en el servidor Aquiacute aparece la configuracioacuten que se ha utilizado para compilar el parser las libreriacuteas auxiliares que contiene el sistema que se estaacute utilizando etceacutetera

Introduccioacuten a PHP 5 47

Nota r Durante el proceso de aprendizaje del libro conoceraacute muchas funshyciones y sus aplicaciones inmediatas En el capiacutetulo 5 del libro aprenderaacute a crear sus propias funciones

El resultado de la ejecucioacuten del programa lo muestra la figura 15

Figura 15 Resultado de nuestro primer script

Repaso de HTML

El lenguaje de marcas de hipertexto se ha convertido en el principal refeshyrente de la Web Para seguir adecuadamente los contenidos del libro neshycesitaraacute conocer el funcionamiento de HTML para insertar sus programas escritos en PHP 5

Cabecera y cuerpo de una paacutegina Web

Todo documento escrito en HTML estaacute contenido entre las etiquetas ltHTMLgt y ltHTMLgt Se pueden estructurar en

bull Cabecera Entre las etiquetas ltHEADgt y ltHEADgt Contiene informashycioacuten relativa al documento

48 Capiacutetulo 1

bull Cuerpo Entre las etiquetas ltBODYgt y ltBODYgt Debe contener la inshyformacioacuten que el usuario veraacute en el navegador

Cabecera

El tiacutetulo del documento debe ir entre las etiquetas ltTITLEgt y ltTITLEgt Este tiacutetulo se mostraraacute en la parte superior del navegador Ademaacutes se utiliza como descripcioacuten si guarda la paacutegina en el apartado de Favoritos

Para antildeadir informacioacuten sobre el autor fecha de expiracioacuten o el programa con el que hemos disentildeado la Web puede utilizar la etiqueta ltMETAgt

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODYgt ltBODYgt

ltHTMLgt

Algunas etiquetas permiten la inclusioacuten de atributos La etiqueta ltMETAgt contiene el atributo NtildeAME y CONTENT para sentildealar en el documento el autor de la paacutegina Los buscadores haraacuten buen uso del contenido de estas etishyquetas para enlazarlas en sus motores de buacutesqueda

Cuerpo del documento

La etiqueta ltBODYgt tambieacuten puede contener atributos que modifiquen el aspecto exterior de la paacutegina

Los principales atributos son

bull BGCOLOR Indica el color de fondo de la Web

bull TEXT Color general del texto

bull LINK Color del texto de los enlaces

bull VLINK Color de los enlaces que ya han sido utilizados

bull ALINK Color de activacioacuten del texto

bull BACKGROUND Imagen de fondo de un documento

En el siguiente ejemplo puede ver la utilizacioacuten de los atributos de la etishyqueta del cuerpo

ltHTMLgt ltHEADgt

introduccioacuten a PHP 5 49

ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODY BGCOLOR=FF0 0 00 LINK=000000 VLINK=FF00FFgt ltBODYgt ltHTMLgt

Nota

El color se escribe en formato RGB Esto quiere decir que un color puede dividirse en tres componentes (rojo verde y azul) y elishygiendo la intensidad de cada componente se forma el color deseashydo Cada componente tiene 2 cifras en hexadecimal Asiacute el color FF0000 tiene al nuacutemero FF hexadecimal (255 en decimal) en su componente rojo y los demaacutes a 0 por lo tanto el color resulshytante seraacute Rojo intenso

Paacuterrafos y saltos de liacuteneas

Los textos pueden escribirse dentro de la etiqueta ltBODYgt en el orden que quiera los navegadores no interpretan los saltos de liacuteneas o liacuteneas en blanshyco eliminando todos los espacios vaciacuteos Para crear un salto de liacutenea tiene que utilizar ltBRgt escrito despueacutes del texto Para crear paacuterrafos tendraacute que escribir el texto entre las etiquetas ltPgt ltpgt

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltHEADgt ltB0DYgt ltPgt Esto es paacuterrafo y tambieacuten un salto de liacuteneasbrgt ltPgt ltBODYgt ltHTMLgt

Estilo de texto

Podemos resaltar partes del texto con algunas etiquetas

bull ltBgt Bloque de texto en negrita bull ltIgt Texto en cursiva

Figura 16 Diferentes estilos de textos

Ademaacutes puede elegir el formato de las fuentes de cada bloque de texto

50 Capiacutetulo 1

bull ltUgt Bloque de texto subrayado bull ltBIGgt Texto con su mayor tamantildeo bull ltSMALLgt Texto con m tamantildeo pequentildeo bull ltCENTERgt Texto centrado

bull ltSUPgtSuperiacutendice bull ltSUBgt Subiacutendice

El ejemplo siguiente que tambieacuten se muestra en la figura 16 muestra la utilizacioacuten de alguna de las etiquetas anteriores

ltHTMLgt

ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODYgt ltCENTERgtTexto centrado-CENTERxBRgt ltUxIxBIGgtTexto subrayado y cursivaltBIGxIgtltUxBRgt ltBgtTexto en negritaltBxBRgt ltSUPgtTexto superiacutendiceltSUPxBRgt Este cont iene un ltSUBgtsubiacutendiceltSUBgt ltBRgt ltBODYgt ltHTMLgt

Introduccioacuten a PHP 5 51

La etiqueta ltFONTgt permite seleccionar entre varios atributos para utilishyzar distintas fuentes colores o tamantildeos Entre los atributos que podemos utilizar

bull COLOR Color de la fuente

bull SIZE Tamantildeo de la fuente

bull FACE Tipo de fuente ltFONT SIZE=1 FACE=ComicgtTexto con tamantildeo y fuente determinadosltFONTgt

Enlaces de texto

Un enlace es un mecanismo que permite dirigirse a una paacutegina determishynada despueacutes de hacer clic en el texto Si entre las etiquetas ltAgt y ltAgt aparece alguacuten contenido (texto o imagen) al hacer clic en la situacioacuten denshytro de navegador la paacutegina seraacute dirigida a la nueva direccioacuten

El atributo HREF contiene la direccioacuten del enlace

ltA HREF=pagina2htmgtenlaceltAgt

Listas

Las listas son capaces de presentar ordenadamente una serie de concepshytos Los tipos de lista son

bull ltULgt Lista desordenada

bull ltOLgt Lista ordenada

bull ltDLgt Lista de definicioacuten

La diferencia entre los tipos de lista radica en el caraacutecter que aparece en la zona izquierda de cada liacutenea de la lista Las listas desordenadas tendraacuten un graacutefico formal (una forma geomeacutetrica) las ordenadas tendraacuten un nuacuteshymero de orden y las listas de definicioacuten una letra

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltHEADgt ltBODYgt ltBgtLiacutesta desordenada-BxBRgt ltULgt

ltLIgtLiacutenea 1 laquoLis-Liacutenea 2 ltLIgtLiacutenea 3

Figura 17 Listas ordenadas y desordenadas

52 Capiacutetulo 1

ltUI-igt

ltLIgtLiacutenea 31 ltLIgtLiacutenea 32

ltULgt ltLIacutegtLiacutenea 4

ltULgt ltBgtLiacutesta ordenadaltBgtltBRgt ltOLgt

ltLIacutegtLiacutenea 1 ltLJgtLiacutenea 2 ltLlgtLiacutenea 3 ltotgt

ltLIgtLiacutenea 31 ltLIgtLiacutenea 32

ltOLgt ltLIacutegtLiacutenea 4

ltOLgt ltBODYgt ltHTMLgt

Cada liacuteitea de una lista debe estar precedida de la etiqueta ltLIgt El coacutedishygo anterior genera la Web de la figura 17

Imaacutegenes

La etiqueta lt IMGgt utiliza el atributo SRC para insertar la imagen seleccioshynada en el documento

Introduccioacuten a PHP 5 53

Ademaacutes puede utilizar ALT para antildeadir una descripcioacuten a la imagen Entre las imaacutegenes que se pueden incluir en la Web estaacuten los tipos de archishyvos GIF PNG y JPG

ltIMG SRC=fo to l jpg ALIGN=centergt

La alineacioacuten de la imagen con respecto a la pantalla se puede controlar con el atributo ALIGN

Tablas

El elemento estrella en una paacutegina Web es la tabla Actualmente las tashyblas se utilizan para colocar en lugares determinados de la pantalla texshytos imaacutegenes o el menuacute de seleccioacuten Para definir u n a tabla tiene que insertar todos los datos entre las etiquetas ltTABLEi y ltTABLEgt

A continuacioacuten antildeada las filas y las columnas de nuestras tablas Para antildeadir una fila tendraacute que utilizar la etiqueta ltT^gt y para incluir una nueva columna la etiqueta ltTDgt

Para disentildear una tabla de 3 filas y 4 columnas siga los pasos que muestra el ejemplo

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author COMTENT=Luis Miguel Cabltbzas Granadogt ltHEADgt ltBODYgt ltTABLE B0RDER=1gt ltTRgt ltTDgtColumna 11ltTDgt ltTDgtColumna 12ltTDgt ltTDgtColumna 13ltTDgt ltTDgtColumna 14ltTDgt ltTRgt ltTRgt ltTDgtColumna 2 1ltTDgt ltTDgtColumna 2 2ltTDgt ltTDgtColumna 2 3ltTDgt ltTDgtColumna 24ltTDgt ltTRgt ltTRgt ltTDgtColumna 31ltTDgt ltTDgtColumna 3 2ltTDgt ltTDgtColumna 33ltTDgt ltTDgtColumna 34ltTDgt ltTRgt

Figura 18 Tabla de 3 filas y 4 columnas

54 Capiacutetulo 1

ltTABLEgt ltBODYgt ltHTMLgt

Como muestra el coacutedigo la etiqueta ltTABLEgt puede contener atributos como BORDER que antildeade un borde a todas las celdas de la tabla Esta forshyma de actuar la vemos en la figura 18

Resumen

Es muy importante para la lectura de los capiacutetulos del libro que conozca el lenguaje HTML en profundidad PHP 5 se encarga de generar datos dinaacutemicamente desde una base de datos archivos o haciendo caacutelculos complejos pero al final seraacute una etiqueta HTML la que muestre esos dashytos en pantalla Puesto que el objetivo de este libro no es conocer los asshypectos de HTML invito al lector a indagar en otras publicaciones o en Internet para suplir las posibles carencias que pueda tener

Los ejemplos del libro se han escrito directamente en un editor de textos pero esta no es la uacutenica posibilidad Tambieacuten puede utilizar para realizarshylos alguacuten programa de disentildeo Web con la ventaja de que las etiquetas HTML seraacuten antildeadidas a golpe de clic

Capiacutetulo 2

Variables constantes y tipos

de datos

En este capiacutetulo aprenderaacute a

bull Almacenar informacioacuten en variables bull Manejar variables constantes y constantes predefinidas por PHP 5

bull Utilizar funciones de manejo de datos

56 Capiacutetulo 2

Variables en PHP 5

Como en todos los lenguajes de programacioacuten PHP 5 permite almacenar datos de distintos tipos en memoria Estas zonas de memoria se llaman variables Las variables comienzan por el siacutembolo de doacutelar ($) y no necesishytan ser declaradas antes de comenzar el programa como en otros lenguashyjes

Tipos de Variables

Existen varios tipos de variables

bull Entero (integer) Almacena nuacutemeros sin decimales Se puede utilizar la notacioacuten decimal (83) octal (0123) o hexadecimal (0x12)

bull Coma Flotante (double) Nuacutemeros con decimales bull Caraacutecter (string) Texto o informacioacuten numeacuterica escrita entre comillas

dobles () o simples () bull Bootean Soacutelo tiene dos posibles valores Verdadero o Falso bull Nulo NULL) Es un tipo especial que solo contiene un valor NULL bull Vectores (array) Colecciones de datos

bull Objetos (object) Conjunto de datos y funciones independientes

Los 5 primeros tipos son simples y los 2 siguientes (array y object) son comshypuestos Trataremos los tipos compuestos en capiacutetulos sucesivos

ltphp Asignacioacuten de nuacutemeros enteros de coma flotante y cadenas de caracteres $numero_entero = 12343 $numero_flotante = 12343123 $cadena_caracter = 12 34 3 Asignacioacuten de los tipos especiales boolean y NULL $verdadero = TRUE $vacio = NULL gt

Hay que tener en cuenta que el nombre de las variables no puede empeshyzar por un nuacutemero pero siacute puede contenerlos Tambieacuten pueden empezar por un guioacuten bajo (__) Puesto que PHP 5 es sensible a las mayuacutesculas y minuacutesculas las variables $numero y $NUMERO seraacuten distintas

ltphp $4numero = 23 Esta liacutenea da error

Variables constantes y tipos de datos 57

$_numero = 45 Las liacuteneas siguientes muestran que PHP 5 es sensible a mayuacutesculas $numero = 23 $NUMERO = 24 $Numero = 25 echo (numero es $numeroltbrgt) echo (NUMERO es $NUMEROltbrgt ) echo (Numero es $Numeroltbrgt) gt

Nota

Es una buena praacutectica de programacioacuten llamar a las variables de una forma descriptiva Si tenemos un formulario que intenta pashysar datos sobre el nombre y apellido de una persona lo maacutes coshyrrecto es llamar a las variables $nombre y $ ape l l i do en vez de $n y $a Hay que buscar siempre la similitud entre el dato que pasamos y el nombre de la variable para que el programa resulte legible

Asignacioacuten de variables

La asignacioacuten es simplemente dar un valor a la variable Esto se hace poshyniendo un siacutembolo = entre la variable y el dato que queremos asignar

ltphp $numero_pi = 314159 Aproximadamente gt

Si se fija en el ejemplo acabamos de asignar un nuacutemero de coma flotante a la variable $numero_pi En este momento podemos cambiar el valor de la variable asignando un nuevo valor que puede ser de un tipo difeshyrente

ltphp $numerojiacute = 314159 El tipo se convierte a cadena de caracteres gt

Tipos simples

Los tipos de variables simples (enteros coma flotante cadenas de caracteshyres boolean y NULL) deberiacutean ser familiares si conocemos alguacuten lenguaje

58 Capiacutetulo 2

de programacioacuten como C Puesto que la base de la programacioacuten consiste en almacenar datos correctamente vamos a ver las peculiaridades de los diferentes tipos

Enteros (integer)

Corresponde a un nuacutemero entero sin decimales pudiendo ser negativo o el nuacutemero cero Pueden ser almacenados en diferentes formatos corresshypondiendo con las bases decimal (base 10) octal (base 8) y hexadecimal (base 16) Por defecto se utiliza la numeracioacuten decimal Para utilizar base 8 debe ponerse un 0 delante del nuacutemero asignado y un Ox si queremos utilizar base 16 Para antildeadir un nuacutemero negativo basta con poner el signo menos (-) delante del nuacutemero

ltphp $entero_baselO = 1234 $entero_base8 = 01234 $entero_basel6 = 0x1234 $entero_negativo = -1234 echo (Decimal $entero_baselOltbrgt) echo (Octal $entero_base8ltbrgt) echo (Hexadecimal $entero_basel6ltbrgt) echo (Negativo $entero_negativoltbrgt) gt

La salida del navegador es

Figura 21 Asignacioacuten de enteros en decimal octal y hexadecimal

Variables constantes y tipos de datos 59

La salida de los nuacutemeros se hace en decimal aunque la asignacioacuten se haya hecho en hexadecimal o en octal Esto es asiacute porque PHP trabaja internashymente en binario y hace la conversioacuten a decimal de todos los nuacutemeros enteros y de coma flotante

Nuacutemeros de coma flotante (double)

Este tipo de dato contiene nuacutemeros enteros con decimales Se almacenan de forma diferente a los nuacutemeros enteros por lo que las sumas de cantishydades de coma flotante con cantidades enteras daraacuten como resultado un nuacutemero de coma flotante

ltphp Nuacutemeros de coma flotante $numero__double = 1234123 $numero_double2 = 01213 $numero_double3 = -12 3 40 echo (Salida de la funcioacuten echo() $numero_double3ltbrgt) gt

La salida en el navegador seriacutea S a l i d a de echo -1234

Como puede comprobar parece que el nuacutemero que se muestra en pantashylla es del tipo entero Esto es porque la funcioacuten echo 0 no muestra el forshymato del dato Para que esto ocurra debemos utilizar otro tipo de funcioacuten

ltphp $numero_double3 = -12340 echo (Salida de printft) ) printf(f$numero_double3) gt

El coacutedigo anterior muestra ahora una salida por pantalla maacutes coherente Salida de printf() es -1234000000

Cadena de caracteres (string)

Es un conjunto de caracteres encerrados entre comillas dobles () o sim-pies ( )bull

ltphp Definicioacuten de variables de tipo string $cadenal = Esto es una cadena de caracteres $cadena2 = Esto es una cadena entre comillas simples $cadena3 = Cadena con 0 caracteres gt

60 Capiacutetulo 2

La diferencia entre las comillas simples y las comillas dobles radica en

bull Comillas simples Permiten imprimir el contenido iacutentegro de caracteshyres que esteacute entre las dos comillas

bull Comillas dobles Permiten incluir variables para imprimirlas junto al texto ltphp $dato = IMPRIMIBLE $texto_simple = No puede imprimir la variable $dato $texto_doble = Imprime la variable dato como $dato echo ($texto_simpleltbrgt) echo ($texto_doble) gt

Existen algunos caracteres especiales que no pueden ser antildeadidos a una variable de tipo string a menos que avisemos antes a PHP para que tenga cuidado a la hora de manejar el dato Este aviso se conoce como secuenshycia de escape y no es maacutes que la inclusioacuten delante del caraacutecter especial de un siacutembolo Asiacute si quiere insertar unas comillas dobles entre un texto tendraacute que escribir para que no se produzca un error

ltphp Secuencias de escape $cadenal = Aquiacute se pueden antildeadir comillas doblesltbrgt $cadena2 = Aquiacute se pueden antildeadir comillas simplesltbrgt $cadena3 = Esta cadena da errores por las comillas doblesltbrgt $cadena4 = Esta cadena no da errores por las comillas doblesltbrgt echo $cadenal echo $cadena2 echo $cadena3 echo $cadena4 gt

El resultado muestra la impresioacuten de las cadenas excepto la cadena3 que da un error por no incluir la secuencia de escape para las comillas

Tabla 21 Secuencias de escape comunes

Secuencia Valor

$ Signo de doacutelar $

Comillas dobles

V Comillas simples

Bar ra invert ida

Variables constantes y tipos de datos 61

Secuencia Valor

n Nueva liacutenea

r Retorno de carro

t Tabulador

Boolean

Una variable de tipo boolean soacutelo puede contener dos valores Verdadero o Falso Se suelen utilizar para comprobar si se cumple una condicioacuten en el programa

ltphp $variable_booleana = TRUE if ($variable_booleana) echo (El resultado es VERDADERO)

gt

El resultado se muestra en la figura 22

Aunque todaviacutea no hemos visto las estructuras de control podemos adshyvertir que la salida del programa anterior da como resultado la impresioacuten en pantalla del texto que contiene la funcioacuten echo () Ademaacutes de las vashyriables boolean podemos tomar otros tipos de datos como Verdaderos o Falsos para hacer nuestras comprobaciones

62 Capiacutetulo 2

bull Los nuacutemeros enteros o decimales positivos o negativos son todos Verdashyderos El 0 se considera Falso En cualquier caso se recomienda no utilishyzar variables de coma flotante para comprobar si son Verdaderos o Falsos

bull Las cadenas de caracteres son Verdaderas excepto cuando no contieshynen ninguacuten dato o contienen uacutenicamente el caraacutecter 0

bull Las variables del tipo NULL son siempre Falsas

NULL

Es un tipo especial de datos que soacutelo contiene el valor NULL Aunque se suele utilizar por norma en mayuacutescula PHP 5 lo acepta escrito de divershysas formas NULL nuil NuLl

ltphp $variable_nula = NuLl if ($variable_nula) echo (La comprobacioacuten es VERDADERA)

else echo (La comprobacioacuten es FALSA) gt

Variables de variables

Las variables son en definitiva nombres descriptivos que asocian un esshypacio en memoria del servidor con una palabra entendible por nosotros En ese espacio de memoria podemos almacenar diferentes tipos de datos Podemos definir una variable de la siguiente forma

ltphp $variablel = hola gt

En este momento tenemos un espacio de memoria llamado $ v a r i a b l e l donde se aloja el dato hola iquestQueacute pasa si queremos tratar la palabra hola como una variable Podemos hacerlo antildeadiendo un signo de $ delante de $ v a r i a b l e l por lo que se reservaraacute otro espacio en memoria para aloshyjar el nuevo contenido esta vez con el nombre $hola

ltphp $variablel = hola $$variablel = mundo

Variables constantes y tipos de datos 63

Las dos liacuteneas siguientes producen la misma salida echo ($variablel $$variablelltbrgt) echo ($variablel $holaltbrgt) gt

La salida por pantalla nos da el siguiente resultado hola mundo hola mundo

Constantes

Las constantes son tipos de datos que no variacutean en el desarrollo de un programa En la vida real existen muchos tipos de constantes el nuacutemero pi la temperatura de congelacioacuten del agua el nombre de la Empresa etshyceacutetera Para crear una constante tiene que usar la funcioacuten de f ine () de la siguiente forma

ltphp define(EMPRESAZendSA) define(AutorLuis Miguel Cabezas Granado) gt

Para mostrar el valor de las constantes uacutenicamente hay que invocar su nombre esta vez sin utilizar el siacutembolo de $

ltphp Definimos primero la constante define (COLOR_ROJO FF0000) Y ahora escribimos en pantalla su resultado echo COLOR_ROJO Hay que destacar que el signo de $ no hace falta ponerlo Existe otra funcioacuten que nos permite averiguar el valor de la constante echo constant ( C0L0R_R0JO) gt

defined()

Puede utilizar def ined () para averiguar si una constante ya se ha creado

ltphp define(EditorialAnaya) if (defined(Editorial) ) echo La Editorial es Editorial

gt

64 Capiacutetulo 2

Constantes predefinidas

PHP 5 define varias constantes cada vez que se ejecuta un script y que son accesibles por nosotros

Tabla 22 Algunas constantes definidas por PHP 5

Nombre Descripcioacuten

PHP_VERSION Versioacuten del parse de PHP que estamos utilizando

PHP_OS Sistema operativo del servidor de PHP

PEAR_EXTENSION_DIR Ruta donde estaacute instalada la extensioacuten PEAR

PHP_LIBDIR Ruta donde estaacuten almacenadas las libreriacuteas de PHP 5

Finalmente tenemos 5 constantes maacutegicas tal y como las definen en el sishytio Web wwwphpnet que cambian de valor dependiendo del lugar donshyde se usen Por ejemplo el valor de la constante LINE depende de la liacutenea donde la estemos usando en nuestro programa

Tabla 23 Constantes maacutegicas

Nombre Descripcioacuten

LINE Indica el nuacutemero de liacutenea desde la que imprimimos el

valor

FILE Ruta completa al fichero

FUNCTION Nombre de la funcioacuten que la contiene

CLASS Nombre de la clase

_ M E T H O D _ Nombre del meacutetodo

Advertencia

Hay que tener cuidado con el nombre de las constantes maacutegicas Los siacutembolos que hay a la izquierda y ala derecha del nombre son dos guiones bajos seguidos (_)

ltphp echo LINE - VERSIOacuteN de PHP 5PHP_VERSION echo ltbrgt

Variables constantes y tipos de datos 65

echo LINE - SISTEMA Operativo Servidor PHP_OS echo ltbrgt echo LINE - Ruta de las extensiones PHP_EXTENSION_DIR echo ltbrgt echo LINE - API de Servidor PHPJ3API gt

Funciones relacionadas con variables

PHP 5 brinda al programador una serie de funciones para el manejo de variables

isset()

Con esta funcioacuten podemos averiguar si una funcioacuten existe dentro de nuesshytro programa Si existe devuelve true y si no existe false

ltphp $DNI = 8868543-Z if (isset($DNI)) echo (La variable DNI existe)

66 Capiacutetulo 2

gt

unset()

Libera la memoria ocupada por una variable destruyendo su nombre y su contenido Despueacutes de usar unset () la variable destruida apareceraacute comoase al utilizar la funcioacuten i s s e t ()

ltphp $Nombre = Mariacutea Fernanda if (isset($Nombre)) echo (El nombre existe)

Podemos comprobar queacute pasa si liberamos la variable $Nombre unset($Nombre)iexcl if (isset($Nombre)) echo (El nombre existe) else echo (El nombre ya no existe) gt

El resultado es el siguiente El nombre e x i s t e El nombre ya no e x i s t e

gettype()

Con esta funcioacuten podemos averiguar el tipo de dato almacenado en la variable Nos puede devolver uno de los siguientes valores

bull integer

bull double

bull string

bull array

bull object

bull class

bull unknown type ltphp $correo = luisnccextremaduraorg echo la variable correo es del tipo

Variables constantes y tipos de datos 67

echo g e t t y p e ( $ c o r r e o ) gt

settype()

Convierte el tipo de la variable al especificado en la funcioacuten El tipo debe especificarse eligiendo uno de los siguientes array double integer object o string Si la funcioacuten no es capaz de convertir el tipo de la variable devuelshyve el valor false

ltphp $correo = luisnccextremaduraorg if (settype($correointeger))

echo (Variable correo convertida a Enteroltbrgt)

else

echo (Imposible convertir al tipo Enteroltbrgt)

echo (Valor actual de correo es $correo) gt

Al tratar de convertir un tipo string (una cadena de caracteres) a un enteshyro PHP 5 comprueba si existe alguacuten nuacutemero Si no existe cambia el valor a O y la funcioacuten s e t t y p e () la evaluacutea como correcta

empty()

Comprueba si una variable estaacute vaciacutea no existe o su valor es 0 ltphp $correo = luisnccextremaduraorg if (empty($nombre))

echo (La variable nombre no existe)

$numero_entero = O if (empty($numero_entero))

echo (La variable numero_entero no existe o tiene el valor O) gt

isjntegerf) is_double() is_string()

Estas funciones devuelven true si la variable pasada coincide con el tipo que indica la funcioacuten

68 Capiacutetulo 2

Si la variable $numero_en te ro se evaluacutea con la funcioacuten i s _ i n t e g e r ( ) devolveraacute true

ltphp $numero_entero = 0 if (is_integer()($numero_entero))

echo (numero_entero es del tipo integer)

gt

intval() doublevalQ strval()

Convierte el valor de una variable al tipo indicado en la funcioacuten Esta funshycioacuten no permite la conversioacuten a tipos object o array

ltphp Conversioacuten de un tipo string a un integer $cadena = 232 echo El tipo de la variable cadena es gettype($cadena)ltbrgt $numero = intval($cadena) echo (el numero es $numero) gt

Resumen

La base de la programacioacuten reside en la creacioacuten de datos y su procesashymiento En este capiacutetulo hemos visto coacutemo declarar variables de diferenshytes tipos y coacutemo utilizar funciones para averiguar las propiedades de cada una de ellas Ademaacutes de las variables las constantes juegan un papel muy importante sobre todo las predefinidas por PHP 5 que nos dan informashycioacuten muy uacutetil con la que poder trabajar

En este capiacutetulo aprenderaacute a

bull Utilizar los diferentes tipos de operadores existentes bull Distinguir entre operadores unarios binarios y ternarios

bull Comprender la preferencia de ejecucioacuten entre operadores

70 Capiacutetulo 3

Introduccioacuten

En el capiacutetulo anterior hemos visto ejemplos de coacutedigo escrito en PHP que utilizan siacutembolos muy comunes en el ambiente matemaacutetico e inforshymaacutetico Estos siacutembolos que aparecen entre variables o dentro de funciones son conocidos como operadores Existen varios tipos de operadores

bull De asignacioacuten bull Unario bull Aritmeacuteticos bull De comparacioacuten bull Loacutegicos bull Ternario bull Bit a bit bull Asignacioacuten combinados bull De ejecucioacuten bull Supresioacuten de errores

Operador de asignacioacuten

El maacutes baacutesico es el siacutembolo de asignacioacuten (=) utilizado para dar valores a las variables que usamos en nuestro coacutedigo

ltphp $variable = 34 $variable2 = Asignacioacuten de valores gt

Las variables que estaacuten a la izquierda del operador toman el valor que se encuentra en la expresioacuten de la derecha

Advertencia

No hay que confundir el operador de asignacioacuten (=) con el operashydor de comparacioacuten (==) sobre todo en bucles de control donde seriacutea difiacutecil encontrar alguacuten fallo

Operadores 71

Operador Unario

El signo menos (-) se utiliza delante de un nuacutemero o variable numeacuterica Este operador tiene la propiedad de hacer a los nuacutemeros negativos o poshysitivos dependiendo del signo actual

ltphp $entero = 23 $entero_negativo = -$entero El valor es ahora -23 entero2 = -$entero__negativo El valor cambia ahora a 23 gt

Operadores Aritmeacuteticos

Este tipo de operadores forman parte de la aritmeacutetica baacutesica Nos resultashyraacute familiar porque son siacutembolos muy utilizados en el aprendizaje de las matemaacuteticas

Tabla 31 Operadores aritmeacuteticos

Ejemplo Nombre Resultado

$a + $b suma Suma las dos variables $a - $b resta Hace la diferencia de las dos variables Sa $b multiplicacioacuten Producto de las variables $a $b divisioacuten Cociente entre las dos variables $a $b Moacutedulo Resto de la divisioacuten de $a entre $b

Nota

-rr PHP 5 ignora los espacios en blanco entre las variables y los opeshyradores Aunque $a + $b es equivalente a $a + $b es preferible utilizar la primera forma de escribir porque se hace maacutes legible

Operadores de comparacioacuten

En algunos ejemplos del capiacutetulo anterior puede ver que se utiliza la esshytructura de control if el se Como veremos maacutes adelante esta estructu-

72 Capiacutetulo 3

ra compara dos valores y elige el camino a seguir El valor de la comparashycioacuten siempre es true ofalse

Tabla 32 Operadores de comparacioacuten

Ejemplo Nombre Resultado

$a == $b Igualdad Devuelve true si $a y $b son iguales $a === $b Identidad Verdadero si son iguales y del mismo tipo $a = $b Distinto True si son distintos $a ltgt $b Distinto True si son distintos $a lt $b Menor que Cierto si $a es menor que $b $a gt $b Mayor que Cierto si $a es mayor que $b $a lt= $b Menor o igual Correcto si $a es menor o igual que $b $a gt= $b Mayor o igual Correcto si $a es mayor o igual que $b

ltphp $a = 23 Asignacioacuten de los valores $b = 75 if ($a gt= $b) La condicioacuten no se cumple El resultado es false

echo Esta parte no se ejecuta else

echo La comparacioacuten es false porque $a es menor que $b

gt

Operadores 73

Operadores Loacutegicos

Durante el desarrollo de su proyecto puede encontrarse con situaciones en las que necesite hacer varias comparaciones seguidas para que se cumshypla una determinada condicioacuten PHP 5 permite unir todas las comparashyciones en una mediante el uso de los operadores loacutegicos

Tabla 33 Operadores loacutegicos

Ejemplo Nombre Resultado

expresionl and expresion2 Y Si las dos expresiones son vershydaderas el valor es true

expresionl or expresion2 O Si una de las expresiones es vershydadera el valor es true

expresionl xor expresion2 O exclusivo True si una expresioacuten es verdashydera y la otra falsa

expresionl Negacioacuten Verdadero si la expresioacuten no es cierta

expresionl ampamp expresion2 Y Si las dos expresiones son vershydaderas el valor es true

expresionl || expresion2 O Si una de las expresiones es vershydadera el valor es true

El listado siguiente muestra dos condiciones anidadas lt php $a = 2 3 Sb = 75 $c = true if ($a lt $b)

if ($c) echo (Se cumplen las dos condiciones)

gt gt

Egtta expresioacuten se puede hacer maacutes legible utilizando alguacuten operador loacuteshygico

ltphp $a = 23 3b = 75 $c = t rue

74 Capiacutetulo 3

i f ($a lt $b and $c) echo Se cumplen l a s dos cond ic iones

gt

Operador Ternario

Los operadores que hemos visto hasta ahora son capaces de manejar un operando (Unarios) o dos operandos (binarios) El operador ternario o de comparacioacuten evaluacutea un operando y dependiendo de si es falso o vershydadero evaluacutea el segundo operando o el tercero La expresioacuten que se quiere evaluar se escribe delante de un siacutembolo () despueacutes la expresioacuten que tiene que ejecutarse si la evaluacioacuten anterior es true seguida del siacutembolo () con la expresioacuten que debe ejecutarse si es false

ltphp $valor = false $valor == true $resultado = OK $resultado = FALLO Si $value es true $resultado seraacute OK Si es false $re sultado seraacute FALLO echo $resultado gt

Operadores bit a bit

Estos operadores son complicados de entender si no conoce la loacutegica bishynaria Afortunadamente se utilizan en muy pocas ocasiones Los operashydores de bit utilizan las variables a nivel bajo tal y como se almacenan en memoria fiacutesica y comparan bit a bit los valores Lo mejor es verlo con un ejemplo

ltphp bull$a = 4 Valor binario 100 $b = 5 Valor binario 101 $c = $a amp $b echo $c El valor de c es 100 gt

El operador binario Y (siacutembolo amp) compara bit a bit las variables $a y $b Si los bits de una misma posicioacuten son true (tienen el valor 1) el bit resultashydo es 1 En este caso soacutelo existe una pareja de bits que es igual a true (sus

Operadores 75

dos valores son 1) por lo tanto el valor de la variable $c es 4 (en binario 100)

Tabla 34 Operadores bit a bit

Ejemplo Nombre Resultado

$a amp $b Y Si las parejas de bits son verdaderas el resultado es

verdadero

$a | $b O Si alguacuten bit de la pareja es verdadero el resultado es

verdadero

$a A $b O Si un bit de la pareja es true y el otro false el resultado exclusiva es verdadero

~$a No Los bits 1 se vuelven 0 y viceversa Tambieacuten cambia el bit que se refiere al signo positivo o negativo

$a ltlt $b Desplaza- Desplaza a la izquierda los bits de la variable $a tantos miento a bits como indique la variable $b la izquierda de bits

$a gtgt $b Desplaza- Desplaza a la derecha los bits de la variable $a tantos miento a bits como indique la variable $b la derecha

Nota

Puesto que la notacioacuten binaria se escapa del enfoque de este libro le recomiendo algunas lecturas posteriores referidas a la loacutegica de bit si es que tiene curiosidad Probablemente no utilizaraacute estos operadores nunca pero eso depende de la magnitud de los proyecshytos a los que se enfrente

Operadores de asignacioacuten combinados

En numerosas ocasiones se nos presentan situaciones en las que una va-riable debe incrementar o disminuir su valor en 1

ltphp

$a =23

$a = $a +1 Incrementamos en 1 el valor de la variable gt

HP 5 provee operadores combinados que permiten asignar raacutepidamente crementos de valor concatenaciones de caracteres etceacutetera

76 Capiacutetulo 3

Tabla 35 Operadores de asignacioacuten combinados

Ejemplo Nombre Equivalencia

$a++ Incremento $a = $a +1

$a~ Decremento $a = $a -1

++$a Incremento $a = $a +1

~$a Decremento $a = $a -1

$a += $b Suma $a = $a + $b

$a -= $b Resta $a = $a - $b

$a = $b Multiplicacioacuten $a = $a $b

$a = $b Divisioacuten $a = $a $b

$a = $b Moacutedulo $a = $a $b

$a amp= $b Y $a = $a amp $b

$a |= $b O $a = $a | $b

$a A= $b O exclusiva $a = $a A $b

$a = $b Concatenacioacuten $a = $a $b

$a gtgt= $b Desplazamiento a la derecha $a = $a gtgt $b

$a ltlt= $b Desplazamiento a la izquierda $a = $a ltlt $b

Advertencia

Como vemos en la tabla 35 iexclos operadores de incremento y deshycremento pueden aparecer a la derecha o a la izquierda de un vashyriable La posicioacuten del operador influye en el orden en el que la variable se asigna o se incrementa Mejor verlo en un ejemplo ltphp $a = 23 $b = $a++ $b es igual a 23 porque $a se incrementa despueacutes de la asignacioacuten

$a = 2 3 $c = + + $a $c es igual a 24 porque $a se incrementa antes de la asignacioacuten

echo la variable b es $b y c es $c gt

Operador de ejecucioacuten

Si tiene experiencia con la programacioacuten en shell de Unix o gnuLinux sabraacute que el apostrofe invertido sirve para ejecutar comandos del sis-

Operadores 77

tema PHP 5 ha adoptado esta nomenclatura y funciona exactamente igual

ltphp $listado_archivos = Is -la~ Hacemos un listado de los ficheros del directorio actual echo $listado_archivos y lo sacamos por pantalla gt

Nota

El comando ls del ejemplo anterior es propio de sistemas Unix y gnuLinux Siacute hace pruebas sobre un sistema basado en el Sistema Operativo Windows el ejemplo anterior no funcionariacutea tendriacutea que cambiar el comando por dir

Operador de supresioacuten de errores

La mayoriacutea de las funciones que se utilizan en PHP 5 muestran errores en el navegador cuando algo falla

Si intenta abrir un fichero que no existe PHP mostraraacute un mensaje de error v continuaraacute la ejecucioacuten del programa

78 Capiacutetulo 3

El operador () colocado delante de una funcioacuten evitaraacute que se muestre el error

ltphp $fichero = fopen(pruebatxt r) Muestra un error en el navegador echo (El programa sigue ejecutaacutendose) gt

El coacutedigo siguiente oculta la salida de error por pantalla

ltphp $fichero = fopen(pruebatxtr) echo (El programa sigue ejecutaacutendose) gt

Precedencia de Operadores

Vamos a echar un vistazo al coacutedigo siguiente

ltphp $resultado = 20 + 10 10 echo $resultado gt

Aparentemente es un coacutedigo muy simple pero encierra un problema mashytemaacutetico

Existen dos resultados posibles en funcioacuten del operador que debe ejecushytarse antes

Si la suma se ejecuta antes la variable $ r e s u l t a d o tendraacute el valor 300 y si la multiplicacioacuten se ejecuta antes tendremos q u e $ r e s u l t a d o equivashyle a 120

Si comprobamos el coacutedigo el resultado que nos muestra es 120 por lo tanto el operador de multiplicacioacuten () es preferente con respecto al operador de suma (+)

Si los operadores que aparecen son ideacutenticos existe un orden de ejecushycioacuten que puede ser desde la izquierda a la derecha o derecha a izquierda

ltphp $resultado = 2 0 1 0 2 echo $resultado gt

El valor de $ r e s u l t a d o es ahora 1 porque primero se calcula 20 10 y despueacutes ese mismo resultado se divide entre 2 es decir la asociacioacuten enshytre operadores de divisioacuten es desde la izquierda

Operadores 79

Tabla 36 Orden de preferencia de los operadores

Operador Operacioacuten Asociacioacuten

() Pareacutentesis de preferencia NA

new Instancia de objeto NA

[] array Derecha

NO loacutegico Derecha

Signo menos Derecha

++ -- Incremento decremento Derecha

Supresioacuten de errores Derecha

Multiplicacioacuten divisioacuten y moacutedulo Izquierda

+ - Suma resta concatenacioacuten Izquierda

ltlt gtgt Desplazamiento izquierda y derecha Izquierda

lt lt = gt gt = Menor que menor o igual NA

mayor que mayor o igual

== = Igual no igual NA

amp Y izquierda A O exclusivo Izquierda

| O Izquierda

ampamp Y loacutegico Izquierda

|| O loacutegico Izquierda

condicional Derecha = += = = = Asignacioacuten Derecha = = amp= = -= ltlt= gtgt=

and Y loacutegico Izquierda

xor O exclusivo loacutegico Izquierda

or O loacutegico Izquierda

El operador pareacutentesis tiene la propiedad de dar preferencia en la evaluashyron a todos los operadores que contiene El siguiente ejemplo muestra oacutemo podemos utilizar correctamente el operador pareacutentesis

ltphp $resultado = 2 0 1 0 + 2 echo $resultado El resultado es 4 $resultado = 20 (10 + 2) echo $resultado El resultado es 166666667 gt

Resumen

Los operadores son responsables de todas las operaciones que realizamos en nuestros programas Por eso es importante conocer las propiedades v los casos de uso de cada uno de ellos para poder sacarles el maacuteximo partishydo Sin embargo si ya conoce alguacuten lenguaje de programacioacuten la intuishycioacuten le haraacute utilizarlos adecuadamente sin pararse a pensar en el tipo de operador

Por uacuteltimo debe prestar un especial intereacutes a la preferencia de uso ya que una mala utilizacioacuten redundaraacute en un error muy difiacutecil de controlar

En este capiacutetulo aprenderaacute a

bull Utilizar las estructuras de control de eleccioacuten simple y muacuteltiple bull Crear bucles de diferentes tipos bull Crear sus primeros programas bull Conocer las sentencias para interrumpir un bucle

82 Capiacutetulo 4

Introduccioacuten

Es difiacutecil imaginar un programa sin estructuras de control Eacutestas nos permishyten elegir diferentes caminos en funcioacuten de los datos que evaluamos en cada momento En este capiacutetulo trataremos dos tipos de estructuras de control

bull Estructuras de eleccioacuten

bull Estructuras de bucle

Las estructuras de eleccioacuten permiten evaluar una condicioacuten o varias y eleshygir el camino correcto Las de bucle repiten un nuacutemero determinado de veces un conjunto de instrucciones

Estructuras de eleccioacuten

Existen dos tipos

bull Eleccioacuten simple bull Eleccioacuten muacuteltiple

if-else

La sintaxis de esta estructura es if (condicioacuten) instruccioacuten

Si se cumple la condicioacuten se ejecuta la instruccioacuten que le sigue Si quiere que se ejecuten varias instrucciones debe utilizar el siacutembolo llave ( insshytrucciones iexcl )

if (condicioacuten) instruccionl instruccion2iexcl

instruccion3

La estructura if puede ampliarse para que se pueda elegir entre condishycioacuten verdadera y falsa

if (condicioacuten) instruccionl instruccioacuten2 instruccion3

else

Estructuras de control 83

instruccionl -instruccioacuten2 instruccion3

Si la condicioacuten es verdadera se ejecutan las instrucciones inmediatamente despueacutes del if y si la condicioacuten es falsa se ejecutan las instrucciones disshypuestas despueacutes de la palabra e l s e Puede ver un ejemplo completo

ltphp $valor = 23 $valor2 = 27 if ($valor lt $valor2)

echo La variable valor es menor que valor2 else

echo La variable valor es mayor que valor2

gt

elseif

Es muy comuacuten hacer comparaciones en cascada para comprobar varios valores

ltphp $ d i a = 4 if ($d ia == 1)

84 Capiacutetulo 4

echo El diacutea es Lunes else

if ($dia == 2) echo El diacutea es Martes

else if ($dia == 3)

echo El diacutea es Mieacutercoles else

if ($dia == 4) echo El diacutea es Jueves

gt

El patroacuten anterior es tan comuacuten que existe una estructura especial para manejarlo

Puede escribir el ejemplo anterior con la palabra reservada e l s e i f de la siguiente forma

ltphp $dia=4

if ($dia == 1) echo El diacutea es Lunes

elseif ($dia == 2) echo El diacutea es Martes

elseif ($dia == 3) echo El diacutea es Mieacutercoles

elseif ($dia == 4) echo El diacutea es Jueves

gt

El ejemplo anterior evaluacutea la variable $dia hasta que encuentra el valor correcto y ejecuta las instrucciones

switch

La construccioacuten swi t ch comprueba el valor de una expresioacuten y permite elegir entre un conjunto de instrucciones El formato es el siguiente switch (expresioacuten)

case valorl instruccionl instruccion2 instruccion3 break

Estructuras de control 85

case valor2 instruccionl instruccion2 instruccion3 break

case valor3 instruccionl instruccion2 instruccion3 break

default instruccionl instruccion2

instruccion3

La expresioacuten puede ser de cualquier tipo siempre que devuelva un valor de tipo entero de coma flotante o de cadena de caracteres Una vez evashyluada la expresioacuten se busca el valor en la instruccioacuten case y si coincide se ejecutan todas las instrucciones hasta la palabra reservada break Si no coincide ninguacuten valor se ejecutan las instrucciones por defecto Veamos un ejemplo completo

ltphp $dia = 4 switch ($dia)

case 1

echo El diacutea es Lunes break

case 2 echo El diacutea es Martes break

case 3 echo El diacutea es Mieacutercoles break

case 4 echo El diacutea es Jueves break

case 5 echo El diacutea es Viernes break

case 6 echo El diacutea es Saacutebado break

case 7 echo El diacutea es Domingo break

default

Bucles

Los bucles son estructuras de control que permiten repetir varias veces las mismas instrucciones

while

El bucle while es el maacutes baacutesico de todos La construccioacuten baacutesica es la sishyguiente

while (condicioacuten) instruccioacutenlbull instruccioacuten2 instruccioacuten3

La condicioacuten se evaluacutea al principio

Si es verdadera se ejecutan las instrucciones que estaacuten dentro del bucle y se vuelve a evaluar la condicioacuten

86 Capiacutetulo 4

echo El diacutea de la semana es incorrecto

gt

Estructuras de control 87

Si la condicioacuten es falsa no se ejecutan las instrucciones y se continuacutea con el desarrollo del programa

Puesto que la condicioacuten se evaluacutea antes de ejecutar las instrucciones es posible que algunos bucles no se ejecuten ninguna vez

El siguiente ejemplo muestra una instruccioacuten while que no se ejecuta nunshyca porque la condicioacuten es falsa

ltphp $variable = false while ($variable)

echo Esta linea no se ejecuta nunca

gt

Existe la posibilidad de que un bucle se ejecute infinitas veces si dentro de las instrucciones no existe nada que cambie la condicioacuten que se evaluacutea al principio

ltphp $variable = true while ($variable)

echo CUIDADO Esta liacutenea se ejecuta siempre

gt

88 Capiacutetulo 4

El bucle while se puede utilizar para ejecutar un nuacutemero determinado de veces las instrucciones que implica

Veacutease el ejemplo de la serie de Fibonacci

ltphp $numero_anterior = 1 $numero_posterior = 1 $serie = 1 $fin = 10000 echo Serie de Fibonacci while ($serie lt $fin) echo $serie $serie = $numero_anterior + $numero_posterior $numero_anterior = $numero_posterior $numero_posterior = $serie

gt

Cada nuacutemero de la serie de Fibonacci se forma sumando los dos nuacutemer -anteriores

En el ejemplo la condicioacuten es que el nuacutemero de la serie sea menor que t

nuacutemero que marca la variable $f i n es decir si el nuacutemero que indica iquest serie es mayor que 10000 el bucle finaliza

La variable $f in sirve de valor maacuteximo y puede cambiarlo en funcioacuten la cantidad de nuacutemeros que quiera tener en pantalla

Estructuras de control 89

do-while

Este bucle es igual que el anterior pero la condicioacuten se evaluacutea al final de las instrucciones Por lo tanto el coacutedigo que estaacute entre las llaves se ejecuta al menos una vez El formato baacutesico es el siguiente

do instruccioacutenl instruccioacuten2 instruccioacuten3

while (condicioacuten)

Puede comprobar que la diferencia es miacutenima cuando utiliza esta estrucshytura de control para la serie de Fibonacci

ltphp $numero_anterior = 1 $numero_posterior = 1 $serie = 1 $fin = 6765 echo Serie de Fibonacci do

echo $serie $serie = $numero_anterior + $numero_posterior $numero_anterior = $numero_posterior $numero_posterior = $serie

whi le ($ser ie lt $ f i n ) gt

for

La construccioacuten de bucle maacutes complicada es la del for Tiene la siguiente sintaxis

for (expresioacuten inicial condicioacuten de fin expresioacuten de fin) instruccioacutenl instruccioacuten2

instruccioacuten3

El funcionamiento es muy sencillo La expresioacuten inicial se ejecuta una sola vez al principio del bucle La condicioacuten de fin se evaluacutea cada vez que se ejecuta el bucle Si es verdashydera se continuacutea la ejecucioacuten y si es falsa se sale del bucle Al final de cada interaccioacuten se ejecuta la expresioacuten de fin

90 Capiacutetulo 4

Puede simular la instruccioacuten f or con una instruccioacuten w h i l e de esta forma

expresioacuten inicial

while (condicioacuten de fin)

instruccioacutenl

instruccioacuten2

instruccioacuten3

expresioacuten de fin

Otra forma poco corriente es eliminar alguna o todas las expresiones de bucle Si quita todas las expresiones se crea un bucle infinito

fOr ( )

instruccioacutenl

instruccioacuten2

instruccioacuten3

equivale a

while (true)

instruccioacutenl

instruccioacuten2

instruccioacuten3

El caso contrario es antildeadir maacutes de una condicioacuten en cada clase de expreshysioacuten separadas por comas En este caso la condicioacuten de fin se evaluara falso si alguna de las claacuteusulas es falsa En realidad funciona como un C loacutegico

ltphp

for ($x = 1 $y = 1 $z = 1 $y lt 10 $z lt 10 $x++ $y = $y -

2 $z = $z + 3)

echo ($x $y $zltbrgt)

gt

Un ejemplo claacutesico es la tabla de multiplicar lthtmlgt ltbodygt ltbgtTABLA DE MULTIPLICARltbgt lttable border=lgt ltphp echo (lttrgt) echo (ltthxthgt ) for ($cabecera = 1 $cabecera lt= 10 $cabecera++)

echo (ltthgt) echo $cabecera

Estructuras de control 91

echo (ltthgt)

echo (lttrgt) for ($x = l$x lt= 10 $x++ )

echo (lttrgt) echo (ltthgt) echo $x echo (ltthgt) for ($y = l$y lt= 10 $y++ )

$multiplicacion = $x $y echo (lttdgt) echo ($multiacutepliacutecaciacuteon) echo (lttdgt)

echo (lttrgt) gt gt lttablegt ltbodygt lthtmlgt

[ ejemplo se sirve de un bucle for que crea una cabecera de tabla con la queta especial ltthgt donde inserta los nuacutemeros del uno al diez Estos umeros escritos en horizontal se podraacuten cruzar con los verticales para atener asiacute el resultado de una multiplicacioacuten

92 Capiacutetulo 4

El siguiente paso es un conjunto de dos bucles anidados El primer bucle almacena en la variable $x los valores numeacutericos que apareceraacuten como cabecera de la columna uno El segundo bucle seraacute el encargado de multishyplicar el valor actual de $x por los valores del 1 al 10

Cada vez que se ejecuta el segundo f o r se obtiene una celda nueva con un valor determinado por la multiplicacioacuten y cada vez que se ejecuta el primer bucle aparece una nueva fila cuya cabecera es un nuacutemero del 1 al 10

break y continueacute

El camino ordinario para salir de un bucle es que la condicioacuten se evaluacutee a false Existe una forma especial de salir de un bucle utilizando las palashybras reservadas b r e a k y c o n t i n u eacute Su forma de actuar es la siguiente

bull break Sale del bucle actual y continuacutea el programa

bull continueacute Salta hasta el final de la interaccioacuten y continuacutea la ejecucioacuten desde el principio del bucle

El coacutedigo siguiente muestra la forma de utilizar b r e a k

ltphp for ($x = 1 $x lt 20 $x++)

if ($x == 10) break

else echo $xltbrgt

La salida por pantalla es una sucesioacuten de nuacutemeros del 1 al 9 Al llegar la variable $x al nuacutemero 10 la condicioacuten del if se cumple y se ejecuta la instruccioacuten b r e a k saliendo del bucle Veamos ahora el mismo ejemplo pero utilizando c o n t i n u eacute

ltphp for ($x = 1 $x lt 20 $x++)

if ($x == 10) continueacute

else echo $xltbrgt

gt

Estructuras de control 93

En este caso cuando $x alcanza el valor 101o que hace la instruccioacuten conshyt i n u eacute es ir hacia el final de bucle y volver al principio comprobando la condicioacuten

El resultado por pantalla es una sucesioacuten de nuacutemeros desde el 1 hasta el 19 sin incluir el nuacutemero 10

Finalizar la ejecucioacuten de un programa

Hay veces que necesitamos parar la ejecucioacuten de un programa por divershysas causas ha ocurrido un error un fallo en la entrada del nombre y la conshytrasentildea La funcioacuten para la ejecucioacuten es e x i t () o d i e () Estas dos funciones aceptan un paraacutemetro que se imprime en pantalla Por ejemplo considere el siguiente coacutedigo que asume la conexioacuten a una base de datos

ltphp $conexion = conectar_base_datos(libros) if ( $conexion)

die (Se ha producido alguacuten error en la conexioacuten)

gt

Se puede apreciar que si la variable $ c o n e x i oacute n se evaluacutea false (no se ha conseguido la conexioacuten) se detiene la ejecucioacuten del programa Una vershysioacuten maacutes compacta se consigue utilizando el operador or

ltphp $conexion = conectar_base_datos(libros) or die (Se ha producido alguacuten error en la conexioacuten) gt

Nota

e x i t () y d i e () eran iexclas uacutenicas alternativas para el control de errores criacuteticos en versiones anteriores de PHP En PHP 5 aforshytunadamente se ha incluido un potente manejo de excepciones que hace la ejecucioacuten maacutes flexible

Sintaxis alternativa

Algunas estructuras de control pueden escribirse de una forma distinta Las estructuras i f w h i l e f or y s w i t c h pueden escribirse sustituyen-

94 Capiacutetulo 4

do la llave de inicio por un siacutembolo de dos puntos () y la llave de cierre por e n d i f e n d w h i l e endf or y e n d s w i t c h respectivamente

Como ejemplo podemos ver la estructura i f

ltphp $variable = 10 if ($variable == 10)

echo Nueva estructura de control gt

El coacutedigo siguiente es equivalente al anterior

ltphp $variable = 10 if ($variable == 10)

echo Nueva estructura de control end i f

gt

Resumen

Si ha llegado hasta aquiacute ya conoceraacute los secretos baacutesicos de la programashycioacuten en PHP 5 Como puede darse cuenta lo uacutenico necesario para hacer un programa es tener claro la forma de utilizar las variables los operadoshyres y las estructuras de control Una vez dominado esto lo demaacutes es aprenshyder funciones de PHP y teacutecnicas de recuperacioacuten e insercioacuten de datos

Los capiacutetulos siguientes hacen un estudio maacutes concienzudo de las variashybles y las funciones que facilitan el proceso de interaccioacuten entre ellas

En este capiacutetulo aprenderaacute a

bull Crear sus propias funciones bull Utilizar paraacutemetros fijos y variables

bull Realizar funciones recursivas bull Separar el coacutedigo fuente en varios ficheros

96 Capiacutetulo 5

Introduccioacuten

Las funciones son grupos de instrucciones independientes que tienen un propoacutesito determinado

Asiacute tenemos funciones que calculan la raiacutez cuadrada de un nuacutemero nos dan un nuacutemero aleatorio o permiten contar los caracteres de una palabra La sintaxis baacutesica de una funcioacuten es la siguiente

nombre_funcioacuten (paraacutemetrol paraacutemetro2 paraacutemetro3paraacutemetro_n)

Las funciones pueden ser llamadas con varios paraacutemetros o con ninguno dependiendo de su definicioacuten

Cuando PHP encuentra en el coacutedigo la llamada a una funcioacuten primero evaluacutea cada argumento y los utiliza como paraacutemetro de entrada Despueacutes ejecuta la funcioacuten y devuelve el valor solicitado o realiza alguna accioacuten sin enviar ninguacuten valor de salida

El siguiente ejemplo contiene un conjunto de llamadas a funciones con 01 oacute 2 paraacutemetros de entrada

ltphp echo sqrt(9) Raiacutez cuadrada de 9 es 3 echo rand(1020) Nuacutemero aleatorio entre 10 y 20 echo pi() Nuacutemero pi gt

Valores de las funciones

Cada funcioacuten en PHP se considera como una expresioacuten Se pueden utilishyzar las funciones para lo mismo que se utilizan las expresiones como alshymacenar su resultado en una variable o formar parte de una expresioacuten maacutes compleja

ltphp $numero_aleatorio = rand (1100) Se almacena en una variable $numero_aleatorio = rand (1100) + rand (1100) sqrt(9) Expresioacuten compleja gt

No todas las funciones devuelven un valor numeacuterico Tambieacuten pueden devolver caracteres array o truefalse si la funcioacuten ha tenido eacutexito o no Este tipo de funciones se utiliza para conectar a bases de datos escribir a ficheros de texto manipular imaacutegenes etceacutetera

Funciones 97

Funcioacuten de ejemplo Obtencioacuten de la fecha actual

Existen un conjunto de funciones que permiten averiguar la fecha actual del sistema Una de estas funciones es d a t e ( ) que permite recuperar el antildeo diacutea mes etceacutetera del momento en el que se hace la consulta Para averiguar el diacutea de hoy podemos utilizar la construccioacuten

lt d a t e (d) gt

El paraacutemetro que pasamos entre pareacutentesis indica a la funcioacuten el formato de fecha que queremos obtener En este caso la d indica que queremos obtener el diacutea en formato numeacuterico La siguiente tabla relaciona los caracshyteres dentro de la funcioacuten d a t e () con su aplicacioacuten praacutectica

Tabla 51 Formato de fecha con date()

Caraacutecter Valor

a Imprime am o pm

A AM o PM

h La hora en formato (01-12)

H Hora en formato 24 (00-23)

g Hora de 1 a 12 sin un cero delante

G Hora de 1 a 23 sin cero delante

i Minutos de 00 a 59

s Segundos de 00 a 59

d Diacutea del mes (01 a 31)

j Diacutea del mes sin cero (1 a 31)

w Diacutea de la semana (0 a 6) El 0 es el domingo

m Mes actual (01 al 12)

n Mes actual sin ceros (1 a 12)

Y Antildeo con 4 diacutegitos (2004)

y Antildeo con 2 diacutegitos (04)

z Diacutea del antildeo (0 a 365)

t Nuacutemero de diacuteas que tiene el mes actual

98 Capiacutetulo 5

Se pueden utilizar varios caracteres dentro de la funcioacuten indicando el forshymato de fecha que nos interesa

ltphp $meses = array (Enero Febrero Marzo Abril Mayo

Junio Julio Agosto Septiembre Octubre Noviembre Diciembre)

echo Fecha actual date(d-m-Y) ltbrgt echo Diacutea del antildeo date(z) ltbrgt echo Estamos en el mes $meses[date(n) ] ltbrgt gt

El resultado en pantalla es el siguiente

Documentacioacuten sobre funciones

Desde sus inicios PHP se disentildeoacute para que fuera sencillo de utilizar y de extender por la comunidad de desarrolladores La potencia reside en la gran cantidad de funciones escritas de todo tipo Este libro cubre las funciones maacutes utilizadas en el desarrollo de un proshyyecto profesional pero seriacutea imposible cubrir todas las funciones existenshytes con detalle Por esta razoacuten es imprescindible tener como referencia la

Funciones 99

guiacutea on-line de PHP en wwwphpnet donde podemos encontrar clasifishycadas por temaacutetica todas las funciones existentes hasta ahora

Ademaacutes contamos con un buscador de apoyo que nos permite buscar la definicioacuten de una funcioacuten y ejemplos de uso escritas por usuarios de PHP

Para los usuarios que no conocen la forma de trabajar con el lenguaje C se hace necesario explicar coacutemo aparecen las funciones descritas en el mashynual de wwwphpnet El formato es el siguiente

tipo_devuelto nombre_funcioacuten (tipol argl tipo2 arg2) -

El t i p o - d e v u e l t o es el tipo de valor que la funcioacuten daraacute como salida Puede ser un integer double array etceacutetera El nombre de la f u n c i oacute n es la forma correcta de ejecutar el coacutedigo Los p a r aacute m e t r o s de e n t r a d a (arshygumentos) deben pertenecer al tipo que define la funcioacuten Un ejemplo de definicioacuten es

string substr (string string int start[ int length] )

Puede ver que la funcioacuten s u b s t r () devolveraacute como resultado una cadeshyna de caracteres y que tiene 2 argumentos de entrada como miacutenimo El paraacutemetro que se encuentra entre dos corchetes es opcional y puede decishydir usarlo o no

Funciones de usuario

Para realizar programas complejos en PHP 5 no es necesario escribir funshyciones Se pueden escribir programas utilizando todo lo aprendido hasta ahora

A medida que el proyecto se haga maacutes complejo el coacutedigo se haraacute maacutes extenso y menos legible En este punto deberiacutea comenzar a pensar en crear funciones que realicen determinadas tareas

Definicioacuten de funciones

El formato es el siguiente

function nombre_funcioacuten($argumentol $argumento2 )

instruccioacutenl instruccioacuten2 instruccioacuten3

100 Capiacutetulo 5

Como puede ver se comienza con la palabra reservada f u n c t i o n seguishyda del nombre de la f u n c i oacute n y el nuacutemero de p a r aacute m e t r o s n e c e s a shyr i o El bloque de coacutedigo que pertenece a nuestra funcioacuten debe introducirse entre dos siacutembolos de llave ( ) Un ejemplo claacutesico consiste en calcular el factorial de varios nuacutemeros El factorial del nuacutemero x se obtiene multishyplicando el nuacutemero x por el factorial de (x-1) teniendo en cuenta que el factorial de 1 es 1 Por ejemplo el factorial de 3 seriacutea 3 por el factorial de 2 es decir 3 2 1 El coacutedigo sin utilizar funciones es

ltphp $resultado = 1 $factorial = 3 Queremos calcular el factorial de 3 for ($x = $factorial $x gt 0 $x--)

^resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt bull

$resultado = 1 $factorial = 4 Queremos calcular el factorial de 4 for ($x = $factorial $x gt 0 $x--)

$resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt

$resultado = 1 $factorial = 5 Queremos calcular el factorial de 5 for ($x = $factorial $x gt 0 $x--)

$resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt

gt

Si se fija en el coacutedigo anterior podraacute comprobar que sigue un patroacuten muy evidente El caacutelculo del factorial se realiza en un bucle que va disminushyyendo el valor de una variable y multiplicando todos los valores entre siacute Aprovechando este patroacuten puede crear una funcioacuten que realice el factoshyrial del nuacutemero x ahorrando liacuteneas de coacutedigo

ltphp function factorial($numero)

$resultado = 1 for ($x = $numero $x gt 0 $x--)

$resultado = $resultado $x return $resultado

echo El factorial de 3 es factorial(3)ltbrgt

Funciones 101

echo El factorial de 4 es factorial(4)ltbrgt echo El factorial de 5 es factorial(5) ltbrgt gt

Si comparamos los dos ejemplos podemos llegar a la conclusioacuten de que el segundo es mucho maacutes legible y maacutes sencillo de realizar Como puede ver la funcioacuten f a c t o r i a l () hace uso de la palabra reservada r e t u r n que es la encargada de devolver el valor que estamos solicitando cuando se invoca la funcioacuten

Nota

Aunque en el ejemplo la funcioacuten f a c t o r i a l () recibe como pashyraacutemetro el nuacutemero 3 4 oacute 5 tambieacuten es posible llamarla con una variable del tipo integer o double

Paraacutemetros insuficientes

Si llama a una funcioacuten con menos paraacutemetros de los que debe utilizar por definicioacuten apareceraacute el siguiente error por defecto

Warning Missing argument 1 for factorial()

Este tipo de error no es criacutetico y puede controlarse con excepciones como veremos en capiacutetulos sucesivos Ademaacutes de las excepciones podemos utilishyzar el operador de supresioacuten de error delante de la funcioacuten de esta forshyma f a c t o r i a l ( )

No se recomienda eliminar los mensajes de error en este caso ya que hace complicado la correccioacuten de los posibles fallos

Paraacutemetros en exceso

Si al contrario que en el apartado anterior le pasa a una funcioacuten maacutes paraacuteshymetros que los definidos eacutestos seraacuten omitidos y la ejecucioacuten continuaraacute normalmente sin ninguacuten mensaje de error Esta propiedad de PHP 5 pershymite utilizar variables con un nuacutemero de paraacutemetros variable

Aacutembito de las variables

Las variables definidas en un archivo de PHP permanecen declaradas en todo el fichero menos en las funciones Las funciones crean un entorno de ejecucioacuten donde soacutelo pueden ver las variables que estaacuten dentro de las mismas Aunque no parece muy loacutegico esto nos permite tener variables

Funciones 103

con el mismo nombre en diferentes funciones haciendo el coacutedigo reutili-zable

Si nos fijamos en el ejemplo

ltphp $pi = 3 1 4 funct ion v a l o r _ p i ( )

if ( uuml s s e t ($pi) ) $pi = p i ()

re turn $pi

echo v a l o r _ p i ( ) gt

Se puede observar que definimos al comienzo del coacutedigo la variable $pi como un valor aproximado del nuacutemero pi (314) La funcioacuten v a l o r _ p i () comprueba si la variable $pi estaacute definida y si no lo estaacute recupera ese valor con una funcioacuten de PHP 5 Para entender el alcance de las variables vamos a ir paso a paso viendo queacute es lo que ocurre

bull Se define $pi a nivel global en el programa

bull Se define la funcioacuten v a l o r _ p i () que por ahora no se utiliza

bull Se lanza la ejecucioacuten de la funcioacuten

bull La funcioacuten evaluacutea si existe la variable $pi y da como resultado false Esto es asiacute porque la variable estaacute definida fuera de la funcioacuten y no dentro de ella por lo tanto se considera que la variable $p i dentro de la funcioacuten es distinta (entorno local) a la variable $pi definida fuera de la funcioacuten (entorno global)

bull El resultado por pantalla es 31415926535898

Esta forma de programar se considera la correcta en la comunidad de de-sarrolladores de PHP Auacuten asiacute existen mecanismos que permiten que una variable definida fuera de una funcioacuten pueda ser utilizada dentro de la misma simplemente anteponiendo la palabra reservada g l o b a l a la vashyriable definida dentro de la funcioacuten

Utilizando el ejemplo anterior tenemos

ltphp $pi = 3 1 4 funct ion v a l o r _ p i ( )

g l o b a l $pi if ( Uuml s s e t ($pi) )

$pi = pi ()

104 Capiacutetulo 5

re turn $pi

echo v a l o r _ p i ( )

gt

Si vemos paso a paso el ejemplo

bull Se define $pi a nivel global en el programa bull Se define la funcioacuten v a l o r _ p i () que por ahora no se utiliza bull Se lanza la ejecucioacuten de la funcioacuten

bull Dentro de la funcioacuten la variable $pi se define como global es decir se utiliza la variable creada al principio del coacutedigo

bull La funcioacuten evaluacutea si existe la variable $p i y da como resultado true

bull El resultado por pantalla es 314

Variables estaacuteticas

Por defecto las funciones que creamos en PHP 5 no retienen en memoria el valor de las variables que se utilizan Cada llamada a una funcioacuten imshyplica la nueva creacioacuten de las variables locales con su valor inicial La deshyclaracioacuten static antildeadida a una variable causa que la funcioacuten retenga en memoria el valor de esa variable en cada llamada Como puede ver en el ejemplo las 100 llamadas a la funcioacuten c o n t a d o r () dan siempre el misshymo resultado porque la variable $ c o n t a d o r se crea con cada llamada

ltphp function contador()

$contador = 0 $contador = $contador +1 return $contador

for ($x = 1 $X lt= 100 $x++)

echo contador() gt

Sin embargo podemos hacer que la funcioacuten recuerde los valores antildeadienshydo la palabra s t a t i c a la definicioacuten de la variable

ltphp function contador()

static $contador = 0 $contador = $contador + 1 return $contador

for ($x = 1 $x lt= 100 $x++)

Funciones 105

echo contador()

gt

iacutenclude() y require()

A medida que su proyecto se hace maacutes complejo comenzaraacute a crear funshyciones muy uacutetiles para conectar a bases de datos crear imaacutegenes al vuelo conectar por FTP etceacutetera y seguramente quiera emplear estas funcioshynes en otros proyectos distintos para ahorrar tiempo El camino para hashycer esto es muy sencillo Soacutelo tiene que guardar las funciones necesarias en un fichero con extensioacuten php htm c s s i n c etceacutetera y utilizar las directivas i n c l u d e () o r e q u i r e f ) desde la Web que vaya a utilizarlas

En PHP 5 no existen apenas diferencia entre ambas funciones salvo que la funcioacuten i n c l u d e () es maacutes tolerante a fallos que r e q u i r e () y permishyte continuar la ejecucioacuten del programa aunque se haya encontrado un fashyllo

La conclusioacuten es que debe utilizarse r e q u i r e () para aplicaciones que necesiten obligatoriamente alguacuten archivo criacutetico y no pueda continuarse la ejecucioacuten sin eacutel

Si en el desarrollo de nuestro proyecto nos encontramos con que vamos a utilizar varios archivos que hacen llamadas unos a otros podriacutea pasar que hagamos varias inclusiones del mismo archivo en distintos puntos proshyvocando alguacuten fallo difiacutecil de detectar Las funciones r e q u i r e _ o n c e () e i n c l u d e _ o n c e () solucionan eacuteste problema ya que si se intenta incluir un fichero varias veces con dichas funciones PHP 5 simplemente ignorashyraacute las llamadas El formato es el siguiente

require base_datosphp include contador_vistasphp require_once test php-include_once visitasphp

Recursividad

El paradigma de la programacioacuten nos lleva a los desarrolladores a invenshytar foacutermulas que minimicen el esfuerzo en nuestros programas pecando

106 Capiacutetulo 5

algunas veces de complejidad Las funciones recursivas son aquellas cashypaces de llamarse a siacute mismas Como uacutenico requisito es que haya una forshyma de salir en la llamada recursiva Si volvemos al ejemplo del nuacutemero factorial nos encontramos en que se puede escribir de la siguiente forma

ltphp function factorial($numero)

if ($numero == 1) return $numero

else return $numero factorial($numero-l)

echo El factorial de 7 es factorial(7) ltbrgt gt

Lo primero que llama la atencioacuten es que carece de un bucle f or para ir disminuyendo los nuacutemeros implicados en el factorial Lo que hace la funshycioacuten es multiplicar el nuacutemero que se pasa por el factorial del nuacutemero-1 Si el nuacutemero que se pasa es igual a 1 la funcioacuten deja de hacer llamadas reshycursivas y comienza a devolver los valores hasta llegar al resultado final

Funciones con nuacutemero de argumentos variables

Es habitual que el nuacutemero de paraacutemetros que se le pase a una funcioacuten dependa de la situacioacuten en la cual es llamada Hay tres formas de hacer esto en PHP

bull Definiendo la funcioacuten con argumentos por defecto Este meacutetodo pershymite hacer llamadas con menos paraacutemetros sin que aparezca un error

bull Usando un array para pasar las variables

bull Usando las funciones de argumento variable f unc_num_args () f u n c _ g e t _ a r g () y f u n c _ g e t _ a r g s () ya utilizadas en PHP 4

Argumentos por defecto

Para definir paraacutemetros de este tipo se sustituyen las variables por exshypresiones de asignacioacuten El formato es el siguiente

function nombre_funcioacuten($argumentol=valorl $argumento2=valor2 )

Funciones 107

De esta forma al llamar a la funcioacuten podemos hacerlo con varios paraacutemeshytros Si alguno de los paraacutemetros es obviado la variable tendraacute como vashylor el valor por defecto de la definicioacuten

ltphp function capitales($Pais$Capital = Madrid$habitantes = muchos)

re turn (La c a p i t a l de $Pais es $Capi ta l y t i ene $habi tantes hab i tan tes ltbrgt)

echo capitales(Espantildea) echo capitales(PortugalLisboa) echo capitales(FranciaParismuchiacutesimos) gt

La salida por pantalla es la siguiente

La capital de Espantildea es Madrid y tiene muchos habitantes La capital de Portugal es Lisboa y tiene muchos habitantes La capital de Francia es Paris y tiene muchiacutesimos habitantes

La funcioacuten c a p i t a l e s () tiene un paraacutemetro fijo y dos paraacutemetros por defecto El paraacutemetro $ P a i s es obligatorio pero los demaacutes pueden queshydarse en blanco recibiendo el valor por defecto La limitacioacuten de este meacutetodo es que los argumentos tienen un orden y no podemos saltarnos ninguno es decir no podemos dar los valores $ C a p i t a l y $ h a b i t a n -t e s porque en medio hay otro paraacutemetro

Argumentos mediante un array

Si no encontroacute alguna utilidad a la anterior forma de pasar valores variashybles quizaacutes necesite utilizar un array para pasarlos El ejemplo siguiente usa esta estrategia y algunos trucos maacutes como el operador ternario y los array asociativos

ltphp function capitales($datos)

$Pais = isset ($datos[Pais ] ) $datos [Pais] Espantildea $Capital = isset ($datos[Capital] ) $datos [Capital] Madrid $habitantes = isset ($datos[habitantes] ) $datos [habitantes] muchos return (La capital de $Pais es $Capital y tiene $habitantes habitantesltbrgt)

Introducimos en el array los datos uno por uno para que sea maacutes faacutecil de entender $datos [Pais] = Espantildea echo capitales($datos) $datos [Pais] = Portugal

108 Capiacutetulo 5

$datos [Capital] = Lisboa echo capitales($datos) $datos [Pais] = Francia $datos [Capital] = Paris $datos [habitantes] = muchiacutesimos echo capitales($datos) gt

Como puede ver la funcioacuten tiene un uacutenico argumento que contiene toshydos los datos que nuestro programa necesita Esta vez los valores por defecto los introducimos mediante el operador ternario que chequea si existe el dato referido al P a i s C a p i t a l o h a b i t a n t e s y si no existe se antildeaden los datos E s p a ntilde a Madr id y muchos El ejemplo utiliza la funcioacuten con 0 2 y 3 paraacutemetros La ventaja de este meacutetodo es que podraacute utilizar los argumentos que quiera y en el orden que necesite sin encasishyllarse en una forma especial de pasar los datos

Nota

Jgt Aunque todaviacutea no hemos visto el capiacutetulo 7 que trata con detalle el manejo dearrays el lector puede hacerse una idea de coacutemo funshycionan en el aacutembito de los paraacutemetros defunciones Si queda alshyguna duda de coacutemo utilizarlos siempre puede echar un breve vistazo al capiacutetulo 7 para aclarar esas lagunas

Funciones 109

Muacuteltiples argumentos con func_num_args()

Desde la versioacuten 4 PHP ofrece algunas funciones que pueden ser utilizashydas para recuperar los argumentos

Son muy similares al lenguaje C

bull func_num_args() Devuelve el nuacutemero de argumentos que recibe la funcioacuten desde la que es llamada

bull func_get_arg() Devuelve uno a uno los argumentos pasados de la sishyguiente forma func_get_arg(0) func_get_arg(l) func_get_arg(5)

bull func_get_args() Devuelve un array con todos los argumentos pasashydos a la funcioacuten con los iacutendices del array empezando desde 0

Cualquiera de estas funciones daraacute un error si son llamadas fuera del enshytorno de una funcioacuten y f u n c _ g e t _ a r g () produciraacute un fallo si es llashymada con un nuacutemero maacutes alto que los argumentos que se reciben

Las funciones anteriores dan una ventaja a largo plazo ya que si durante el periacuteodo de vida de una funcioacuten necesita antildeadir alguacuten argumento maacutes puede capturar sin necesidad de cambiar el coacutedigo de las llamadas o el de definicioacuten de la funcioacuten

En el ejemplo siguiente puede comprobar coacutemo se utiliza este meacutetodo

ltphp function capitales()

$numero_argumentos = func_num_args() $Pais = $numero_argumentos gt 0 func_get_arg(0) Espantildea $Capital = $numero_argumentos gt 1 func_get_arg(1) Madrid $habitantes = $numero_argumentos gt 2 func_get_arg (2) muchos return (Nuacutemero de argumentos es $numero_arguraentos La capital de $Pais es $Capital y tiene $habitantes habitantesltbrgt)

echo capitales() echo capitales(Portugal Lisboa) echo capitales(Francia Paris muchiacutesimos) gt

Esta forma de utilizar los argumentos sigue teniendo una limitacioacuten Los argumentos deben ser pasados en un lugar determinado sino la funcioacuten no haraacute bien su trabajo Utilizar los paraacutemetros como array es el meacutetodo maacutes flexible y el maacutes utishylizado en los programas PHP Auacuten asiacute es muy uacutetil cuando no sepa cuaacutentos datos necesita manejar una funcioacuten Podemos utilizarlo para funciones que sumen todos los parame-

110 Capiacutetulo 5

tros que introduzca o concatenen todas las palabras como el ejemplo sishyguiente

ltphp function concatenar()

$resultado = $numero_argumentos = func_num_args() $array_parametros = func_get_args() for ($x = 0 $x lt= $numero_argumentos $x++)

$resultado = $resultado $array_parametros[$x]

return $resultadoltbrgt

echo concatenar(Hola Mundo) echo concatenar(Esto es una prueba dela potencia de este meacutetodo) gt

Llamadas por valor

Por defecto las llamadas a funciones se hacen por valor Esto quiere decir que las variables que se utilizan como paraacutemetros se copian al entorno de la funcioacuten

Todos los cambios de valor que sufra la variable en este entorno no afecshytaraacuten al programa fuera de la funcioacuten

ltphp function elevado($nuraero$ iacutendice)

$resultado = $numero for ($x = $indice $x gt 0 $x--)

$resultado = $resultado $nuraero

$numero = $resultado return $numero

$numero = 2 $indice = 5 echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt echo $numero elevado a $indice es igual a elevado ($numero$ indice) ltbrgt gt

El resultado por pantalla es

2 elevado a 5 es igual a 64 2 elevado a 5 es igual a 64

Funciones 111

El ejemplo anterior calcula el resultado de $numero elevado a $ Iacute n d i c e La funcioacuten e l e v a d o () crea un bucle para multiplicar $numero por las veces que indica el $ iacute n d i c e y lo va almacenando en la variable temporal $resultado

Cuando el bucle termina este resultado se vuelve a pasar a la variable $ numero que es devuelta como salida de la funcioacuten Cuando volvemos a ejecutar la funcioacuten con los mismos paraacutemetros vemos que la variable $nu-mero no ha cambiado en la ejecucioacuten anterior porque en realidad lo que se pasa es una copia del valor y todas las modificaciones se hacen sobre la copia y no sobre la variable original

Llamadas por referencia

PHP 5 ofrece actualmente dos caminos diferentes para cambiar sus argushymentos en la definicioacuten de la funcioacuten y en la llamada a la misma

Las variables pasadas por referencia pueden ser modificadas durante el proceso de una llamada porque lo que se pasa no es una copia sino la variable en siacute misma

Para pasar variables por referencia hay que utilizar el operador (amp) deshylante de la variable

Lo mejor es verlo en un ejemplo

ltphp function elevado(amp$numeroamp$indice)

$resultado = $numero for ($x = $iacutendiacutece $x gt 0 $x--)

$resultado = $resultado $numero

$numero = $resultado return $numero

$numero = 2 $ iacutendice = 5 echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt gt

El resultado por pantalla es ahora

2 elevado a 5 es igual a 64 64 elevado a 5 es igual a 68719476736

El funcionamiento es exactamente igual pero el resultado es distinto El operador (amp) hace que la variable $numero pueda ser modificada dentro de la funcioacuten y guarde este nuacutemero fuera de ella

Tambieacuten puede forzar a una funcioacuten a tomar argumentos por referencia aunque esta capacidad de PHP puede desaparecer en futuras versiones del lenguaje Las llamadas pueden hacerse de la siguiente forma

$numero = 2 $indice = 5 echo $numero elevado a $indice es igual a elevado(amp$numeroamp$indice)ltbrgt echo $numero elevado a $indice es igual a elevado(amp$numeroamp$indice)ltbrgt

El resultado es exactamente igual que al poner la referencia en la definishycioacuten de la funcioacuten

Referencia a variables

Las referencias pueden usarse tambieacuten fuera de las funciones en el aacutembishyto de las variables El ejemplo siguiente muestra coacutemo trabaja el operador (amp) con las variables

ltphp $nombre = Luis Miguel

Funciones 113

$apelliacutedos = Cabezas Granado $nombre auxiliar es simplemente una copia de $nombre $nombre_auxiliar = $nombre-$nombre_referencia es una referencia a la variable $nombre_referencia = amp$nombre echo $nombre $apellidosltbrgt $nombre_auxiliar = Alberto echo $nombre $apellidosltbrgt $nombre_referencia = Felipe echo $nombre $apellidosltbrgt gt

$nombre__aux i l i a r es una copia de la variable $nombre y por mucho que la cambiemos $nombre permaneceraacute con el mismo valor En cambio la variable $nombre_ref e r e n c i a es un alias de $nombre por lo tanto todos los cambios que se hagan en cualquiera de las dos variables les afecshytaraacute por igual

Funciones variables

Uno de los trucos que se pueden hacer con PHP es utilizar variables para almacenar el nombre de funciones Si una variable almacena el nombre de una funcioacuten simplemente tendraacute que antildeadir unos pareacutentesis al final de la variable para hacer la llamada correctamente

ltphp function saludo_maniana()

return (Buenos Diacuteas)

function saludo_tarde()

return (Buenas Tardes)

function saludo_noche()

return (Buenas Noches) $horario = tarde $funcion_variable = saludo_$horario echo $funcion_variable () gt

En el ejemplo anterior tenemos tres funciones que nos saludan depenshydiendo del horario en el que ejecutemos el programa Este valor se recoge en la variable $ h o r a r iacute o Sabemos que todas las funciones comienzan con la palabra saludo_ Si a la variable $f u n c i o n _ v a r iacute a b l e le concatenashymos el valor de $ h o r a r i o tenemos como resultado el nombre de la fun-

1 1 4 Capiacutetulo 5

cioacuten que nos daraacute el saludo Para que esto funcione antildeadimos dos siacutemboshylos de pareacutentesis al final de la expresioacuten

Resumen

Si el capiacutetulo anterior daba rienda suelta a su imaginacioacuten para comenzar con el desarrollo de pequentildeos scripts despueacutes de leer este capiacutetulo estaraacute en situacioacuten de realizar un gran proyecto Ahora que conoce el secreto para almacenar en distintos archivos funciones y partes de un programa escrishyto en PHP podraacute crear aplicaciones maacutes extensas y complejas

Ahora bien debe tener en cuenta que hay que tener cuidado con el alcanshyce de las variables y los pasos por valor y referencia aspecto muy relevanshyte en el capiacutetulo referido a los objetos

En este capiacutetulo aprenderaacute a

bull Diferenciar entre las comillas simples y las comillas dobles bull Trabajar con cadenas de muacuteltiples liacuteneas bull Concatenar varias cadenas bull Generar nuevas cadenas de caracteres a partir de una original bull Eliminar los espacios en blanco de las cadenas bull Convertir a mayuacutesculas o minuacutesculas bull Definir patrones de verificacioacuten de cadenas

116 Capiacutetulo 6

Introduccioacuten

Si pensamos en los tipos de datos que circulan por la red llegaremos a la conclusioacuten de que una gran porcioacuten la ocupan las imaacutegenes animaciones en Macromedia Flash videos o subprogramas escritos en Java La otra gran porcioacuten mayoritaria son los textos o las cadenas de caracteres

Las cadenas de caracteres o string son secuencias de caracteres que pueshyden ser tratadas como una unidad asignadas a variables pasadas como paraacutemetros a funciones o enviadas como salida al navegador Un string se diferencia de otro tipo de dato en PHP 5 porque va encerrado entre comishyllas dobles ( ) o simples ( )

Cadena entre comillas dobles Cadena entre comillas simples

PHP interpreta de distinta forma las cadenas que van entre comillas doshybles y las que van entre comillas simples Losstrings entre comillas dobles pueden sustituir ciertos siacutembolos por acciones como la inclusioacuten del vashylor de una variable Las comillas simples simplemente muestran todo el contenido sin atender a caracteres especiales Podemos ver un ejemplo donde sucede esto

ltphp $variable = Domingo $frase_l = Hoy es $variable el cielo estaacute gris $frase_2 = Hoy es $variable el cielo estaacute gris echo $frase_l echo $frase_2 gt

El resultado en el navegador es

Hoy es Domingo el cielo estaacute gris Hoy es $variable el cielo estaacute gris

Como se puede observar la cadena $f r a s e _ l es capaz de sustituir la vashyriable por su valor por el simple hecho de estar entre comillas dobles

Propiedades de las cadenas

iacutendices de string

Si pensamos en las cadenas como una sucesioacuten de caracteres en un orden determinado podemos llegar a desear acceder libremente a parte de los

Cadenas de caracteres y expresiones regulares 117

caracteres Esto es posible gracias a los siacutembolos de llave ( ) y un iacutendice numeacuterico que se corresponderaacute con la posicioacuten del caraacutecter que buscamos El ejemplo muestra coacutemo crear una funcioacuten que duplica las letras de una cadena aprovechando esta forma de acceder a los caracteres

ltphp function duplicar_caracteres($cadena)

$tamanio = strlen ($cadena) $cadena_auxiliar = for ($x = 0$x lt $tamanio $x++)

$cadena_auxiliar = $cadena_auxiliar $cadena$x $cadena$x

return $cadena_auxiliar

$cadena = Duplicar las letras echo duplicar_caracteres($cadena)iexcl gt

La salida por pantalla como puede adivinar es

118 Capiacutetulo 6

Operadores

En este punto aprovecharemos para hacer un breve repaso de los operashydores de string vistos en el capiacutetulo 3 En otros lenguajes como Java se utiliza el operador suma (+) para unir dos cadenas En PHP este mismo resultado se obtiene con el operador punto ( ) Asiacute podemos concatenar varias cadenas de la forma siguiente

ltphp $cadenal = Hola $cadena2 = Mundo $cadena3 = iexclQueacute tiacutepico $supercadena = $cadenal $cadena2 $cadena3 echo $supercadena gt

Es faacutecil intuir que el operador puede concatenar caracteres y variables de tipo string de forma conjunta Es posible que desee ahora antildeadir texto a una cadena ya existente esto se puede hacer de dos formas muy similashyres La primera es asignando a la variable su valor maacutes el valor a antildeadir de la siguiente forma

ltphp $cadenal = Hola $cadena2 = Mundo $cadenal = $cadenal $cadena2 echo $cadenal gt

O utilizando el operador de concatenacioacuten y asignacioacuten ( = ) como en el ejemplo

ltphp $cadenal = Hola $cadena2 = Mundo $cadenal = $cadena2 echo $cadenal gt

Sintaxis para muacuteltiples liacuteneas

Existe en PHP una forma maacutes de introducir cadenas aparte de las comishyllas muy recomendable para largos textos o un considerable conjunto de etiquetas HTML La sintaxis es muy sencilla y comienza con el operador (ltltlt) seguido de una etiqueta que indica el principio del texto Despueacutes de esto podemos escribir un conjunto de caracteres muy numerosos y para

Cadenas de caracteres y expresiones regulares 119

finalizar la etiqueta de fin El ejemplo muestra coacutemo almacenar un forshymulario en una variable

ltphp $formulario = ltltltINICIO ltformgt ltiacutenput type=text name=Nombre value=Luiacutes Miguel Cabezasgt ltbrgt ltinput type=submit name=submit value=Enviar gt ltformgt INICIO echo $formulario gt

Siempre debe comenzar por el operador (ltltlt) seguido de un identifica-dor por ejemplo INICIO Despueacutes se incluye el texto en este caso un forshymulario y para finalizar la misma etiqueta de inicio Esta forma de almacenar datos permite utilizar indistintamente comillas simples o doshybles dentro de una variable La imagen 62 muestra el resultado del script

Funciones de string

Si conoce el lenguaje C podraacute comprobar que las funciones de manejo de caracteres son muy parecidas en nombre y uso Los desarrolladores de PHP

120 Capiacutetulo 6

siempre han querido que exista esta similitud para facilitar el aprendizaje del lenguaje

La mayoriacutea de las funciones existentes en PHP 5 tienen una homologa en C

Tamantildeo de la cadena

La funcioacuten s t r l e n () devuelve como resultado el tamantildeo en caracteres de la cadena que pasemos de paraacutemetro Este valor puede asignarse a una variable como indica el ejemplo

ltphp $cadena = Esta cadena tiene muchas letras $numero_letras = strlen($cadena) echo cadena tiene $numero_letras caracteres gt

Simplemente imprime

cadena tiene 31 caracteres

Posicioacuten de los caracteres

Para crear buenos motores de buacutesqueda en nuestros sitios Web necesitashyremos potentes herramientas que sean capaces de buscar caracteres cashydenas o patrones coincidentes dentro de textos extensos La funcioacuten s t r p o s () encuentra en un string la posicioacuten de un caraacutecter determinado

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de a es strpos($cadena a) ltbrgt echo La primera ocurrencia de m es strpos($cadena m) ltbrgt gt La s a l i d a en el navegador no es o t ra que La primera ocur renc ia de a es 3 La primera ocur renc ia de m es 18

Si s t r p o s () se utiliza para averiguar la posicioacuten de la primera L mashyyuacutescula de $ cadena vemos que nos devuelve un 0 esto es asiacute porque el iacutendice de caracteres comienza en 0 como pasa en muchos lenguajes de programacioacuten Si no se encuentra ninguna ocurrencia del caraacutecter buscashydo el resultado seraacutease

Cadenas de caracteres y expresiones regulares 121

La funcioacuten s t r p o s () tambieacuten puede utilizarse para buscar varios caracshyteres seguidos en una misma cadena

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de tiene es strpos($cadenatiene) ltbrgt gt

Si lo que nos interesa es encontrar caracteres buscando desde el final de la cadena la funcioacuten que tenemos que utilizar es s t r r p o s () (la letra r que se antildeade viene del ingleacutes reverse) El ejemplo anterior nos sirve para comshyprobar el funcionamiento de la funcioacuten

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de a es strpos($cadena a ) ltbrgt echo La primera ocurrencia desde atraacutes de a es strrpos($cadena a) ltbrgt gt

siendo el resultado

La primera ocurrencia de a es 3 La primera ocurrencia desde atraacutes de a es 29

Comparacioacuten

El operador (==) nos puede servir para evaluar si dos cadenas de caracteshyres son iguales dentro de una estructura de control Ademaacutes tenemos la funcioacuten s t r c m p ( ) que compara bit a bit dos cadenas de caracteres Atenshydiendo al valor de salida de la funcioacuten podemos obtener los siguientes resultados

bull Si el valor que se obtiene es 0 las dos cadenas son exactamente igual

bull Si obtenemos un valor negativo el primer string es maacutes pequentildeo que el segundo

bull Si obtenemos un valor positivo el primer string es maacutes grande que el segundo ltphp $cadenal = Prueba $cadena2 = Prueba if (strcmp($cadenal$cadena2) == 0)

echo Las dos cadenas son iguales elseif (strcmp($cadenal$cadena2) lt 0)

echo La cadenal es menor que la cadena2

122 Capiacutetulo 6

else echo La cadenal es mayor que la cadena2

gt

La comparacioacuten anterior soacutelo da como resultado dos cadenas iguales si las dos cadenas son exactamente iguales haciendo distincioacuten entre mashyyuacutesculas y minuacutesculas

Para evitar este problema podemos utilizar la funcioacuten s t r c a s e c m p ( ) que no es sensible a mayuacutesculas Asiacute s t r c a s e c m p (HoLa hOlA) da como resultado 0 es decir las dos cadenas son iguales

Buacutesqueda de caracteres

Siguiendo con las buacutesquedas de texto la funcioacuten s t r s t r () recibe como paraacutemetros una cadena de caracteres donde buscar y otra con un conjunshyto de caracteres que queremos encontrar Si se encuentra el patroacuten de buacutesshyqueda el resultado seraacute una cadena de caracteres que comenzaraacute justo en el patroacuten hasta el final del string primero Si no se encuentra el patroacuten el resultado seraacutefalse

lt php $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de cadena es strstr ($cadenacadena) ltbrgt

gt

Como cabe esperar el resultado es La primera ocurrencia de cadena es cadena tiene muchas letras

Seleccioacuten de subcadenas

La funcioacuten s u b s t r () permite seleccionar un conjunto de caracteres de una cadena quedando intacto el string original Puede tomar varios paraacuteshymetros

bull s u b s t r ( c a d e n a iacute n d i c e ) Cadena es el conjunto de caracteres que queremos cortar e iacute n d i c e la posicioacuten a partir de la cual se cortaraacute la cadena hasta el final

bull s u b s t r ( cadena iacute n d i c e numero) Cadena es el conjunto de cashyracteres que queremos cortar e iacute n d i c e la posicioacuten a partir de la cual se cortaraacute la cadena tantas posiciones como indique el nuacutemero

Cadenas de caracteres y expresiones regulares 123

Por ejemplo

ltphp $cadena = Esta cadena tiene muchas letras Devuelve la cadena completa echo substr($cadena 0) echo ltbrgt Desde el caraacutecter 12 hasta el final echo substr($cadena 12) echo ltbrgt Devuelve 6 caracteres desde el caraacutecter 18 echo substr($cadena 186) echo ltbrgt Devuelve los 6 uacuteltimos caracteres echo substr($cadena -6) echo ltbrgt Desde la posicioacuten 26 contando desde atraacutes 6 caracteres echo substr($cadena -266) echo ltbrgt Empezando en el caraacutecter 4 y terminando en el 7 desde atraacutes echo substr($cadena 4-7) gt

El resultado lo podemos ver maacutes abajo Recuerde que la variable $ cade -na queda intacta

124 Capiacutetulo 6

Dependiendo de la posicioacuten del nuacutemero negativo s u b s t r () actuaraacute de una forma u otra

Tabla 61 Respuestas de la funcioacuten substr ()

Ejemplo Resultado

substr(Hola2) Devuelve la cadena completa empezando por el caraacutecter 2 substr(Hola-2) Devuelve la cadena completa empezando por el caraacutecter

2 esta vez empezando a contar desde atraacutes

substr(Hola13) El resultado son 3 caracteres empezando desde el caraacutecshyter 1

substr(Hola-32) Doscaracteres empezando desde el caraacutecter 3 contando desde la uacuteltima letra

substr(Hola2-1) Devuelve un conjunto de caracteres que estaacuten desde la posicioacuten 2 a la posicioacuten 1 comenzando desde atraacutes

substr(Hola-2-3) No tiene aplicacioacuten posible

Funciones de limpieza de cadenas

Sirven para limpiar espacios en blanco al principio de la cadena al final o en cualquier parte desde el principio al final y son respectivamente l t r i m ( ) chop () y t r i m () Su aplicacioacuten es tan sencilla que bastaraacute un ejemplo para entender su funcionamiento

ltphp $salto_linea = n $cadena = cadena con varios espacios en blanco echo $salto_linea $cadena tamantildeo strlen($cadena) echo ltbrgt echo $salto_linea ltrim($cadena) tamantildeo strlen(ltrim($cadena)) echo ltbrgt echo $salto_linea chop($cadena) tamantildeo strlen(chop($cadena)) echo ltbrgt echo $salto_linea trim($cadena) tamantildeo strlen(trim($cadena)) gt

Cada liacutenea realiza una de las operaciones vistas e imprime el resultado de la cadena en el navegador junto con el tamantildeo de la cadena

La figura 64 muestra el resultado por pantalla

126 Capiacutetulo 6

Sustitucioacuten de cadenas

La funcioacuten s t r _ r e p l a c e () toma como paraacutemetros un conjunto de cashyracteres a buscar un grupo que debe sustituirse por el anterior y una cashydena de caracteres sobre la que actuar

ltphp $cadena = Esta cadena tiene muchas letras $cadena = str_replace(EstaEste$cadena) echo str_replace(cadenaconjunto$cadena) gt

Si en la cadena existiera maacutes de una instancia del conjunto buscado todas las ocurrencias quedariacutean cambiadas

ltphp cadena = Esta cadena tiene muchas letras y cadenas $cadena = str_replaceacute(EstaEste$cadena) echo str^replace(cadenaconjunto$cadena) gt

El resultado es Este conjunto tiene muchas letras y conjuntos

Truco

Puede probar esta funcioacuten para cambiar todos iexclos caracteres de un tipo de una cadena de iexcla siguiente forma s t r _ r e p l a c e (h j hola h o l a )

Funciones de mayuacutescula y minuacutescula

Las funciones s t r t o l o w e r () y s t r toupper () devuelven la cadena que se pasa como argumento completamente en minuacutescula o mayuacutescula resshypectivamente

ltphp $cadena = Hay palabras en MAYUacuteSCULAS y en minuacutesculasltbrgt echo strtolower($cadena) echo strtoupper($cadena) gt

El resultado es hay palabras en mayuacutesculas y en minuacutesculas HAY PALABRAS EN MAYUacuteSCULAS Y EN MINUacuteSCULAS

Si lo que realmente nos interesa es que la primera letra de un texto apashyrezca como letra Capital o que letras iniciales de cada palabra en una fra-

Cadenas de caracteres y expresiones regulares 127

se aparezcan en mayuacutescula tenemos las funciones u c f i r s t ( ) y u c w o r d s ( )

ltphp $cadena = habiacutea una vezltbrgt echo ucfirst($cadena) $cadena2 = linux user group echo LUG significa ucwords($cadena2) gt

Expresiones regulares

Las funciones vistas anteriormente basan su potencia en la buacutesqueda o susshytitucioacuten de los caracteres de una cadena pero son poco uacutetiles cuando tratashymos de comprobar si un conjunto de caracteres cumple un formato determinado Si solicitamos mediante un formulario un correo electroacutenico necesitamos saber a priori si ese correo por lo menos estaacute bien construido

luisnccextremaduraorg luiszendcom

La idea es poder descartar de alguna forma los correos escritos de esta manera

l u i s (Snccextremaduraorg E s p a c i o en medio

128 Capiacutetulo 6

LUISzendcom En mayuacutesculas luisaupexorg Dos

Las expresiones regulares son patrones de buacutesqueda dentro de cadenas Estos patrones se construyen mediante caracteres especiales que cumplen unas reglas determinadas

Tabla 62 Reglas de expresiones regulares

Ejemplo Regla

aabb Los caracteres no especiales como un grupo de letras se escriben como de costumbre

A Indica que hay que buscar el patroacuten desde el principio de la cadena $ Este simbolo obliga al patroacuten a cumplirse hasta el final de la

cadena Simboliza cualquier caraacutecter

Indica que puede haber O o maacutes instancias de una expresioacuten + Indica que puede haber 1 o maacutes instancias de una expresioacuten [ab] Indica que se puede encontrar el caraacutecter a o el b y la expresioacuten

seriacutea correcta Lo podemos acompantildear de [ab] para evaluar si hay varias letras seguidas del tipo a o b

[a-z] Indica que se puede elegir entre un rango de caracteres que va desde la a hasta la z

Si queremos utilizar cualquiera de los anteriores caracteres como parte del patroacuten tendremos que utilizar eacuteste siacutembolo para indicarle a PHP que es un literal

Como ejemplo vamos a intentar hacer un patroacuten que verifique si un coshyrreo electroacutenico estaacute correctamente construido o no Seriacutea faacutecil pensar en una expresioacuten parecida a la siguiente

[ a - z ] + [ a - z ] + o r g

La primera parte [ a - z ] + nos dice que aceptaraacute una letra o conjunto de letras sin espacios y en minuacutesculas que pueden corresponderse con el nombre de usuario de la cuenta de correo Despueacutes aceptaraacute un siacutembolo seguido de otro conjunto de caracteres correspondientes al servidor de correo La uacuteltima parte de la expresioacuten la componen los siacutembolos que indican que tiene que aparecer un punto que separe la descripcioacuten del servidor del dominio y la cadena o r g que obliga a que todos los correos sean de dominio no gubernamental

Cadenas de caracteres y expresiones regulares 129

La expresioacuten anterior tiene algunas limitaciones que veremos como solshyventar La primera es que se puede aplicar a cualquier texto con indepenshydencia del tamantildeo Si en alguna parte de ese texto aparece un conjunto de caracteres que cumpla con la expresioacuten la validacioacuten seriacutea true Esto no es bueno cuando queremos chequear si un correo es introducido correctashymente La solucioacuten es aplicar las reglas de inicio y fin que obligan a que el comienzo de la cadena y el final sean parte de la expresioacuten

[ a - z ] + [ a - 2 ] + o r g $

Tambieacuten podemos encontrarnos con que existen correos introducidos coshyrrectamente pero el dominio es otro distinto a org Esta vez la solucioacuten es introducir el operador O loacutegico | que permite elegir entre varias opcioshynes

^ [ a - z ] + [ a - z ] + ( o r g | c o m | n e t ) $

Por uacuteltimo un problema menor aunque habitual en el aacutembito de los coshyrreos electroacutenicos es la utilizacioacuten de signos de puntuacioacuten para separar nombres y apellidos y servidores de servidores virtuales Por ejemplo el correo siguiente es correcto pero no seriacutea evaluado por la expresioacuten anteshyrior

l u iacute s c a b e z a s n c c a u p e x o r g

Una posible solucioacuten es

[ a - z | ] + [ a - z | ] + ( o r g | c o m ( n e t ) $

Comprobar expresiones regulares

La funcioacuten e reg () es capaz de comprobar si una cadena se corresponde con el patroacuten que se pasa como paraacutemetro Toma dos argumentos obligashytorios una expresioacuten regular y una cadena de caracteres donde buscar el patroacuten Seguidamente puede ver un ejemplo completo de utilizacioacuten de expresiones regulares y la funcioacuten

ltphp $correo = luiscabezasnccaupexorg $correol = LUISnccaupexorg $correo2 = luiscabezasnccaupexorg if (ereg ( [a-z|]+[a-z|]+ (org|com|net)$$correo))

echo El correo $correo se aceptaltbrgt else

echo El correo $correo no cumple el patroacutenltbrgt

iacutef (ereg(^ [a-z|]+ [a-z|]+ (org|comjnet)$$correol) )

echo El correo $correol se aceptaltbrgt

130 Capiacutetulo 6

else echo El correo $correol no cumple el patroacutenltbrgt

if (ereg(A [a-zj]+ [a-zj]+ (org|com|net)$$correo2))

echo El correo $correo2 se aceptaltbrgt else

echo El correo $correo2 no cumple el patroacutenltbrgt gt

El resultado por pantalla es

Puesto que hay muchos usuarios acostumbrados a escribir su correo elecshytroacutenico completamente en mayuacutesculas se hace necesario comprobar este contratiempo tambieacuten Lo maacutes raacutepido es utilizar la funcioacuten e r e g i () que funciona exactamente igual que e r e g ( ) pero no es sensible a mayuacutescula o minuacutescula El ejemplo anterior lo podemos arreglar de la siguiente forma

ltphp $correo = LUISnccaupexorg if (ereg([a-z|]+[a-z|]+(org|com|net)$$correo$pepe))

echo El correo $correo se aceptaltbrgt else

echo El correo $correo no cumple el patroacutenltbrgt

gt

Cadenas de caracteres y expresiones regulares 131

Nota

e reg () y e r e g i () tienen un tercer argumento opcional del tipo array Si iexcla expresioacuten regular la dividimos en pequentildeas parshytes entre pareacutentesis cada ocurrencia encontrada en la cadena se va almacenando como un elemento del array

Reemplazar patrones

e r e g _ r e p l a c e () y e r e g i _ r e p l a c e () tiene tres paraacutemetros El prishymero es una expresioacuten regular el segundo un string por el que se cambiashyraacuten todas las ocurrencias del patroacuten y por uacuteltimo una cadena donde buscar Como antes la diferencia entre las dos es uacutenicamente que la prishymera es sensible a mayuacutesculas El siguiente ejemplo muestra el funcionashymiento

ltphp $texto = El correo es de luisnccaupexorg echo ereg_replace([a-z|]+[a-z|]+(org|com|net)Luis Miguel$texto) gt

Asiacute da como resultado el cambio del correo electroacutenico por el nombre de la persona asociada

Resumen

Desde hace unos antildeos se ha puesto de moda una serie de productos donshyde prima el contenido frente al disentildeo Los CMS (Content Manager System) son programas la mayoriacutea escritos en PHP que permiten gestionar mushycho contenido escrito por diferentes personas El tratamiento de los textos se agudiza al maacuteximo en este caso siendo indispensable la utilizacioacuten de expresiones regulares para verificar los datos nuevos que puedan incor- porarse Ademaacutes suelen llevar un buscador capaz de encontrar patrones determishynados dentro de las noticias expuestas Este capiacutetulo le ha servido para conocer funciones para concatenar recorshytar o verificar cadenas Con esto bien aprendido ya puede comenzar a crear su propio CMS

En este capiacutetulo aprenderaacute a

bull Comprender queacute es un array y coacutemo se define bull Trabajar con funciones que definen listas de datos bull Diferenciar entre los distintos meacutetodos para recorrer los array

bull Ordenar los conjuntos de datos con diferentes meacutetodos bull Crear pilas y colas

134 Capiacutetulo 7

Introduccioacuten

Un array es una coleccioacuten de valores con un uacutenico nombre Para acceder a los distintos valores de la variable se utiliza un iacutendice numeacuterico o alfanu-meacuterico Nos vamos a servir de la definicioacuten de un array en el lenguaje C para ver la potencia de este tipo de datos en PHP La definicioacuten es la siguiente

int mi_array[100] Esto es C

Lo primero que debe llamarnos la atencioacuten es que la variable estaacute predefishynida como i n t (entero) En PHP los arrays no tienen que definirse de una forma concreta sino que pueden tomar distintos tipos de valores enteshyros caracteres objetos etceacutetera Lo siguiente es que en C se necesita sashyber de antemano el nuacutemero de valores maacuteximo que podraacute tomar el array Esto no es necesario en PHP ya que podraacute ir creando valores nuevos a medida que lo vaya necesitando Lo uacuteltimo es que en C el iacutendice para acshyceder a los 100 valores distintos debe ser numeacuterico en cambio en PHP el iacutendice puede ser numeacuterico o alfanumeacuterico

ltphp $mi_array[l] = 23 $mi_array[2] = Este valor es un string $mi_array[ejemplo] = Esto es un array asociativo gt

Creacioacuten de arrays

Vamos a ver tres formas distintas de crear un array dentro de un script de PHP

Asignacioacuten directa

El camino maacutes simple y por otro lado loacutegico es asignar valores cuando se necesiten La primera vez que asignemos un valor el array se crearaacute en el entorno

ltphp $mi_array[l] = 23 Asignacioacuten directa gt

De esta forma tenemos un valor asignado al iacutendice 1 del array Puede asigshynar cualquier iacutendice en la creacioacuten de este tipo de dato e incluso no asig-

Conjuntos de datos del tipo array 135

nar ninguno de forma que PHP se encarga de asociar un iacutendice distinto para cada valor

ltphp $mi_array[] = 23 Empieza en el iacutendice 0 $mi_array[] = 54 iacutendice 1 gt

array()

Esta funcioacuten crea un array con los valores que pase como datos de entrashyda Los iacutendices seraacuten antildeadidos automaacuteticamente empezando desde 0

Si no asigna paraacutemetros a a r r a y ( ) la funcioacuten le devolveraacute un array vaciacuteo

ltphp $mi_array = array(2345762365) gt

El meacutetodo es similar a

ltphp $mi_array[0] = 23 $mi_array[l] = 4 5 $mi_array[2] = 76 $mi_array[3] = 23 $mi_array[4] = 65 gt

La funcioacuten a r r a y () permite tambieacuten antildeadir iacutendices a los valores que se introducen

Para ello se utiliza el operador =gt de esta forma

ltphp $mi_array = array0 =gt 23 1 =gt 45 2 =gt 76) gt

Tambieacuten es posible antildeadir iacutendices que no sean correlativos o iacutendices alf-anumeacutericos incluso mezclar los dos tipos

ltphp $mi_array = a r r a y ( c e r o =gt 23 uno =gt 45 2 =gt 7 6 ) gt

Para recuperar cualquier valor se utiliza el iacutendice dentro de los corchetes

ltphp $mi_array = array(cero =gt 23 uno =gt 45 2 =gt 76) echo $mi_array [ uno] ltbrgt echo $mi_array[2] gt

136 Capiacutetulo 7

Funciones que devuelven arrays

La uacuteltima forma de obtener un array es utilizando alguna de las funcioshynes que devuelven este tipo de datos

Es muy frecuente que las funciones que manejan bases de datos devuelshyvan las ocurrencias dentro de un array

Por ejemplo la funcioacuten r a n g e () devuelve un array con valores numeacuterishycos que van desde un nuacutemero de inicio hasta un nuacutemero final tal y como se muestra en el ejemplo

ltphp $mi_array = range(120130) gt

Esta funcioacuten crea un array empezando desde el iacutendice 0 y el valor 120 hasta el iacutendice 10 y el valor 130

Arrays multidimensionales

Hasta aquiacute hemos visto ejemplos de arrays de una sola dimensioacuten PHP soporta el uso de arrays de varias dimensiones faacutecilmente aunque son complejos de entender y de usar El array siguiente es de 5 dimensiones

ltphp $ m i _ a r r a y [ l ] [ 1 ] [ 2 3 ] [ 4 3 ] [ 0 ] = A r r a y de 5 d i m e n s i o n e s gt

Cada iacutendice encerrado entre corchetes corresponde a una dimensioacuten disshytinta En realidad cada dimensioacuten es un array que se introduce como vashylor dentro de la dimensioacuten anterior

Asiacute podraacute crear un array multidimensional de la siguiente forma

ltphp $colores = array(fuertessuaves) $colores [fuertes] = array ( rojo =gt FF0000 verde =gt 00FF00 azul =gt 0000FF)

$ c o l o r e s [ s u a v e s ] = a r r a y ( r o s a =gt FE9ABC a m a r i l l o =gt FDF189 malva =gt 9 A 2 F 6 8 ) echo $colores[fuertes] [rojo] gt

Para recuperar los valores se utilizan un iacutendice del primer array (fuertes o suaves) y un iacutendice de alguno de los dos arrays secundarios

Conjuntos de datos del tipo array 137

Otra forma de definir el array anterior es

ltphp

$colores = array( fuertes =gt array ( rojo =gt FF0000 verde =gt 00FF00 azul =gt 0000FF)

suaves =gt array ( rosa =gt FE9ABC amarillo =gt FDF189 malva =gt 9A2F68))

echo $colores[fuertes] [rojo] gt

Propiedades de arrays

Existen numerosas funciones que son capaces de averiguar datos de los arrays tales como el tamantildeo si un valor forma parte del conjunto o si un determinado iacutendice estaacute registrado

count()

Cuenta el nuacutemero de elementos que contiene un array

ltphp echo elementos de 1 dimensioacuten count ($colores) ltbrgt echo elementos de 2 dimensiones count ($colores[fuertes]) gt

El ejemplo anterior se basa en la definicioacuten del array de colores inicializa-do antes Para contar el nuacutemero de elementos debe ponerse tambieacuten la dimensioacuten Si el array es de una sola dimensioacuten no hace falta La funcioacuten s i z e o f () actuacutea de la misma forma

in_array()

Busca dentro de un array un valor pasado como paraacutemetro y si lo encuenshytra devuelve el valor true si no devuelve false Toma dos argumentos el valor a buscar y el array doacutende buscar

ltphp $colores = array (rojoverdeamarilloazul) if (in_array(rojo$colores))

echo Se ha encontrado el valor rojo

138 Capiacutetulo 7

e l s e echo No se ha encontrado

gt

Borrar ocurrencias

Para borrar un elemento simplemente se utiliza la misma funcioacuten que borra las variables definidas unset ()

ltphp $colores = array (rojoverdeamarilloazulrosa) echo El nuacutemero de elementos de colores es count ($colores) ltbrgt unset ($colores[2]) echo El nuacutemero de elementos de colores es count ($colores) ltbrgt gt

Se puede observar que para borrar un elemento hay que conocer el iacutendishyce El resultado del ejemplo por pantalla es

El nuacutemero de elementos de colores es 5 El nuacutemero de elementos de colores es 0

Advertencia

Debe tener cuidado el lector con utilizar unset () con el nombre de un array sin iacutendice pues esto causaraacute el borrado del conjunto de datos en su totalidad Unset ($colores) borra el array comshypleto unset ($colores [2] borra soacutelo el iacutendice 2 del conjunto

Interactuar con arrays

Anteriormente tuvo la oportunidad de conocer las estructuras de control existentes en PHP La estructura f oreach quedoacute en el aire para tratarlo a fondo en el presente capiacutetulo El uso es asiacute

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) foreach ($colores as $valor)

echo (El valor es $valorltbrgt)

gt

Conjuntos de datos del tipo array 139

La construccioacuten anterior recorre el array desde el principio En el ejemplo se puede ver que f oreach toma el array a recorrer y sus valores los va almacenando en la variable $ v a l o r a medida que el bucle se ejecuta Existe una segunda construccioacuten que permite recuperar el iacutendice y el valor Veashymos un ejemplo de esto

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) foreach ($ciacuteudades as $iacutendiacutece =gt $valor)

echo (El iacutendice $indice tiene el valor $valorltbrgt)

gt

La salida en el navegador nos la muestra la figura 71

Es un meacutetodo muy bueno para imprimir los valores de un array que tiene iacutendices numeacutericos y alfanumeacutericos

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia] = Paris foreach ($ciudades as $indice =gt $valor)

echo (El Iacutendice $indice tiene el valor $valorltbrgt)

gt

140 Capiacutetulo 7

Funciones para avanzar en un array

Cada vez que creamos un array dentro de un programa PHP se crea un puntero que permite recorrer en su totalidad el conjunto de valores Este puntero se inicializa al valor inicial del array La funcioacuten c u r r e n t () deshyvuelve el valor al que apunta el puntero La funcioacuten n e x t () hace avanshyzar el puntero una posicioacuten en el conjunto de datos

Si el puntero se encuentra al final del conjunto n e x t () devuelve un vashylor false El ejemplo siguiente muestra coacutemo utilizar estas funciones para recorrer un array

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia] = Paris do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

while (next($ciudades) ) gt

Podemos crear una funcioacuten que realice este traacutemite

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) Sciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia ] = Paris

function recorre($ciudades) do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

Jwhile (next($ciudades))

recorre($ciudades) recorre($ciudades) gt

La funcioacuten r e c o r r e () utiliza un array como paraacutemetro y va utilizando las funciones de introspeccioacuten para sacar los resultados Puesto que los valores son pasados por valor la funcioacuten r e c o r r e () crea una copia de los datos que recibe y genera el resultado de la figura 72

De esta forma no hay manera de controlar el puntero porque siempre que pase la variable $ c i u d a d e s el puntero comenzaraacute desde el principio

Conjuntos de datos del tipo array 141

La forma de arreglar esto es hacer las llamadas por referencia r e c o r r e (Sc$ciudades) r e c o r r e (amp$ciudades)

142 Capiacutetulo 7

Ahora ya no es una copia de $ c iudades lo que se pasa como paraacutemetro sino una referencia al valor real Esto hace posible tener una memoria de la situacioacuten del puntero Una vez recorrido elarray el puntero queda fijado al final del conjunto de datos Para volver al principio se puede utilizar la funcioacuten r e s e t () que enviacutea al puntero al principio La funcioacuten puede quedar asiacute

function recorre($ciudades) if (current($ciudades))

reset($ciudades)

do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

Jwhile (next($ciudades))

Ahora lo que hacemos es comprobar si el puntero estaacute al final del array si esto es asiacute se llama a la funcioacutenreset 0 y el puntero se coloca al prinshycipio

Funciones para retroceder en un array

La funcioacuten prev () retrocede una posicioacuten el puntero y la funcioacuten end () se coloca al final de una lista de valores Esto puede ser uacutetil para mostrar el contenido en sentido inverso como puede ver en la nueva funcioacuten que hemos creado

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal ] = Lisboa $ciudades[Francia ] = Paris function recorre($ciudades)

if ( lcurrent($ciudades)) reset($ciudades)

do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

jwhile (next($ciudades))

function recorre_atras($ciudades)

end($ciudades) do

$valor = current($ciudades)

Conjuntos de datos del tipo array 143

echo (El valor es $valorltbrgt) while (prev($ciudades))

recorre(amp$ciudades) recorre_atras(amp$ciudades) gt

El navegador muestra El valor es Badajoz El valor es Meacuterida El valor es Caacuteceres El valor es Plasencia El valor es Madrid El valor es Lisboa El valor es Paris El valor es Paris El valor es Lisboa El valor es Madrid El valor es Plasencia El valor es Caacuteceres El valor es Meacuterida El valor es Badajoz

Por uacuteltimo para obtener el valor del iacutendice puede utilizar la funcioacuten key() La funcioacuten r e c o r r e () la puede actualizar de la siguiente forma

function recorre($ciudades) if ( current($ciudades) )

reset($ciudades)

do

$valor = current($ciudades) $indice = key($ciudades)

echo ($indice valor $valorltbrgt)

while (next($ciudades))

Intercambio de valores

La funcioacuten a r r a y _ f l i p () intercambia los valores de iacutendices y datos es decir los iacutendices seraacuten guardados como datos y los valores seraacuten sus nueshyvos iacutendices

ltphp function recorre ($numero)

foreach ($numero as $indice =gt $valor) echo $indice $valorltbrgt -

144 Capiacutetulo 7

$numero = array(uno =gt ldos =gt 2 tres =gt 3cuatro =gt 4) echo (Nuacutemerosltbrgt ) recorre($numero) echo (Nuacutemeros intercambiadosltbrgt) recorre(array_fliacutep$numero)) gt

El resultado es el esperado

Nuacutemeros uno 1 dos 2 tres 3 cuatro 4 Nuacutemeros intercambiados 1 uno 2 dos 3 tres 4 cuatro

Puede ver el resultado en la figura 74

Inversioacuten del contenido

Tambieacuten es posible ordenar a la inversa una lista de datos Esto se consishygue con la funcioacuten a r r a y _ r e v e r s e ()

Conjuntos de datos del tipo array 1 4 5

Si modifica el coacutedigo anterior tendraacute

echo (Nuacutemeros intercambiadosltbrgt ) recorre(array^reverse($numero))

Dando como resultado

Nuacutemeros uno 1 dos 2 tres 3 cuatro 4 Nuacutemeros intercambiados cuatro 4 tres 3 dos 2 uno 1

Mezcla de los valores

Si necesita alguna vez elegir un valor aleatorio de un array la funcioacuten shu-f f le () puede ser de gran ayuda ya que mezcla todos los valores cada vez que se ejecuta Parte del coacutedigo puede ser este

echo (Nuacutemeros mezcladosltbrgt ) shuffle($numero) recorre($numero)

Pilas

Las pilas son estructuras de datos que se utilizan mucho en el mundo de la informaacutetica La filosofiacutea baacutesica de las pilas es que todos los valores deshyben introducirse en un orden especiacutefico y soacutelo podemos recuperar esos valores en el orden inverso estricto al que fueron insertados Las pilas LIFO (Last ln First Out el uacuteltimo en entrar es el primero en salir) utilizan unas funciones especiacuteficas que permiten manejar todos los datos A r r a y _ p u s h () permite insertar en la pila un dato y a r r a y _ p o p () exshytrae un valor Es necesario antes que nada definir la variable como array pues ninguna de las funciones descritas lo hace

A r r a y _ p u s h () y a r r a y _ p o p () toman como argumento la variable array y los valores a introducir

lt php $pila = array() array_push($pilaunodostres)

146 Capiacutetulo 7

array_jpush($pilacuatrocinco) while ($valor = arrayjop($pila) )

echo valor extraiacutedo es $valorltbrgt

gt

El resultado por pantalla muestra que la extraccioacuten de los valores se hace en orden inverso del que fueron introducidos

valor extraiacutedo es cinco valor extraiacutedo es cuatro valor extraiacutedo es tres valor extraiacutedo es dos valor extraiacutedo es uno

Ordenacioacuten de los valores

Finalmente PHP ofrece una gran variedad de funciones para ordenar arrays Las funciones pueden verse en la tabla siguiente

Tabla 71 Funciones de ordenacioacuten

Funcioacuten Explicacioacuten

asort() Ordena de forma ascendente el array pasado como argumento Ordena las parejas iacutendicevalor atendiendo al dato Es un buen meacutetodo para los arrays asociativos

arsort() Igual que asort () pero ordena en sentido descendente ksort() Ordena de forma ascendente el array pasado como argumento

Ordena las parejas iacutendicevalor atendiendo esta vez al iacutendice

krsort() Igual que ksort () pero ordena en sentido descendente

sort() Ordena de forma ascendente el array pasado como argumento Se pierde el valor asociativo entre el iacutendice y el valor

rsort() Igual pero en orden descendente

Puede ver actuar todas las funciones de ordenacioacuten en el ejemplo sishyguiente

ltphp function recorre ($numero)

foreach ($numero as $indice =gt $valor) echo $indice $valorltbrgt

Conjuntos de datos del tipo array 147

$pi la = array(cinco = gt5uno = gtl cuatro = gt4dos = gt2 tres = gt3) echo Array sin ordenarltbrgt recorre($pila) echo Ordenacioacuten asort()ltbrgt asort($pila) recorre($pila) echo Ordenacioacuten arsort)ltbrgt arsort($pila) recorre($pila) echo Ordenacioacuten ksort()ltbrgt ksort($pila) recorre ($pila) echo Ordenacioacuten krsort()ltbrgt krsort ($pila) -recorre($pila) echo Ordenacioacuten sort()ltbrgt sort($pila) recorre($pila) echo Ordenacioacuten rsort()ltbrgt rsort($pila) recorre($pila) gt

La figura 75 muestra todos los tipos de ordenacioacuten que puede utilizar sobre un array

148 Capiacutetulo 7

Resumen

En este capiacutetulo ha conocido el tipo de variable estrella de PHP el array Controlar los meacutetodos y las funciones para extraer la informacioacuten le daraacute ventaja en los capiacutetulos posteriores Muchas funciones que tienen que ver con el manejo de datos como funciones de bases de datos XML o generashycioacuten de plantillas devuelven un array como respuesta El tipo array es el vehiacuteculo estaacutendar para la recuperacioacuten de datos estrucshyturados como veremos en los proacuteximos capiacutetulos

En este capiacutetulo aprenderaacute a

bull Crear formularios para pasar datos entre paacuteginas

bull Utilizar las variables suacuteper-globales para recibir la informacioacuten de un formulario

bull Diferenciar entre los meacutetodos de enviacuteo GET y POST

bull Encontrar posibles errores revisando las variables suacuteper-globales

150 Capiacutetulo 8

Introduccioacuten

Hasta ahora en los capiacutetulos anteriores hemos visto coacutemo construir dishyversos programas en PHP con un limitado radio de accioacuten La verdadera potencia del lenguaje reside en la aplicacioacuten de las teacutecnicas aprendidas a traveacutes de varias paacuteginas Web pasando informacioacuten de unas a otras Como veremos maacutes adelante las dos teacutecnicas principales son el uso de formulashyrios y la utilizacioacuten de la barra de direccioacuten para pasar los valores

Argumentos GET

Los argumentos GET pasan la informacioacuten como parte de la URL Cuando utilice esta forma de trabajar las parejas de variable valor podraacuten verse en la casilla de direccioacuten del navegador Para probar esto podemos escrishybir un pequentildeo script que guardaremos como paacutegina Web

lthtmlgt ltbodygt ltphp echo Variables pasadas mediante GETltbrgt foreach ($_GET as $indice =gt $valor)

echo $indice $valor

gt ltbodygt lthtmlgt

Si ejecuta el coacutedigo anterior veraacute que uacutenicamente se imprime en pantalla el texto que muestra la orden echo En realidad esto es correcto puesto que no hemos introducido ninguna variable tipo GET a la Web Para hashycerlo debemos escribir el nombre de la paacutegina Web seguido de un siacutembolo de interrogacioacuten () y el conjunto de parejas de variable valor separadas del siacutembolo (amp)

La direccioacuten queda algo asiacute f o r m u l a r i o php v a r i a b l e l = H o l a M u n d o amp v a r i a b l e 2 = 1234 Ahora el resultado es diferente El bucle f o shyr e a c h inspecciona el array $_GET e imprime en pantalla

Variables pasadas mediante GET variablel Hola Mundo variable2 1234

El array $_GET es considerado en PHP 5 una variable suacuteper-global Este en concreto almacena todas las variables pasadas entre paacuteginas mediante

Paso de informacioacuten entre formularios 151

el meacutetodo GET Para extraer el valor de una variable pasada por este meacuteshytodo soacutelo hay que escribir $_GET [ n o m b r e _ v a r i a b l e ] en la paacutegina que recibe los datos

Advertencia

En versiones anteriores de PHP para recuperar el valor de una variable simplemente habiacutea que escribir un siacutembolo $ delante del nombre como $ n o m b r e _ v a r i a b l e Esto es porque el paraacutemeshytro register_globals del fichero de configuracioacuten php i n i estaacute en PHP 5 a off

Formularios con GET

La forma maacutes utilizada para recabar informacioacuten acerca de los usuarios es emplear formularios HTML Los formularios pueden hacerse escribiendo en un editor de texto las etiquetas HTML o utilizando alguacuten editor Web profesional como Macromedia Dreamweaver Netscape Composer o Nvu La siguiente paacutegina Web llamada f o r m u l a r i o php muestra coacutemo reshycoger informacioacuten

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt

ltpgtIntroduzca sus datos personales ltpgt ltform name=formulario method=GET action=formulario2 php gt lttable width=50 border=0 cellspacing=0 cellpadding=0gt lttrgt lttd width=24gtNombrelttdgt lttd width=76xinput name=nombre type=text id=nombrextdgt

lttrgt lttrgt lttdgtApellidoslttdgt lttdxiacutenput name=apellidos type=text id=apellidos2gtlttdgt

lttrgt lttrgt lttdgtCorreolttdgt lttdxinput name=correo type=text id= correo xtdgt

lttrgt lttrgt lttdgtEstado civil lttdgt lttdxselect name= estado id= estado gt ltoption value=SolterogtSolteroltoptiongt ltoption value=CasadogtCasadoltoptiongt

152 Capiacutetulo 8

bullcoption value=DivorciadogtDivorciadoltoptiongt ltoption value=ViudogtViudoltoptiongt

ltselectgtlttdgt lttrgt lttrgt lttdgtNampuacutemero hijos lttdgt lttdgt 0 ltinput name=hijos type=radio value=0 checkedgt

1 ltinput name=hijos type=radio value=lgt 2 ltinput name=hijos type=radio value=2gt 3 ltinput name=hijos type=radio value=3gtlttdgt

lttrgt lttrgt lttdgtGustoslttdgt lttdgt Informampaacutetica ltinput type=checkbox name=gustos []

value=Informaacuteticagt Buceo ltinput type=checkbox name=gustos [] value=Buceogt Magia ltinput type=checkbox name=gustos [ ] value=Magiagt Jazz ltinput type=checkbox name=gustos [] value=Jazzgtlttdgt

lttrgt lttrgt lttdxinput type=submit name=Submit value=Enviargtlttdgt lttdgtampnbsplttdgt

lttrgt lttablegt

ltformgt ltpgtampnbsp ltpgt ltbodygt lthtmlgt

La figura 81 muestra el aspecto en el navegador Hay varios aspectos a tener en cuenta Lo primero es que el apartado a c t i o n de la etiqueta ltFORMgt contiene la paacutegina Web a la que se enviaraacuten los datos y el apartashydo method permite seleccionar el meacutetodo de enviacuteo por ahora utilizareshymos el meacutetodo GET La paacutegina f o r m u l a r i o 2 php recoge la informacioacuten del formulario y la imprime en pantalla utilizando un bucle f o r e a c h a la variable suacuteper-global $_GET

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidosltpgt ltphp foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

gt ltbodygt lthtmlgt

Para sacar los datos hemos utilizado un bucle que busca todos los valores dentro de $__GET Otra forma de hacerlo es imprimir los datos uno a uno

154 Capiacutetulo 8

si sabemos el nombre de las variables definidas en el formulario anterior de la siguiente forma $_GET [ n o m b r e ] $_GET [ a p e l l i d o s ] $_GET [ c o r r e o ]

Existen en el formulario visto varias teacutecnicas de recogida de informacioacuten Los cuadros de texto que permiten escribir valores alfanumeacutericos lista de seleccioacuten y botones de opcioacuten es donde podemos elegir una de las opciones existentes y casillas de verificacioacuten que permiten elegir 0 o maacutes opciones existentes Todas estas partes del formulario tienen una variable asociada que puede buscarse en $_GET

El uacutenico meacutetodo que puede plantear alguacuten problema es el que utiliza cashysillas de verificacioacuten Puesto que podemos elegir varias opciones eacutestas son enviadas como un array y deben recuperarse atendiendo a esta razoacuten

Advertencia

Para que los valores de las casillas de verificacioacuten sean enviados como array hay que declararlas en el formulario como tal escrishybiendo dos siacutembolos de corchetes en la propiedad ntildeame asociada a las casillas por ejemplo lt i n p u t t y p e = c h e c k b o x n a m e = g u s t o s [] v a l u e = I n f o r m aacute t i c a gt

La paacutegina f o r m u l a r i o 2 php queda de esta forma para que pueda recishybir los gustos de los usuarios

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidos ltpgt ltphp foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

echo ltbrgtGUSTOSltbrgt $gustos = $_GET[gustos] foreach ($gustos as $indice =gt $valor)

echo $indice $valorltbrgt gt ltbodygt lthtmlgt

La figura 83 muestra la mejora incluida en el programa Ahora es capaz de recuperar los gustos de los usuarios e imprimirlos en pantalla Para esto

Paso de informacioacuten entre formularios 155

hemos antildeadido un bucle nuevo que inspecciona los valores enviados al array $gustos

Paso de informacioacuten con GET

Si se fija en la barra de direccioacuten de los navegadores cuando visita paacutegishynas Web sobre noticias o carritos de la compra en la URL van aparecienshydo variables que tienen que ver con los distintos menuacutes que existen en la Web

El siguiente ejemplo muestra una pequentildea revista digital escrita en pocas liacuteneas y en una sola paacutegina Web que cambia sus noticias eligiendo las disshytintas opciones del menuacute

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitIacuteonalEN

httpwwww3orgTRhtml4loosedtdgt lthtmlgt ltbodygt ltphp $menu = array (1 =gt Editorial 2 =gt Opinioacuten 3 =gt Regional 4 =gt Nacional) echo (--Revista Digital --ltbrxbrgt) echo (--MENU--ltbrgt ) foreach ($menu as $indice =gt $valor)

echo (lta href = Iacutendexphpmenu=$indicegt$valorltaxbrgt)

156 Capiacutetulo 8

j

echo ( ltbrgt--NOTICIAS--ltbrgt) switch ($_GET[menuacute])

case 1 echo (Editorial) break

case 2 echo (Opinioacuten) break

case 3 echo (Regional) break

case 4 echo (Nacional) break

default echo (Noticias de Portada) break

gt ltbodygt lthtmlgt

El array $menu se carga de los distintos valores que podemos ir seleccioshynando

En la actualidad estos valores se suelen extraer de una base de datos

Para mostrar el menuacute se hace un bucle donde se extraen todos los valores e iacutendices del array y se ponen como valores en los enlaces

echo (lta href=Iacutendexphpmenu=$indicegt$valorltaxbrgt)

Los enlaces siempre se dirigen a la paacutegina principal pero con un valor distinto en la variable menuacute

La segunda parte de la Web es una eleccioacuten muacuteltiple mediante la estrucshytura s w i t c h donde en funcioacuten del valor de la variable menuacute pasada por GET se eligen unas noticias vi otras

Puede ver el resultado en la figura 84

echo (lta href=Iacutendexphpmenu=$indicegt$valorltaxbrgt)

Los enlaces siempre se dirigen a la paacutegina principal pero con un valor distinto en la variable menuacute

La segunda parte de la Web es una eleccioacuten muacuteltiple mediante la estrucshytura s w i t c h donde en funcioacuten del valor de la variable menuacute pasada por GET se eligen unas noticias u otras

Puede ver el resultado en la figura 84

Argumentos POST

La utilizacioacuten del meacutetodo GET es totalmente inseguro porque no hay forshyma de ocultar datos privados en la direccioacuten Web tales como la contraseshyntildea de entrada o el nuacutemero de cuenta bancaria

El meacutetodo POST arregla estos problemas siendo el preferido de los desa-rrolladores Este meacutetodo es tan sencillo como cambiar en el formulario el meacutetodo de enviacuteo de datos

ltpgtIntroduzca sus datos personalesltpgt ltform name=formulario method=POST action=formulario2 php gt

lttable width=50 border=0 cellspacing=0 cellpadding=0gt

En cuanto a la recuperacioacuten de los datos tambieacuten debe cambiar el nombre de la variable suacuteper-global $_GET por $_POST de esta manera

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidosltpgt ltphp foreach ($_POST as $indice =gt $valor)

echo $indice $valorltbrgt

e c h o ltbrgtGUSTOSltbrgt $ g u s t o s = $ _ P O S T [ g u s t o s ]

158 Capiacutetulo 8

foreach ($gustos as $indice =gt $valor) echo $indice $valorltbrgt

gt ltbodygt lthtmlgt

Variables suacuteper-globales

Desde PHP 4 se vienen utilizando los arrays suacuteper-globales para almaceshynar los valores que pasan de unas paacuteginas a otras se almacenan en el orshydenador del usuario o en el servidor En PHP 5 el uso de estas variables se hace obligatorio para recuperar todos los valores Las variables a utilizar son

bull $_GET Almacena las variables que se pasan desde un formulario meshydiante el meacutetodo GET

bull $_POST Almacena las variables pasadas por POST

bull $_COOKIE Guarda los valores que estaacuten almacenados en cookies Ya veremos en capiacutetulos sucesivos coacutemo utilizarlo

bull $_SESSlON bull Guarda las variables que se pasan entre sesiones

bull $_SERVER Contiene numerosos valores relativos al servidor

bull $_FILES Los archivos que enviemos a traveacutes de un formulario seshyraacuten recogidos en este array

Una equivocacioacuten en el nombre de una variable puede llevarle a dar vuelshytas sobre el coacutedigo hasta encontrar el error Por eso es necesario conocer el contenido de las variables suacuteper-globales asiacute podraacute averiguar si estaacute pasando los datos correctamente La funcioacuten siguiente se puede utilizar cada vez que le surja un error de este tipo La funcioacuten muestra todos los valores de los arrays suacuteper-globales

ltphp function depuracioacuten() echo --Variables GET--ltbrgt foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

echo --Variables POST--ltbrgt foreach ($_POST as $indice =gt $valor)

echo $indice $valorltbrgt

echo --Variables COOKIES--ltbrgt

Paso de informacioacuten entre formularios 159

foreach ($_COOKIE as $indice =gt $valor) echo $iacutendiacutece $valorltbrgt

echo --Variables SESSION--ltbrgt foreach ($_SESSION as $indice =gt $valor)

echo $iacutendiacutece $valorltbrgt

echo --Variables SERVER-~ltbrgt foreach ($_SERVER as $indice =gt $valor)

echo $indice $valorltbrgt

depuracioacuten () gt

La figura 85 muestra los valores de todas las variables suacuteper-globales

Resumen

Hasta ahora soacutelo habiacuteamos tenido la oportunidad de crear programas en PHP que realizaran tareas en una uacutenica paacutegina Web

Este capiacutetulo ha dado una visioacuten praacutectica de coacutemo utilizar los conceptos aprendidos para escribir programas distribuidos en varias paacuteginas

160 Capiacutetulo 8

Aunque no ha aprendido ninguna funcioacuten nueva ha descubierto el vershydadero secreto del disentildeo de una Web dinaacutemica el paso de variables

Si viene de otras versiones de PHP tendraacute que tener en cuenta que la forshyma de recuperar las variables es a partir de la versioacuten 43 a traveacutes de las variables suacuteper-globales

En este capiacutetulo aprenderaacute a

bull Diferenciar entre clase y objeto bull Crear clases que hereden de otras clases bull Utilizar los modificadores pr iacutevate protected ypubl ic

bull Crear meacutetodos estaacuteticos y finales bull Guardar el estado de un objeto mediante la sentildealizacioacuten bull Recuperar informacioacuten referente a las clases meacutetodos y propiedades

162 Capiacutetulo 9

Introduccioacuten

PHP comenzoacute su andadura como un simple lenguaje de scripts A medishyda que las versiones avanzaban se fueron incluyendo algunas caracteshyriacutesticas que permitiacutean programar con orientacioacuten a objetos Con la aparicioacuten de PHP 5 los desabolladores tenemos una verdadera platashyforma de programacioacuten orientada a objetos gracias a la potencia del nuevo engine Zend 20 que permite ejecutar maacutes raacutepido y eficientemenshyte este tipo de programas

La programacioacuten orientada a objetos utiliza los elementos c l a s e y o b shyj e t o con punto de inicio Actualmente en las carreras teacutecnicas es posishyble encontrar ensentildeanzas sobre lenguajes orientados a objetos como Java o C++

Nota

En realidad Java y C++ son considerados como seudo lenguajes orientados a objetos Un ejemplo de lenguaje puro es SmallTalk o su versioacuten graacutefica Squeak (httpsqueaklinexorg) con muchos antildeos de antiguumledad

La programacioacuten orientada a objetos en PHP 5 no necesita una sintaxis muy diferente sino que es una aproximacioacuten a la realidad en otro camino diferente al acostumbrado Por ejemplo si piensa en un programa que tenga que averiguar la letra del DNI de un cliente lo normal es que cree una funcioacuten con un paraacutemetro al que le pase el nuacutemero de DNI y le deshyvuelva la letra buscada

Un desarrollo orientado a objetos pensariacutea en cada problema como una idenshytidad uacutenica como un objeto Puesto que el DNI siempre va asociado a una persona puede crear un objeto que identifique a personas y dentro de ese objeto programar una funcioacuten (meacutetodo en este caso) que calcule la letra La aproximacioacuten procedural (crear una funcioacuten) no asocia esa funcioacuten a persoshynas directamente y le podriacutea pasar cualquier nuacutemero entero recibiendo una respuesta vaacutelida En cambio la aproximacioacuten de objetos crea la funcioacuten dentro del objeto c l i e n t e y soacutelo permite mediante teacutecnicas que veremos maacutes adelante recuperar la letra del DNI de una persona

La programacioacuten orientada a objetos desarrolla nuevos conceptos y termishynologiacuteas que deben aprenderse correctamente para generar buen coacutedigo

Programacioacuten orientada a objetos 163

Definicioacuten de clases

Una clase es un tipo de dato que contiene en una misma estructura vashyriables y funciones Una clase es una especie de plantilla desde la que los objetos son instanciados y toman su valor Desde una clase se pueden consshytruir varios objetos del mismo tipo La definicioacuten es la siguiente

class pagina_Web

var $titulo function getTitulo()

return $this-gttitulo

Mediante la palabra reservada c l a s s definimos una clase completa Utishylizando va r podemos definir las variables que utilizaremos en el desarroshyllo del programa La palabra reservada va r desapareceraacute en versiones siguientes de PHP a favor de las palabras publ ic p r iacute v a t e y p r o t e c -ted Las funciones se definen como en el capiacutetulo 5 siempre que esteacuten dentro de la construccioacuten de la clase En este capiacutetulo vamos a definir una clase completa cuya misioacuten seraacute mostrar una paacutegina Web Podemos seshyguir con el ejemplo ampliando las funciones

ltphp class pagina_Web

var $titulo function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

function getTitulo() return $this-gttitulo

function cabecera() echo (lthtmlxheadxtitlegt) echo $this-gttitulo echo ( lttitlexheadxbodygt) bull

function cuerpo() echo(Este es el cuerpo de la paacutegina Web)

164 Capiacutetulo 9

function pie ( )

echo (ltbodyxhtmlgt)

function mostrar_pagina()

echo $thiacutes-gtcabecera () echo $this-gtcuerpo()

echo $this-gtpie()

Como puede ver la clase se divide en varias funciones y en una sola vashyriable La variable $ ti t u l o guardaraacute el tiacutetulo deacute la paacutegina Web Las funshyciones c a b e c e r a ( ) c u e r p o () y p i e () son las encargadas de mostrar las distintas partes de una Web

Estas funciones se llaman desde la f u n c i oacute n m o s t r a r _ p a g i n a ( ) Es inteshyresante observar que en unas pocas liacuteneas de coacutedigo hemos definido un objeto que podriacutea utilizarse como base de muchas aplicaciones El operador $ t h i s es una variable que contiene el objeto actual desde el que la invocamos Para acceder dentro de un objeto a funciones o variashybles propias debe anteponerse al nombre de eacutestas la expresioacuten $ t h i s - gt Para acceder desde la funcioacuten m o s t r a r _ p a g i n a () a cualquiera de las funciones de la clase tendraacute que escribir

$this-gtcabecera () $this-gtcuerpo ( ) $this-gtpie ()

Instancia de clase

Para que el coacutedigo funcione necesita crear el objeto Esto se hace utilizanshydo el operador new seguido del nombre de la clase

$ p a g i n a = new p a g i n a _ W e b ( )

Con el coacutedigo anterior hemos creado un objeto que contiene todas las vashyriables y funciones de la clase pag ina_Web ( ) La variable que contiene ese objeto es $pag ina

Para acceder a las funciones desde el nuevo objeto creado tenemos que utilizar la variable que contiene al objeto en este caso $ p a g i n a seguido del operador - gt y el nombre de la funcioacuten Para mostrar la Web tenemos que seguir estos sencillos pasos

$ p a g i n a = new p a g i n a _ W e b ( )

Programacioacuten orientada a objetos 165

$pagina-gtsetTitulo(Paacutegina Web nueva) $pagina- gtmostrar__pagina ( )

Funcioacuten constructor

Existen algunas funciones especiales en la definicioacuten de una clase La maacutes importante es el constructor Esta se ejecuta cada vez que se crea un nueshyvo objeto y permite crear las variables iniciales que se necesitan como el tiacutetulo de la Web o el autor El nombre de la funcioacuten debe ser c o n s -t r u c t () Nuestro constructor se encargaraacute de crear el tiacutetulo de la paacutegina Web que estamos creando

funct ion c o n s t r u c t ( $ t i t u l o )

$this-gtsetTitulo($titulo)

Herencia

La programacioacuten orientada a objetos permite heredar de otras clases Con esta teacutecnica puede ahorrar mucho tiempo de trabajo La clase hija (clase que hereda de otra) adquiere estas propiedades

bull Automaacuteticamente obtiene todas las variables miembro de la clase padre

bull Tambieacuten obtiene todas las funciones miembro de la clase padre que funcionaraacuten exactamente de la misma forma

bull La clase hija puede a su vez definir nuevas variables y funciones

La sintaxis es la siguiente

class pagina_Web_formulario extends pagina_Web

function formulario_inicio() Escribir el coacutedigo necesario

La palabra reservada e x t e n d s indica que la nueva clase creada seraacute una extensioacuten (heredaraacute) de la clase que se escribe justo a la derecha de la deshyfinicioacuten Puede crear un objeto formulario a partir de la clase pagina_Web de la siguiente forma

class pagina_Web_formulario extends pagina_Web

166 Capiacutetulo 9

function formulariacuteo_inicio($accion)

echo (ltform action=$acciongt)

function formulario_fin() echo (ltformgt)

function formulario_caj a_texto($nombre) echo ($nombre ltinput type=text name=$nombregt)

function formulario_boton() echo (ltinput type=submit name=Submit

valuacutee = Enviargt )

function mostrar_pagina () $this-gtcabecera () $this- gtf ormulario__inicio ( Iacutendex php) $this- gtf ormulario__caj a_texto (Nombre) $this-gtformulario_boton() $this-gtformulario_fin()

$this- gtpie ()

Si ahora ejecuta el coacutedigo instanciando la clase que hemos creado puede ver que las funciones c a b e c e r a () p i e ( ) incluso el constructor pueshyden ser utilizadas auacuten no perteneciendo a la clase p a g i n a _ W e b _ f o r -m u l a r i o

$formulario = new pagina_Web_formularioPagina con f o r m u l a r i o ) $formular io-gtmostrar_pagina ( )

La figura 91 muestra la ejecucioacuten del objeto anterior

Meacutetodos o funciones de objeto

Cuando definimos una clase hija las funciones de la clase padre son autoshymaacuteticamente heredadas Se llama redefinicioacuten de meacutetodos a la creacioacuten de funciones en la clase hija con el mismo nombre que en la clase padre En el ejemplo anterior la funcioacuten m o s t r a r _ p a g i n a ( ) de la clase pag ina_Web_f o r m u l a r i o estaacute redefinida ya que existe una funcioacuten con

Programacioacuten orientada a objetos 167

el mismo nombre en la clase pag ina_Web Al instanciar el objeto y ejecushytar el meacutetodo m o s t r a r _ p a g i n a ( ) el meacutetodo que se ha definido es la clase hija

PHP 5 con su nuevo motor Zend Engine 2 introduce la palabra reservashyda f i n a l

Si en la clase padre ponemos delante de cualquier funcioacuten la palabra f i n a l eacutesta funcioacuten no podraacute ser sobrecargada en las clases que la heshyreden

Tambieacuten podemos declarar clases completas como f i n a l lo que signifishycaraacute que no podraacuten ser heredadas

final function mostrar_pagina()

echo $this-gtcabecera() echo $this-gtcuerpo()

echo $this-gtpie()

Si definimos la funcioacuten anterior como f i n a l en la clase pag ina_Web la clase p a g i n a _ W e b _ f o r m u l a r i o no podraacute tener una funcioacuten con este mismo nombre y mostraraacute un error en pantalla La figura 92 muestra el error que se produce al intentar sobrecargar un meacutetodo que estaacute marcado como f i n a l

Herencia encadenada

Algunos lenguajes de programacioacuten permiten heredar de varias clases a la vez esto es conocido como herencia muacuteltiple PHP 5 no permite herenshycia muacuteltiple pero siacute herencia encadenada es decir permite heredar de varias clases padres correlativamente Un ejemplo es

class A

class B extends A

class C extends B

class D extends C

Valores y alcance de variables

En versiones anteriores de PHP los objetos eran pasados por valor a otras funciones por lo tanto el estado de los objetos no se conservaba En PHP 5 los objetos son pasados por defecto por referencia gracias al Zend Engine 2

ltphp

Programacioacuten orientada a objetos 169

class Nombre

i var $nombre function setNombre($nombre)

$this-gtnombre = $nombre

function getNombre() return $this-gtnombre

function cambiaNombre($obj eto$nombre)

$objeto-gtsetNombre($nombre)

$luis = new Nombre $luis-gtsetNombre(Luis Miguel) echo El nombre del objeto es $luis-gtgetNombre() ltbrgt cambiaNombre($luisPedro) eche El nombre del objeto es $luis-gtgetNombre() ltbrgt gt

El coacutedigo muestra coacutemo cambiar las propiedades de un objeto desde una funcioacuten con PHP 5 El resultado en el navegador puede comprobarlo en la figura 93

170 Capiacutetulo 9

Dentro de los objetos debe tener tambieacuten cuidado con el alcance de las variables Las variables definidas fuera del entorno del objeto no son acshycesibles desde los meacutetodos de las clases a menos que anteponga la palashybra g l o b a l

Miembros puacuteblicos privados y protegidos

Mientras no se especifique otra cosa los meacutetodos y propiedades de una clase son siempre puacuteblicos es decir son accesibles desde fuera del objeto de la forma o b j e t o - gtf u n c i oacute n Pero existe un camino para que las vashyriables y los meacutetodos no puedan ser accedidos desde fuera del objeto Eche un vistazo ahora al objetopagina_Web Su variable $ t i t u l o es puacuteblico porque no lo hemos definido de alguna forma especial Para cambiar el valor de esta variable podriacutea utilizar la funcioacuten asociada o directamente haciendo $ o b j e t o - gt t i t u l o = nuevo v a l o r Esta forma de actuar rompe con la filosofiacutea de la programacioacuten orientada a objetos Como norshyma general las propiedades de los objetos deben estar ocultas al entorno exterior y tomar sus valores desde funciones definidas dentro del objeto

Meacutetodos privados

Si declaramos un meacutetodo o propiedad como privada soacutelo se podraacute acceshyder a eacutel desde la clase que lo define Las clases que hereden de una clase con meacutetodos privados no tendraacuten acceso a eacutestos meacutetodos y tampoco seraacute posible desde fuera del objeto hacer llamadas Para hacer un meacutetodo o propiedad privado soacutelo hay que anteponer la palabra p r iacute v a t e delante de la declaracioacuten

class pagina_Web

priacutevate $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

priacutevate function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

De esta manera la clase p a g i n a _ W e b _ f o r m u l a r i o que hereda de pagina_Web no puede acceder directamente a la funcioacuten s e t T i t u l o ()

Programacioacuten orientada a objetos 171

de la siguiente forma $ t h i s - gt s e t T i t u l o ( T i t u l o n u e v o ) porque obtenemos un error de acceso ilegal Despueacutes de esta modificacioacuten soacutelo es posible dar un tiacutetulo a la paacutegina Web a traveacutes del constructor que como siacute estaacute dentro de la clase tiene potestad para utilizarla

Meacutetodos protegidos

Los meacutetodos protegidos son menos restrictivos que los privados Cuando declaramos un meacutetodo como protegido su visibilidad es en la clase que lo declara y en todas las clases que lo heredan El ejemplo anterior puede modificarse de la siguiente forma

c l a s s pagina_Web

protected $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

protected function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

Meacutetodos puacuteblicos Por defecto todos los meacutetodos y propiedades que se declaren en un objeshyto son puacuteblicos a menos que lleven asociados la palabra p r o t e c t e d o p r iacute v a t e Como buena praacutectica de programacioacuten las variables deben deshyfinirse como privadas o protegidas para que no puedan modificarse desshyde fuera del objeto Ademaacutes deben llevar dos meacutetodos puacuteblicos asociados s e t V a r i a b l e () para dar un nuevo valor a la variable y g e t V a r i a b l e () para recibir el valor actual de la propiedad Veamos el ejemplo

class pagina_Web

private $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

public function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

172 Capiacutetulo 9

public function getTitulo()

return $this-gttitulo

Interfaces

En proyectos profesionales a veces es necesario que un equipo de varias personas trabajen juntas En este caso se hace imprescindible definir unas pautas generales de trabajo para que el resultado final sea el esperado Si el desarrollo consiste en programar varios objetos el analista de la aplicashycioacuten puede definir la estructura baacutesica en papel o crear una pequentildea planshytilla con meacutetodos que el objeto final deberiacutea tener obligatoriamente Esta plantilla es un i n t e r f a c e y permite definir una clase con funciones deshyfinidas pero sin desarrollar que obliga a todas las clases que lo imple-menten a declarar estos meacutetodos como miacutenimo

i n t e r f a c e Web

public function setTitulo($titulo = Titulo por defecto)

public function getTitulo()

La interface anterior define la estructura baacutesica que queremos para el obshyjeto declarando las funciones setTitulo y getTitulo Para que una clase haga uso de la i n t e r f a c e se declara de la siguiente forma

class pagina_Web implements Web

Clases abstractas

Un i n t e r f a c e no permite crear el cuerpo de ninguna funcioacuten dejando esta tarea a las clases que la implementen Las clases abstractas permiten definir funciones que deben implementarse obligatoriamente en los objetos que hereden y ademaacutes permiten definir funciones completas que pueden heredarse Las clases abstractas deben llevar la palabra rese rvadaabs t rac t en la declaracioacuten de la clase y en todos los meacutetodos que soacutelo definan su nombre

abstract class Web

protected $titulo

Programacioacuten orientada a objetos 173

public function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

a b s t r a c t pub l i c funct ion g e t T i t u l o ( )

En lugar de un i n t e r f a c e hemos optado por utilizar una clase abstracshyta porque tenemos claro que el meacutetodo s e t T i t u l o () tiene que funcioshynar asiacute Tambieacuten se define el meacutetodo abstracto g e t T i t u l o () que obligatoriamente debe ser declarado en la clase que herede de eacutesta En realidad un i n t e r f a c e es una clase que tiene todos sus meacutetodos absshytractos

Clases con meacutetodos estaacuteticos

En PHP 5 puede declarar funciones dentro de una clase que no utilicen propiedades o meacutetodos de la misma Estos meacutetodos pueden calcular valoshyres numeacutericos hacer una conexioacuten a una base de datos o comprobar que un correo electroacutenico esteacute bien definido Aunque no existe ninguna palashybra reservada para definirlo son conocidos como meacutetodos estaacuteticos y pueshyden ser utilizados sin necesidad de instanciar un objeto

ltphp class Nombre

protected $nombre public function getNombre(

return $this-gtnombre

public function setNombre($nombre)

$this-gtnombre = $nombre

public function NombreDefecto()

return Luis Miguelltbrgt

$luis = new Nombre echo $luis-gtNombreDefecto() Tambieacuten se puede acceder al nombre por defecto echo NombreNombreDefecto() gt

174 Capiacutetulo 9

Para acceder a un meacutetodo estaacutetico desde el cuerpo del programa se escrishybe el nombre de la clase que lo implementa seguido del operador ( ) y el nombre del meacutetodo En el ejemplo vemos que se puede acceder al meacutetoshydo NombreDef e c t o () creando un objeto o mediante la construccioacuten Nombre NombreDef e c t o Si intenta llamar a un meacutetodo que no es estaacutetico de esta forma se imprimiraacute un error en pantalla La figura 94 muestra el error que recibe si intenta llamar a un meacutetodo no estaacutetico desshyde fuera de un objeto

Llamadas a funciones padre

El operador ( ) se puede utilizar tambieacuten dentro de una clase para hacer llamadas a funciones de la clase padre que esteacuten sobrecargadas Si define un constructor para la clase padre y otro para la clase hijo cuando cree el objeto el constructor que se ejecuta es el de nivel infeshyrior el constructor hijo Para llamar al constructor padre debe utilizarshyse la nomenclatura N o m b r e _ c l a s e _ p a d r e c o n s t r u c t ()

ltphp class Nombre

protected $nombre

Programacioacuten orientada a objetos 175

f unet ion construct ( $nombre)

$this-gtnombre = $nombre

publie function getNombre() return $this-gtnombre

publie function setNombre($nombre) $this-gtnombre = $nombre

publie function NombreDefecto() return Luis Miguelltbrgt

class Apellido extends Nombre

protected $apellidos function construct($nombre$apellidos)

$this-gtapellidos = $apellidos Nombre construct(Snombre)

publie function getApellidos () return $this-gtapellidos

$luis = new Apellido(Luis MiguelCabezas Granado) echo $luis-gtgetNombre() ltbrgt echo $luis-gtgetApellidos() gt

Puede ver que el constructor de la clase Ape l l ido inicializa la variable $ape-11 idos y seguidamente llama al constructor de la clase padre Nombre Esta forma de actuar puede resultar complicada si no conoce el nombre de la clase padre La solucioacuten a este pequentildeo inconveniente la tenemos en la palabra parent que hace alusioacuten a la clase de la que heredamos El coacutedigo anterior puede quedar de esta forma

class Apellido extends Nombre

protected $apellidos function construct($nombre$apellidos)

$this-gtapellidos = $apellidos

176 Capiacutetulo 9

p a r e n t cons t ruc t ($nombre) public function getApellidos()

return $this-gtapellidos

Sobrecarga de meacutetodos

Algunos lenguajes de programacioacuten orientados a objetos permiten declashyrar maacutes de un meacutetodo con el mismo nombre La definicioacuten de estos meacutetoshydos variacutea en el nuacutemero de paraacutemetros o en los tipos de datos de los argumentos PHP 5 no permite sobrecarga de meacutetodos pero puede simushylar esta actuacioacuten empleando la teacutecnica de las funciones con un nuacutemero variable de paraacutemetros El constructor de la clase A p e l l i d o puede queshydar de la siguiente forma

class Apellido extends Nombre

protected $apellidos function construct($nombre)

if (func_num_args()= = 2 ) $apellidos = func_get_arg(1) $this-gtnombre = $nombre $this-gtapellidos = $apellidos parent construct($nombre)

else $this-gtnombre = $nombre $this-gtapellidos = $apellidos parent construct($nombre)

public function getApellidos()

return $this-gtapellidos

Sentildealizacioacuten

Los objetos son en realidad un conjunto de datos y funciones que guarshydan una serie de estados de ejecucioacuten Este conjunto de bits se pueden al-

Programacioacuten orientada a objetos 177

macenar en un momento dado y recuperar justo en el mismo estado en el que se encontraba cuando lo guardamos Esta teacutecnica se llama sentildealizashycioacuten y permite almacenar y recuperar el conjunto de bits que forman un objeto

PHP 5 ofrece dos funciones s e r i a l i ze () y u n s e r i a l i z e ( ) que toshyman como paraacutemetro un objeto y devuelven una cadena de caracteres Los objetos serializados los podemos almacenar en base de datos ficheros etshyceacutetera

$luis = new Apellido(Luis Miguel) echo $luis-gtgetNombre() ltbrgt echo $luis- gtgetApellidos () -$manuel = serialize($luis) $pedro = unserialize($manuel) echo $pedro-gtgetNombre ()

El coacutedigo anterior crea el objeto $ l u i s y utiliza los meacutetodos propios de la clase y los heredados Despueacutes utilizamos la funcioacuten s e r i a l i z e () para grabar el estado del objeto como un conjunto de caracteres en la variable $manuel La variable $pedro contiene el resultado de aplicar u n s e r i a shyl i z e () a $manuel

De esta forma conseguimos recuperar el objeto $ l u i s con los datos que ya habiacuteamos almacenado

Funciones de manejo de clases

Las funciones siguientes son uacutetiles para recuperar informacioacuten sobre la herencia de las clases sobre meacutetodos o variables miembro o llamadas a las funciones

Tabla 91 Funciones de clases

Funcioacuten Descricioacuten

ge t c l a s s () Devuelve el nombre de la clase que iexclmplementa el objeto pasado como paraacutemetro

g e t _ p a r e n t _ c l a s s 0 Devuelve el nombre de la clase padre

c l a s s _ e x iacute s t ( ) Si el paraacutemetro es el nombre de una clase devuelve un true

g e t _ d e c l a r e d _ c l a s s () Devuelve un array con el nombre de todas las clases definidas en el coacutedigo actual

178 Capiacutetulo 9

Funcioacuten Descricioacuten

i s _ s u b c l a s s _ o f () Toma dos paraacutemetros Si el primer paraacutemetro es una subclase del segundo paraacutemetro la funcioacuten devuelve un true

i s _ a ( ) g e t _ c l a s s _ v a r s ( ) Devuelve un array con parejas variable valor de una clase que tengan valores por

defecto

g e t _ o b j e c t _ v a r s () Devuelve un array con parejas variable valor de un objeto que tengan valores por defecto

method_ex is ts () Toma dos paraacutemetros Si el objeto pasado tiene un meacutetodo con el nombre del segundo paraacutemetro la funcioacuten devuelve true

ge t_c lass_method () Devuelve un array de meacutetodos definidos en una clase

Puede ver el funcionamiento de la funcioacuten g e t _ c l a s s () en el ejemplo siguiente y el resultado en la figura 95

$luis = new Nombre echo $luis-gtNombreDefecto() echo La variable $luis es un objeto del tipo get_class($luis)

Programacioacuten orientada a objetos 179

Resumen

Existe en el mundo de los desabolladores de PHP una antigua disputa sobre la mejor forma de afrontar un proyecto Web Unos opinan que la forma maacutes raacutepida de crear una Web es realizar funciones separadas en ficheros y desde las paacuteginas del proyecto hacer las llamadas necesarias

La otra vertiente opina que merece la pena dedicar un poco maacutes de tiemshypo al desarrollo de objetos porque despueacutes redundaraacute en un gran benefishycio en futuros programas En realidad depende del proyecto Si soacutelo necesita crear un formulario para recibir datos de un usuario quizaacute no merezca la pena crear un objeto y siacute algunas funciones de control Si su proyecto va a ser muy extenso la recomendacioacuten es que prepare un comshypendio de objetos que se interrelacionen para llevar a buen teacutermino el programa

Puesto que el libro versa sobre PHP 5 y sus mejoras con respecto a las vershysiones anteriores intentaremos en los capiacutetulos siguientes realizar la mashyyoriacutea de los ejemplos en metodologiacutea orientada a objetos

En este capiacutetulo aprenderaacute a

bull Abrir y cerrar ficheros de lectura y escritura

bull Utilizar funciones para leer el contenido de un fichero

bull Realizar programas para la escritura de informacioacuten en un fichero

bull Gestionar los ficheros y directorios de un sistema operativo

bull Crear ficheros de configuracioacuten

bull Generar cabeceras para la descarga de archivos

182 Capiacutetulo 10

Introduccioacuten

Antes de que la proliferacioacuten de los gestores de bases de datos se hiciera efectiva los lenguajes de programacioacuten utilizaban el acceso a ficheros para almacenar sus datos Asiacute los lenguajes COBOL Pascal o incluso C comenshyzaron a utilizar el manejo de archivos en aquellos programas que necesishytaban guardar datos para recuperarlos posteriormente

Actualmente la informacioacuten puede almacenarse en ficheros o en bases de datos Los ficheros pueden almacenar textos que pueden ser leiacutedos faacutecilshymente por nosotros y por un ordenador Ademaacutes existe una serie de utishyl idades que permiten al sistema operat ivo (gnuLinux o MacOSX) interactuar con ellos hacer buacutesquedas etceacutetera

Nota

El sistema operativo Windows tiene algunas restricciones con resshypecto al manejo de ficheros y no se recomienda para gestionar los archivos

Funciones de lectura y escritura de ficheros

Existen en PHP 5 un conjunto muy numeroso de funciones que permishyten manejar ficheros de diferentes formas La idea baacutesica para trabajar con ficheros es la siguiente

bull Abrir el fichero para su lectura escritura

bull Leer el fichero

bull Cerrar el fichero (puede hacerse maacutes tarde)

bull Realizar las operaciones necesarias en el contenido

bull Escribir los datos

Abrir el fichero

La funcioacuten f open () asigna a una variable un puntero (un descriptor) al fichero que quiera abrir La variable puede utilizarse despueacutes para hacer cualquier tipo de operacioacuten Si el fichero que intenta abrir no existe o no puede utilizarse en ese momento f open () devolveraacute un valor false

Ficheros y almacenamiento de datos 183

Los ficheros pueden abrirse en varios modos tal y como indica la tabla 101

Tabla 101 Modos de apertura de los ficheros

Modo Explicacioacuten

Soacutelo lectura (r) Soacutelo permite leer el fichero Si intenta hacer otra cosa le saldraacute un error

Lectura y escritura si existe el Permite leer y escribir un fichero que exis-fichero (r+) ta El contenido del fichero no se borra

sino que se escribe a continuacioacuten Soacutelo escritura (w) Soacutelo se puede escribir Sobrescribe cualshy

quier fichero afectado Escritura y lectura (w+) Si el fichero no existe intenta crearlo Escritura al final (a) Escribe siempre al final del fichero tanto si

existe como si no Lectura y escritura al final (a+) Escribe al final del fichero y permite leer

Desde la versioacuten 4 de PHP puede abrir ficheros remotos que esteacuten almashycenados en servidores Asiacute podraacute utilizar el protocolo HTTP o FTP para recuperar datos remotamente Puede ver como ejemplo varias formas de abrir un fichero con f open ()

ltphp Los ficheros HTTP solo pueden abrirse de lectura $descriptor = fopen(httpwwwluisyfernandanet noticiastxtr) FTP permite abrir ficheros de lectura y escritura $descriptor2 = fopen(ftp usuariocontrasentildealuisyfernandanetnoticiastxtr) Apertura normal de un fichero guardado en el ordenador local $descriptor3 = fopen(noticiastxt a+) gt

Lectura de ficheros

f r e a d () tiene como paraacutemetro un descriptor de fichero devuelto por la funcioacuten f o p e n () y el tamantildeo del bloque de datos que queremos leer

$variable = fread($descriptor 4000)

Normalmente no conoceraacute el tamantildeo del fichero y por lo tanto debe utishylizar alguna teacutecnica para leerlo correctamente Lo maacutes sencillo es apoyar-

184 Capiacutetulo 10

se en la funcioacuten f i l e s i z e () que devuelve el tamantildeo en bytes del fichero que pase como argumento Asiacute la lectura anterior quedariacutea

$variable = fread($descriptor filesize(noticiastxt))

Advertencia

Tiene que notar que el lector f i l e s i z e () no toma como paraacuteshymetro el descriptor devuelto por la funcioacuten f o p e n O sino el nombre del fichero que estamos tratando

La funcioacuten anterior devuelve un bloque completo de caracteres leiacutedos desde un fichero y puede hacerse poco manejable cuando intente buscar alguacuten dato especiacutefico PHP 5 posee algunas funciones para leer liacutenea a liacuteshynea desde un fichero f r e a d () tiene como paraacutemetros el descriptor del fichero y un bloque maacuteximo de caracteres a leer La utilizacioacuten praacutectica es la siguiente

ltphp $descriptor = fopen (librotxta +) $linea_numero = 1 while (feof($descriptor))

$linea = fgets ($descriptor4096) echo liacutenea nuacutemero $numero_linea es $linea $linea_numero++

f c l o s e ($desc r ip to r ) gt

El bucle actuacutea hasta que la funcioacuten f e o f () encuentra el final del fichero apuntado por el descriptor Mientras que no sea el fin del fichero la funshycioacuten f g e t s () iraacute leyendo liacutenea a liacutenea todo el contenido e imprimieacutendoshylo en pantalla

La forma ideal de trabajar con ficheros es ir leyendo poco a poco su conshytenido para poder buscar datos que nos interesen en cada liacutenea o conshyjunto de caracteres Existe una funcioacuten que nos permite almacenar todo el contenido de un fichero en un array para su posterior proceso con las funciones propias de las colecciones de datos La funcioacuten e x p l o d e () toma como paraacutemetros un caraacutecter por donde cortar la cadena y el nomshybre de la variable que contiene los datos Podemos ver su funcionamienshyto en el ejemplo

ltphp $descriptor = fopen (librotxta+) $linea__numero = 1

Ficheros y almacenamiento de datos 185

$archivo = while ( feof($descriptor) )

$linea = fgets($descriptor4096) $archivo = $archivo liacutenea nuacutemero $numero__linea es

$linea $1inea_numero++

fclose($descriptor) $lista = explode( $archivo) gt

En este caso e x p l o d e () busca en la variable $ a r c h i v o todos los espashycios en blanco y va almacenando en el array caracteres que esteacuten entre dos ocurrencias (entre dos espacios) Asiacute obtenemos una gran lista de palashybras almacenadas por separado que hacen muy faacutecil buscar ordenar o borrar cualquier contenido

Por uacuteltimo la funcioacuten f ge te () permite leer un fichero caraacutecter a caraacutecshyter Esto es muy uacutetil cuando construimos un parse (un programa que inshyterpreta el contenido de un fichero) y debemos ir evaluando las palabras letra por letra para actuar en consecuencia

Escritura de ficheros

Las funciones para escribir ficheros son tan sencillas de utilizar como las de lectura La funcioacuten principal f w r i t e () escribe en un fichero apuntashydo por un descriptor una cadena de caracteres Es imprescindible que el fichero esteacute abierto en uno de los modos de escritura para que no deacute error

Veamos ahora un ejemplo completo El coacutedigo siguiente es un pequentildeo libro de visitas donde todo aquel que navegue por nuestra Web puede dejar mensajes de agradecimiento y aacutenimo Aunque no es el mejor libro de visitas escrito nunca siacute es un buen ejemplo de coacutemo utilizar la lectura v escritura de archivos dentro de un entorno orientado a objetos

ltphp class libro_visitas

priacutevate $tamano priacutevate $nombre priacutevate $descriptor priacutevate $contenido function construct($nombre)

$this-gtnombre = $nombre

i

186 Capiacutetulo 10

public function leer_libro)

$this-gtdescriptor = fopen ($this-gtnombrea+) $this-gttamano=filesize($this-gtnombre) if ($this-gttamano gt 0)

$this-gtcontenido = fread($this-gtdescriptor $this-gttamano)

fclose ($this-gtdescriptor) return $this-gtcontenido

pub l i c funct ion esc r ib i r__ l ib ro ($riombre $texto)

$ t h i s - gt d e s c r i p t o r = fopen ($this-gtnombrea+) $nombre = lt t r x t d bgcolor=CCCCCCgt$nombrelttdgtlttrgt $texto = lt t r x t d bgcolor=FFFFFFgt$textolt tdx t rgt f w r i t e ( $ t h i s - gt d e s c r i p t o r $ n o m b r e ) f w r i t e ( $ t h i s - gt d e s c r i p t o r $ t e x t o ) f c l o s e ($ th i s -gtdesc r ip to r )

gt ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtralgt ltheadgt lttitlegtLibro de visitaslttitlegt ltmeta http-eguiv=Content-Type content=texthtml charset=iso-8859-lgt ltheadgt ltbodygt ltp align=centerxstronggtLibro de visitas ltstrongxpgt lttable width=100 border=0 cellspacing=0 cellpadding=0gt

ltphp if (isset ($_POST[nombre ] ) |] isset($_POST[texto]))

$libro = new libro_visitas(librotxt) $librogtescribir_libro($_POST[nombre]$_POST[texto])

$libro_ver = new libro__visitas(librotxt) echo $libro_ver-gtleer_libro() gt lttablegt ltform action=librophp raethod=POST gt Nombre ltinput name=nombre tYpe=text id=nombregt

ltpgt ltpgtTexto

Ficheros y almacenamiento de datos 187

lttextarea name=texto id= tex togtlt tex ta reagt ltpgt ltpgt

ltinput type=submit name=Submit value=Enviar gt ltpgt ltformgt ltbodygt lthtmlgt

La figura 101 muestra el resultado del libro de visitas Como puede ver el coacutedigo tiene dos partes diferenciadas La primera es la definicioacuten de una clase con tres meacutetodos que es la encargada de almacenar y recuperar los datos La segunda parte es el coacutedigo HTML que nos permite visualizar los comentarios de las personas que nos visitan Lo maacutes recomendable es seshyparar ambas partes en dos ficheros distintos y hacer uso de la funcioacuten r e q u i r e _ o n c e () para utilizar el coacutedigo PHP

Si se fija en el coacutedigo HTML hay una parte central escrita en PHP que comprueba si existen datos pasados mediante el meacutetodo POST es decir si existen datos para escribir en el fichero Si es asiacute creamos el objeto $1 lishyb r o y llamamos al m eacute t o d o e s c r i b i r _ l i b r o ( ) que se encarga de guarshydar los datos correctamente Si no hay datos que guardar simplemente se crea un objeto y se lee el archivo donde estaacuten los comentarios

188 Capiacutetulo 10

La clase l i b r o _ v i s i t a s escribe en el fichero filas de una tabla que desshypueacutes se interpretan en el HTML colocando todo correctamente

Sistema de ficheros y directorios

Existe un conjunto de funciones que permiten manejar ficheros y directoshyrios del sistema Estas funciones son muy parecidas a comandos de Unix gnuLinux y seguramente le resulten familiar al lector

Copiar borrar y renombrar

Las operaciones baacutesicas de manejo de ficheros y que se aprenden cuando comenzamos a utilizar un sistema operativo concreto son las de copia borrado y modificacioacuten

Para copiar un fichero se utiliza la funcioacuten copy ( ) que toma como paraacuteshymetros el fichero que quiere copiar y el destino donde quiere guardar la copia

Puede antildeadir un meacutetodo nuevo a la clase l i b r o _ v i s i t a s para que reashylice funciones de copia de seguridad

public function copia_seguridad()

c o p y ( $ t h i s - gt n o m b r e c o p i a t x t )

La siguiente funcioacuten u n l i n k ( ) toma como paraacutemetro el nombre de un fichero y lo borra Puede hacer uso de esta funcioacuten para ampliar su clase y permitir que se puedan borrar los ficheros que almacenan los libros de visitas

public function borrar_libro()

unlink($this-gtnombre)

Como el meacutetodo c o p i a _ s e g u r i d a d () soacutelo permite almacenar un fichero puede ampliar su gama de meacutetodos y antildeadir uno que le deacute la posibilidad de renombrar el fichero c o p i a t x t a otro nombre

public function renombrar_copia($nuevo_nombre)

rename ($this- gtnombre $nuevo__nombre)

Ficheros y almacenamiento de datos 189

Funciones de comprobacioacuten

Es necesario antes de borrar copiar o renombrar un fichero hacer una comprobacioacuten miacutenima para saber si el fichero existe

De esta forma evitaraacute errores innecesarios y tendraacute maacutes control en el flujo de su programa

La funcioacuten f i l e _ e x i s t s () comprueba si un fichero existe dando el valor tnte en caso afirmativo yfalse en caso contrario

El meacutetodo b o r r a r _ l i b r o () puede quedar de la siguiente forma

public function borrar_libro()

if (file_exists($this-gtnombre))

unlink($this-gtnombre)

En los sistemas operativos UNIX gnuLinux todos los recursos hardware se corresponden con un fichero Puede que alguna vez necesite saber el tipo de fichero con el que va a tratar (fichero directorio recurso) La funshycioacuten f i l e t y p e () devuelve un valor que indica el tipo de fichero que coshyrresponde al valor pasado como paraacutemetro

Tabla 102 Tipos de ficheros

Valor Descripcioacuten

fifo Es de tipo FIFO

char Dispositivo de caraacutecter

dir Directorio

block Dispositivo especial de bloques

link Enlace

file Fichero

unknown Tipo desconocido

Ademaacutes de la funcioacuten anterior existe un conjunto de funciones que preshyguntan directamente al archivo por su tipo y el resultado es true ofalse en funcioacuten de la veracidad de la pregunta Las funciones i s _ d i r ( ) i s__execu tab le () i s _ f i l e () y i s _ l i n k ( ) preguntan a su argumento si es del tipo directorio ejecutable fichero o enlace respectivamente

190 Capiacutetulo 10

Directorios

Es muy uacutetil disponer de un gestor de ficheros Web que nos permita naveshygar entre los archivos y directorios Para hacer esto en PHP existen dos meacutetodos El primero utiliza las funciones o p e n d i r ( ) r e a d d i r () y c l o -s e d i r ( ) muy parecidas en su funcionamiento a f open () f r e a d () y f c i oacute s e ( ) Lo mejor es ver coacutemo trabajan juntas con un ejemplo

ltphp $directorio = $descriptor = opendir($directorio) while ($entrada = readdir($descriptor) )

if (is_dir($directorio$entrada) ) echo [Directorio] $entrada ltbrgtbull

elseif ( is__f ile ($directorio $entrada) ) echo [Fichero] $entrada ltbrgt

closedir($descr iptor) gt

Como puede intuir no existe ninguna diferencia significativa entre abrir un fichero o abrir un directorio Lo primero es crear un puntero hacia el directorio que quiera observar y guardarlo en $ d e s c r i p t o r El bucle va leyendo entrada por entrada con la funcioacuten r e a d d i r () y dependiendo

Ficheros y almacenamiento de datos 191

del resultado de las funciones i s _ d i r () o i s _ f i l e () se imprimiraacute el directorio o el fichero pertinente

Existe una segunda forma de visualizar lo mismo pero utilizando proshygramacioacuten orientada a objetos PHP 5 provee un objeto que implementa toda la loacutegica vista anteriormente La funcioacuten d i r () devuelve un objeto que permite examinar el directorio pasado como paraacutemetro El objeto poshysee un meacutetodo llamado r e a d () que va leyendo todas las entradas y un meacutetodo c i oacute s e ( ) que cierra el objeto El ejemplo anterior puede verse asiacute

ltphp $directorio = $fichero = dir(directorio) while ($entrada = $fichero-gtread())

if (is_dir(directorioentrada)) echo [Directorio] $entrada ltbrgt

elseif (is_file($directorio$entrada)) echo [Fichero] $entrada ltbrgt

$ f i c h e r o - gt c l o s e ( ) gt

Ficheros de configuracioacuten

Cuando sea un excelente programador en PHP 5 necesitaraacute conocer teacutecshynicas para almacenar datos de configuracioacuten en un fichero Una teacutecnica habitual es crear un fichero con variables de PHP que toman los valores adecuados y en el transcurso del programa utilizar una llamada a la funshycioacuten r e q u i r e j o n e e () para poder utilizarlas De esta forma podriacuteamos utilizar el siguiente ejemplo como configuracioacuten para conectar a una base de datos

ltphp servidor = localhost usuario = luis $password = secreta $base_datos = anaya gt

Otra alternativa es utilizar un tipo de fichero de configuracioacuten que utiliza la misma estructura que el fichero php i n i La estructura es la siguiente

Los comentarios van despueacutes de un punto y coma

192 Capiacutetulo 10

[Base__datos] servidor=localhost usuario=luis password=secreta base_datos=anaya Creamos un nuevo apartado [Preferencias] color=rojo tamanio=medio fuente=verdana

Este archivo almacena las variables que necesite en el transcurso del proshygrama

Para leerlo existe una sentencia especial que almacena el resultado en un array Para acceder a cada uno de los campos hay que utilizar la notacioacuten de un array de dos dimensiones como muestra el ejemplo La figura 103 muestra el resultado de leer un archivo de configuracioacuten

ltphp $configuracion = parse_ini_file(configuracioacuteniniTRUE) Ejemplos de variables echo $configuracion[Base__datos] [servidor] echo $configuracion[Preferencias] [fuente] gt

Ficheros y almacenamiento de datos 193

Manejo de ficheros en el servidor

Conociendo todas las posibilidades que ofrece PHP 5 a la hora de controshylar archivos llega la hora de aplicar a la praacutectica casos reales de funcionashymiento Los dos usos maacutes comunes de manejo de ficheros en la Web tienen que ver con la subida de los mismos a un servidor o con la descarga desshyde una paacutegina Web

Subida de ficheros

Cuando utilice un formulario Web puede introducir los datos solicitados a traveacutes de cajas de texto listas desplegables o botones de seleccioacuten Adeshymaacutes existe una etiqueta HTML que permite elegir un fichero de nuestro ordenador local y subirlo al servidor Puede crear un formulario miacutenimo que contenga la etiqueta en el siguiente ejemplo

ltHTMLgt ltBODYgt ltform action=subirphp method=POST enctype=multipartform-datagt Introduce el fichero ltinput type=file name=fichero gtltbrgt ltinput type=hidden ntildeameTAMANIO valueacute = 1000gt ltinput type=subraitgt ltformgt ltBODYgt ltHTMLgt

Como puede ver el atributo e n c t y p e debe tener el valor m u l t i p a r t = f o r m - d a t a para que el formulario trabaje correctamente Ademaacutes heshymos antildeadido una etiqueta llamada TAMANIO que guarda el valor maacutexishymo en bytes que nuestro script va a permitir subir Esto debe controlarse en la Web que reciba los datos mediante PHP Puede ver el aspecto graacutefishyco en la figura 104

Cuando el formulario se enviacutea PHP detecta automaacuteticamente que hemos enviado un fichero y lo almacena en un directorio temporal del servidor La Web que recibe los datos introduce dentro de la variable suacuteper-global 3_FILES [ nombre_f i c h e r o ] un conjunto de propiedades tales como el nombre del fichero subido el nombre temporal del recurso el tamantildeo o si ha tenido alguacuten error la subida Vamos a ampliar el formulario con coacuteshydigo para el manejo de ficheros

ltHTMLgt ltBODYgt ltform action=subirphp method=POST enctype=multipartform-datagt

194 Capiacutetulo 10

Introduce el fichero ltinput type=file name=ficherogtltbrgt ltinput type=submit gt ltformgt ltPHP

$fichero = $_FILES[fichero] foreach ($_FILES[fichero] as $indice =gt $valor)

echo $indice $valorltbrgt if ($_POST[TAMANIO]lt$_FILES[fichero] [size])

echo ltbrgtEl fichero tiene un tamantildeo adecuado copy ($_FILES[fichero] [tmp_name]archivotxt)

else echo ltbrgtEl fichero es demasiado grande

gt

ltBODYgt ltHTMLgt

i n L )T^ M ^ ir 7~n l a

L- I r

1 1 1 4 t r 1 c c - 1 r

f - 1 tlf 1 4 4

1 l 1 1 4 4 1

directorios ocultos Cenes ar

Terminado

f f t Eacute f l U B M I - B [luis] v Moziacutella Firefc V E l GIMP bull $ ^ C 7

Figura 104 Formulario de entrada de ficheros

El resultado muestra un formulario donde debe introducir un fichero que puede ver en la figura 105

Cuando activa el botoacuten de subida la paacutegina vuelve a cargar pero esta vez muestra informacioacuten sobre el fichero y si el tamantildeo es adecuado o no para su almacenamiento Nos hemos apoyado en la construccioacuten foreach para averiguar las proshypiedades del fichero subido

Ficheros y almacenamiento de datos 195

Si el tamantildeo en bytes que tenemos puesto como liacutemite en el formulario es menor que el tamantildeo del archivo se utiliza la funcioacuten c o p y () para coshypiar el fichero y guardarlo en el servidor

Descarga de ficheros

Normalmente dejamos al lenguaje HTML el trabajo de enlazar los archishyvos que deseamos que los usuarios de nuestra Web puedan descargar Esto se puede hacer simplemente con un enlace del tipo

lthtmlgt ltBODYgt lta href=ejemplozipgtPincha aquiacute para descargarltagt ltBODYgt ltHTMLgt

Cuando hacemos clic en el enlace normalmente el navegador averigua el tipo de fichero que vamos a descargar (ZIP PDF imagen) y nos muestra una pequentildea ventana con informacioacuten sobre el fichero

Imagine ahora que los ficheros que queremos poner en descarga se geneshyran en ese mismo instante como los archivos PDF Tenemos que seguir una pauta distinta para permitir la descarga desde el sitio Web utilizanshydo cabeceras HTTP La figura 106 muestra la ventana del navegador que recibe la cabecera MIME

196 Capiacutetulo 10

ltphp $fichero = ejemplozip $mimeType = appliacutecationzip Si el navegador es Explorer u Opera cambiamos el tipo de cabecera if (strpos($_SERVER[HTTP_USER_AGENT]MSIE 5) |[

strpos($_SERVER[HTTP_USER_AGENT]Opera 7)) $mimeType = applicationx-download

Se genera la cabecera header(content-disposition attachment f ilename = ej emplo__personal zip) header(content-type $mimeType) header(content-length filesize($fichero)) Se enviacutea el archivo al navegador readfile($fichero) gt

Los tipo MIME identifican el tipo de fichero y lo asocian a una aplicacioacuten determinada en un sistema operativo determinado Si utiliza el tipo MIME de PDF en un sistema Windows la aplicacioacuten asociada puede ser Acrobat Reader de Adobe Casi todos los archivos llevan asociado un tipo MIME y sirve entre otras cosas para que el navegador reconozca el tipo de archishyvo que estaacute descargando y optar por mostrarlo directamente en pantalla o guardarlo en alguna ubicacioacuten del disco duro Si comprueba antes el nomshybre del navegador que ha solicitado la descarga puede cambiar el tipo para que sea compatible con distintas versiones Las cabeceras HTTP deshyben generarse con la funcioacuten h e a d e r () y debe ser lo primero que se enshyviacutea al navegador Si enviacutea alguacuten dato o etiqueta antes que la cabecera obtendraacute un error

Ficheros y almacenamiento de datos 197

La cabecera que utilizamos en este caso es la de enviacuteo de un fichero del tipo MIME indicado y tamantildeo calculado con la funcioacuten f i l e s i z e ( ) No es necesario que el archivo que vaya a enviar tenga el mismo nombre en la descripcioacuten de la cabecera que en el servidor

Finalmente la funcioacuten r e a d f i l e () lee el fichero completamente y lo enviacutea al navegador

Resumen

Situados ya en el ecuador del libro podemos asegurar que estaacute preparado para enfrentarse a programas serios Los conceptos baacutesicos los aprendioacute en los capiacutetulos 1 2 3 4 5 6 y 7 El capiacutetulo 8 le mostroacute la forma de utilishyzar las variables entre varias paacuteginas Web y el 9 la verdadera potencia de uso de PHP 5

Este capiacutetulo le ha mostrado la forma de guardar datos para que permashynezcan almacenados indefinidamente y meacutetodos para abrir cerrar copiar o borrar los ficheros que utilice Aunque no es el mejor meacutetodo para guarshydar los datos muchas aplicaciones existentes se sirven de las funciones de archivos en vez de la utilizacioacuten de bases de datos

Los dos capiacutetulos siguientes le guiaraacuten por el apasionante mundo de los gestores de bases de datos La potencia de estos gestores le permitiraacute errashydicar de sus scripts la gestioacuten de datos mediante ficheros A partir de enshytonces la gestioacuten de archivos quedaraacute relegada al manejo de ficheros graacuteficos copias o gestioacuten de la configuracioacuten

En este capiacutetulo aprenderaacute a

bull Crear sus propias bases de datos con el lenguaje SQL bull Realizar consultas con SQL para insertar modificar o borrar registros

bull Conocer las funciones baacutesicas de SQLite

bull Recuperar los datos de una tabla y el nuacutemero de registros bull Moverse entre los registros de una base de datos

200 Capiacutetulo 11

Introduccioacuten

Este capiacutetulo pretende ser una introduccioacuten al lenguaje estructurado de consulta (SQL) que es primordial conocer a la hora de utilizar alguna base de datos relacional Puesto que no es un libro dedicado a SQL soacutelo vereshymos las estructuras baacutesicas del lenguaje para poder realizar nuestros ejemshyplos por eso recomiendo leer alguacuten libro deciicado a consultas SQL para sacar el maacuteximo partido a las bases de datos

Tambieacuten conoceremos la nueva implementacioacuten de PHP 5 para bases de datos SQLite Lejos de ser un gestor de bases de datos es sencillamente una libreriacutea que nos permite tratar un fichero de iexcla misma forma que utishylizamos una base de datos SQLite viene instalado en los binarios de PHP 5 y no utiliza ninguacuten puerto de conexioacuten externo tan soacutelo funciona cuanshydo se hace una llamada a las funciones de SQLite

SQL

La estructura baacutesica de una base de datos SQL es muy sencilla Los datos de una base de datos se almacenan en tablas donde cada fila identifica uniacutevocamente a un elemento distinto Por ejemplo la tabla de usuarios tendraacute tantas filas como usuarios tenga la paacutegina Web Cada tabla puede definir varias columnas Las columnas hacen referencia a las propiedades de cada fila Por ejemplo la tabla de usuarios podriacutea tener como columshynas el coacutedigo de usuario el nombre los apellidos y la direccioacuten postal

Nota

Hoy en diacutea tedas las aplicaciones profesionales escritas en PHP se basan en la interaccioacuten entre el coacutedigo y los datos almacenados en alguna base de datos Recomiendo al lector que no escatime esfuerzos en aprender el lenguaje SQL pues le seraacute muy uacutetil para realizar despueacutes aplicaciones basadas en cualquier base de datos MySQL SQLite SQL Server o incluso Oracle

El lenguaje SQL nos permite elegir varias filas atendiendo a un criterio insertar nuevas filas actualizar los datos o borrarlas con las sentencias SELECT INSERT UPDATE y DELETE respectivamente Este lenguaje per-

Bases de datos con SQL y SQLite 201

mite soacutelo manipular los datos contenidos en las tablas Si quiere modificar la estructura tiene que apoyarse en el lenguaje de definicioacuten de datos que le permite crear nuevas tablas o bases de datos insertar nuevas propiedashydes en forma de columnas o borrar tablas con las sentencias CREacuteATE ALTER v DROP respectivamente Para seguir los ejemplos vamos a basarshynos en una pequentildea base de datos con tres tablas

Tabla 1 1 1 Usuario

id_usuario nombre cuenta

1 Luis Miguel 7011

2 Mariacutea Fernanda 3454

3 Pedro 3445

4 Javier 1123

La tabla de U s u a r i o s tiene 4 filas Cada una de ellas es diferente a las demaacutes y el paraacutemetro que las identifica uniacutevocamente es i d _ u s u a r i o En Espantildea todas las personas tienen un coacutedigo numeacuterico el DNI que las identifica y las hace distintas frente a otras personas que tengan el mismo nombre y apellidos En las tablas ocurre lo mismo Necesitamos un coacutedigo numeacuterico que nos identifique personas distintas Las dos propiedades sishyguientes son el nombre y la c u e n t a del banco para hacer los pagos

Tabla 112 Producto

id_producto nombre precio

1 ratoacuten 6

2 portaacutetil 1000

3 libro PHP5 20

La tabla de P r o d u c t o s es muy similar a la de U s u a r i o s e identifica toshydos los productos que se pueden encontrar en nuestra Web de venta

Tabla 113 Carrito

id_compra id_usuario Jd_producto

1 1 1

202 Capiacutetulo 11

idcompra iexcldusuario id_producto

2 1 2

3 2 1

4 3 3

La tabla C a r r i t o de la compra mantiene un listado que relaciona los usuashyrios con los productos que han comprado Si se fija en la primera fila el i d_compra es el nuacutemero de factura que debe ser distinto siempre en el antildeo actual el i d _ u s u a r i o es 1 lo que quiere decir que el usuario 1 Luis Miguel ha comprado el producto 1 un ratoacuten de PC Si ha entendido esto ya podemos empezar a ver las sentencias SQL para manejar los datos

SELECT

Este es el comando principal que usaraacute en todas sus aplicaciones de bases de datos La sintaxis baacutesica es la siguiente

SELECT campol campo2 campo3 FROM tabla WHERE condicioacuten

La sentencia SELECT permite escoger los campos que especifiquemos de un conjunto de filas que cumplan una condicioacuten escrita despueacutes de la claacuteushysula WHERE Por ejemplo para recuperar todos los nombres de los usuashyrios almacenados en la tabla U s u a r i o tendriacuteamos que hacer

SELECT nombre FROM Usuario

El resultado es una columna con todos los nombres

Luis Miguel Maria Fernanda Pedro Javier

Advertencia

Si se fija iexcla claacuteusula WHERE no aparece porque estamos seleccioshynando todas iexclas filas Si quisieacuteramos seleccionar todas las filas cuyo i d _ u s u a r i o sea mayor que 2 tendriacuteamos que antildeadir WHERE i d_usua r io gt 2

Bases de datos con SQL y SQLite 203

Si necesita utilizar todos los campos de una tabla puede utilizar el siacutemboshylo para seleccionar todos

SELECT FROM U s u a r i o

Un uacuteltimo truco permite conocer el nuacutemero de filas que cumplen la conshydicioacuten Si despueacutes de la sentencia SELECT escribimos c o u n t ( ) el gesshytor de bases de datos nos contaraacute el nuacutemero de filas implicadas en la seleccioacuten

SELECT c o u n t ) ) FROM U s u a r i o

El resultado devuelto es 4 el nuacutemero de usuarios dados de alta

Uniones

Imagine ahora que queremos conocer el nombre de los usuarios que han comprado un producto determinado Si nos fijamos en la tabla C a r r i t o soacutelo podemos sacar el i d _ u s u a r i o con lo aprendido hasta ahora

Existe la posibilidad de cruzar varias tablas Cuando unimos dos tablas lo que realmente pasa es que obtenemos como resultado una tabla mayor con la suma del nuacutemero de columnas de las tablas y tantas filas como inshydique la multiplicacioacuten de las filas de las tablas implicadas

Si hacemos algo asiacute

SELECT FROM Usuario Carrito

El resultado es la unioacuten de las tablas Usuario y Carrito cuyo resultado tiene la suma de las columnas (3 + 3) y la multiplicacioacuten de las filas (4 x 4)

Tabla 114 UsuarioxCarrito

idusuario nombre cuenta id_carrito id_usuario idproducto

1 Luis Miguel 7011 1 1 1

1 Luis Miguel 7011 2 1 2

1 Luis Miguel 7011 3 2 1

1 Luis Miguel 7011 4 3 3

2 Ma Fernanda 3454 1 1 1

2 Ma Fernanda 3454 2 1 2

2 Ma Fernanda 3454 3 2 1

2 Ma Fernanda 3454 4 3 3

204 Capiacutetulo 11

idusuario nombre cuenta id_carrito id_usuario id_producto

3 Pedro 3445 1 1 1

3 Pedro 3445 2 1 2

3 Pedro 3445 3 2 1

3 Pedro 3445 4 3 3

4 Javier 1123 1 1 1

4 Javier 1123 2 1 2

4 Javier 1123 3 2 1

4 Javier 1123 4 3 3

Aquiacute es donde realmente se necesita utilizar la claacuteusula WHERE Lo que queshyremos conocer es el nombre de los usuarios que han comprado el producto nuacutemero 1 Al hacer una unioacuten lo primero que tenemos que hacer es eliminar las filas repetidas mediante una sentencia que relacione las dos tablas Si se fija bien puede ver que la columna i d _ u s u a r i o aparece en las dos tablas por lo tanto es una buena referencia Observe la siguiente sentencia SQL

SELECT FROM Usuario Carrito WHERE Usuario id_usuario = Carrito id__usuario

Lo que hemos hecho es crear una unioacuten de dos tablas donde cada fila debe tener las dos columnas i d _ u s u a r i o iguales

Como las dos tablas tienen el mismo nombre para la columna i d _ u s u a r i o es necesario anteponer la tabla a la propiedad para que la consulta funshycione de la siguiente forma U s u a r i o i d _ u s u a r i o o C a r r i t o i d _ u s u a r i o

El resultado de la sentencia anterior es

Tabla 115 UsuarioxCarrito

idusuario nombre cuenta id_carrito idusuario id_producto

1 Luis Miguel 7011 1 1 1

1 Luis Miguel 7011 2 1 2

2 Ma Fernanda 3454 3 2 1

3 Pedro 3445 4 3 3

Bien ahora tenemos un conjunto de datos que nos da el nombre de los usuarios que han comprado algo en nuestra tienda Si queremos averi-

Bases de datos con SQL y SQLite 205

guar quieacuten ha comprado el producto nuacutemero 1 tendremos que modificar la sentencia

SELECT FROM Usuario Carrito WHERE Usuarioid_usuario - Carritoid_usuario AND id_producto = 1

El resultado ahora se acerca maacutes a la realidad de lo que necesitamos

Tabla 116 UsuarioxCarrito

id_usuario nombre cuenta id_carrito id_usuario id_producto

1 Luis Miguel 7011 1 1 1

2 Ma Fernanda 3454 3 2 1

Acotando un poquito maacutes la sentencia

SELECT nombre FROM Usuario Carrito WHERE Usuarioid_usuario = Carritoid_usuario AND id_producto = 1

Ahora el resultado siacute es el esperado

Tabla 117 Nombre de los usuarios que han comprado el producto 1

nombre

Luis Miguel

Ma Fernanda

Dominar la sentencia SELECT con todas sus variaciones es un trabajo duro de varios meses o antildeos pero la recompensa se recoge en los primeros pashysos cuando comenzamos a ver la potencia del lenguaje y el uso en los disshytintos gestores de bases de datos

INSERT

Para poder seleccionar los datos primero hay que poder insertarlos en las tablas La sentencia necesaria para introducir nuevos datos es

INSERT INTO tabla (columnal columna2 columna3) VALUacuteES (valorl valor2 valor3)

206 Capiacutetulo 11

El resultado de esta operacioacuten es la inclusioacuten de un registro nuevo en la tabla en las columnas indicadas y con los valores dados Aquellas columshynas que no aparezcan no tomaraacuten valor en ese registro o tomaraacuten el vashylor NULL Para insertar un nuevo cliente en la tabla de U s u a r i o puede utilizar la sentencia

INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (5 Feo Joseacute 78 98)

La tabla resultante quedaraacute de esta forma

Tabla 118 Usuario

idusuario nombre cuenta

1 Luis Miguel 7011

2 Ma Fernanda 3454

3 Pedro 3445

4 Javier 1123

5 Feo Joseacute 7898

UPDATE

Se utiliza para editar informacioacuten que ya estaacute almacenada en la base de datos En otras palabras podemos cambiar selectivamente cierta informashycioacuten sin tener que borrar un registro e insertarlo de nuevo

La sintaxis baacutesica es

UPDATE tabla SET carapol = valorl campo2 = valor2 campo3 = valor3 WHERE condicioacuten

La condicioacuten se utiliza para seleccionar el nuacutemero de filas a las que afectashyraacute el cambio Si no ponemos nada se supone que la actualizacioacuten de datos se hace sobre todas las filas de una tabla por eso es necesario poner algushyna condicioacuten

Podemos utilizar UPDATE para cambiar el nuacutemero de cuenta de uno de los usuarios

UPDATE Usuario SET cuenta = 4455 WHERE id_usuario = 2

Lo que hemos hecho es cambiar el nuacutemero de cuenta de Mariacutea Fernanda de 3454 a 4455

Bases de datos con SQL y SQLite 207

DELETE

Eacutes la sentencia maacutes peligrosa de las vistas Permite borrar de uno a varios registros de una tabla La sintaxis es

DELETE FROM tabla WHERE condicioacuten

Si se omite la claacuteusula WHERE se borran todas las filas de una tabla Es aconsejable no precipitarse en el uso de esta opcioacuten y detenerse antes un momento a recapacitar si se necesita realmente dejar la tabla vaciacutea La fila que contiene al usuario Javier puede borrarse de la siguiente forshyma

DELETE FROM Usuario WHERE nombre=Javier

Definicioacuten de tablas

El primer paso para poder interactuar con los datos de una tabla es su creacioacuten Para este fin se utiliza la sentencia CREacuteATE que define los campos y el tipo de datos que se va a almacenar en cada columna

Ll formato simplificado es CREacuteATE TABLE tabla (columnal tipo_dato columna2 tipo_dato columna3 tipo_dato)

Los tipos de datos de SQL estaacutendar pueden variar dependiendo del gesshytor de bases de datos que utilice pero baacutesicamente pueden ser

Tabla 119 Tipos de datos en SQL 92

Especificacioacuten Tipo de dato

INT INTEGER Entero grande

SMALLINT Entero pequentildeo

REAL FLOAT Coma flotante

DEC DECIMAL Decimal

CHAR(n) CHARACTER(n) Alfanumeacuterico de longitud fija n

208 Capiacutetulo 11

Especificacioacuten Tipo de dato

VARCHAR(n) Alfanumeacuterico de longitud variable como maacutexishy

mo n caracteres

DATE Fecha

TIME Hora

TIMESTAMP Instante Conjunto de Fecha y Hora de un momento determinado

Con estos datos podemos ver la definicioacuten de la tabla de U s u a r i o

CREacuteATE TABLE Usuario (id_usuario INTEGER nombre CHAR(255)

cuenta INTEGER)

Si alguno de los campos es obligatorio es decir si siempre que realice una insercioacuten de nuevos datos necesita que ciertos campos sean introducidos obligatoriamente puede utilizar la sentencia NOT NULL despueacutes de la deshyfinicioacuten del campo

El campo nombre es obligatorio en la tabla U s u a r i o ya que un registro de usuarios sin almacenar su nombre no tiene sentido

CREacuteATE TABLE Usuario (id_usuario INTEGER nombre CHAR(255) NOT

NULL cuenta INTEGER NOT NULL)

El i d _ u s u a r i o identifica un registro y soacutelo uno No puede haber en la misma tabla dos nuacutemeros iguales en esta columna La forma de encontrar raacutepidamente una fila determinada es preguntar por este dato

La clave primaria de una tabla es un identificador uacutenico en cada tabla y que puede utilizarse para relacionar una tabla con otra En nuestro ejemshyplo podemos ver claramente que i d _ u s u a r i o es la clave primaria de la tabla U s u a r i o

CREacuteATE TABLE Usuario (id_usuario INTEGER PRIMARY KEY nombre

CHAR(255) NOT NULL cuenta INTEGER NOT NULL)

SQLite

SQLite es una libreriacutea que implementa un conjunto de sentencias bastanshyte amplio de SQL 92 estaacutendar La libreriacutea es muy pequentildea y 2 oacute 3 veces maacutes raacutepida que los gestores de bases de datos MySQL o PostgreSQL Neshycesita muy poco tiempo de ejecucioacuten y muy poca memoria para el proceshyso No se necesita administrar la base de datos fuera del entorno de

Bases de datos con SQL y SQLite 209

programacioacuten ya que no es un servidor Existe un problema derivado de esto

SQLite se basa en el almacenamiento de datos en un fichero por lo tanto cada vez que se almacenan datos el fichero que contiene los registros se bloquea durante el tiempo de la actualizacioacuten y no permite a otros usuashyrios interactuar Si la base de datos se utiliza solamente para leer la veloshycidad seraacute muy elevada pero si la utilizamos para actualizar constanteshymente los datos SQLite perderaacute maacutes tiempo negociando los bloqueos del fichero que dando servicio

Entre las caracteriacutesticas de SQLite tenemos

bull Implementa muchas funcionalidades de SQL 92 incluido disparadoshyres y transacciones

bull Proteccioacuten de integridad de datos con cominit y r o l l b a c k

bull Los ficheros de datos pueden moverse de servidor y seguiraacuten funcioshynando

bull Soporta bases de datos de 2 Terabytcs

bull El coacutedigo fuente es de dominio puacuteblico

Creacioacuten de bases de datos

La interfnce de programacioacuten de la extensioacuten SQLite es muy similar al gesshytor de bases de datos MySQL y PostgeSQL La diferencia principal es que SQLite aunque acepta la definicioacuten de datos con la sentencia CREacuteATE internamente soacutelo diferencia entre valores alfanumeacutericos o valores numeacuteshyricos es decir que podemos omitir el tipo de los campos en la definicioacuten de las tablas

La funcioacuten s q l i t e _ o p e n () recibe como paraacutemetro el nombre de una base datos Si la base de datos no existe la crea Ademaacutes de esta funcioacuten neceshysitaremos otra para poder enviar consultas a la base de datos La funcioacuten s q l i t e _ s i n g l e _ q u e r y () toma como paraacutemetros la base de datos creada con s q l i t e _ o p e n () y un literal con la sentencia SQL que queremos ejeshycutar

El ejemplo siguiente crea la base de datos de usuario e inserta las filas que estamos utilizando para aprender el lenguaje SQL

ltphp

$base_datos = sqlite_single_open(Usuariodb) $consulta = CREacuteATE TABLE Usuario

(id_usuario PRIMARY KEY

210 Capiacutetulo 11

nombre CHARIacute2 55) NOT NULL

cuenta INTEGER NOT NULL)

sqlite__query ( $base_datos $ consulta)

$consultal = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (1 Luis Miguel7011)

$consulta2 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (2 Mariacutea Fernanda3454 )

$consulta3 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (3 Pedro3445)

$consulta4 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (4 Javier1123)

sqlite_single_query($base_datos$consultal)

sqlite_ single_query($base_datos$consulta2 )

sqlite_ single_query($base_datos$consulta3)

sqlite_ single_query($base_datos$consulta4)

gt

De esta forma se ha creado la tabla U s u a r i o pero hemos necesitado hashycer 4 consultas adicionales para antildeadir los datos Esto se puede simplifishycar utilizando la funcioacuten s q l i t e _ q u e r y ( ) que acepta maacutes de una liacutenea de SQL Vamos a crear de esta forma la tabla P r o d u c t o y C a r r i t o

ltphp

$consulta = CREacuteATE TABLE Producto

(Iacuted_producto INTEGER PRIMARY KEY

nombre CHAR(255) NOT NULL

precio INTEGER NOT NULL)

INSERT INTO Producto (id_producto nombre precio)

VALUacuteES (1 Ratoacuten 6)

INSERT INTO Producto (idjroducto nombre precio)

VALUacuteES (2 Portaacutetil1000)

INSERT INTO Producto (id_producto nombre precio)

VALUacuteES (3 Libro PHP520)

sqlite_query($base_datos$consulta)

consulta = CREacuteATE TABLE Carrito

(id^compra INTEGER PRIMARY KEY

id^usuario INTEGER NOT NULL

id^producto INTEGER NOT NULL)

INSERT INTO Carrito (id^compra id_usuario id_producto)

VALUacuteES (1 1 1)

INSERT INTO Carrito (id^compra id_usuario id_producto)

VALUacuteES (2 1 2)

INSERT INTO Carrito (id_compra id_usuario id_producto)

VALUacuteES (3 2 1)

INSERT INTO Carrito (id_compra id_usuario idjroducto)

VALUacuteES (4 3 3)

sqlite_query($base_datos$consulta)

gt

Bases de datos con SQL y SQLite 211

Algunos gestores de bases de datos necesitan antildeadir una sentencia espeshyciacutefica para que uno de los campos sea auto incremental es decir que su valor aumente poco a poco sin necesidad de antildeadirlo nosotros en realishydad es gestionado por la propia base de datos

Los campos enteros que llevan asociada la sentencia PRIMARY KEY autoshymaacuteticamente son tratados como campos auto incremeacutentales y en las oacutershydenes INSERT se puede omitir la inclusioacuten del valor porque SQLite le daraacute el valor correlativo de la fila que le corresponda

Uacuteltimos cambios en una tabla

Hay veces que necesitamos saber el uacuteltimo valor auto incremental que SQLite ha generado para asociar una imagen o un archivo a un registro de una tabla Para aver iguar este dato p o d e m o s usar la funcioacuten sqlite_last_insert_rowid()

ltphp $base_datos = sqlite_open(Usuariodb) sqlite_single_query($base_datosINSERT INTO Usuario (nombre cuenta) VALUacuteES (Joseacute A2677)) $ultimo_usuario = sqlite_last_insert_rowid($base_datos) sqlite_single_query($base_datosINSERT INTO Producto (nombre precio) VALUacuteES (Ibook1200)) $ultimo_producto = sqlite_last_insert__rowid($base_datos) sqlite_single_query($base_datosINSERT INTO Carrito (id_usuario id_producto) VALUacuteES ($id_usuario$id_producto)) gt

En el ejemplo puede ver la posible utilizacioacuten de la funcioacuten Con ella exshytraeraacute el uacuteltimo usuario y el uacuteltimo producto introducido y aprovecharaacute para insertarlos en la tabla de compras

Otra funcioacuten muy uacutetil es s q l i t e _ _ c h a n g e s ( ) que devuelve el nuacutemero de filas afectadas por una consulta anterior

Si borra varias filas esta funcioacuten le devolveraacute el nuacutemero de filas que han sido borradas como puede ver en la figura 1 1 1

lt php $base_datos = sqlite_open(Usuariodb)

sqlite_single_query($base_datosUPDATE Usuario set cuenta =

2 2 2 2) echo Nuacutemero de filas afectadas

sqlite_changes($base_datos) gt

Seleccioacuten de datos

Como hemos visto antes la funcioacuten s q l i t e _ q u e r y () da la posibilidad de hacer cualquier tipo de consulta vista al principio del capiacutetulo

Las sentencias CREacuteATE INSERT DELETE o UPDATE no necesitan devolshyver ninguacuten dato pero la sentencia SELECT tiene que devolver los datos requeridos

La variable que obtiene los datos se considera como un recurso y debe aplicarse una funcioacuten para recuperar las filas una a una

Lo podemos comprobar con un ejemplo cuyo resultado se muestra en la figura 112

lt php $base_datos = sqlite_open(Usuariodb) ^resultado = sqlite_query($base_datosSELECT FROM Usuario) if ( $resultado)

echo Parece que hay un error else

while ($fila = sqlite_fe tch__array ($resu l taaacuteo) ) foreach ($fila as $indice =gt $valor)

echo $indice $valorltbrgt

gt

Despueacutes de hacer una consulta con la funcioacuten s q l i t e _ q u e r y ( ) la vashyriable $ r e s u l t a d o recibe un tipo de dato que no es manejable La funshycioacuten s q l i t e _ f e t c h _ a r r a y () extrae de la variable $ r e s u l t a d o todas las filas devueltas en forma de array Para ello hemos construido un bucle w h i l e donde la variable $f i l a va recibiendo los registros

Para acceder a cada columna de un registro simplemente tenemos que hacer uso de la variable como si fuera un array y como iacutendice el nombre de la columna o el nuacutemero de registro de esta forma $f i l a [nombre] $ f i l a [ c u e n t a ] $ f i l a [ 0 ] $ f i l a [ l ]

Dentro del bucle hemos utilizado otro bucle f o r e a c h para mostrar por pantalla todos los valores del array

SQLite orientado a objetos

Puesto que la potencia de PHP 5 radica en la fuerte orientacioacuten a objetos es de agradecer que SQLite provea alguacuten objeto para la interaccioacuten con bases de datos SQLite tiene una potente interface orientada a objetos que puede ser usado para un eficaz manejo de los datos librando al progra-mador de crear su propio objeto con las funciones procedurales El objeto se llama S Q L i t e D a t a b a s e () y el constructor recibe como paraacutemetro la base de datos

214 Capiacutetulo 11

El ejemplo muestra coacutemo utilizarlo aunque el lector ya conoceraacute el funshycionamiento baacutesico de los objetos

lt php $base_datos = new SQLiteDatabase(Usuariodb) $consulta = CREacuteATE TABLE Usuario

(id^usuario INTEGER PRIMARY KEY nombre CHAR(2 55) NOT NULL cuenta INTEGER NOT NULL) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (1 VLuis Miguel7 011) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (2 VMariacutea Fernanda3454) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (3 Pedro3445) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (4 Javier1123)

$base_datos-gtquery($consulta) gt

El meacutetodo q u e r y ( ) funciona exactamente igua l que la funcioacuten s q l i t e _ q u e r y ( ) pero soacutelo recibe como paraacutemetro la consulta ya que la base de datos va impliacutecita en el objeto

Seleccioacuten de registros

Las consultas SELECT se tratan de manera parecida a lo visto anteriorshymente Puesto que estamos utilizando un objeto para recibir el resultado de una consulta tendremos que utilizar meacutetodos que nos permitan maneshyjarlos En la figura 113 puede ver el resultado

ltphp

$base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtquery($consulta) while ($resultado-gtvalid() )

$fila = $resultado-gtcurrent() echo $fila[0] ltbrgt echo $fila[l] ltbrgt echo $fila[2] ltbrgt $ resultado- gtnext () bull

gt

El meacutetodo v a l id () da un resultado true si existen valores que no se han mostrado si devuelve false es que ya hemos extraiacutedo todas las filas El meacutetodo c u r r e n t () nos da la fila actual deacutela consulta La variable $f i l a

Bases de datos con SQL y SQLite 215

obtiene un array con los datos del registro actual Para avanzar de registro en la consulta se utiliza el meacutetodo n e x t ( )

Funciones de Array para recuperar datos

SQLite ofrece tambieacuten un nuacutemero de nuevas funciones que simplifican y aceleran la recogida de informacioacuten de la base de datos Por ejemplo el meacutetodo A r r a y Q u e r y () devuelve un array de dos dimensiones donde la primera dimensioacuten indica el nuacutemero de la fila y la segunda dimensioacuten el nuacutemero de columna de esa fila Si la variable $ r e s u l t a d o recoge el resultado de A r r a y Q u e r y ( ) puede acceder a los registros de la siguienshyt e forma $ r e s u l t a d o [ 0 ] [ 0 ] $ r e s u l t a d o [ l ] [ 0 ] $ r e s u l t a -do [2] [3] Puede utilizar alguacuten bucle foreach para sacar todos los datos

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtArrayQuery($consulta) $filas = 0 while (isset ($resultado [$filas] ) )

foreach ($resultado[$filas] as $indice =gt $valor) echo $indice $valorltbrgt

$filas++

216 Capiacutetulo 11

gt

Ademaacutes de esta forma de trabajar puede hacer que el resultado de la consulshyta se devuelva en forma de objeto PHP 5 permite utilizar la construccioacuten fo-reach para interactuar con objetos v recuperar los datos de la siguiente forma

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario bullresultado = $base_datos-gtunbufferedQuerv($consulta) foreach ($resultado as $valor)

echo Svalor[0]ltbrgt echo $vaior[1]ltbrgt echo $valor[2]ltbrgt

gt

La construccioacuten unbuf f e r edQuery () devuelve las filas en forma de objeshyto y ademaacutes no almacena el resultado en buffer por lo que es muy raacutepida

Nuacutemero de filas

La extensioacuten SQLite posee un meacutetodo para determinar el nuacutemero de camshypos devueltos en una consulta en un resultado El meacutetodo n u m F i e l d s () se encarga de devolver este resultado Para poder utilizarlo debe recupeshyrar los datos con la funcioacuten unbuf f e r e d Q u e r y () y el objeto devuelto seraacute el que le indique el nuacutemero de campos que almacena

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtunbufferedQuery($consulta) $numero_filas = $resultado-gtnumFields() echo El nuacutemero de filas es $numero_filas foreach ($resultado as $valor)

echo $valorf0]ltbrgt echo $valor[1]ltbrgt echo $valor[2]ltbrgt

gt

Moverse entre registros

En muchos casos querraacute utilizar la menor memoria posible y se haraacute inshydispensable utilizar el meacutetodo unbuf f e r e d Q u e r y ( ) aunque esto hace perder funcionalidad y puede no resultar la mejor eleccioacuten

Bases de datos con SQL y SQLite 217

Por ejemplo imagine que quiere saber cuaacutentas filas devuelve un resulshytado

Usando unbuf f e r e d Q u e r y () tenemos que hacer un bucle para contar una a una las filas del resultado Con la funcioacuten q u e r y () tan soacutelo hay que llamar al meacutetodo numRows () para conocer el nuacutemero de registros implicados en la consulta

Las consultas con q u e r y () permiten ademaacutes recuperar la informacioacuten en el orden que queramos y no secuencialmente

El ejemplo siguiente muestra coacutemo utilizar una consulta para ver los reshygistros empezando desde el uacuteltimo hasta el primero

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtquery($consulta) $numero_filas = $resultado-gtnumRows() $resultado-gtseek($numero_filas-1) do

$fila = $resultado-gtcurrent () foreach ($fila as $valor)

echo $valorltbrgt

while ($resultado-gthasPrev() ampamp $resultado-gtprev()) gt

218 Capiacutetulo 11

El meacutetodo s e e k () se mueve a traveacutes del resultado y permite posicionar-nos en el registro que pasemos como paraacutemetro El meacutetodo h a s P r e v () es true si existe un registro previo y p r e v () es true si ha sido posible moshyverse a un registro anterior La figura 114 es un fiel reflejo del funcionashymiento

Resumen

SQLite es una de las caracteriacutesticas estrella de PHP 5 Se ha incluido para que no necesite instalar un gestor de bases de datos para sus proyectos Esto hace maacutes sencillo distribuir aplicaciones porque no dependen de un software adicional tan soacutelo de PHP 5

SQLite es a la vez un servidor de bases de datos y un cliente La libreriacutea permite operar con la mayor parte de las instrucciones de SQL posee un mayor juego de instrucciones que MySQL 4

Pero como todo lo bueno tiene una pequentildea pega Como SQLite trata las bases de datos como ficheros del sistema operativo cuando un usuario hace una conexioacuten para escribir datos el fichero queda bloqueado para inclusiones de otros usuarios Cuando termina la insercioacuten del primer usuario el segundo tendraacute acceso a escribir los datos Por lo tanto SQLite es muy recomendable cuando realice proyectos donde la mayor parte de las veces se hacen lecturas de la base de datos como un perioacutedico digital o un WebLog En otro caso es mejor utilizar un gestor de bases de datos como MySQL que veraacute en el siguiente capiacutetulo

En este capiacutetulo aprenderaacute a

bull Conocer la forma de conectarse a un servidor de bases de datos bull Realizar consultas y recuperar los datos de distintas formas bull Recuperar el nuacutemero de filas que intervienen en una consulta

bull Crear nuevas bases de datos y tablas

220 Capiacutetulo 12

Introduccioacuten

PHP 5 soporta muchos de los gestores de bases de datos relacioacutenales exisshytentes en el mercado Las dos alternativas maacutes comunes son ProstgreSQL y MySQL

Aunque PostgreSQL es mucho mejor en cuanto a caracteriacutesticas y funcioshynes soportadas del SQL 92 estaacutendar MySQL se ha hecho maacutes popular en el ambiente de los servidores Web Cuando los servidores Web ofrecen su sershyvicio como LAMP se refieren a Linux + Apache + MySQL + PHP

Este capiacutetulo cubre las operaciones maacutes comunes que los desarrolladores de PHP pueden hacer con MySQL desde recuperar o modificar datos buscar textos o hacer una copia de seguridad de la base de datos

Administracioacuten de usuarios

Una gran parte del uso de la seguridad y efectividad de MySQL tiene que ver con comprender el sistema de privilegios MySQL permite dar permishysos al detalle basaacutendose en grupos usuarios conexiones y comandos a utilizar En teoriacutea se puede dar privilegios a ciertos usuarios para que soacutelo puedan escribir en algunas columnas de varias tablas Es una buena idea dar a cada usuario los permisos miacutenimos necesarios para que pueda inte-ractuar con su base de datos En realidad en un mundo ideal no deberiacutea preocuparse por dar permisos a los usuarios o crear bases de datos Si su trabajo profesional se basa en el desarrollo de aplicaciones su adminisshytrador de bases de datos deberiacutea poner a punto el servidor de MySQL para facilitar su trabajo Si se estaacute interesado en conocer los entresijos del servishydor de bases de datos recomiendo al lector que lea la documentacioacuten o-line de la Web wwwmysql com o consiga uno de los muchos libros que tratan el tema

En el Apeacutendice A puede ver coacutemo instalar MySQL y dar los permisos neshycesarios para que pueda probar los ejemplos

Conexioacuten a MySQL

La conexioacuten no puede ser maacutes sencilla Es un proceso de dos pasos

bull Se conecta con el servidor de MySQL

PHP 5 y MySQL 221

bull Se solicita la conexioacuten a una base de datos especiacutefica Es importante recordar que MySQL es un servidor que puede estar alojashydo en el mismo ordenador que PHP 5 o en otro diferente Por eso la coshynexioacuten se hace de forma distinta a SQLite

Para conectar a MySQL es necesario enviar como paraacutemetros la direccioacuten del servidor el usuario y la contrasentildea

ltphp $servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras Conexioacuten al servidor de bases de datos $descriptor = mysql_connect($servidor$usuario $pass) Se selecciona la base de datos mysql_select_db($base_datos$descriptor) Se cierra la conexioacuten cuando terminemos mysql__close ( $descriptor) gt

La funcioacuten m y s q l _ c o n n e c t () permite conectar a un servidor En este caso hemos puesto como servidor a l o c a l h o s t porque estamos utilizanshydo nuestro ordenador local para hacer las pruebas

Otra cuestioacuten importante es que el servidor MySQL puede almacenar varias bases de datos de un mismo usuario por eso tenemos que utilizar la f u n c i oacute n m y s q l _ s e l e c t _ d b ( ) para seleccionar la que queremos utishylizar

Por uacuteltimo tenemos la funcioacuten m y s q l _ c l o s e () que se encarga de ceshyrrar una conexioacuten con el servidor

El ejemplo siguiente muestra coacutemo se puede crear una clase reutilizable en todos los proyectos que sirva para conectarse a una base de datos

ltphp class Servidor_Base_Datos

private $servidor private $usuario private $pass private $base_datos private $descriptor function construct($servidor$usuario$pass$base_datos)

$this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtpass = $pass

222 Capiacutetulo 12

$this-gtbase_datos = $base_datos $this-gtconectar_base_datos()

priacutevate function conectar_base_datos()

$this-gtdescriptor = mysql__connect($this-gtservidor$this-gtusuario$this-gtpass) mysql_select_db($this-gtbase_datos$this-gtdescriptor)

$servidor = localhost $usuario = luis $pass = secreto $base_datos = Usuario $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) gt

Nota

No he antildeadido al objeto ninguacuten tipo de control de errores ya que veremos ese tema con profundidad en el capiacutetulo 17

Seleccionar datos

Existen diferentes formas de recuperar datos desde MySQL pero los maacutes usados son seguramente m y s q l _ f e t c h _ q u e r y () y m y s q l _ q u e r y () Si leyoacute el capiacutetulo anterior sobre S Q L i t e no tendraacute ninguacuten problema para asimilar el funcionamiento de estas funciones

Vamos a antildeadir dos meacutetodos nuevos a la definicioacuten de la clase anterior para que nos pueda servir en otras aplicaciones

public function consulta($consulta)

$this-gtresultado = mysql_query($consulta$this-gtdescriptor)

public function extraer_registro ()

if ($fila = mysql_fetch_array($this-gtresultadoMYSQL_ASSOC)) bull return $fila

else return false

PHP 5 y MySQL 223

El meacutetodo c o n s u l t a () recibe una sentencia SQL que debe ejecutarse en la base de datos apuntada por el descriptor $ t h iacute s- gt d e s c r i p t o r

El meacutetodo e x t r ae r _ r eg i s t r o ( ) comprueba con la funcioacuten m y s q l _ f e t c h _ a r r a y () si existen ficheros en el resultado de la conshysulta

En caso afirmativo devuelve un arraxj con los datos de ese registro En el capiacutetulo anterior vimos que un registro pasado comoarray permitiacutea acceder a las columnas mediante un iacutendice numeacuterico ($f i la [0] ) o meshydiante el nombre de la columna (($f i l a [ i d _ u s u a r i o ]))

La directiva MYSQL_ASSOc elimina la posibilidad de extraer los datos con un Iacutendice numeacuterico mejorando la recuperacioacuten en Jos bucles del foreach El ejemplo siguiente muestra coacutemo utilizar los nuevos meacutetodos

ltphp Primero se antildeade el fichero que contiene la clase require_once(MySQLphp) $servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $usuario-gtconsulta (seslect from Usuario) while ($fila = $usuario-gtextraer_registro() )

foreach ($fila as $indice =gt $valor) echo $indice $valorltbrgt

gt

El coacutedigo anterior recupera la clase del fichero MySQL php e inicializa las variables necesarias para conectar con la base de datos

Tambieacuten podemos utilizar un fichero de configuracioacuten como el que vishymos en el capiacutetulo 10 para almacenar los datos de la conexioacuten

La variable $ u s u a r i o recoge la creacioacuten del objeto de conexioacuten y utiliza el meacutetodo c o n s u l t a () para recuperar el nombre de los usuarios de nuesshytra Web

Para extraer todos los datos nos encontramos con un bucle que va recupeshyrando un arraxj por registro almacenaacutendolo en $f i l a

Utilizando f o r e a c h podemos extraer todas las columnas de la fila indishycada

La figura 121 presenta el resultado del script

Manipulacioacuten de datos

Seleccionar datos de una base de datos es soacutelo el principio la potencia de SQL nos permite tambieacuten insertar actualizar y borrar filas de una tabla Con el objeto que hemos creado es muy sencillo hacer consultas del tipo INSERT UPDATE o DELETE llamando al meacutetodo c o n s u l t a ()

Insertar una fila

Para insertar una fila con nuestro objeto tendremos que definir la consulshyta y ejecutar el meacutetodo c o n s u l t a ()

ltphp require_once(MySQLphp) $servidor = localhost -$usuario = root $pass = $base_datos = Compras $insertar = INSERT INTO Usuario (nombrecuenta) VALUacuteES (Cristina2119) $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) ^usuario-gtconsuIta($insertar) gt

PHP 5 y MySQL 225

Actualizar una fila

Antes de actualizar una fila necesita identificar la fila o filas de la tabla que quiere cambiar En este ejemplo se ha utilizado una sentencia SE-LECT para averiguar primero el valor id_usuar io de Luis Miguel y desshypueacutes proceder a cambiar su cuenta bancaria

ltphp require_once(MySQLphp) $serviacutedor = localhost $usuario = root $pass = $base_datos = Compras $consulta = SELECT id_usuario FROM Usuario WHERE nombre=Luis Miguel $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $id_usuario = $fila[id_usuario] $actualizar = UPDATE Usuario SET cuenta=9999 WHERE id_usuario=$id_usuario $usuario-gtconsulta($actualizar) gt

En un caso praacutectico UPDATE puede utilizarse para modificar los datos introducidos en un formulario Web

Borrar una fila

Para borrar una fila puede seguir el mismo camino que se ha utilizado antes para actualizar Primero averiguumle el registro que quiere eliminar y despueacutes ejecute la consulta con la sentencia DELETE

ltphp require_once(MySQLphp) $servidor = localhost usuario = luis $pass = secreto $base_datos = Compras $consulta = SELECT id_usuario FROM Usuario WHERE nombre=Luis Miguel $usuario = new Servidor_Base_Datos$servidor$usuario$pass$base_datos) $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $id_usuario = $fila[id_usuario ]

226 Capiacutetulo 12

$borrar = DELETE FROM Usuario WHERE id_usuario = 1$id_usuario $usuario-gtconsulta($borrar) gt

Errores con las comillas

Examinemos ahora el coacutedigo siguiente ltPHP require_once(MySQLphp) if (isset ($_POST[nombre] ) ]| isset ($_POST[cuenta ]) )

$servidor = localhost $usuario = root $pass = $base_datos = Compras $nombre = $_POST[nombre ] $cuenta = $_POST[cuenta] $usuario = new Servidor_Base_Datos($servidor$usuario $pass$base_datos) $insertar = INSERT INTO Usuario(nombrecuenta) VALUacuteES ($nombre$cuenta) $usuario-gtconsulta ($insertar)

gt ltHTMLgt ltBODYgt ltform action=formulario_Usuario php method=POSTgt Nombre ltINPUT type=text name=nombregtltbrgt Cuenta ltINPUT type=text name=cuentagtltbrgt ltinput type=submit name=Enviar gt ltformgt ltBODYgt ltHTMLgt

El pequentildeo formulario que muestra la figura 122 permite insertar en la tabla Usuario nuevos clientes Los campos de texto que recogen el nombre y la cuenta pueden recibir cualquier tipo de caraacutecter hay ciertos siacutembolos que pueden provocar que un programa falle y son utilizados malintencionadamente por hackers para corromper el sistema Si en la casilla destinada a escribir el nombre escribe un nombre y en medio una comilla simple y otra doble tal y como muestra el ejemplo

Luis Migue1 Cabezas Granado

PHP 5 y MySQL 227

El meacutetodo c o n s u l t a () intentaraacute ejecutar

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Migue1 Cabezas Granado))

iquestPuede ver el problema Cuando MySQL lee la sentencia cree que es

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Migue

El resto de la sentencia causaraacute un error y fallaraacute la consulta La solucioacuten es antildeadir el siacutembolo de escape delante de la comilla simple para que MySQL tome el siacutembolo como un simple caraacutecter

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Miguel Cabezas Granado))

Existen tres soluciones para antildeadir el siacutembolo de escape a todas las comishyllas que aparezcan en campo de texto

bull Lo primero que puede hacer es configurar el archivo phpini activanshydo la opcioacuten m a g i c _ q u o t e s _ g p c Con esta opcioacuten a todos los datos pasados entre paacuteginas Web por los meacutetodos GET y POST se les inserta automaacuteticamente siacutembolos de escape en las comillas que aparezcan

bull Si m a g i c _ q u o t e s no estaacute activo en su servidor PHP 5 tiene la funshycioacuten a d d s l a s h e s ( ) que tiene el mismo cometido que la opcioacuten anshyterior Si m a g i c _ q u o t e s estaacute activo no podraacute utilizar esta funcioacuten porque se antildeadiriacutean dos siacutembolos de escape

228 Capiacutetulo 12

bull El tercer camino muy similar a a d d s l a s h e s usa la funcioacuten m y s q l _ e s c a p e _ s t r i n g Esta funcioacuten antildeade siacutembolo de escape a las comillas simples comillas dobles caracteres de final de fichero y reshytorno de carro Es un meacutetodo implementado por MySQL por eso es maacutes recomendable utilizar a d d s l a s h e s

Para saber si el fichero phpini tiene activado m a g i c _ q u o t e s existe la funcioacuten g e t _ m a g i c _ q u o t e s _ g p c ( ) Puede antildeadir algunas liacuteneas de coacutedigo a su formulario para que controle este tipo de error de la siguiente forma

ltphp require_once(MySQLphp) if (isset($_POST[nombre]) || isset($_POST[cuenta ]))

$servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras if (get_magic_quotes_gpc())

$nombre = $_POST[nombre] $cuenta = $__POST [cuenta ]

else $nombre = addslashes($_POST[nombre]) $cuenta = addslashes($_POST[cuenta])

$usuario = new Servidor_Base_Datos($servidor$usuario $pass$base_datos) $insertar = INSERT INTO Usuario(nombrecuenta) VALUacuteES ($nombre$cuenta ) $usuario-gtconsulta($insertar)

gt

Contando filas

A menudo es uacutetil conocer el nuacutemero de filas devueltas por una consulta antes de hacer cualquier cosa con el resultado Puede averiguar el nuacutemeshyro de filas mediante el uso de alguna funcioacuten de PHP o la utilizacioacuten de MySQL para obtener el nuacutemero de registros

Contar filas con PHP

La funcioacuten mysql_num_rows () devuelve el nuacutemero de filas seleccioshynadas

PHP 5 y MySQL 229

Su uso puede ampliar el objeto de bases de datos

public function numero_filas()

return mysql_num_rows($this-gtresultado)

Ademaacutes de esta funcioacuten tenemos mysql_num_f i e l d s ( ) que devuelve el nuacutemero de campos del una tabla es necesaria cuando hacemos una conshysulta de datos y no sabemos cuaacutentas columnas hemos seleccionado

Contar filas con MySQL

La alternativa es utilizar una consulta de SQL con la sentencia c o u n t ( ) Esto requiere hacer dos consultas una para obtener el nuacutemero de filas y otra para obtener el resultado

Utilicemos el objeto para realizar la operacioacuten

ltphp

require_once(MySQLphp) $servidor = localhost $usuario = root $pass = $base_datos = Compras $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $consulta = select count() as numero_filas from Usuario $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $numero_filas = $fila[numero_filas] $consulta = select from Usuario $usuario-gtconsulta($consulta) echo El nuacutemero de filas es $numero__f ilasltbrgt while ($fila = $usuario-gtextraer_registro())

foreach ($fila as $indice =gt $valor) echo $indice $valorltbrgt

gt

La primera sentencia SELECT cuenta el nuacutemero de filas y al resultado le da el nombre numero__f i l a s

Para acceder al nuacutemero se hace como siempre leyendo el resultado del irray $f i l a [ numero_f i l a s ]

La figura 123 muestra el resultado

Contar filas afectadas

Es posible que sea necesario saber cuaacutentas filas han sido afectadas desshypueacutes de antildeadir actualizar o borrar algunas filas

La funcioacuten m y s q l _ a f f e c t e d _ r o w s () devuelve el nuacutemero de registros afectados despueacutes de un cambio en las filas de una tabla Actualizando nuestra clase tenemos

public function filas_afectadas()

return mysql_affected_rows($this-gtdescriptor)

Uacuteltimo nuacutemero insertado

Cuando utilice campos auto numeacutericos en una tabla e inserte un nuevo registro seraacute uacutetil conocer el nuacutemero de la uacuteltima fila insertada

Para obtener este nuacutemero tan solo t iene que u t i l izar la funcioacuten m y s q l _ i n s e r t _ i d ( ) Se puede utilizar de la siguiente forma

public function ultima_fila()

PHP 5 y MySQL 231

return mysql_insert_id($this-gtdescriptor)

Buacutesquedas dentro de una tabla

La forma de buscar ocurrencias en una columna es utilizar la sentencia LIKE de SQL

SELECT FROM Usuario WHERE nombre LIKE Luis

El siacutembolo es un comodiacuten es decir puede sustituir a cualquier caraacutecter dentro de la columna donde busque

Definicioacuten de bases de datos

Como indicamos antes lo ideal es que un administrador de MySQL le genere las bases de datos y las tablas Despueacutes de esto con su usuario y contrasentildea podraacute hacer las consultas que tenga autorizadas

En muchos casos la figura del administrador de bases de datos no existe y es el desarrollador el que asume este papel En este caso le interesaraacute conocer la forma de crear desde un script sus bases de datos

Creacioacuten de bases de datos

Para crear una base de datos tiene que utilizar la funcioacuten m y s q l _ c r e a t e _ db () Recibe dos paraacutemetros el primero es el nombre de la base de datos que quiere crear y el segundo el descriptor devuelto por la funcioacuten m y s q _ c o n n e c t () La funcioacuten m y s q l _ d r o p _ d b () borra la base de dashytos del gestor de MySQL

ltphp $descriptor = mysq_connect($servidor $usuario $clave) mysql_create_db(Nueva_Base $descriptor) gt

Creacioacuten de tablas

La creacioacuten de tablas debe hacerse a traveacutes del lenguaje de consultas SQL como vimos en el capiacutetulo anterior Como ya sabe la funcioacuten m y s q l _

232 Capiacutetulo 12

q u e r y () acepta consultas de distintos tipos Aprovechando esto puede incluir una consulta para crear una tabla nueva

SQLite es una base de datos poco tipada es decir que soacutelo es capaz de almacenar dos tipos de datos nuacutemeros o caracteres En cambio MySQL es fuertemente tipada porque tiene un elevado conjunto de tipos para aplicar a sus columnas La tabla 121 muestra algunos tipos de datos que puede aplicar en la sentencia CREacuteATE

Tabla 121 Tipos de datos de MySQL

Nombre Tamantildeo Uso

BIT BOOLEAN 1 byte Almacena valores desde 0 a 255 sin

signo o -128 a 127 con signo SMALLINT 2 bytes De 0 a 65535 sin signo y de -32768 a

32767 con signo

MEDIUMINT 3 bytes De 0 a 16777215 sin signo o-8388608 a 8388607

INT INTEGER 4 bytes De0a4294967295ode-2147483648a 2147483647

BIGINT 8 bytes De 0 a 18446744073709551615 o -9223372036854775808a 9223372036854775807

FLOAT(precisioacuten) De 4 a Nuacutemero de coma flotante con precisioacuten

8 bytes

DATE 3 bytes Almacena una fecha

DATETIME 8 bytes Almacena una fecha con la hora y minutos

VARCHAR(nuacutemero) Nuacutemero Almacena tantos caracteres como indi-bytes ca el nuacutemero El tamantildeo es menor que

255 caracteres

TINYBLOB TINYTEXT Mayor que Almacena caracteres 255 bytes

BLOB TEXT Maacutes de Almacena un nuacutemero elevado de carac-64 kb teres

Como ejemplo puede ver el siguiente coacutedigo

lt $descriptor = mysq_connect($servidor $usuario $clave) mysql_create_db(Concesionario $descriptor) mysql_ select_db ( Concesionario) -

PHP 5 y MySQL 233

$consulta = CREacuteATE TAELE vehiacuteculos ( Iacuted_vehicul0 INT NOT NULL AUTO_INCREMENT PRIMARY KEY color VARCHAR(25) fecha_compra DATETIME)

$resultado = mysql_query($consulta) $mensaje = mysql_drop_db(Concesionario) gt

La columna i d _ v e h i c u l o identifica a un uacutenico vehiacuteculo de la tabla Como puede ver en MySQL tiene que antildeadir algunos modificadores a la columshyna para identificar sus caracteriacutesticas Estos modificadores son obligatoshyrios en MySQL Por ejemplo en SQLite no hace falta antildeadir ninguna propiedad para que el valor se incremente automaacuteticamente En MySQL es necesario especificar la propiedad AUTO_lNCREMENT Es obligatorio ademaacutes que todas las columnas tengan un tipo de dato definido

Resumen

MySQL es sin duda el sistema maacutes utilizado a escala mundial La mayor parte de las aplicaciones en PHP estaacuten escritas para MySQL porque da una fiabilidad y velocidad absolutas Hay que decir tambieacuten que la vershysioacuten 4 tiene bastantes restricciones con respecto a otros gestores de bases de datos como PostgreSQL pero se iraacuten solventando en las futuras vershysiones

Si terminoacute el capiacutetulo con eacutexito todaviacutea le queda un paso por andar La extensioacuten de MySQL que hemos utilizado es la que viene por defecto funshycionando con PHP 5 Recientemente se ha creado desde cero una nueva forma de interactuar con MySQL que permite hacer transacciones o conshysultas almacenadas (de la forma que lo hace Oracle) La extensioacuten se llashyma MySQLi y por su leve dificultad se escapa del objetivo de este libro

En este capiacutetulo aprenderaacute a

bull Diferenciar entre sesiones cookies y cabeceras HTTP bull Utilizar sesiones para ocultar variables entre usuarios y paacuteginas Web bull Almacenar la configuracioacuten de un usuario con cookies

bull Enviar informacioacuten de cabecera viacutea Web

236 Capiacutetulo 13

Introduccioacuten

Una sesioacuten es un periacuteodo de tiempo durante el cuaacutel una persona detershyminada ve un nuacutemero de diferentes paacuteginas Web de un determinado doshyminio

El protocolo HTTP no tiene forma alguna de distinguir un usuario que se conecte desde Espantildea de otro que se conecte desde Japoacuten PHP 5 proshyvee un mecanismo que permite antildeadir cierto nivel de diferenciacioacuten enshytre usuarios

Miremos un ejemplo

ltHTMLgt ltBODYgt ltphp switch ($_GET[opcioacuten ] )

case 1 echo La opcioacuten es 1 break

case 2 echo La opcioacuten es 2 break

case 3 echo La opcioacuten es 3 break

gt ltBODYgt ltHTMLgt

Esta paacutegina elige una de las opciones en funcioacuten del paraacutemetro GET que obtenga Como ya sabe GET pasa todos los valores junto a la direccioacuten Web y es visible para nosotros

El meacutetodo GET no es muy funcional cuando necesite pasar datos comproshymetidos a traveacutes de varias paacuteginas Web POST resuelve en parte este proshyblema

Este meacutetodo permite pasar entre paacuteginas las variables que quiera queshydando ocultas para el usuario A priori parece una buena forma de oculshytar datos pero nos encontramos que es necesario un formulario en cada paacutegina para utilizarla

Las sesiones y las variables de sesioacuten permiten pasar datos entre paacuteginas sin necesidad de utilizar formularios y es la mejor forma para ocultar dashytos comprometidos

Sesiones y Cookies 237

Sesiones en PHP 5

Las sesiones deben soportar

bull Detectar que durante el transcurso de la navegacioacuten por varias paacutegishynas Web la sesioacuten permanece invariable

bull Almacenar informacioacuten que formaraacute parte de una sesioacuten en concreto

PHP trabaja con una combinacioacuten de meacutetodos que son capaces de ocultar variables y cookies de las que hablaremos en un apartado posterior

Instanciando sesiones

El primer paso que nuestro script debe realizar es la llamada a la funcioacuten s e s s i o n _ s t a r t () Esta funcioacuten registra una sesioacuten en el servidor y la identifica con una cadena de 32 caracteres Cada persona que entre en ese mismo instante en la Web desde un ordenador diferente obtendraacute un iden-tificador distinto

La funcioacuten s e s s i o n _ s t a r t () debe incluirse en todas las paacuteginas Web que formen parte de la aplicacioacuten porque no soacutelo se encarga de iniciali-zar la sesioacuten sino que tambieacuten se encarga de mantener la misma sesioacuten durante el proceso La funcioacuten actuacutea de la siguiente forma

bull Si no existe una sesioacuten activa crea una nueva con un identificador

bull Si existe una sesioacuten que puede ser recuperada se extrae la sesioacuten y las variables asociadas ltphp session_start() gt ltHTMLgt ltBODYgt ltphp echo La variable de sesioacuten es SID gt ltBODYgt ltHTMLgt

La figura 131 muestra la variable de sesioacuten En el momento en que elscript escribe cualquier cosa el servidor termina de enviar las cabeceras HTTP y empieza a enviar el contenido No se puede enviar una nueva cabecera cuando ya estamos enviando el cuerpo de la Web Puesto que la funcioacuten s e s s i o n _ s t a r t () utiliza cabeceras para pasar la informacioacuten de sesioacuten

Sesiones y Cookies 239

La primera vez que instanciamos una sesioacuten seacute crea una constante llamashyda S ID que contiene el identificador de 32 caracteres que nos identifica

Variables de sesioacuten

Existe una variable suacuteper-global que se encarga de almacenar las variashybles que quiere pasar entre paacuteginas de una sesioacuten El array $_SESSION permite almacenar datos de cualquier tipo para recuperarlos en otras paacuteshyginas que tengan la misma sesioacuten El coacutedigo para propagar variables de sesioacuten puede ser tan sencillo como la paacutegina s e s i o n l php

ltphp session_start () gt ltHTMLgt ltBODYgt ltphp $_SESSION[nombre] = Luis Miguel Caberas $_SESSION[edad] = 29 echo lta href = sesion2phpgtPasar variablesltagt gt ltBODYgt ltHTMLgt

La vatvabie suacutepex-^toacutebal almacena valores de d-feteate tupo y creamas UTJ enlace a la paacutegina s e s i o n 2 php para poder recuperarlos

ltphp session_start () gt ltHTMLgt ltBODYgt ltphp echo Mostrar las variables de sesioacutenltbiacutegt foreach ($_SESSION as $indice =gt $valor)

echo $indice $valorltbrgt

echo Mostrar las COOKIESltbrgt foreach ($_COOKIE as $indice =gt $valor)

echo $indice $valorltbrgt gt ltBODYgt ltHTMLgt

Si se apoya en el bucle foreach podraacute extraer todos los valores pasados desde la Web s e s i o n l php Como curiosidad hemos introducido un bucle que extrae las variables almacenadas en c o o k i e s y puede ver en

Nota

Como veremos maacutes adelante iexclas cookies son pequentildeos contenishydos que se almacenan en el ordenador local Las cookies son muy utilizadas por los servidores Web para guardar las preferencias de un usuario o alguacuten dato interesante En realidad son variables que se guardan en el ordenador local del usuario y pueden ser resshycatadas por PHP en alguna otra ocasioacuten en la que se necesite

Problemas con los navegadores

Un problema muy comuacuten es que el usuario tenga por razones de segurishydad desactivada la opcioacuten de permitir c o o k i e s en su navegador El proshyb lema es que el o rdenador local no va a aceptar nuestra variable PHPSESSID y todas las paacuteginas creeraacuten que no existe sesioacuten activa y no podraacuten recuperar las variables Se puede resolver con unas pocas liacuteneas de coacutedigo para la paacutegina s e s i o n l php

ltphp

Sesiones y Cookies 241

session_start() gt ltHTMLgt ltBODYgt ltphp $_SESSION[nombre] = Luis Miguel Cabezas $_SESSION[edad] = 29 $id_sesion = SID echo lta href=sesion2php$id_sesiongtPasar variablesltagt gt ltBODYgt ltHTMLgt

Esta forma de trabajar implica tener que pasar en todos los enlaces el iden-tificador de sesioacuten La forma correcta de hacerlo es la que muestra el ejemshyplo ya que produce una URL de este tipo s e s i o n 2 phpPHPSESSID = 9 0 9 7 c 4 3 a a 8 6 d 3 4 5 9 b l 6 6 d 7 1 c 4 e a 4 c 9 3 0

Nota

Si quiere que PHP sea transparente manejando el paso de variashybles a traveacutes de c o o k i e s o viacutea el meacutetodo GET necesita tener configurado PHP 5 con las directivas - e n a b l e - t r a n s - s i d y - e n a b l e - t r a c k - v a r s Si estas opciones no estaacuten activashydas el uacutenico traacutemite para utilizar variables es pasar mediante GET o POST el identificado de sesioacuten corno en el ejemplo anterior

Funciones para el manejo de sesiones

La tabla 131 muestra algunas funciones interesantes con la descripcioacuten de uso

Tabla 131 Funciones relacionadas con las sesiones

Funcioacuten Descripcioacuten

session_start() Inicia una sesioacuten y permite almacenar variables en la

estructura $ _ S E S S I O N

session_destroy() Elimina todas las variables de sesioacuten

session_name() Devuelve el nombre de la sesioacuten normalmente PHPSES-SID

session_id() Devuelve los 32 caracteres que forman el identificador de sesioacuten

242 Capiacutetulo 13

Con las funciones relacionadas en la tabla anterior podemos construir un objeto que nos facilite el manejo de sesiones en nuestras aplicaciones

ltphp class sesioacuten

function constructor()

session_start() public function set($nombre$valor)

$_SESSION[$nombre] = $valor public function get($nombre)

if (isset ($_SESSION[$nombre] ) ) return $_SESSION[$nombre]

else return false

public function borrar_variable($nombre)

unset ($_SESSION[$nombre] ) public function borrarsesiacuteon()

$_SESSION = a r r a y O s e s s i o n _ d e s t r o y ( )

gt

Las paacuteginas s e s i o n l php y s e s i o n 2 php pueden manejarse ahora con la clase que hemos creado de la siguiente forma

ltphp require_once (clase__sesion php) $sesioacuten = new sesioacuten() gt ltHTMLgt ltBODYgt ltphp $sesioacuten-gtset(nombreLuis Miguel Cabezas) $sesioacuten-gtset(edad29) $id_sesion = SID echo lta href=sesion2php$id_sesiongtPasar variablesltagt gt ltBODYgt ltHTMLgt

Sesiones y Cookies 243

Cookies

Una cookie es una pequentildea parte de informacioacuten que queda almacenashyda en el ordenador local de los usuarios de una paacutegina Web Debe conteshyner siempre un nombre y un valor Es muy usual utilizar cookies para guardar preferencias de cada usuario en el uso de una Web pero hay que tener cuidado con el nuacutemero de variables que se pueden almacenar pues norshymalmente hay un maacuteximo de 20 por dominio seguacuten el navegador

En PHP 5 la funcioacuten s e t c o o k i e () se encarga de registrar las cookies durante el enviacuteo de las cabeceras Para recuperar el valor tiene que utilizar la variable suacuteper-global $_COOKIE

setcookie()

La funcioacuten s e t c o o k i e () normalmente tiene 2 argumentos el nombre de la variable y el valor Ademaacutes podemos pasar varios paraacutemetros que permiten dar un tiempo de vida a las variables asociar un dominio o aseshygurar el enviacuteo mediante HTTPS

La tabla 132 muestra en orden todos los argumentos que puede recibir una cookie

Tabla 132 Argumentos de la funcioacuten setcookie()

Argumento Tipo Descripcioacuten -

nombre caraacutecter El nombre de la variable cookie valor caraacutecter El valor que debe almacenar la variable Si este

valor no se indica la cookie seraacute automaacuteticashymente borrada

tiempo de vida entero Indica el tiempo de vida de unacookie Si el valor es 0 la variable nunca expiraraacute Si indica un nuacutemero entero tendraacute el tiempo que la variable permaneceraacute activa El valor hay que asignarlo en tiempo absoluto (como el devuelto por la funcioacuten mkt ime ())

ruta entero Permite distinguir entre dos variables con el mismo nombre pero llamadas desde distinta ruta en el servidor La cookie nombre llamada desde la ruta fo ro seraacute distinta a la cookie nombre llamada desde la ruta usuario

244 Capiacutetulo 13

Argumento Tipo Descripcioacuten

dominio caraacutecter Asegura el dominio de servidor que puede leerla cookie

Secure entero (0 Si el argumento es 1 la cookie soacutelo seraacute enviada oacute 1) a traveacutes de una conexioacuten segura HTTPS

Borrar una cookie

Borrar una cookie es faacutecil Si llama a la funcioacuten s e t c o o k i e () con los misshymos argumentos que para habilitarla excepto el valor la variable se elimishynaraacute del sistema local del usuario Si usa los paraacutemetros r u t a y dominio deben aparecer tambieacuten y con los mismos valores

Como de costumbre vamos a implementar una pequentildea clase para maneshyjar las cookies

ltphp

class Cookie

function constructor()

El constructor no hace nada

public function set($nombre$valor$expire=0$ruta= $dominio=$seguro=0)

setcookie($nombre$valor$expire$ruta$dominio$seguro)

public function get($nombre)

if (isset ($_COOKIE [$nombre] )) return $_COOKIE[$nombre] else return false

public function borrar_cookie($nombre)

setcookie($nombre$valor$expire$ruta$dominio$seguro

gt

El argumento tiempo de vida debe proporcionarse en valor de tiempo absoluto Esto a veces puede resultar incoacutemodo y seriacutea maacutes sencillo pro-

Sesiones y Cookies 245

porcionar el tiempo de vida de la variable en minutos o segundos La clase anterior solicita el tiempo en segundos y se encarga de antildeadir esos segundos al valor absoluto haciendo maacutes simple la asignacioacuten

Para ver coacutemo funciona podemos utilizar la Web c o o k i e l php

ltphp require_once(clase_cookiephp) $cookie = new CookieO $cookie-gtset(nombreLuis Miguel10) gt ltHTMLgt ltBODYgt ltphp echo La COOKIE es $cookie-gtget(nombre) echo lta href = cookie2phpgtPasar variablesltagt gt ltBODYgt ltHTMLgt

Como puede ver es muy sencilla la asignacioacuten de cookies y su recupeshyracioacuten

Cabeceras HTTP

Las funciones s e t c o o k iacute e () o s e s s i o n _ s t a r t () introducen su conteshynido en una cabecera HTTP sin necesidad de especificacioacuten por el usuashyrio Es posible enviar cabeceras desde PHP con la utilizacioacuten de la funcioacuten h e a d e r () La funcioacuten h e a d e r () es muy simple tan soacutelo toma como arshygumento un conjunto de caracteres que seraacute la cabecera a enviar Por ejemshyplo una forma muy uacutetil de redirigir una paacutegina a otra es utilizando la cabecera Location

lt php if (isset($_GET[usuario] ) ampamp $_GET[usuario] == Luis)

header(Location httpwwwluisyfernandanet)

gt lthtmlgt ltbodygt Si ve esta paacutegina su nombre no es Luis ltbodygt lthtmlgt

Este script evaluacutea si en la variable suacuteper-global $_GET existe un identifi-cador llamado u s u a r i o y si su valor es L u i s En caso afirmativo se enviacutea

246 Capiacutetulo 13

la cabecera al navegador que invita a cargar la Web especificada En caso negativo se enviacutea la paacutegina Web que hay despueacutes de la estructura if

Este tipo de uso de las cabeceras puede servir para redireccionar a una paacutegina de error cuando un usuario intente entrar sin permiso o cometa un fallo en la entrada de un nombre o correo electroacutenico

Resumen

Las sesiones resuelven los problemas muy comunes de seguridad El uso conjunto de sesiones cookies y cabeceras HTTP permiten un control absoshyluto sobre las variables de la aplicacioacuten Casi todos los programas que necesitan autentificar un usuario (como una tienda on-line) se sirven de estas teacutecnicas Pero el lector no debe quedarse aquiacute hay muchas cabeceras distintas que pueden ser uacutetiles en diferentes momentos como la autenticacioacuten viacutea HTTP

248 Capiacutetulo 14

Introduccioacuten

XML (Lenguaje de Marcas eXtensible) forma parte de SGML (Lenguaje de Marcas Generalizado eStandar) Auacuten asiacute no es necesario saber nada de SGML para utilizar XML El lenguaje XML define una estructura de documentos que pueden ser leiacutedos por personas y por ordenadores

El camino maacutes sencillo para comprender XML es pensar en coacutemo se utilishyzan los documentos HTML Estos documentos estaacuten estructurados y funshycionan con etiquetas y atributos Las etiquetas van encerradas entre siacutembolos de mayor y menor (ltbgt) y deben cerrarse de la misma forma antildeadiendo un siacutembolo de barra invertida (ltbgt) Los documentos HTML tienen una ortografiacutea especiacutefica es decir unas reglas que definen la forshyma correcta de estructurar un documento por ejemplo la etiqueta ltBODYgt debe ir siempre despueacutes de ltHEADgt o s ino existe eacutesta de ltHTMLgt Adeshymaacutes HTML contiene un diccionario cerrado de etiquetas que definen el lenguaje y no podemos utilizar otras que no esteacuten especificadas

En cambio XML no tiene un diccionario de etiquetas Las etiquetas que aparecen son las que nosotros mismos creamos La uacutenica norma que teneshymos que seguir es que toda etiqueta de inicio (ltcoche gt) debe tener una etiqueta de fin ( lt c o c h e gt )

El documento siguiente muestra un archivo XML bien formado

ltxml version=10 gt ltbibliotecagt lttema id=informaacuteticagt

ltlibrogt lttitulogtManual Imprescindible de PHP 5lttitulogt ltautorgtLuis Miguel Cabezas Granadoltautorgt

ltlibrogt ltlibrogt

lttitulogtDelphi 7lttitulogt ltautorgtMarco Cantultautorgt

ltlibrogt ltlibrogt

lttitulogtDelphi 6 y Kylixlttitulogt ltautorgtFrancisco Charte Ojedaltautorgt

ltlibrogt lttemagt

ltbibliotecagt

Como puede ver la estructura del documento es muy similar a la de una paacutegina Web Estaacute formado por etiquetas y atributos cuya definicioacuten pueshyde inventarse sobre la marcha es decir las etiquetas lt l i b r o gt lt t i t u -

Lectura y escritura de archivos XML 249

l o gt o lt s e c c i o n gt podriacutean tener un nombre totalmente diferente pero no asiacute en HTML que estaacute obligado a mantener el lenguaje definido Algushynos navegadores como Mozilla interpretan los ficheros XML como en la figura 141

Un documento XML estaacute obligado a cumplir ciertas normas que permishyten definir un texto bien formado

bull Debe tener un uacutenico elemento raiacutez Soacutelo puede haber un par de etishyquetas que diferencien el inicio y el final del documento como en HTML donde se utiliza ltHTMLgt y lt HTMLgt

bull Los elementos deben ser hereditarios La estructura lt A x B x B gt lt Agt se permite pero no la siguiente lt A x B x A x B gt En la primera forma la etiqueta ltAgt envuelve a la etiqueta ltBgt que es la forma coshyrrecta de escribir un documento XML HTML sin embargo permite la segunda forma de componer un documento ltA HREF=indexphpgt ltBxAx Bgt

bull Todos los elementos tienen que tener una etiqueta de cierre La pareja ltt i tulogtltt i tulo es correcta HTML permite etiquetas sin cerrar como ltBgt o ltLIgt

bull Los elementos pueden tener entre las dos etiquetas cualquier tipo de contenido como lttitulogtManual imprescindible de PHP 5lttitulogt

250 Capiacutetulo 14

bull Los caracteres amp lt gt las comillas simples y las comillas dobles estaacuten prohibidas como contenido y deben utilizarse siacutembolos de escape para utilizarlas

SAX DOM y SimpleXML

Lo primero que tenemos que hacer antes de leer archivos XML es conocer las tres formas existentes con sus ventajas e inconvenientes

bull SAX Es maacutes ligero y faacutecil de aprender trata los archivos XML como un flujo de datos que se leen poco a poco

bull DOM Lee el fichero completo y crea un objeto en memoria Permite crear archivos desde cero

bull SimpleXML Es el maacutes sencillo de utilizar Los elementos se pueden leer con un simple f o r e a c h

SAX

Se utiliza para parsear elementos XML Estaacute basado en eventos lo que sigshynifica que el parse hace llamadas a determinadas funciones dependiendo de los elementos que examina

Los eventos de SAX son proporcionados por PHP en forma de funcioacuten Al parsear se reconocen piezas de XML como etiquetas de inicio o fin datos o entidades externas y cada una de estas piezas hace una llamada a un evento El procedimiento para parsear un archivo XML con SAX debe seshyguir los siguientes pasos

bull Determinar queacute clase de eventos queremos manejar

bull Escribir una funcioacuten que maneje cada evento Es muy comuacuten escribir una funcioacuten para manejar los datos y las etiquetas de inicio y de fin

bull Crear el parse usando la funcioacuten x m l _ p a r s e r _ c r e a t e () y hacer la llamada con x m l _ p a r s e ()

bull Liberar la memoria usada con la funcioacuten x m l _ p a r s e r _ f r e e ( )

Hemos creado un objeto para leer archivos XML En principio no hace gran cosa tan solo examina las etiquetas de inicio y fin y las imprime en pantalla pero con esto bastaraacute para aprender la peculiar estructura de un parse SAX

ltphp

Lectura y escritura de archivos XML 251

class xml

function construct($fichero_xml)

$this-gtfichero_xml = $fichero_xml $this-gtxml_parser=xml_parser_create()

Puesto que el parse lo creamos desde un objeto debemos registrar la incidencia con xml_set_object

xml_set_obj ect($this~ gtxml_parser$this) Funciones de callback para manejar XML mediante SAX

xml_set_element_handler($this-gtxml_parserelemento_ inicioelemento_fin) if (($fp = fopen($this-gtfichero_xmlr)))

die (Error de Entrada y Salida)

while ($datos = fread($fpfilesize($this-gtfichero_xml)))

if (xml_parse($this-gtxml_parser$datos feof($fp)))

die (Fallo en el XML) xml_error_string(xml_get_error_ code($this-gtxml_parser))

xml_parser_free($this-gtxml_parser)

function elemento_inicio ($parser$nombre$atributos)

echo $nombreltbrgt

function elemento_fin ( $parser$nombre)

echo $nombreltbrgt

$biblioteca = new xml(bibliotecaxml) gt

Si guarda la clase en un archivo llamado c l a s e _ x m l php podraacute usarla en sus proyectos tan soacutelo con instanciar el objeto Si comienza por el consshytructor veraacute que el paraacutemetro que recibe es el archivo que quiere par-sear Debe crear el parse con la f u n c i oacute n x m l _ p a r s e _ c r e a t e () y despueacutes registrarlo en PHP como un objeto mediante la funcioacuten x m l _ s e t _ o b -j e c t () Si crea un parse fuera de la estructura de un objeto no haraacute falta hacer la llamada a la funcioacuten anterior

252 Capiacutetulo 14

La funcioacuten x m l _ s e t _ h a n d l e r () indica al parse que los eventos encarshygados de encontrar las etiquetas de inicio y de fin seraacuten manejadas con las funciones que se pasan como paraacutemetro En este c a s o e l e m e n t o _ i n i c i o ( ) se ejecutaraacute cada vez que se encuentre una etiqueta de inicio y e l e m e n t o _ f in ) cuando se encuentre la etiqueta de cierre

La uacuteltima parte del constructor lee el archivo pasado como argumento y analiza los datos a traveacutes de la funcioacuten x m l _ p a r s e ( ) que inicia la seshycuencia de anaacutelisis Si ejecuta una instancia de la clase comprobaraacute que el navegador muestra todas las etiquetas de inicio y de fin con una rigurosa herencia La figura 142 muestra las etiquetas leiacutedas del archivo XML

Para poder ver los datos tiene que antildeadir una nueva funcioacuten que maneje ese evento La f u n c i oacute n x m l _ s e t _ c h a r a c t e r _ d a t a _ _ h a n d l e r () permite manejar el evento que se dispara cada vez que se encuentra un dato entre dos etiquetas Esta funcioacuten tendraacute que antildeadirla al constructor despueacutes del meacutetodo que maneja los eventos de etiquetas

xml_set_character_data_handler($this-gtxml_parserdatos)

Ademaacutes de esto tendraacute que incluir una nueva funcioacuten que se encargaraacute de mostrar los datos

function datos($parser$valor)

Lectura y escritura de archivos XML 253

echo $v9lorltbrgt

Nota

Los eventos antildeadidos deben iexcllevar Jos argumentos necesarios para recuperar los datos Cada vez que cree un par se del tipo SAX las funciones tienen que tener los paraacutemetros que indicamos en nuesshytra clase de ejemplo

Despueacutes de comprobar el funcionamiento de la clase puede modificarla para que haga algo realmente uacutetil como mostrar ordenadamente los dashytos del fichero Las funciones de la clase pueden quedar de esta forma

function elemento_inicio ($parser$nombre$atributos)

switch($nombre) case TEMA

$tema = $atributos [ ID ] bull echo Tema $temaltbrgt break

case TITULO echo ltbgt break

case AUTOR echo - break

function elemento_fin ($parser$nombre)

switch($nombre) case TITULO

echo ltbgt break

case AUTOR echo ltbrgt break

function datos($parser$valor)

echo $valor

En este caso el parser iraacute analizando las etiquetas que nos interesan y reashylizaraacute una accioacuten determinada Por ejemplo cuando se comprueba la exis-

254 Capiacutetulo 14

tencia de una etiqueta TITULO escribimos en HTML la etiqueta de negrishyta ltBgt para resaltar este dato como muestra la figura 143

Elaborando un poco maacutes la clase obtendraacute un objeto de gran utilidad que podraacute recuperar informacioacuten de bases de datos o archivos de configurashycioacuten

DOM

Esta API define un completo camino para crear definir y parsear archivos XML D O M es una recomendacioacuten del consorcio World Wide Web

La idea baacutesica consiste en que todos los archivos XML pueden verse como un conjunto de nodos que forman parte de un aacuterbol Empezando desde el elemento raiacutez del que todos los elementos nacen como hijos cualquier programa deberiacutea ser capaz de crear una estructura loacutegica del documento

La API puede utilizarse para leer archivos en memoria modificarlos y volver a escribir el archivo con los nuevos datos

DOM estaacute escrito en metodologiacutea orientada a objetos y todos los nodos son instancias de diferentes objetos

Lectura y escritura de archivos XML 255

Usar DOM para leer archivos

El siguiente coacutedigo muestra un archivo XML muy simple

ltxml version=l0 gt lttema id=informaacuteticagt

lttitulogtManual Imprescindible de PHP 5lttitulogt lttemagt

Si parseamos este documento con DOM la etiqueta t i t u l o seraacute consideshyrada un nodo y ademaacutes un hijo del nodo raiacutez que en este caso es tema Esta parte queda maacutes o menos clara debido a la jerarquiacutea de etiquetas que tiene XML La controversia llega con el texto que hay en el nodo tema que no se considera como una parte sino como un nodo independiente cuyo valor es el texto Manual I m p r e s c i n d i b l e de PHP 5 Este nodo permite recuperar el valor con el meacutetodo n o d e V a l u e

Vamos a ver los pasos necesarios para leer el archivo b i b l i o t e c a xml ya que difiere bastante la metodologiacutea con respecto a SAX

Todo es un objeto

PHP 5 implementa una clase DOM para representar los archivos XML llashymada domDocument Como ya sabe para instanciar la clase soacutelo tiene que hacer uso del operador de objetos

$biblioteca = new domDocument

La extensioacuten D O M sigue las especificaciones de XML y trata los espacios en blanco como contenido Esto significa que si entre dos etiquetas existe un espacio el contenido seraacute tratado como un objeto de texto Para evitar fallos de este tipo puede ejecutar el siguiente meacutetodo

preserveWhiteSpace = f a l s e

Lo siguiente que tendraacute que hacer es leer el archivo b i b l i o t e c a xml con el meacutetodo l o a d () del objeto $ b i b l i o t e c a Si el contenido XML se almacena en una variable puede utilizar el meacutetodo loadXML ()

$biblioteca-gtload(bibliotecaxml)

A partir de aquiacute ya puede recuperar el contenido del fichero atendienshydo a sus preferencias En SAX teniacutea que leer el documento completo e ir preguntando etiqueta por etiqueta para averiguar todos los autores que estaban dados de alta en el archivo XML En D O M puede recupeshyrar esta informacioacuten usando g e t E l e m e n t s B y T a g n a m e () que devuelshyve un conjunto de objetos que coinciden con la etiqueta que pase como paraacutemetro

256 Capiacutetulo 14

ltphp Instanciamos el objeto $biblioteca = new domdocument Anulamos la posibilidad de que un espacio en blanco sea un obj eto $biblioteca-gtpreserveWhiteSpace = false Leemos el archivo XML $biblioteca-gtload(bibliotecaxml) Buscamos todas las etiquetas libro $libros = $biblioteca-gtgetElementsByTagname(libro) Imprimimos todos los libros foreach ($libros as $libro)

echo $libro-gtfirstChild-gtnodeVaiue ltbrgt

gt

La variable $ l i b r o s es en realidad un objeto de la clase d o m n o d e l i s t y guarda una relacioacuten de nodos cuya etiqueta es l i b r o es decir hemos seleccionado todos los libros del archivo Con un bucle f o r e a c h podeshymos sacar todos los valores Antes vimos que el texto asociado a un nodo es un nodo hijo con un valor determinado por eso debe llamar al meacutetodo f i r s t C h i l d

El hijo de la etiqueta l i b r o es el texto asociado y su valor lo podemos recibir llamando a n o d e V a l u e

El resultado es la lista de libros

Manual Imprescindible de PHP 5 Delphi 7 Delphi 6 y K y l i x

Atributos

Para recuperar los atributos de los nodos estaacute el meacutetodo g e t A t t r i b u -te ( ) al que tiene que pasar como argumento el nombre del atributo El archivo b i b l i o t e c a xml tiene una uacutenica etiqueta con el atributo id pero nos sirve para mostrar coacutemo funciona el meacutetodo

ltphp $biblioteca = new domdocument -$biblioteca-gtpreserveWhiteSpace = false $biblioteca-gtload(bibliotecaxml) $temas = $biblioteca-gtgetElementsByTagname(tema) foreach ($temas as $tema)

echo $tema-gtgetAttribute(id)

gt

El resultado es el nombre del tema o temas que esteacuten almacenados

Lectura y escritura de archivos XML 257

Buacutesquedas muacuteltiples

Nuestro objetivo final es mostrar todos los tiacutetulos con sus autores ordeshynados por temaacutetica Conociendo ya los meacutetodos principales para recorrer los objetos DOM es sencillo pensar en un coacutedigo que implemente lo que pedimos

ltphp $biblioteca = new domdocument Sbiblioteca-gtpreserveWhiteSpace = false $biblioteca-gtload(bibliotecaxml) $biblioteca-gtdocumentElement $temas = $biblioteca-gtgetElementsByTagname(tema)bull foreach ($temas as $tema)

echo Tema $tema-gtgetAttribute(id) ltbrgt $libros = $tema-gtgetElementsByTagname(libro) foreach ($libros as $libro)

echo ltbgt $libro-gtfirstChild-gtnodeValue ltbgt - $autores = $libro-gtgetElementsByTagname(autor) foreach ($autores as $autor)

echo $autor-gtfirstChild-gtnodeValue ltbrgt

gt

Aunque es un poco maacutes complejo el fundamento baacutesico es ir utilizando bucles para leer los hijos de un nodo determinado hasta recuperar todos los datos necesarios

Escribir archivos XML con DOM

D O M permite hacer maacutes cosas que la simple impresioacuten de los datos en pantalla Se puede utilizar para crear nuevos documentos con el nivel de jerarquiacutea que quiera Para hacer esto debe apoyarse en la creacioacuten de obshyjetos de la clase domElement ()

Vamos a crear un script para crear el siguiente archivo XML ltxml ve r s ion=1 0gt lt b i b l i o t e c a gt

lttemagtTextolttemagt lt b i b l i o t e c a gt

Para crearlo necesita instanciar una serie de objetos que empieza por la creacioacuten de un documento DOM mediante la utilizacioacuten del objeto d o shymdocument ()

ltphp

258 Capiacutetulo 14

$biblioteca = new doradocument(10) $raiz = new domelement(biblioteca) $raiz = $biblioteca-gtappendChild($raiz) $tema = new domelement(temaTexto) $tema = $raiz-gtappendChild($tema) $biblioteca-gtsave(bibliotecaxml) gt

La variable $ r a i z es el objeto que contendraacute todo el documento Para crear las etiquetas tiene que utilizar el meacutetodo a p p e n d C h i l d ( ) El objeto que llama al meacutetodo contendraacute como hijo al elemento que se pasa como paraacuteshymetro

Si se fija en el ejemplo $tema es un nuevo elemento que tendraacute la etiqueshyta tema

Para que $tema sea un hijo de la raiacutez debe hacer que el objeto padre $ r a i z llame al meacutetodo a p p e n d C h i l d () con el paraacutemetro $tema

Para grabar el resultado final el objeto D O M tiene que llamar al meacutetodo s a v e ( ) El fichero b i b l i o t e c a xml lo puede crear con el coacutedigo sishyguiente

ltphp $biblioteca = new domdocument(10) $raiz = new domelement(biblioteca) $raiz = $biblioteca-gtappendChild($raiz) $tema = new domelement(tema) $tema = $raiz-gtappendChild($tema) $tema-gtsetAttribute(idinformaacutetica) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloManual Imprescindible de PHP 5 bull $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autor Luis Miguel Cabezas Granado) $autor = $libro-gtappendChild($autor) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloDelphi 7 ) $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autorMarco Cantu) $autor = $libro-gtappendChild($autor) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloDelphi 6 y Kylix) $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autor Francisco Charte Ojeda) $autor = $libro-gtappendChild($autor) $biblioteca-gtsave(bibliotecaxml) gt

Lectura y escritura de archivos XML 259

El conjunto de liacuteneas de coacutedigo anterior crea un archivo completo XML Quizaacute sea mejor dividir el texto en funciones recursivas que permitan teshyclear menos a la hora de crear los documentos pero eso ya es trabajo para el lector El meacutetodo s e t A t t r i b u t e () antildeade un atributo al objeto que hace la llamada el primer argumento seraacute el nombre del atributo y el segundo su valor La llamada a domelement () puede tener uno o dos valores Si lleva un atributo significaraacute que el nombre de la etiqueta seraacute ese paraacutemeshytro Si se llama con dos paraacutemetros el primero seraacute el nombre de la etiqueta y el segundo un objeto de texto que se antildeadiraacute como texto hijo del nodo

Modificar archivos XML

La verdadera potencia de D O M reside en el poder de gestionar los archishyvos para antildeadir modificar o eliminar nodos La mayoriacutea de los algoritmos que realizan alguna de estas operaciones se basan en la buacutesqueda de los nodos para posteriormente antildeadir hijos nuevos o eliminar los encontrashydos Para antildeadir nuevos elementos se hace como cuando creamos el ficheshyro b i b l i o t e c a xml con el meacutetodo a p p e n d C h i I d ( ) Antes de antildeadir nuevos nodos tiene que localizar el lugar exacto donde quiere antildeadir las etiquetas El ejemplo siguiente muestra coacutemo antildeadir un nuevo nodo tema

ltphp $biblioteca = new domdocument(10) $biblioteca-gtload(bibliotecaxml) $raiz = $biblioteca-gtdocumentElement $tema_nuevo = new domelement(tema) $tema_nuevo = $raiz-gtappendChild($tema_nuevo) $tema_nuevo-gtsetAttribute (id ficcioacuten ) $biblioteca-gtsave(biblioteca2xml) gt

Los pasos son los que ya ha aprendido Cargue el documento y cree un objeto llamado $ r a i z que se convierta en la etiqueta raiacutez mediante el meacutetodo documentElement Cree un nuevo elemento del tipo tema y antildeaacuteshydalo para despueacutes insertar el atributo que se necesita Por uacuteltimo guarde el archivo en el fichero b i b l i o t e c a 2 xml

SimpleXML

Probablemente el punto maacutes fuerte de PHP 4 fue la incorporacioacuten de heshyrramientas para el soporte de XML PHP 5 le da una vuelta maacutes a la tuerca

260 Capiacutetulo 14

implementando nuevas herramientas de lectura elaboracioacuten y modificashycioacuten de archivos XML basado en la libreriacutea l i b x m l 2 y una nueva API llamada SimpleXML

Si XML es un lenguaje bien construido y legible por personas y ordenadoshyres los programas para manipular estos archivos deberiacutean ser tambieacuten sencillos de utilizar SimpleXML nace con esta premisa permitiendo leer un fichero completo con una sola instruccioacuten e inmediatamente despueacutes poder leer los datos como conjunto de variables PHP

El conjunto de funciones que pertenece a la API SimpleXML es nuevo en PHP 5 Mantiene una absoluta flexibilidad a favor de la simplicidad y bajo nivel de memoria usado SimpleXML utiliza el menor nuacutemero de liacuteneas de coacutedigo para leer o escribir datos en un fichero XML El e jemplo s iguiente muestra coacutemo p o d e m o s parsear el a rch ivo b i b l i o t e c a xml

ltphp $biblioteca = simplexTnl_load_fiie(bibliotecaxml) foreach ($biblioteca-gttema as $tema)

echo Tema es $tema[id] ltbrgt foreach ($tema-libro as $libro)

echo ltbgt $libro-gttitulo ltbgt -

echo $libro-gtautor ltbrgt

gt

Lo primero que llama la atencioacuten es que en apenas 10 liacuteneas de coacutedigo se ha conseguido extraer todos los datos necesarios a diferencia de SAX o DOM

La funcioacuten s implexml__load_f i le () crea un objeto con el archivo XML que pase como argumento

A partir de aquiacute puede acceder a todos los datos asiacute como acceder a las variables de los objetos

echo $biblioteca-gttema-gtlibro [0] -gttitulo echo $biblioteca-gttema-gtlibro[1]-gttitulo

Para extraer el contenido que necesita lo maacutes sencillo es crear una estrucshytura de bucles f o r e a c h para ir sacando los datos ordenados

El nombre SimpleXML es totalmente descriptivo aunque no hay que conshyfundir la palabra simple con baacutesico La prueba de su potencia estaacute en que los desarrolladores de PEAR van a utilizar SimpleXML para desarrollar su libreriacutea de SOAP

Lectura y escritura de archivos XML 261

Resumen

XML se ha convertido en un estaacutendar para el intercambio de informacioacuten en Internet Numerosas aplicaciones estaacuten construidas con alguacuten tipo de tecnologiacutea que implementa XML como XML-RPC RSS o SOAP

En este capiacutetulo ha aprendido a leer y escribir documentos de tres formas posibles La maacutes completa sin duda es DOM que permite ademaacutes de leer archivos escribir y modificarlos a nuestro antojo El problema es que pueshyde resultar algo complicado de entender al principio y quizaacute no merezca la pena en aplicaciones sencillas

En el capiacutetulo siguiente conoceraacute la verdadera aplicacioacuten praacutectica Basaacutenshydonos en SimpleXML y en DOM crearemos algunas clases para leer archishyvos de noticias o ejecutar funciones definidas en un ordenador remoto

264 Capiacutetulo 15

Introduccioacuten

Existen en el mercado muchas publicaciones que hablan sobre XML y sus tecnologiacuteas derivadas En estos libros que suelen ser de unas 1000 paacuteginas se hace un recorrido por todos los rincones de XML DTD XLST etceacutetera Si lee alguna publicacioacuten de este tipo puede quedar desencanshytado porque entre tantos conceptos no se ve una aplicacioacuten real de la tecnologiacutea

Como este libro es eminentemente praacutectico me gustariacutea que el lector aprenshydiera dos metodologiacuteas que se utilizan actualmente en la Web RSS y XML-RPC La primera describe una forma de exportar informacioacuten noticias o datos al exterior para que desde cualquier paacutegina Web puedan leerse La segunda es una forma de trabajar que permite ejecutar funciones que esshytaacuten almacenadas en un ordenador remoto

Compartir informacioacuten con RSS

RSS es un mecanismo para publicar informacioacuten sobre el contenido de un sitio Web y es muy comuacuten utilizarlo para dar las uacuteltimas noticias Esto permite introducir en su sitio Web un documento XML con noticias de otras paacuteginas

La versioacuten original de RSS la 090 fue creada por Netscape con el objetishyvo de crear portales servidores de noticias de distinta categoriacutea pero reshysultoacute algo complejo de utilizar La versioacuten 091 mucho maacutes simple la desarrolloacute la empresa UserLand Software quien lo comercializoacute como parte de sus productos basados en paacutegina Web como los Weblogs

Un tercer grupo de desabolladores independientes basaacutendose en los coshymienzos de RSS la versioacuten 090 escribioacute una nueva revisioacuten basada en RDF esta versioacuten recibe el nombre de RSS 10 Desde la aparicioacuten de la versioacuten 01 UserLand Software ha seguido desarrollando las versiones 092 093 094 y la 20

Distintos formatos

Existen 7 formatos distintos y como programador deberiacutea ser lo suficienshyte habilidoso como para manejar cualquiera de ellos Pero como el conteacute-

Aplicaciones praacutecticas de XML 265

nido lo produce la Web que desea exportar su informacioacuten tendraacute que tener en cuenta las caracteriacutesticas de cada formato

Tabla 151 versiones de RSS

Versioacuten Desarrollo Descripcioacuten Status Recomendacioacuten

090 Netscape Obsoleta No usar por la apashyricioacuten de 10

091 UserLand Simple Muy popular Sencilla y faacutecil de pero obsoleta migrar a la versioacuten por la aparicioacuten 20 de 20

092 UserLand Permite texto Obsoleto por Mejor usar la 20 093 enriquecido y la 20 094 metadatos

10 Grupo de Basado en Muy estable Usar si necesitamos desarrollo RDF y exten- especificaciones RSS-DEV sible con avanzadas

moacutedulos

20 UserLand Exter=Aacuteble corraquo EsteWe y ef Uso de caraacutecter moacutedulos Faacutecil continuo general con meta-de migrar desarrollo datos y texto enri-desde cualquier quecido versioacuten 09

Como ejemplo vamos a leer el RSS 10 de la Web del autor wwwluisy fernandanet que contiene esta informacioacuten

ltxml version=10 encoding=iso-8859-1 gt ltrdfRDF xmlnsrdf=httpwwww3org19990222 -rdf-syntax-ns xmlns=httpmynetscapecomrdfsimple09gt

ltchannelgt lttitlegtwwwluiacutesyfernandanetlttitlegt ltlinkgthttpwwwluisyfernandanetiacutendexphp

blogId=2ltlinkgt ltdescriptionxdescriptiongt

ltchannelgt ltitemgt

lttitlegtPHP 5 en la liacutenea de salidalttitlegt ltdescriptiorvgtiacuteuumladi Gutwampias dice que en 24 horas estaraacute lista la nueva versioacuten de PHP5 bull que nervios ampltbr

266 Capiacutetulo 15

ampgtPara el que no pueda esperar la Releacutease Candidate 4 estaacute en amplta href =ampquothttp snapsphpnet~andiampquotampgthttpsnapsphpnet ~andiampltaampgtampltbrampgt ampltbrampgtampltbrampgtlt descriptiongt

ltlinkgthttpwwwluisyfernandanetiacutendexphpop=View ArticleampamparticleId=41ampampblogId=2ltlinkgt ltitemgt

lt itemgt lttitlegtGalopiacuten 10lttitlegt ltdescriptiongt amplt a

href=ampquothttpwwwluisyfernandanetresserverphp blogId=2amp amp resource=DSCN0840 JPG ampquot ampgt amplt img align=ampquot rightampquot style=ampquotmargin 5pxampquot border=ampquotOampquot alt=ampquotRueda de prensaampquot src=ampquothttpwwwluisyfernandanetresserver phpblogId=2ampampresource=DSCN0 840JPGampampmode=previewampquot ampgtampltaampgt

Hoy se ha presentado en la AAVV de La Antigua en Meacuterida la versioacuten 10 de Galopiacuten una herramienta escrita en PHP por dos desarrolladores extrementildeos Tras los forcejeos con la prensa y las salidas con quite de los implicados nos quedamos con la miel en los labios deseando probar la aplicacioacuten y porqueacute no destriparla para ver como funciona el chismeampltbr ampgtEl que quiera descargarla puede hacerlo desde la Web de sinuh en amplta href=ampquothttp galopinsinuhorgampquotampgtgalopinsinuhorgampltaampgtampltbr

ampgtScltbxSiacutegpound ampltbr ampgtltdescriptiongt ltlinkgthttpwwwluisyfernandanet

indexphpop=ViewArticleampamparticleld=4 0ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtEL TIEMPO DE MERIDAlttIacutetlegt ltdescriptiongt Hace unos diacuteas empeceacute escribir alguna cosilla para averiguar

la temperatura que hay en Meacuterida Los datos los recojo de la Web del Instituto Nacional de Meteorologiacutea y los plasmo en una tabla Si quieres puedes utilizar los datos llamando a la Web amplt a href = ampquothttpwwwluisyfernandanet clase_tiempophpLOCALIDAD=MERIDAampquotampgthttp wwwluisyfernandanetclase_tiempophpLOCALIDAD=MERIDAamplt aampgtampltbr ampgtDonde pone LOCALIDAD se puede poner alguna poblacioacuten distinta como CORIA CACERES BADAJOZUNIVERSIDAD etcampltbr ampgtEl moacutedulo estaacute en fase alfa y el dibujito que aparece puede que no corresponda con la realidad pero es un avance )ampltbr ampgtEn unas semanas implementareacute el servicio en SOAP como lo hace weathercomampltbr ampgtSaludosampltbr ampgtampltbr ampgtampltbr ampgtampltbrampgt

Aplicaciones praacutecticas de XML 267

ampltbr ampgtltdescriptiongt ltlinkgthttpwwwluisyfernandanet

indexphpop=ViacuteewArticleampamparticleld=3 6ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtPHP 5 a punto de caramelolttitlegt ltdescriptiongtHace un par de diacuteas en la lista interna de

desarrolladores de PHP Andi Gutmans ha escrito que PHP5 ya estaacute horneado y le falta un poquito de chocolate para salir al mercado Estaacuten teniendo alguacuten problemilla con libreriacuteas que controlan el acceso a memoria pero se preveacute que la primera versioacuten estable salga esta semana ampltbr ampgtamplta href=ampquothttpwwwzendcomlistsphp-dev2004 07 msg00059htmlampquot ampgtNotica de Zend ampltaampgtampltbr ampgtampltbr ampgtltdescriptiongt

ltlinkgthttpwwwluisyfernandanet indexphpop=ViewArticleampamparticleld=3 3ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtOpenOffice2htm en Sourceforgelttitlegt ltdescriptiongt Acaban de aceptar el Proyecto OpenOffice2htm

en sourceforge ellos sabraacuten lo que hacen Lo que pasa es que tengo un pequentildeo problema entre tanto menuacute de administracioacuten de ficheros documentos etc me pierdo y por ahora no he podido subir ninguacuten fichero de la clase Espero aclararme estos diacuteas y tener listo la primera Releacutease en amplta href=ampquothttpwwwluisyfernandanet wwwsourceforgecomampquotampgtwwwsourceforgecomamplt aampgtampltbr ampgtampltbrampgtampltbr ampgtltdescriptiongt

ltlinkgthttpwwwluisyfernandanet indexphpop=ViewArticleampamparticleld=17ampampblogId=2ltlinkgt ltitemgt ltrdfRDFgt

El archivo anterior muestra las uacuteltimas noticias de la Web www lu i sy fernadanet sobre PHP y proyectos en los que el autor estaacute involucrado

Si se fija no es maacutes que un archivo XML con un formato determinado

Puede verlo en la figura 151

Tiene dos partes diferenciadas

bull Una parte de descripcioacuten del documento entre las etiquetas ltchan-n e l gt En esta zona puede encontrar el tiacutetulo de Web donde estaacuten las noticias la URL del archivo RSS y una descripcioacuten de la temaacutetica que aborda

bull Otra zona entre los nodos lt i t emgt que contiene todas las noticias que quiere exportar

Leer un archivo RSS

En el capiacutetulo anterior vimos coacutemo parsear un archivo XML creado por nosotros mismos Esta vez tenemos que extraer el contenido que nos inshyteresa de un archivo con un formato determinado Vamos a crear un peshyquentildeo objeto que sea capaz de insertar en nuestra Web las noticias de la paacutegina wwwluisyfernandanet Por supuesto vamos a utilizar SimpleXML por ser una de las herramientas estrella de PHP 5

ltphp class SimpleRSS

priacutevate $RSS function construct($fichero)

$this-gtRSS = simplexml_load_file($fichero)

public function parsea_item() foreach ($this-gtRSS-gtitem as $item)

$this-gtparsea_titulo($item) $this-gtparsea_descripcion($item) $this-gtparsea_enlace($item)

private function parsea_titulo($item)

Aplicaciones praacutecticas de XML 269

echo $item-gttitle bull ltbrgt echo lthrgt

priacutevate function parsea_descripcion ($item)

echo $item-gtdescription ltbrgt

priacutevate function prsea_enlace($item)

echo $item-gtlink bull ltbrgt

public function paiacutesea_cabecera()

ampc^o Titilo- laquo St^va-^SSS-gtet^trade^l-gttltLe -JaxV- echo Web $this-gtRSS-gtchannel-gtlink ltbrgt echo lthrgt

$RSS = new SimpleRSS(httpwwwluisyfernandanet rssphpcategoryId = 3ampblogId=2 ) $RSS-gtparsea_cabecera () $RSS-gtparsea_item() gt

Si ejecuta el programa tendraacute como resultado las uacuteltimas noticias sobre PHP del portal wwwluisyfernandanet separadas por liacuteneas horizontashyles El meacutetodo puacuteblico p a r s e a _ i t e m () es el encargado de extraer notishycia a noticia y mandarlas al navegador Este meacutetodo hace 3 llamadas a 3 meacutetodos distintos que se encargan de recuperar el tiacutetulo el enlace a la noticia y la descripcioacuten Hemos separado los meacutetodos para que cada lector personalice la forma de visualizar los distintos datos Mi forma particular puede verla en la fishygura 152 Por ejemplo el tiacutetulo podriacutea mostrarlo en azul y el texto en gris todo metido en una tabla-

Escribir archivos RSS

Los archivos XML y en particular los archivos RSS pueden generarse de la misma forma que creamos un fichero de texto antildeadiendo etiquetas con cierto criterio a un archivo de texto pero la opcioacuten maacutes correcta es utilizar DOM para generar nuestros propios documentos de noticias Como ya sabe la extensioacuten DOM permite antildeadir borrar y modificar eleshymentos a lo largo de un documento en cualquier orden

Para este cometido tenemos la siguiente clase que nos va a generar docushymentos RSS a partir de cualquier fuente de datos

ltphp class GeneraRSS

priacutevate documento private $raiz priacutevate $channel private $titulo private $enlace private descripcioacuten private $item function construct() $this-gtdocumento = new domdocument(1bull0 ) $this-gtinicio ( )

private function inicio() $this-gtraiz = $this-gtdocumento-gtcreateElement(rdfRDF ) $this-gtraiz-gtsetAttribute(xmlnsrdfhttpwwww3org1999 0222-rdf-syntax-ns) $this-gtraiz-gtsetAttribute(xmlnshttppurlorgrss10) $this-gtraiz = $this-gtdocumento-gtappendChild($this-gtraiz)

Aplicaciones praacutecticas de XML 271

pub l i c funct ion c a n a l ( $ t i t u l o $ e n l a c e $ d e s c r i p c i o n $ s o b r e )

$this-gtchannel = $this-gtdocumento-gtcreateacuteElement(channel) $this-gtchannel = $ th i s -gtra iz -gtappendChi ld ($ th i s -gtchanne l ) $ th i s -gt t i tu lo=$th i s -gtdocumento-gtcrea teElement ( t i t l e ) $ th i s -gt tex to t i t u lo=$ th i s -gtdocumen to -gtc rea t eTex tNode($ t i tu lo ) $ t h i s - gt t i t u l o - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o t i t u l o ) $ t h i s - gt c h a n n e l - gt a p p e n d C h i l d ( $ t h i s - gt t i t u l o ) $ t h i s - gt e n l a c e = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l s m e n t ( l i n k ) $ th i s -gt tex toen lace=$th i s -gtdocumento-gtcrea teTextNode($en lace) $ t h i s - gt e n l a c e - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o e n l a c e ) $ th i s -gtchanne l -gtappendChi ld ($ th i s -gten lace ) $ t h i s - gt d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( d e s c r i p t i o n ) $ t h i s - gt t e x t o d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e T e x t N o d e ( $ d e s c r i p c i o n ) $ t h i s - gt d e s c r i p c i o n - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o d e s c r i p c i o n $ th i s -gtchanne l -gtappendCh i ld ($ th i s -gtdesc r ipc ion )

pub l i c funct ion i t em_nuevo($ t i tu lo $en lace $descr ipcion)

$this-gti tem = $this-gtdocumento-gtcreateElltment( i tem) $ this-gti tem = $ th i s -gtra iz -gtappendChi ld ($ th i s -gt i t em) $ t h i s - gt t i t u l o = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( t i t l e ) $ th i s -gt t ex to t i t u lo=$ th i s -gtdocumen to -gtc rea t eTex tNode ($ t i t u lo ) $ t h i s - gt t i t u l o - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o t i t u l o )

$ t h i s - gt i t e m - gt a p p e n d C h i l d ( $ t h i s - gt t i t u l o ) $ t h i s - gt e n l a c e = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( l i n k ) $ th i s -gt tex toen lace=$th i s -gtdocumento-gtcrea teTextNode($en lace) $ t h i s - gt e n l a c e - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o e n l a c e ) $ t h i s - gt i t e m - gt a p p e n d c h i l d ( $ t h i s - gt e n l a c e ) $ t h i s - gt d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( d e s c r i p t i o n ) $ t h i s - gt t e x t o d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e T e x t N o d e ( $ d e s c r i p c i o n ) $ t h i s - gt d e s c r i p c i o n - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o d e s c r i p c i o n ) $ t h i s - gt i t e m - gt a p p e n d C h i l d ( $ t h i s - gt d e s c r i p c i oacute n ) $ th i s -gt i t ems [ ]=$ th i s -gt i t em

public function grabar($fichero) $this-gtdocumento-gtsave($fichero)

^documento = new GeneraRSS () ^documento-gtcanal (wwwluisyfernandanet httpwwwluisy fernandanet La Web del auto) $docimeito-gtitev1_YYievo VMaiwial Imprescindible de PHP 5 http- v iwwluisyfernandanet Ya a la v e n t a )

272 Capiacutetulo 15

$documento-gtitem_nuevo(Nueva releacutease de PHP 5http wwwiuisyfernandanetLa nueva releacutease corrige algunos fallos) Sdocumento-gtgrabar(miRSSxml) gt

La clase anterior se puede guardar en un archivo independiente y utilizar cuando sea necesario en el transcurso de un proyecto

Aunque no implementa todas las especificaciones de RSS 10 puede utilishyzarse para generar noticias de nuestra base de datos

Nota

Si desea modificar ia ciase para que contemple todas las opciones de Ja especificacioacuten RSS 10 puede visitar ia Web httpllpurtorgl rss10

En el capiacutetulo anterior vimos coacutemo se puede generar un archivo XML con una sucesioacuten de llamadas a meacutetodos Esta vez hemos encapsulado todas las llamadas en varios meacutetodos que se encargan de generar la parte de descripcioacuten del RSS y por otro lado las noticias

El meacutetodo c r e a t e E l e m e n t () se encarga de crear nuevos nodos para desshypueacutes encadenarlos c o n a p p e n d C h i l d () a los nodos padre Para crear un nodo de texto sin embargo tenemos que utilizar el meacutetodo c r e a t e T e x t -Node () una vez creado el nodo de texto tenemos que asociarlo a un nodo-elemento (una etiqueta)

El uacuteltimo paso es hacer una llamada al meacutetodo s a v e () con el nombre del fichero como paraacutemetro para guardar el archivo RSS

Servicios Web XML-RPC

El trabajo como programador puede llevarle a desarrollar aplicaciones para distintos Sistemas Operativos y en distintos lenguajes de prograshymacioacuten

Si en alguacuten momento necesita comunicar dos programas que estaacuten funshycionando en maacutequinas distintas (un servidor Windows y otro gnuLinux) y escritos con lenguajes diferentes puede que XML-RPC sea la solucioacuten perfecta

El mecanismo permite que el ordenador cliente pueda acceder a los meacutetoshydos del ordenador servidor y ejecutar rutinas almacenadas remotamente

Aplicaciones praacutecticas de XML 273

Este apartado muestra alguacuten ejemplo de coacutemo implementar y explotar un servicio Web con la libreriacutea de clase IXR creada por Simoacuten Willison bajo el auspicio de Open Source

Una llamada XML-RPC consiste en dos partes una pregunta y una resshypuesta

Cada una de las partes es un archivo XML que contiene los paraacutemetros solicitados al servidor o los datos devueltos

Una pregunta al servidor puede ser como la que sigue

ltmethodCalIgt ltmethodNamegtconteritgetNotiacuteciasltmethodNamegt ltparamsgt

ltparamgt ltvaluexintgt23ltiacutent gtltvaluegt

ltparamgt ltparams gt

ltmethodCallgt

Como puede ver es un archivo XML con una definicioacuten determinada La etiqueta ltmethodNamegt contiene el nombre del meacutetodo que debe llamarse en el servidor y ltparamgt contiene un paraacutemetro que se le pasaraacute al meacutetoshydo de la llamada

El documento anterior seraacute transmitido viacutea HTTP mediante POST al sershyvidor de XML-RPC que parsearaacute el documento ejecutaraacute la funcioacuten y devolveraacute un documento similar con los datos de la respuesta

Clase IXR

IXR es un conjunto de clases que implementa un servidor y un cliente de XML-RPC

Nota

Puede encontrar la libreriacutea en la Web httpscriptsiricutiocom xmlrpc o en la paacutegina del libro en httpunuzunnaiamulti-mediacom

Lo mejor de la programacioacuten orientada a objetos es que no necesita saber coacutemo funcionan las clases que utilice soacutelo conocer el uso correcto de los meacutetodos Asiacute puede utilizar la clase IXR de la manera que vamos a ver sin conocer siquiera el formato de los archivos XML-RPC

274 Capiacutetulo 15

Cliente XML-RPC

Los servicios XML-RPC tienen una direccioacuten Web con una paacutegina Web escrita en PHP Si escribe la direccioacuten completa en el navegador se proshyduciraacute un error porque la Web esperaraacute que mande mediante POST un archivo XML Para utilizar sus servicios Web o los servicios Web de alshyguna empresa como UserLand tiene que utilizar un cliente XML-RPC escrito en este caso en PHP 5 En este caso vamos a utilizar la clase IXR__Client de la libreriacutea IXR El ejemplo muestra coacutemo utilizar el cliente en varios pasos

bull Crear un objeto cliente con la URL pasada como paraacutemetro

bull Usar el meacutetodo q u e r y () para hacer la consulta al servicio Web

bull Extrae el resultado con el meacutetodo g e t R e s p o n s e ()

Lo primero que vamos a hacer es implementar un pequentildeo objeto para recuperar la fecha de un servidor remoto

ltphp require_once(IXR_Libraryincphp) class XMLRPCFechacliente

private $cliente function construct($url$debug=false) $this-gtcliente= new IXR__Client ($url) $this-gtcliacuteente-gtdebug=$debug

function getFecha($argumentol) if ($this-gtcliente-gtquery(fechagetFecha$argumentol)) trigger_error($this-gtcliente-gtgetErrorCode () $this-gtcliente-gtgetErrorMessage()) return false

return $this-gtcliente-gtgetResponse ()

gt

La clase X M L R P C F e c h a c l i e n t e implementa dos meacutetodos El construcshytor crea un objeto cliente IXR que recibe el servidor de servicios Web El meacutetodo g e t F e c h a () tramita la peticioacuten de la fecha con el servidor y obshytiene una respuesta que devuelve a la paacutegina Web Si todo va bien el sershyvidor enviaraacute la fecha del lugar donde esteacute

La llamada a q u e r y () tiene como paraacutemetro primero el nombre del meacuteshytodo que debe ejecutar el servidor y como segundo paraacutemetro un argu-

Aplicaciones praacutecticas de XML 275

mentoacute que puede pasarse La Web que quiera mostrar esta informacioacuten debe crear el objeto anterior maacutes o menos como se muestra en el siguiente ejemplo

ltphp require_once(XMLRPCFechaclientephp) $servidor=httpwwwluisyfernandanetFechaphp $fechaRemota= new XMLRPCFechacliente($servidor) echo $fechaRemota-gtgetFecha(Hoy) gt

Si evaluacutea el coacutedigo en tan soacutelo 4 liacuteneas puede recibir cualquier tipo de informacioacuten que el servidor tenga Para ello debe crear una variable que contenga el nombre del servidor y la paacutegina PHP que contiene el prograshyma de respuesta La instanciacioacuten del objeto X M L R P C F e c h a c l i e n t e y la llamada al meacutetodo g e t F e c h a () es suficiente para desencadenar la coshynexioacuten con el servidor

Servidor XML-RPC

En el apartado anterior ha visto que puede utilizar servicios Web ofrecishydos por otras empresas para averiguar la hora de un Paiacutes remoto el camshybio de moneda el tiempo o incluso el cataacutelogo de libros de una conocida tienda on-line Pero lo realmente interesante es poder crear sus propios servicios Web

La clase IXR_Server hace la mayoriacutea del trabajo por usted que puede emplear el tiempo en inventar nuevos servicios Web

Hemos creado una clase que implementa el servicio g e t F e c h a ( ) que el objeto cliente utiliza

ltphp require_once(IXR_Libraryincphp) class XMLRPCFechaservidor extends IXR_Server

function construct()

$this-gtIXR_Server(array(fechagetFecha =gt thisgetFecha)) function getFecha($argumentol)

if ($argumentol==Hoy) $fecha = La fecha remota es date(d-m-Y)

else

$fecha = Especifique un dia

2 7 6 Capiacutetulo 15

re turn $fecha

gt

La clave para entender el funcionamiento del servidor estaacute en el construcshytor Aquiacute se crea un array con el nombre de los meacutetodos que se pueden utilizar desde fuera

El primer valor f e c h a g e t F e c h a es el nombre que el cliente debe emshyplear para recuperar la Fecha del Servidor y el segundo valor t h i s g e t Fecha es el meacutetodo perteneciente al servidor que se ejecutaraacute cuando reciba una pregunta a esa funcioacuten

La figura 153 muestra el dato que obtiene el cliente

La definicioacuten del meacutetodo que enviacutea la fecha se hace como ya estamos acosshytumbrados

Lo que hemos visto es soacutelo la definicioacuten de la clase pero necesitamos una paacutegina Web de apoyo que instancie el objeto y lo ejecute Puede ser tan sencillo como

ltphp require_once(XMLRPCFechaservidorphp) $servidor= new XMLRPCFechaservidor() gt

Aplicaciones praacutecticas de XML 277

Usos de XML-RPC

Los ejemplos que hemos visto no son especialmente excitantes pero dan una idea de lo sencillo que es exportar cualquier tipo de informacioacuten La verdadera potencia de los servicios Web es que permiten disfrutar de nueshyvas funcionalidades de las que no disponemos Podriacuteamos crear un servishycio Web que permitiera a usuarios de PHP 4 utilizar nuestro objeto de SimpleXML pero esto lo dejo en manos del lector

Resumen

XML se ha convertido en los uacuteltimos antildeos en un estaacutendar libre para el inshytercambio de informacioacuten Incluso Microsoft poco amiga de los archivos abiertos estaacute implementando servicios en XML con su plataforma NET

Despueacutes de leer este capiacutetulo podraacute crear elegantes paacuteginas que contenshygan noticias relevantes sobre cualquier tema y exportarlas a otras paacuteginas amigas gracias a la tecnologiacutea RSS

En cuanto a la creacioacuten de servicios Web existe una controversia entre dos desarrollos principales XML-RPC y SOAP de Microsoft SOAP (Simshyple Object Access Protocol) es una implementacioacuten muy extensa de Microshysoft para la creacioacuten de servicios Web Pese a que su definicioacuten aboga por la simpleza (Protocolo Simple) la paradoja es que es mucho maacutes complishycada de utilizar que XML-RPC y por eso se escapa de los objetivos de este libro

Una de las nuevas caracteriacutesticas de PHP 5 es la inclusioacuten de una extenshysioacuten para la generacioacuten de servidores y clientes SOAP pero todaviacutea estaacute en fase experimental

El futuro cercano puede estar en SOAP asiacute que recomiendo al lector visishytar algunas paacuteginas Web sobre el tema para comenzar a entender su funshycionamiento

280 Capiacutetulo 16

Introduccioacuten

La construccioacuten de un sitio Web no soacutelo debe contar con textos bases de datos y funciones escritas en PHP para manejar los datos Existe un gran abanico de posibilidades que pueden dotar a la paacutegina de contenido multishymedia (imaacutegenes v sonidos) y que ademaacutes pueden ser procesados de alshyguna forma por PHP

Entre las funciones maacutes baacutesicas de interactuacioacuten con las imaacutegenes PHP puede realizar graacuteficos de barras para mostrar resultados estadiacutesticos antildeadir una marca de agua a todas nuestras fotografiacuteas o mostrar una reacuteshyplica de las imaacutegenes en un formato maacutes reducido para poder seleccionar entre un conjunto de ellas

La mayoriacutea de los ejemplos utilizan la libreriacutea graacutefica GD para PHP que puede instalarse faacutecilmente en los tres Sistemas Operativos maacutes comunes (gnuLinux MacOSX y Windows)

Graacuteficos HTML

Antes de entrar de lleno en las maravillas que ofrece la libreriacutea graacutefica GD vamos a realizar un pequentildeo ejemplo para aprovechar las posibilidades del lenguaje HTML para la creacioacuten de estadiacutesticas graacuteficas Esta posibilishydad nos permite realizar estudios graacuteficos baacutesicos sin tener que instalar ninguacuten paquete adicional a PHP

Puede decantarse por este meacutetodo o por utilizar la libreriacutea dependiendo de la complejidad de su proyecto

Vamos a crear como ejemplo un sistema de votacioacuten electroacutenico que cuente los votos de cada participante y los almacene en una base de datos Vashymos a utilizar el gestor SQLite visto en el capiacutetulo 11 Para tal fin hemos creado una clase de conexioacuten a SQLite muy parecida a la clase de conexioacuten de MySQL

ltphp

class Servidor_Base_Datos

priacutevate $base_datos priacutevate $descriacuteptor priacutevate ^resultado function construct($base_datos)

Generacioacuten de graacuteficos con PHP 5 281

$this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtpass = $pass $this-gtbase_datos = $base_datos $this-gtconectar_base_datos()

priacutevate function conectar_base_datos( )

$thiacutes-gtdescriptor = sqlite_open($this-gtbase_datos)

i public function consulta($consulta)

$this-gtresultado = sqlite_query($consulta $this-

gtdescriptor) public function extraer__registro ()

if ($fila = sqlite_fetch_array($this-

gtresultadoSQLITE_ASSOC)) return $fila

else return false

gt

Los meacutetodos son praacutecticamente iguales y la forma de utilizar el objeto es exactamente igual que en los ejemplos del capiacutetulo 12

Los datos que vamos a manejar en la encuesta son parte de una pequentildea tabla que almacenaraacute el nombre del Lenguaje de Programacioacuten que prefeshyrimos y el nuacutemero de votos que le hemos dado Podemos inicializar la base de datos con el siguiente script

ltphp requirejonee(clase_SQLitephp) $base_datos = new Servidor_Base_Datos(votacionesdb) $base_datos-gtconsulta(creacuteate table lenguaje (id_lenguaje INT PRIMARY KEY lenguaje CHAR(255) votos INT))

$base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees ( PHP 0) ) $base_datos-gtcoacutensulta(insert into lenguaj e (lenguaj evotos) valuacutees (JSPeuro)) $base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees (ASP 0) )

282 Capiacutetulo 16

$base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees (COLD FUSIOacuteN0)) $base_datos-gtconsulta(select from lenguaje)

while ($fila = $base_datos-gtextraer_registro ()) echo $fila [lenguaje] $fila[votos] ltbrgt

gt

Todo deberiacutea serle familiar Lo que hacemos es crear una tabla nueva en la base de datos e insertar los lenguajes objetivo de la encuesta Por uacuteltishymo hacemos una comprobacioacuten para ver si los datos estaacuten almacenados en la base de datos Lo siguiente que vamos a ver es una Web con un formulario para elegir el lenguaje que maacutes nos agrada En la zona inferior de la paacutegina tenemos un contador que nos indica el nuacutemero de votos

ltphp

Primero comprobamos si tenemos un voto

$base_datos = new Servidor_Base_Datos(votaciones2db)

Si hemos votado sumamos el valor al nuacutemero de votos almacenado

if (isset($_POST[voto] ) )

$voto = $_POST[voto] $base_datos-gtconsulta(select votos from lenguaje where id_lenguaj e=$voto) $numero_votos = $base_datos-gtextraer_registro() $numero_votos = $numero_votos[votos] $numero_votos + + $base_datos-gtconsulta(update lenguaje set votos= $numero_votos where id_lenguaje = $voto)

gt lthtmlgt ltbodygt iquestQueacute lenguaje de programacioacuten prefieres

Formulario que permite votar

ltform action=votophp method=post gt ltselect name=votogt ltphp $base_datos-gtconsulta (select from lenguaje) while ($fila = $base_datos-gtextraer_registro () )

$id_lenguaje = $fila[id_lenguaje] $lenguaje = $fila [lenguaje]

Generacioacuten de graacuteficos con PHP 5 283

echo ltoption value=$id_lenguajegt$lenguajeltoptiongt

gt ltselectgt ltinput type=submit name=Enviar value=Enviar gt ltformgt lttablegt ltphp $base_datos-gtconsulta(select from lenguaje) while ($fila = $base_datos-gtextraer_registro () )

$lenguaje = $fila [lenguaje] $votos = $fila [ votos] echo lt t rx tdgt$ lengua j e lt t d x t d gt $votos vo toslt tdgtlt

t r gt

gt lt t ab l egt ltbodygt lthtmlgt

Como puede ver es un mecanismo muy sencillo de entender La parte principal es el formulario que permite elegir entre los 4 lenguajes de script Si enviamos un voto la misma paacutegina recibiraacute el dato y actualizaraacute la base de datos mostrando posteriormente los votos que tienen los lenguajes En la figura 161 puede ver el resultado

284 Capitulo 16

Graacuteficos de barras

Despueacutes de todo este coacutedigo estaraacute preguntaacutendose por las imaacutegenes geshyneradas automaacuteticamente Todaviacutea no hemos hecho nada de eso pero en el coacutedigo siguiente tiene la clave de este apartado Baacutesicamente jugamos con 4 imaacutegenes r o j o png v e r d e p n g a z u l png y a m a r i l l o png Cada imagen tiene un tamantildeo de 1 piacutexel de ancho y alto El truco estaacute en hacer un caacutelculo porcentuado de los valores de votos con respecto al que mayor votos tiene

De ahiacute sacamos el ancho de la imagen Una vez encontrado este ancho se le pasa a la propiedad w i d t h de la etiqueta lt imggt y obtenemos un graacutefishyco con imaacutegenes de distintos anchos es decir obtenemos un graacutefico de barras estadiacutestico

El coacutedigo puede ser como el siguiente

ltphp $imagenes = array(rojopngazulpngverdepngamarillopng) $base_datos-gtconsulta(select from lenguaje) while ($fila = $base_datos-gtextraer_registro() )

$id_lenguaje = $fila [ id_lenguaje ] $lenguaje = $fila [lenguaje] $votos = $fila[votos] $ancho = dame_ancho($votos$id_lenguaje) $imagen = $ imagenes[$ id_ lengua je -1] echo lt t r x t d gt $ l e n g u a j e - $votos v o t o s lt t d x t d x i m g src=$imagen width=$ancho h e i g h t = 2 0 gt lt t d x t r gt

function dame_ancho($votos)

$base_datos2 = new Servidor_Base_Datos(votaciones2db) $base_datos2-gtconsulta(select max(votos) as maacuteximo from lenguaje) $numero_votos = $base_datos2-gtextraer_registro() $maximo_votos = $numero_votos[maacuteximo] return (intval($votos)300)intval($maximo_votos)

gt lttablegt

Antes generaacutebamos una tabla con los lenguajes y el nuacutemero de votos Ahora generamos los lenguajes y calculamos con la funcioacuten dame_an-cho () el porcentaje con respecto al mayor valor de cada uno de los votos de los lenguajes La figura 162 muestra los graacuteficos de barras de la votacioacuten electroacutenica

Libreriacutea GD

La libreriacutea graacutefica GD estaacute escrita en lenguaje C y permite crear y manipushylar graacuteficos faacutecilmente Permite importar y exportar graacuteficos de distinto tipo (GIF JPG y PNG) La filosofiacutea de los archivos GIF y PNG es casi la misma Estos dos archivos guardan en memoria el conjunto completo de piacutexeles con su color concreto y comprimen el resultado para que el archishyvo final no sea muy pesado Los archivos JPG tambieacuten estaacuten comprimishydos pero se basan en algoritmos complejos que permiten un mayor rendimiento y la hacen muy propicia para usarse con fotografiacuteas

Tipos MIME

El estaacutendar MIME se concibioacute originariamente para identificar los difeshyrentes contenidos que podemos enviar por correo electroacutenico Actualmente se utiliza para describir el tipo de archivo que enviamos a traveacutes de Intershynet Es importante conocer los tipos MIME para trabajar con las libreriacuteas GD

En general antes de recibir la respuesta del servidor eacuteste debe enviarnos una cabecera anunciando el tipo de contenido que vamos a recibir usando una cabecera especial C o n t e n t - T y p e PHP por defecto enviacutea el tipo

286 Capiacutetulo 16

MIME t e x t h t m l (documento HTML) Cuando utilice la libreriacutea GD necesitaraacute enviar una cabecera con el tipo de la imagen

ltphp header(Content-Type imagepng) gt

Tabla 161 Tipos MIME

Formato de imagen MIMEacute

JPG iexclmagejpeg

PNG imagepng

GIF imagegif

BMP imagebmp

SVG imagexml+svg

Mostrar una imagen en pantalla

Normalmente utilizamos la etiqueta ltimggt de HTML para mostrar una imagen en un lugar determinado de nuestra paacutegina Web La propiedad s r c debe indicar una imagen determinada con formato coshynocido La liacutenea siguiente mostraraacute en pantalla el logotipo de php

ltimg src=phppnggt

La libreriacutea graacutefica GD tambieacuten permite enviar imaacutegenes con el uso de unas funciones determinadas Como ejemplo vamos a ver coacutemo mostrar el misshymo logotipo esta vez utilizando GD

ltphp $imagen = imagecreatefrompng(phppng) header(Content-Type imagepng) imagepng($imagen) gt

Advertencia

La etiquete ltimggt de nuestra paacutegina Web debe apuntar ahora al

archivo PHP que genera la imagen ltimg s r c = imagen php gt

La funcioacuten i m a g e c r e a t e f rompng () recupera una imagen de un archishyvo y crea un descriptor en la variable $ imagen Para mostrar la imagen

Generacioacuten de graacuteficos con PHP 5 287

tiene que enviar la cabecera del tipo de archivo graacutefico que quiere mosshytrar y despueacutes enviar la imagen con imagepng ()

A simple vista parece demasiado esfuerzo para algo que resuelve perfecshytamente la etiqueta ltimggt pero examine el siguiente coacutedigo

ltphp

$imagenes = array(phppngzendpngparispng) Semilla aleatoria srand( (double)microtime 01000000) $aleatorio = rand(02) $fichero = $imagenes[$aleatorio] $imagen = imagecreatef rompng ($f ichero) header(Content-Type imagepng) imagepng($imagen) gt

El array $ i m aacute g e n e s contiene varios archivos graacuteficos en PNG Generashymos un nuacutemero aleatorio y recuperamos la imagen que ocupa la posicioacuten del nuacutemero

Los siguientes pasos son exactamente iguales a los vistos anteriormente El script muestra una imagen distinta cada vez que lo ejecutamos y puede servir para crear una Web con distintos banners aleatorios Puede ver el resultado en la figura 163

288 Capiacutetulo 16

Crear imaacutegenes en miniatura

Si su paacutegina Web permite enviar fotografiacuteas quizaacute necesite mostrar un gran nuacutemero de ellas en una sola paacutegina HTML permite poner un ancho determinado a la imagen aunque el tamantildeo permaneceraacute invariable Lo ideal es crear dos versiones de cada fotografiacutea Una en miniatura con poco peso en bites y otra la original que puede ser mostrada cuando se haga clic en la imagen pequentildea

Gracias a la libreriacutea GD podraacute modificar el tamantildeo de las fotografiacuteas que quiera Vamos a crear una clase para generar fotografiacuteas con la mitad de tamantildeo

ltphp class imagen

priacutevate $archivo priacutevate $ imagen priacutevate $dimensiones function construct($archivo)

$this-gtarchivo = $archivo $this-gtimagen = imagecreatefromjpeg($archivo) $this-gtdimensiones = getimagesize ($archivo)

i

public function imagen_original()

header(Content-Type imagejpeg) imagejpeg$this-gtimagen)

public function imagen_miniacuteatura()

$dimensionx = $thiacutes-gtdimensiones[0] 2 $dimensiony = $this-gtdimensiones[1] 2 $this-gtminiatura = imagecreatetruecolor($dimensionx $dimensiony) imagecopyresampled($this-gtminiatura $this-gtimagen 0 0 0 0 $dimensionx $dimensiony $this-gtdimensiones[0] $this-gtdimensiones[1])header (Content-Type imagejpeg) imagejpeg($tnis-gtminiatura)

$fotografia = new imagen($_GET[fotografiacutea])

if ($_GET[modo]==original)

$fotografia-gtimagen_original()

Generacioacuten de graacuteficos con PHP 5 289

else $fotografia-gtimagen_miniatura()

gt

La clase estaacute especializada en construir imaacutegenes con la mitad de tamantildeo Para que funcione tiene que hacer una l lamada a la url c l a s e _ imagen php pasando como paraacutemetros GET el nombre de la fotografiacutea y el modo (tamantildeo original o miniatura)

El constructor de la clase rescata el archivo graacutefico y averigua las dimenshysiones X e Y con la funcioacuten g e t i m a g e s i z e ()

El meacutetodo i m a g e n _ o r i g i n a l () funciona exactamente igual que el ejemshyplo anterior El meacutetodo i m a g e n _ m i n u a t u r a () divide entre 2 las dimenshysiones capturadas de la imagen y crea un entorno de trabajo con esas dimensiones con la funcioacuten i m a g e c r e a t e t r u e c o l o r ( ) En este momenshyto la variable $ m i n i a t u r a del objeto tiene un espacio de memoria asigshynado para almacenar un graacutefico pero estaacute vaciacuteo Lo que hacen las liacuteneas siguientes es redimensionar y copiar la imagen original a nuestro entorno de trabajo La funcioacuten i m a g e c o p y r e s a m p l e d () copia la imagen guarshydada en el segundo paraacutemetro en el espacio de trabajo del primer paraacuteshymetro

Los argumentos 3 y 4 son las coordenadas X e Y donde empezaraacute a pegarshyse la imagen copiada y el 5 y 6 las coordenadas desde las que se empezaraacute a copiar la imagen original Los siguientes paraacutemetros son el ancho y alto de las imaacutegenes destino y origen

Una vez copiada la imagen al espacio de trabajo ya podemos mostrarla enviando la cabecera y la imagen con la funcioacuten image j pg ( )

Vamos a crear una Web que haga uso de esta clase

lthtmlgt ltbodygt ltform action=imagenphp method=POST enctype=multipart form-datagt Elige un archivo de imagen jpg ltinput type=file name=ficherogt ltinput type=submit name=Enviar value=Enviargt ltformgt ltphp if (isset($_FILES[fichero] ) )

echo Imagen Originalltbrgt $fotografia = $_FILES[fichero][tmp_name] copy($fotografia$_FILES[fichero] [ntildeame]) $foto_copia = $_FILES[fichero] [ntildeame] ampmodo= original

290 Capiacutetulo 16

$url = clase_imagenphpfotografia=$foto_copia echo ltimg src=$urlgt echo Imagen Miniaturaltbrgt $foto_copia = $_FILES[fichero ] [ntildeame] ampmodo= miniatura $url = clase_imagenphpfotografia=$foto_copia echo ltimg src=$urlgt

gt ltbodygt lthtmlgt

La paacutegina Web muestra un formulario que nos da la posibilidad de enviar al servidor una fotografiacutea de nuestro ordenador

Si le damos a enviar la paacutegina nos mostraraacute la fotografiacutea en su versioacuten original y en su versioacuten reducida como puede comprobar en la figura 164

Generar una marca de agua

Otro problema comuacuten sencillo de resolver es la creacioacuten de marcas de agua sobre las fotografiacuteas que ofrecemos en nuestra Web La marca de agua puede ser un graacutefico o un texto que insertamos encima de la fotografiacutea original

Generacioacuten de graacuteficos con PHP 5 291

Una forma sencilla de implementar marcas de agua es antildeadiendo un meacuteshytodo nuevo a la clase

priacutevate function marca_agua()

$this-gtmarca_agua = imagecreatefrompngphppng) $dimensiones = getimagesize(phppng) $posicionx = $this-gtdimensiones [0] - $dimensiones [0] $posiciony = $this-gtdimensiones [1] - $dimensiones [1] imagecopy($this-gtimagen $this-gtmarca_agua $posicionx $posiciony 0 0 $dimensiones [0] $dimensiones[1] )

Podemos llamar al meacutetodo desde el constructor para que la imagen guarshyde la informacioacuten de la fotografiacutea grabada e inserte la marca en alguna parte de la misma Tambieacuten podemos generar un texto como marca de agua

Vamos a antildeadir un nuevo meacutetodo a la clase para poder marcar las fotoshygrafiacuteas

priacutevate function marca_texto()

$color = imagecolorallocate($this-gtiraagen 25500) iacutemagestriacuteng($thiacutes-gtimagen 4 0 0 Hecho con PHP5

$color)

La figura 165 muestra la inclusioacuten de una marca de agua graacutefica y otra marca de agua de texto

292 Capiacutetulo 16

La funcioacuten i m a g e a l l oacute c a t e () crea un color con los componentes RGB como paraacutemetros La funcioacuten devuelve un nuacutemero que identifica al color creado en la imagen La funcioacuten i m a g e s t r i n g () imprime un texto de color determinado en la imagen El segundo paraacutemetro es el tipo de fuenshyte que queremos introducir

Graacuteficos estadiacutesticos profesionales con JpGraph

JpGraph es una libreriacutea escrita en PHP que permite crear todo tipo de graacuteshyficos estadiacutesticos en dos y tres dimensiones Hace uso de la libreriacutea graacutefica GD en su versioacuten 2 Se puede descargar de la paacutegina wwwjpgraphorg

JpGraph tiene dos licencias de uso Una gratuita para proyectos no coshymerciales y con caraacutecter educativo y otra de caraacutecter comercial de pago Le recomiendo leer ambas licencias para comprobar que puede utilizarshylas

Para instalar la libreriacutea tiene que copiar el directorio con las clases en la ruta donde guarde su aplicacioacuten o en la ruta de buacutesqueda de PHP 5

Graacuteficos de barras

El ejemplo maacutes sencillo es la creacioacuten de un graacutefico con varios valores en el que podemos ver todos los valores interconectados entre siacute por unas liacuteneas

ltphp require_once (jpgraphjpgraphphp) require_once (jpgraph jpgraph_linephp) $datosy = array(11O81251913157) Creamos el graacutefico $grafico = new Graph(350250) $grafico-gtSetScale (textlin) Creamos una nueva linea de puntos $puntos =new LinePlot($datosy) $puntos-gtSetColor(blue) Antildeadimos los puntos al graacutefico $grafico-gtAdd($puntos) Se muestra el graacutefico $grafico-gtStroke ()

bull gt

Suponiendo que la libreriacutea esteacute guardada en la carpeta j p g r a p h haceshymos u n r e q u i r e _ o n c e () de la clase principal j p g r a p h php y de la clase que utilizaremos para graacuteficos de liacutenea j p g r a p h _ l i n e php La variable $ d a t o s y guarda diez valores que pueden identificar el nuacutemero de visishytas a nuestra Web o el nuacutemero de ventas por meses de un artiacuteculo Para crear un graacutefico tiene que crear el objeto Graph con el ancho y alto que quiere que tenga en la Web Lo siguiente es configurar la escala en la que apareceraacute el graacutefico Lo mejor es echar un vistazo al manual para eleshygir el que maacutes le convenga en cada momento

Seguidamente cree un conjunto de puntos con el meacutetodo L i n e p l o t () con los valores del array $ d a t o s y Puede elegir tambieacuten el color de la liacuteshynea resultado con el meacutetodo S e t C o l o r ()

Para finalizar antildeada los valores al graacutefico y mueacutestrelo con S t r o k e ()

Con estas liacuteneas hemos conseguido crear el graacutefico de la figura 166

Puede antildeadir algunas caracteriacutesticas maacutes a sus graacuteficos como tiacutetulos en

los ejes colores o varias liacuteneas de valores para comparar datos

Para antildeadir tiacutetulos a los graacuteficos le pueden servir las liacuteneas siguientes

$graf ico-gttitle-gtset (Graacutefico JpGraph) -

294 Capiacutetulo 16

$grafico-gtxaxis-gttitle-gtset(dia) $grafico-gtyaxis-gttitle-gtset(visitas)

El meacutetodo t i t l e genera un tiacutetulo asociado al objeto inmediatamente anshyterior Si el objeto es $ g r a f i c o el tiacutetulo seraacute el de la imagen completa Si el objeto anterior es el eje x o el eje y ( x a x i s o y a x i s ) el tiacutetulo corresshyponderaacute con cada uno de los ejes Puede ver el resultado en la figura 167

Ademaacutes puede antildeadir tantos datos como quiera para hacer un estudio comparativo de varios datos Para hacer esto debe repetir algunos pasos pero con distintos valores

$datosy2 = array(12378543127) $puntos2 = new LinePlot($datosy2) $puntos2-gtSetColor(red) $grafico-gtAdd($puntos2) $puntos-gtSetLegend(Europa) Spuntos2-gtSetLegend(America) $grafico-gtlegend-gtPos(00505rightcenter)

Como vimos en el ejemplo anterior podemos antildeadir otro array lleno de valores crear una nueva liacutenea de puntos con un color determinado y asoshyciarlo finalmente con el graacutefico que estamos creando como puede ver en

Graacuteficos en 3D

JpGraph realiza casi cualquier tipo de graacutefico estadiacutestico Uno de los maacutes utilizados es el graacutefico de quesito donde podemos evaluar por porcioshynes el dato de mayor amplitud soacutelo con un vistazo El ejemplo siguiente muestra coacutemo hacer un graacutefico de este tipo

ltphp include (jpgraph jpgraphphp) include (jpgraph jpgraph_piephp) include (jpgraph jpgraph_pie3dphp)

$datos = array(4 0So21 33)

$grafico = new PieGraph(300200) $grafico-gtSetShadow()bull

$grafico-gttitle-gtSet(Graacutefico de quesito) $pl = new PiePlot30($datos) $pl-gtSetAngle(20)

Generacioacuten de graacuteficos con PHP 5 295

la figura 168 Las uacuteltimas 3 liacuteneas antildeaden una leyenda en la parte derecha del graacutefico es decir un pequentildeo graacutefico explicativo de las liacuteneas de datos

296 Capiacutetulo 16

$pl-gtSetSize (05) $pl-gtSetCenter (045) $pl-gtSetLegends($gDateLocale-gtGetShortMonth())

$grafic0-gtAdd($pl) $grafic0-gtStroke ()

Para crearlo primero tiene que incluir los archivos j p g r a p h _ p i e php y j p g r a p h ^ p i e 3 d php que permitiraacuten instanciar el tipo de graacutefico P i e P l o t 3 D El meacutetodo SetShadowC) crea una sombra en eiacute contorno exterior del graacutefico La instanciacioacuten del graacutefico circular se hace sobre la variable $pi que empieza a tomar forma con las propiedades S e t A n -g l e () y S e t C e n t e r () que permiten definir el aacutengulo del graacutefico con respecto a la vista frontal y el centrado del graacutefico con respecto a la caja que lo contiene La fase final es antildeadir el quesito al graacutefico creado y mostrarlo en pantalla Una mejora del graacutefico anterior puede ser resaltar la porcioacuten del graacutefico que tiene mayor valor y separarlo notablemente Esto puede hacerse antildeadiendo la liacutenea siguiente

$ p l - gt E x p l o d e S l i c e ( 1 )

El graacutefico de quesito se muestra en la figura 169

Generacioacuten de graacuteficos con PHP 5 297

Resumen

El tratamiento de imaacutegenes desde PHP 5 nos da la posibilidad de crear proyectos muy profesionales Tanto la posibilidad de crear graacuteficos mas pequentildeos marcas de agua o texto sobreimpresos como la de generar esshytadiacutesticas en tiempo real crean un potencial que no todas las paacuteginas Web saben aprovechar

Existen algunos proyectos como K++ que permiten crear imaacutegenes del tipo Flash y que merece la pena indagar en la buacutesqueda de contenido orishyginales para nuestro portal

300 Capitulo 17

Introduccioacuten

Si estaacute familiarizado con otros lenguajes de programacioacuten como C o Java ya conoceraacute algunos mecanismos que permiten manejar errores y excepshyciones Una de las nuevas caracteriacutesticas que PHP 5 incluye es un objeto de manejo de excepciones con una sintaxis muy similar a Java El manejo de excepciones es una herramienta muy potente que podraacute apreciar una vez que comprenda el concepto y haga buen uso del objeto en su coacutedigo Estas funciones permiten depuiacutear condiciones de error reshycuperar situaciones inesperadas y presentar interfaces limpias de errores

Errores y Excepciones

Lo primero que tenemos que hacer es no pensar en una excepcioacuten como si fuera un error Una excepcioacuten es una condicioacuten que se experimenta en un programa inesperadamente y no puede ser manejada por el coacutedigo que hemos escrito Generalmente no causan la parada del programa pero siacute es posible detectarla para que continuacutee normalmente Las excepciones si son tratadas correctamente pueden dar maacutes fiabilidad a su aplicacioacuten y librarle de muchos dolores de cabeza Aunque si no son correctamente utilizadas pueden crear maacutes problemas que resolverlos Debe tomar un tiempo para determinar si necesita crear sus propios meacuteshytodos de manejo de errores y si es asiacute veraacute que a la larga resulta maacutes grashytificante Como ejemplo vamos a ver una pieza de coacutedigo que simula la recepcioacuten de un identificador de usuario y su posible comprobacioacuten en una base de datos Tal y como puede ver se comprueba que los tres prishymeros caracteres sean usr que el tamantildeo en caracteres sea al menos de 9 y que exista en una base de datos

ltphp extraemos el usuario por GET $usuario_id = $_GET[usuario_id ] Si existe el usuario escribimos el mensaje CORRECTO if (usuario_valido($usuario_id))

echo ERROR El usuario $usuario_id no existe else

echo CORRECTO El usuario $usuario_id existe

function usuario_valido($usuario_id)

Gestioacuten de errores en PHP 5 301

$cadena = usr Comprobaciones de usuario if ( (strstr ($usuario_id$cadena) == false) [[

(strpos($usuario_id$cadena) = 0)) return false

if (strlen ($usuario__id) lt 9) return false

if (existe__base_datos ($usuario_id) )

return true else

return false

gt

Como puede ver cualquier condicioacuten que estaacute dentro de la funcioacuten que valida los usuarios puede dar un resultado negativo y soacutelo uno de ellos daraacute un resultado positivo si el usuario existe en la base de datos

Las excepciones permiten distinguir entre distintos tipos de errores y manejarlos dependiendo de su naturaleza

La clase Exception

La clase Except ion se ha creado en PHP 5 para manejar las anomaliacuteas producidas En vez de utilizar comprobaciones que evaluacutean si es falso o verdadero una determinada condicioacuten se utiliza una instancia de la clase Except ion que captura los errores y permite mostrar un mensaje de error personalizado

ltphp extraemos el usuario por GET $usuario__id = $_GET [ usuario_id] Si existe el usuario escribimos el mensaje CORRECTO try

if ( lusuario_valido($usuario_id)) echo ERROR El usuario $usuario_id no existe

else echo CORRECTO El usuario $usuario_id existe

catch(Exception $ex)

Devuelve el mensaje de error $mensaje = ($ex-gtqetMessage() ) echo $mensaje

302 Capiacutetulo 17

function usuario_valido($usuario_id) $cadena = usr Comprobaciones de usuario if ( (strstr ($usuario_id$cadena) == false) |

(strpos($usuario_id $cadena) = 0)) throw new Exception ($usuario_id no contiene el

prefijo)

if (strlen($usuario_id) lt 9)

throw new Exception (El tamantildeo de $usuario_id es menor de 9 caracteres)

if (existe_base_datos($usuario_id) )

return false else

return false

Gestioacuten de errores en PHP 5 303

Como puede ver las excepciones se crean de una manera algo diferente En el momento en el que se escribe th row new E x c e p t i o n los errores que no se controlen con el flujo normal del programa son utilizados como excepciones separadas del resto de la aplicacioacuten

Bloque Try Catch

Las excepciones son controladas por el bloque t r y c a t c h Todo el coacutedishygo que escriba y que pueda generar un error se incluiraacute dentro de una estructura t r y Si dentro del bloque t r y se encuentra un error la ejecushycioacuten del coacutedigo se para y se pasa el control al bloque c a t c h Este bloque se consuita para encontrar la excepcioacuten que ha producido el error de acuershydo con el coacutedigo que hemos escrito

Una de las cosas maacutes convenientes de utilizar excepciones es que puede mostrar tanta informacioacuten o tan poca como quiera El objeto E x c e p t i o n tiene varios meacutetodos para manejar sus propios errores El coacutedigo siguiente muestra coacutemo utilizar t h row e inmediatamente capshyturar la excepcioacuten Podemos capturar tambieacuten algunos paraacutemetros uacutetiles

ltphp try

throw new Exception(Error de sintaxis) catch (Exception $ex)

Mensaje de error $mensaje = ($ex-gtgetMessage ()) Coacutedigo de error configurable $codigo = ($ex-igetCode()) Fichero del error $fichero = ($ex-gtgetFile ( ) ) Linea donde se ha producido el error $linea = ($ex-gtgetLine())

echo Error nuacutemero $codigo $mensaje en el fichero $fichero en la linea $linea

gt

El mensaje de error que se muestra es muy tiacutepico en PHP Como es totalshymente configurable puede generar su propio formato de Mensaje de Error que puede ver en la figura 172

Aunque en este ejemplo el coacutedigo que captura la excepcioacuten soacutelo tiene una liacutenea podraacute incluir dentro del bloque varias liacuteneas o funciones dentro que actuaraacuten de la misma forma

Heredar de (a clase Exception

PHP 5 permite definir sus propias clases qulta heredan de la clase E x c e p shyt i o n Puede hacerlo de la siguiente forma

ltphp class Excepcioacuten extends Exception

function construct($mensaje)

parent Exception($mensaj e)

gt

El siguiente ejemplo muestra coacutemo crear clases propias que manejan erroshyres a partir de la clase E x c e p t i o n

ltphp $usuario_id = $_GET[usuario_id] try

if f J usuario_valido ($usuario__id) ) [ echo ERROR El usuario $usuario id no existe

Gestioacuten de errores en PHP 5 305

else echo CORRECTO El usuario $usuario_id existe

catch(MiExcepcion $ex)

$cadena = usr if ((strpos($usuario_id$cadena) == false) |]

(strpos($usuario_id$cadena) = 0)) $mensaje = $ex-gtgetMessage()

catch(OtraExcepcion $ex)

if (strlen($usuario_id) lt 9) $mensaje = $ex-gtgetMessage()

Definicioacuten de las clases que heredan de Exception class MiExcepcion extends Excepcioacuten

function construct($mensaje)

parentException($mensaje)

class OtraExcepcion extends Excepcioacuten

function construct($mensaje)

parent Exception($mensaj e)

echo $mensaje function usuario_valido($usuario_id)

$cadena = usr if ((strpos($usuario_id$cadena) == false) ||

(strpos($usuario_id$cadena) = 0)) throw new MiExcepcion(Usuario $usuario_id no

contiene el prefijo )

if (strlen($usuario_id) lt 9) throw new OtraExcepcion(Usuario tiene menos de 9

caracteres)

gt

Limitaciones de PHP 5

El objeto de excepciones es totalmente nuevo en PHP 5 Debido a esto algunas funcionalidades creadas en otros lenguajes de programacioacuten como

306 Capiacutetulo 17

Java no han sido todaviacutea implementadas por ejemplo el uso de los meacutetoshydos f i n a l ly () y t h r o w s () Los errores comunes de PHP que se muesshytran en el navegador no son mapeados a excepciones automaacuteticamente Esta funcionalidad seraacute implementada en versiones posteriores de PHP Los errores que no pueden ser controlados por E x c e p t i o n pueden mashynejarse con otras teacutecnicas de programacioacuten

Control de errores sin excepciones

Si ya conoce algunas versiones de PHP sabraacute que hay multitud de funcioshynes capaces de controlar errores incluidos los errores nativos de PHP controladores personalizados de error y los errores de usuario

Errores nativos de PHP

PHP genera 3 tipos de error dependiendo de su seriedad

bull Notice No son errores severos y no crean problemas complejos Por defecto no se muestran en pantalla cuando suceden a menos que dishygamos lo contrario en el archivo de configuracioacuten php i n i

bull Warning Alguna parte del coacutedigo ha causado un error pero la ejecushycioacuten continuacutea

bull Fatal error Un problema serio que hace abortar la ejecucioacuten del proshygrama

Cada tipo de error es representado por una constante diferente E_USER_NOTICE E_USER_WARNING y E_USER_ERROR Puede elegir el nivel de error que quiere mostrar en pantalla con la funcioacuten e r r o r _ r e p o r t i n g ( )

ltphp Mostrar errores fatales error_reporting(E_USER_ERROR) Mostrar advertencias y notificaciones error_reporting(E_USER_WARNING | E_USER_NOTICE) Mostrar todos los errores error_reporting (E__USER__ALL) gt

El manejo de errores queda limitado la mayoriacutea de veces a los del tipo warn ing Los errores fatales se consideran tan criacuteticos que no pueden conshytrolarse y la ejecucioacuten del programa queda suspendida

Gestioacuten de errores en PHP 5 307

Controladores de error

Cuando suceda un error que no tenga contemplado en su aplicacioacuten pueshyden aparecer mensajes en la pantalla que no interesa mostrar La solucioacuten es crear su propia funcioacuten para controlar y mostrar errores

ltphp function errores($errormensaje$fichero$linea)

echo ltbgt ERROR ltbxbrgt echo Sentimos comunicarle que se ha producido un error echo Tipo de error $error $mensaje en $fichero en la linea $linea

gt

Con estas liacuteneas hemos creado una funcioacuten que muestra el error producishydo pero con un disentildeo acorde a nuestra paacutegina Web Puede mostrar tanta informacioacuten como quiera El siguiente paso es llamar a la funcioacuten s e t _ e r r o r _ h a n d l e r () para que PHP sepa que nuestra funcioacuten e r r o shyr e s () se va a encargar a partir de ahora de gestionar los posibles fallos en el flujo del programa

ltphp set_error_handler(errores) gt

308 Capiacutetulo 17

Con el coacutedigo anterior todos los errores producidos del nivel que tenga permitido ( f a t a l e r r o r w a r n i n g o n o t i c e ) seraacuten enviados a la funshycioacuten e r r o r e s () para mostrar su mensaje particular

Errores de usuario con trigger_error()

Desde PHP 4 puede usarse una funcioacuten para identificar los errores proshyducidos por los usuarios muy parecida a la funcioacuten de PHP 5 th row () La funcioacuten t r i g g e r _ e r r o r () genera un error del tipo que quiera ( f a shyt a l e r r o r warn ing o n o t i c e ) y seraacute gestionado por PHP o por su propio gestor de errores

ltphp error_reporting(E_ALL) function errores($error$mensaje$fichero$linea)

echo ltbgt ERROR ltbxbrgt

echo Sentimos comunicarle que se ha producido un error echo Tipo de error $error $mensaje en $fichero en la liacutenea $ linea

set_error_handler(errores)

if (1 = 0 ) trigger_error( Esto es falso E_USER_NOTICE)

gt

Es mejor u t i l izar s iempre la funcioacuten t r i gg e r _ e r r o r ( ) con s e t _ e r r o r _ h a n d l e r () El error que creemos puede ser de cualquiera de los 3 tipos existentes en PHP En este caso generamos un error no t i -ce para indicar que la condicioacuten es falsa

Depuracioacuten de errores

El manejo de errores puede ahorrar esfuerzos a la hora de depurar el funshycionamiento oacuteptimo de su coacutedigo pero tambieacuten puede crear algunos doshylores de cabeza si empieza a suprimir algunos fallos

La f u n c i oacute n e r r o r _ l o g () crea un archivo donde se iraacuten almacenando las ocurrencias de su coacutedigo Con el siguiente ejemplo podraacute capturar todos los errores producidos en el programa para despueacutes hacer un estudio de lo que ha pasado

ltphp

Gestioacuten de errores en PHP 5 309

try if ($usuario = Luis)

throw new Exception(El usuario no existe)

catch (Exception $ex)

$mensaje = ($ex-gtgetMessage() ) $codigo = ($ex-gtgetCode() ) $fichero = ($ex-gtgetFile()) $linea = ($ex-gtgetLine()) $log_mensaje =date(Hi d-m-Y) Error $codigo en

$fichero en la liacutenea $linea Error $mensaje error_log($log_mensaj e3 UsersluisSiteserrorlog) echo $log_mensaje

gt

Nota

Los ficheros l o g son muy utilizados en los Sistemas Operativos para mantener un registro de incidencias Los ficheros l o g guarshydan desde el nuacutemero de veces que ha entrado un usuario hasta los errores que se han producido en el inicio del sistema

La funcioacuten e r r o r _ l o g () puede pasar como segundo paraacutemetro un nuacuteshymero entero que identifica el tipo de error y queacute hacer con eacutel

bull 0 Se utiliza el mecanismo del sistema operativo bull 1 Enviacutea el error a una direccioacuten de correo especificada como cuarto

paraacutemetro (Debe formar parte de una cabecera) bull 2 Enviacutea el error a traveacutes de una sesioacuten de depuracioacuten de PHP (Debe

estar habilitado el modo depuracioacuten)

bull 3 Enviacutea el error a un fichero

Resumen

Como puede darse cuenta la mayoriacutea de los programas incluidos en el libro no tienen ninguacuten tipo de control de errores He preferido evitarlos para ganar en claridad y no tener que empezar explicando los bloques Try Catch desde el principio A partir de ahora sieacutentase libre para modifishycar todos los scripts a su antojo para que sean maacutes fiables y seguros

310 Capiacutetulo 17

El desarrollo de las posteriores versiones de PHP permitiraacute manejar los errores maacutes faacutecilmente El futuro de las excepciones no ha hecho maacutes que empezar con la versioacuten 5 de PHP y se esperan mejoras suculentas con respecto a las anteriores Pese a esto muchas libreriacuteas ya incluyen sus proshypios controles de error como la de MySQL o PEAR

312 Capiacutetulo 18

Introduccioacuten

Transferir ficheros de un ordenador a otro es una tarea que sucede milloshynes de veces a lo largo del diacutea en Internet Ya no es un problema comparshytir un fichero entre dos ordenadores ubicados entre distintos puntos del mundo Los dos meacutetodos maacutes utilizados son el protocolo FTP y el correo electroacutenico

Los ficheros pueden ser transferidos simplemente dejaacutendolos en alguacuten lugar puacuteblico de nuestro servidor Web o utilizando alguacuten programa para enviarlos El protocolo FTP y el correo electroacutenico son programas indeshypendientes que deben estar instalados en el servidor para poder usarse Son dos programas del tipo cliente servidor Para poder utilizar cualshyquiera de los dos servicios anteriores debe conectarse a un servidor en un ordenador remoto y enviar los datos

FTP

Para utilizar el protocolo FTP tiene que tener habilitada la opcioacuten cuando instale PHP Puede utilizar FTP para enviar ficheros en un script escrito en PHP desde alguna paacutegina Web Para conectar a un servidor tendraacute que utilizar la siguiente funcioacuten

$conexioacuten = f tp__connect ( www l u i s y f ernanda net)

Tambieacuten puede utilizar una direccioacuten IP para la conexioacuten $conexioacuten = f tp_connect (12 7 0 0 1)

Nota

La direccioacuten IP identifica un uacutenico ordenador dentro de Internet

La IP 127001 apunta a nuestro propio ordenador

El servidor FTP contiene un listado de usuarios a los que les permite la conexioacuten Dependiendo del usuario que se conecte el servidor le permitishyraacute descargar unos archivos u otros

El siguiente paso es autentificarse como usuario del servidor de FTP con la funcioacuten

ftp_login($conexioacuten $usuario $clave)

Conexiones desde PHP 5 313

Como paraacutemetros tiene que pasar la conexioacuten establecida anteriormente el usuario y la contrasentildea

Advertencia

El protocolo FTP no es seguro El usuario y la contrasentildea se enshyviacutean en formato de texto y podriacutean ser capturados por alguacuten proshygrama sniffer que se encuentre entre su ordenador y el servidor de destino

Como de costumbre puede encapsular todas las funciones para hacer una clase que permita conectar a un servidor

ltphp class ftp

priacutevate $serviacutedor priacutevate $usuario priacutevate $clave priacutevate $conexion priacutevate $login function construct($servidor$usuario $clave)

set_time_limit(0) $this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtclave = $clave $thiacutes-gtconectar($this-gtservidor)

priacutevate function conectar($servidor)

$this-gtconexion = ftp_connect($servidor21 30) priacutevate function loginFtp($usuario$clave)

$this-gtlogin = ftp_login($this-gtconexion usuario $clave)

$ftp = new ftp(127001luissecreto) gt

Como puede ver el meacutetodo constructor utiliza la funcioacuten set__t ime_ l i m i t () Normalmente los script de PHP tienen un tiempo de vida deshyterminado en el fichero de configuracioacuten php i n i Este tiempo suele ser de 30 segundos y es una proteccioacuten para que si un programa se queda

314 Capiacutetulo 18

bloqueado y su ejecucioacuten lleva maacutes de ese tiempo automaacuteticamente queshyde cancelada su ejecucioacuten

La funcioacuten s e t _ t i m e _ l i m i t () le da la posibilidad de ampliar el tiemshypo de ejecucioacuten al nuacutemero de segundos que indique como paraacutemetro Si el argumento es un 0 el tiempo de ejecucioacuten seraacute infinito

La funcioacuten f t p _ c o n n e c t () tambieacuten puede llevar como paraacutemetros el puerto de conexioacuten (por defecto es el 21) y el nuacutemero de segundos que tardaraacute PHP en volver a intentar la conexioacuten si el intento anterior ha sido fallido

Mostrar los archivos remotos

Despueacutes de conectar con el servidor de FTP lo maacutes usual es recuperar un listado de ficheros que estaacuten en el servidor La funcioacuten f t p _ n l i s t () extrae el nombre de los archivos del directorio que pasemos como paraacuteshymetro

El resultado es un array

public function ver($directoriacuteo = )

$this-gtarchivos = ftp_nlist($this-gtconexion$directorio) foreach ($this-gtarchiacutevos as $archivo)

echo $archivoltbrgt

Puede antildeadir el meacutetodo anterior a la clase f t p La funcioacuten f t p _ n l iacute s t () utiliza la conexioacuten almacenada en el constructor de la clase y recibe un listado de ficheros que guarda como array en la variable $this-gtarchivos

Maacutes adelante utilizando un bucle f o r e a c h podraacute extraer todos los nombres e imprimirlos en pantalla como puede comprobar en la figushyra 181

Si no es la primera vez que utiliza el protocolo FTP sabraacute que al conecshytar con un servidor lo maacutes comuacuten es que conecte en el sistema raiacutez donshyde encontraraacute los archivos y directorios que puede utilizar La funcioacuten f t p _ c h d i r () permite cambiar de directorio dentro del sistema de fishycheros

Si en alguacuten momento no sabe en queacute directorio se encuentra puede hashycer uso de la funcioacuten f tp_pwd ( ) que le daraacute la ruta completa de su situacioacuten

Descargar y Enviar ficheros

Puede descargar ficheros con la funcioacuten f tp_ge t () El siguiente ejemshyplo descarga un fichero despueacutes de hacer la conexioacuten

ftp_get($conexioacuten nuevoFicherotxtFicherotxtFTP_ASCII)

El nombre nuevoFichero t x t se corresponde con el nombre del ficheshyro que tendraacute el archivo despueacutes de ser descargado y F iche ro t x t es el archivo remoto que queremos descargar El uacuteltimo paraacutemetro FTP_ASCI I le dice al FTP el tipo de archivo que va a ser descargado Los modos que puede elegir son FTP_ASCI I o FTP_BINARY Los ficheros binarios son archivos escritos en el lenguaje maacutequina como los archivos graacuteficos Ademaacutes puede enviar archivos al servidor con la funcioacuten f tp_put () El siguiente ejemplo muestra coacutemo subir un archivo al servidor

ftp_put($conexion nuevoFicherotxtFicherotxtFTP_ASCII)

Como en el ejemplo anterior n u e v o F i c h e r o t x t seraacute el nombre del archivo en el servidor remoto y F i c h e r o t x t el archivo que vamos a enviar El ejemplo siguiente descarga todos los archivos con extensioacuten PHP en nuestro ordenador local

public function descargaPHP($directorio = )

316 Capiacutetulo 18

$this-gtarchivos = ftp_nlist($this-gtconexion$directorio) foreach ($this-gtarchivos as $archivo)

if (ereg(php$archivo)) if ( f ile__exists ($archivo) )

ftp_get($this-gtconexion$archivo$directorio $archivoFTP_ASCII)

else

echo Fichero $archivo ya existeltbrgt

else

echo El archivo $archivo no es de PHPltbrgt

Otras funciones de FTP

Ademaacutes de las funciones descritas en este capiacutetulo existen otras muchas para el manejo del protocolo FTP

Tabla 181 Funciones comunes al manejo de FTP

Funciones Descripcioacuten

ftp_cdup($conexion) Cambia al directorio inmediatamente

superior al directorio actual ftp_chdir($conexioacuten Cambia al directorio que pasemos como

nombre directorio) paraacutemetro

ftp_close($conexion) Cierra una conexioacuten FTP

ftpconnect(servidor) Establece una conexioacuten con el servidor

ftp_delete($conexioacuten ruta) Borra un fichero del servidor

ftp_exec($conexioacuten comando) Ejecuta un comando del sistema remoto

ftp_fget($conexioacuten $descriptor Descarga un fichero y vuelca los datos Ficherotxt FTP_ASCII) en un fichero abierto en el ordenador

local

ftp_fput($conexioacuten $descriptor Enviacutea un archivo a un fichero abierto Ficherotxt FTP_ASCII)

ftp_get($conexioacuten nuevoFicherotxt Recupera un fichero de un servidor Ficherotxt FTP_ASCII)

ftp_put($conexioacuten nuevoFicherotxt Enviacutea un fichero al servidor

Ficherotxt FTP_ASCII)

Conexiones desde PHP 5 317

Funciones Descripcioacuten

ftp_login($conexiexcloacuten $usuario $clave) Autentifica al usuario en el servidor ftp_mdtm($conexioacutenFicherotxt) Recupera la fecha de la uacuteltima actualishy

zacioacuten del fichero ftp_mkdir($conexioacuten directorio) Crea un directorio

ftp_nlist($conexioacuten directorio) Recupera la lista de archivos de un directorio

ftp_pwd($conexion) Obtiene el nombre del directorio actual ftp_rename($conexioacuten Cambia de nombre un archivo remoto ArchivoAntiguoArchivoNuevo) ftp_size($conexionFicherotxt) Devuelve el tamantildeo de un fichero ftp_systype($conexion) Permite obtener el tipo de sistema

Correo electroacutenico

La aplicacioacuten maacutes utilizada sin duda en Internet es el correo electroacutenico La explosioacuten de Internet y la expansioacuten de servidores gratuitos que ceden cuentas de correo a todos los usuarios ha permitido que el crecimiento de los e-tnail se dispare en estos uacuteltimos antildeos

Para lograr la comunicacioacuten a traveacutes del correo electroacutenico han de intershyvenir numerosas piezas de un puzzle

La mayor parte del modelo utiliza

bull Servidor TCP IP Se encarga de mantener activos para la conexioacuten diversos servicios como FTP SMTP o POP

bull MTA (Mail Transfer Agent) Acepta correo de otros servidores SMTP y busca una ruta para que los correos lleguen a su destino

bull Cola de correo Recipiente donde se almacenan todos los correos enshytrantes dirigidos a una persona

bull MUA (Mail User Agent) Programa muy liviano para leer el correo elecshytroacutenico normalmente desde el servidor

bull Servidor POP IMAP Recibe peticiones de lecturas de correo El sershyvidor chequea si hay correos nuevos y los enviacutea al cliente

bull MLM (Mailing List Manager) Este software ayuda a enviar grandes cantidades de correo

318 Capiacutetulo 18

Enviar correo desde PHP

Soacutelo existe una funcioacuten para enviar correo electroacutenico desde PHP 5 La funcioacuten mail () devolveraacute un valor true si los datos son enviados correcshytamente La forma maacutes sencilla de utilizar esta funcioacuten la puede ver en el ejemplo siguiente

ltphp $resultado = mail ( luisaacutenccextremadura org Ejemplo de Asunto Cuerpo del mensaje) if ($resultado)

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt

El primer paraacutemetro recibe el correo de la persona a la que quiere enviar el mensaje El segundo es un resumen del contenido de su carta electroacutenishyca y por uacuteltimo el tercer paraacutemetro es el mensaje que quiere transmitir Puede dividir la funcioacuten en variables para que sea maacutes sencillo de utishylizar

ltphp $correo = luisnccextremaduraorg $asunto = Ejemplo de Asunto $cuerpo = Cuerpo del mensaje $resultado = mail($correo $asunto $cuerpo) if ($resultado)

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt

Hay veces que necesitaraacute algo maacutes de control sobre lo que quiera enviar o necesite enviar un correo a varias personas a la vez Esto es posible antildeashydiendo cabeceras adicionales a la funcioacuten mail

ltphp $correo = luisnccextremaduraorg $asunto = Ejemplo de Asunto $cuerpo = Cuerpo del mensaje $cabecera = From fernandarnbccpedronccextremaduraorgrnContent-type textplainrnX-mailer PHP phpversion () $resultado = mail($correo $asunto $cuerpo $cabecera) if ($resultado)

Conexiones desde PHP 5 319

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

La cabecera muestra coacutemo enviar junto al correo la direccioacuten de la persoshyna que lo enviacutea y una copia del mismo mensaje al correo pedroncc extremaduraorg Es necesario antildeadir los separadores r y n para indishycar un salto de liacutenea entre los paraacutemetros de la cabecera

Las cabeceras adicionales pueden antildeadir muchos tipos de informacioacuten entre los que se encuentran

bull El nombre del emisor

bull Correo del emisor

bull Correo de respuesta

bull X-mailer y nuacutemero de versioacuten

bull versioacuten MIME

bull Content-type

bull Codificacioacuten

bull Campo de copia y copia oculta

La funcioacuten m a i l () estaacute preparada para emitir mensajes sencillos pero hay muchas caracteriacutesticas que debe implementar con cabeceras Por eso han nacido una serie de libreriacuteas escritas en PHP que facilitan el enviacuteo de correos

La libreriacutea PHPMailer antildeade a la funcioacuten m a i l () muchas funcionalidashydes como ficheros adjuntos o correos HTML

PHPMailer

PHPMailer estaacute basado en programacioacuten orientada a objetos Contiene varios ficheros que deben guardarse en el directorio de PHP dedicado a libreriacuteas o en nuestro espacio de trabajo

La construccioacuten maacutes baacutesica es la siguiente

ltphp require_once(phpmailerclassphpmailerphp) $correo = new phpmailer() Datos personales del emisor $mail-gtFrom = luisnccextremaduraorg

320 Capitulo 18

$mail-gtFromName = Luis Miguel Cabezas

$mail-gtSubject = Mensaje de prueba

$mail-gtBody = Cuerpo del mensaje Direccioacuten de destino $mail-gtAddAddress(zeevSphpzendcomZeev Suraski)

if ( l$mail-gtSend()) echo Correo enviado correctamente

else echo El correo no ha podido enviarse

gt

Como puede ver las propiedades de la clase p h p m a i l e r son auto explishycativas El ejemplo va asociando cada propiedad a un dato necesario para el enviacuteo El meacutetodo A d d A d d r e s s () antildeade una direccioacuten de correo a la que enviar el mensaje y Send () lo enviacutea a traveacutes de Internet

Antildeadir un fichero adjunto

Existen tres meacutetodos para antildeadir un fichero adjunto a un mensaje dos para archivos y otro maacutes especiacutefico para imaacutegenes

bull AddAttachment(ruta nombre) Antildeade un fichero localizado en el servidor Este archivo se puede subir antes al servidor mediante un formulario

bull AddStringAttachment(caracteres fichero) Se puede utilizar para enviar ficheros almacenados en variables

bull AddEmbeddedImage(ruta cid nombre) Antildeade una imagen y pershymite antildeadirla al cuerpo de un correo HTML

Las liacuteneas siguientes se pueden antildeadir al ejemplo anterior para enviar un fotografiacutea almacenada en el servidor

if ($mail-gtAddAttachment(abuelojpgabuelojpg))

echo Falloacute al antildeadir un fichero adjunto

Para demostrar la teoriacutea anterior vamos a crear un pequentildeo formulario que permita enviar correo Es un coacutedigo muy sencillo pero permite enshyviar mensajes escritos en HTML e incluir imaacutegenes

ltphp if (isset($_POST[nombre]))

require_once(phpmailerclassphpmailerphp)

Conexiones desde PHP 5 321

$correo = new phpmailer() Datos personales del emisor $mail-gtFrom = luisnccextremaduraorg $mail-gtFxowpoundawgte = Luis Miguel Cabezas $mail-gtSubject = $_POST [ asunte ] $mail-gtBody = $_POST[mensaje] Direccioacuten de destino $mail-gtAddAddress($_POST[nombre]$_POST[correo]) if ($mail-gtAddEmbeddedImage($_FILES[imagen] [tmp_name 12 34 5 imagen))

echo Falloacute al antildeadir un fichero adjunto

if ( $mail-gtSend() )

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt lthtmlgt ltbodygt ltform action=mailphp method=post enctype=multipartform-data name=formlgt lttable width=50 border=0 cellspacing=0

cellpadding=Ogt lttrgt

lttd width=28gtNombrelttdgt lttd width=72xinput name=nombre type=text

id=nombregtlttdgt lttrgt lttrgt lttdgtCorreolttdgt lttdxinput name=correo type=text id=correogtlttdgt

lttrgt lttrgt lttdgtAsuntolttdgt lttdxinput name=asunto type=text id= asuntogtlttdgt

lttrgt lttrgt lttdgtMensajelttdgt lttdxtextarea name= mensa j e rowS=5 id= mensa j e gtlt textareaxtdgt

lttrgt lttrgt lttdgtSelecciona imagen lttdgt lttdxinput name=imagen type=file id= imagen xtdgt

lttrgt lttablegt ltpgt

322 Capiacutetulo 18

ltinput type=submit name=Submit value=Enviargt ltPgt

lt formgt ltbodygt lthtmlgt

La figura 182 muestra un formulario capaz de enviar contenido HTML e imaacutegenes adjuntas

Resumen

PHP se ha promovido tanto debido a las numerosas extensiones que pershymiten hacer casi cualquier cosa En concreto las dos formas vistas para conectarse con un servidor le seraacuten muy uacutetiles para ofrecer servicios inshynovadores a sus usiiarios

La mayoriacutea de los portales Web que necesitan el registro de sus usuarios enviacutean por correo electroacutenico las contrasentildeas y los datos de inscripcioacuten La funcioacuten mail () le puede servir para hacer sus pequentildeos controles de usuarios

Conexiones desde PHP 5 323

Si se siente maacutes ambicioso tambieacuten puede utilizar PHPMailer para consshytruir una paacutegina Web que permita enviar o recibir correo electroacutenico La recomendacioacuten es que continuacutee investigando en la clase PHPMailer y en todo lo que ofrece que no hemos podido ver en este capiacutetulo

326 Capiacutetulo 19

Introduccioacuten

Como probablemente ya sabe el HTML no es el uacutenico formato para mosshytrar contenido en Internet Ademaacutes de los distintos tipos de imaacutegenes teshynemos varios formatos capaces de contener textos como Adobe PDF Macromedia Flash o algunos documentos alternativos escritos en XML como los archivos graacuteficos SVG (Graacuteficos Vectoriales Escalables) WML (Lenguaje de Marcas Inalaacutembrico) o XUL (Lenguaje de interfaz de Usuashyrio en XML con Mozilla) Cada uno de estos tipos de documentos tiene su propio terreno y de nosotros depende elegir cuaacutel o cuaacuteles utilizar para dotar a nuestra Web de mayores posibilidades

Los archivos Adobe PDF se han establecido como un estaacutendar en los doshycumentos de texto para la Web

Existen dos extensiones escritas para PHP PDFLib y C l ibPDF capaces de generar archivos PDF Desgraciadamente estas libreriacuteas son de uso coshymercial y requieren el pago de alguacuten tipo de licencia Ademaacutes de las extensiones anteriores tenemos una serie de aplicaciones escritas completamente en PHP que permiten llegar al mismo resultado como RampOS PDF o FPDF No son tan raacutepidas como las extensiones pero cumplen perfectamente nuestras expectativas

Libreriacutea FPDF

La libreriacutea FPDF creada en septiembre de 2001 no necesita licencia de uso ni tampoco alguna configuracioacuten especial de PHP Lo uacutenico que neshycesita es la libreriacutea que la puede descargar del sitio Web h t t p wwwfpdforg

La libreriacutea principal contiene la definicioacuten de una clase que debe instan-ciar para poder generar sus documentos Nuestro coacutedigo inicial deberiacutea ser algo parecido a

ltphp require__once ( f pdf fpdf php) $pdf = new FPDF() gt

El constructor se utiliza de esta forma con los valores por defecto que son paacutegina A4 con orientacioacuten vertical y el tamantildeo medido en miliacutemetros El primer paraacutemetro del constructor permite elegir entre orientacioacuten verti-

Creacioacuten de archivos PDF 327

cal (L) u horizontal (P) El segundo paraacutemetro sirve para que las medidas de referencia se hagan en base a puntos (pt) miliacutemetros (mm) centiacutemetro (cm) o pulgadas (in) El uacuteltimo paraacutemetro nos ofrece la oportunidad de elegir entre los diferentes formatos de paacutegina que existen A3 A4 A5 Let-ter y Legal

Nota

Hay que recordar que un punto es 172 pulgadas

$pdf = new FPDF( P cm A 4 )

Nuestro primer documento

El siguiente ejemplo muestra la creacioacuten baacutesica de un documento PDF de forma lineal

ltphp define(FPDF_FONTPATHfpdffont) require_once ( fpdffpdfphp) $pdf = new FPDF() $pdpound-gtAddPageU bull $pdf-gtSetFont(Arial 15) $pdf-gtWrite(155 Mi primer documento) $pdf-gtOutput() gt

La primera liacutenea define una constante que contiene la ruta donde estaacuten almacenadas las fuentes Despueacutes de las funciones que incluyen la clase y la instancia del objeto tenemos una serie de llamadas a meacutetodos que nos permiten manipular el documento a nuestro antojo

Advertencia

FPDF mantiene la posicioacuten de un cursor Las funciones que geneshyran texto imprimiraacuten los datos de acuerdo con la posicioacuten del curshysor en ese momento Es posible de todas formas cambiar de sitio el cursor con algunas funciones que veremos en este capiacutetulo

El meacutetodo AddPage () antildeade una paacutegina al documento con la orientashycioacuten que Le pida En este caso hemos antildeadido una con orientacioacuten vertical que es la elegida por defecto S e t F o n t () selecciona una fuente tomando

Funciones de texto

Meacutetodo Write()

Imprime el texto pasado como paraacutemetro en la posicioacuten que indica el curshysor La construccioacuten es

W r i t e ( a l t u r a t e x t o e n l a c e )

Los paraacutemetros son los siguientes

bull altura Altura de la celda bull texto Texto a imprimir bull enlace Podemos considerar el texto como un enlace a una paacutegina o a

una Web

Como ejemplo puede ver el primer coacutedigo que hemos realizado

328 Capiacutetulo 19

como paraacutemetro el tipo la propiedad (negrita cursiva) y el tamantildeo Por uacuteltimo tenemos una llamada a los meacutetodos Write () y Output () que escriben el texto en una posicioacuten determinada del documento y lo muesshytran en pantalla respectivamente como puede ver en la figura 191

Creacioacuten de archivos PDF 329

Meacutetodo Cell()

El meacutetodo c e l l () puede tomar hasta 8 paraacutemetros y es el encargado de imprimir en el documento PDF un cuadro de texto en la posicioacuten indicashyda El cuadro de texto puede tener un borde alrededor o en alguno de los lados

La construccioacuten es como sigue

cell(ancho altura texto borde liacutenea alineacioacuten relleno enlace)

Los dos primeros paraacutemetros son obligatorios los demaacutes opcionales A continuacioacuten vemos para queacute sirve cada paraacutemetro

bull ancho Ancho de la celda Si es 0 se considera el ancho total del folio

bull altura Altura de la celda

bull texto Texto a imprimir

bull borde Un 1 significa que llevaraacute borde Tambieacuten se pueden incluir algunos caracteres para indicar en cuaacutel de las partes de la celda debe llevar borde L R T y B significan Izquierda Derecha Arriba y Abajo respectivamente

bull liacutenea Cuando termine la llamada a la creacioacuten de la celda indica al generador de PDF doacutende debe colocar el cursor para continuar Un 0 indica a la derecha de la tabla un 1 en la siguiente liacutenea y un 2 seguido

bull alineacioacuten Acepta 3 caracteres L para alinear a la izquierda R a la derecha y C para texto centrado

bull relleno Indica con un 1 si la celda debe tener un relleno para diferenshyciarla del resto del folio

bull enlace Enlace devuelto por la funcioacuten A d d l i n k ()

Como ejemplo puede ver la forma de introducir un tiacutetulo en una paacutegina

lt php define(FPDF_FONTPATHfpdffont) require__once ( fpdffpdf php i $pdf = new FPDF()

$pdf-gtAddPage() $pdf-gtSetFont(Courier 1 0 ) $pdf-gtCell(80) $pdf-gtCell (2010 Titulo 11C) $pdf-gtOutput() gt

Una celda soacutelo puede contener el nuacutemero de caracteres que quepa en una liacutenea Si necesita mostrar maacutes liacuteneas de texto puede utilizar el meacutetodo

330 Capiacutetulo 19

Muiacute ti Ce 11 () que toma los mismo paraacutemetros que Ce 11 ( ) pero cuanshydo el texto llegue al final de la liacutenea se antildeade automaacuteticamente un salto a la liacutenea siguiente

Truco

Puede utilizar Ce 11 () para desplazar el cursor hacia la derecha antildeadiendo como paraacutemetro un ancho de 8 centiacutemetros (80 miliacuteshymetros) Despueacutes para imprimir el texto antildeada otra celda que inshycluya el literal Tiacutetulo centrado dentro de una celda con borde

Desplazamiento de los cursores

Existen varias funciones para colocar el cursor en distintas partes del doshycumento Se tX () y S e t Y () colocan el texto en el punto indicado en la medida seleccionada (centiacutemetros miliacutemetros etc)

Se tX () desplaza el cursor de izquierda a derecha tantas unidades como indique el paraacutemetro y S e t Y () de arriba hacia abajo Si se les pasa un nuacutemero negativo el origen se tomaraacute desde la derecha o desde abajo resshypectivamente

SetXY () toma dos valores y permite realizar las dos operaciones con una sola instruccioacuten

$pdf-gtSetXY(100100) $pdf-gtwrite(2Este texto se mostraraacute a 10 cm del margen)

Salto de paacutegina automaacutetico

El meacutetodo S e t A u t o P a g e B r e a k () activa o desactiva el salto de paacutegina automaacutetico

Esto quiere decir que si estaacute activado cuando el texto llegue al final de la paacutegina se crearaacute una paacutegina nueva para poder contener el resto El primer paraacutemetro debe ser true ofalse para activa o desactivar la proshypiedad

El segundo paraacutemetro indica la distancia desde la parte inferior que desshyencadena la llamada a una nueva paacutegina

Se tAutoPageBreak( t rue 20 )

El coacutedigo anterior activa el salto de paacutegina automaacutetico cuando el texto lleshygue a 2 centiacutemetros del margen inferior

Creacioacuten de archivos PDF 331

Sobrescribir los meacutetodos

La clase FPDF contiene algunos meacutetodos vaciacuteos que debe escribir usted si quiere que sus documentos queden profesionales Puede crear un objeto propio que herede del objeto FPDF e implementar algunas caracteriacutesticas avanzadas

Cabecera

La cabecera de un documento es un conjunto de texto escrito en la parte superior del folio y que debe aparecer en todas las paacuteginas La clase FPDF implementa el meacutetodo header () que se llama cada vez que existe un salto de paacutegina

Puesto que el meacutetodo estaacute vaciacuteo en FPDF tendraacute que crear un objeto nueshyvo que herede todos sus meacutetodos e implemente la cabecera

ltphp define ( FPDF_FONTPATH fpdffont ) requireonce(fpdffpdfphp) class PDF extends FPDF

function Header()

$this-gtSetFont(ArialB15) $this-gtSetX(70) $this-gtCell(100 10 Manual Imprescindible de PHP 510C) $this-gtLn(20)

$pdf = new PDF () for($i=l$ilt=200$i++) $pdf-gtCell(010Imprimiendo liacutenea nuacutemero $i0l)

$pdf-gtOutput () gt

El meacutetodo header () configura un tipo de letra determinado en negrita avanza el cursor 8 centiacutemetros hacia la derecha e imprime una celda con el tiacutetulo El meacutetodo Ln (2 0 ) inserta un salto de liacutenea cuya altura es determinada por el argumento

Para probar el objeto hemos hecho un bucle que imprime 100 liacuteneas y asiacute comprobar que la cabecera aparece invariable El resultado se puede obshyservar en la figura 192

Imagen de cabecera

Tambieacuten es posible antildeadir una imagen a la cabecera con el meacutetodo Ima-ge ( ) La construccioacuten es la siguiente

Image(fichero x y ancho alto tipo enlace)

Los paraacutemetros necesarios son fichero x e y La descripcioacuten de todos los argumentos es

bull fichero Indica la ruta hacia el fichero que va a insertar

bull x Posicioacuten en el eje x de la imagen

bull y Posicioacuten en el eje y de la imagen

bull ancho Ancho de la imagen

bull alto Alto de la imagen Si no se indica y el paraacutemetro ancho estaacute defishynido el alto se escala en funcioacuten del ancho

bull tipo El tipo de imagen Por ahora soacutelo se aceptan imaacutegenes JPG JPEG y PNG

bull enlace La imagen puede ser un enlace

Ahora que sabe coacutemo insertar imaacutegenes puede incluir en la cabecera el logotipo de su empresa o asociacioacuten

funct ion Header()

Creacioacuten de archivos PDF 333

$this-gtSetFontArialB15) $this-gtSetX(70) $this-gtCell(10010Manual Imprescindible de PHP 510C) $this-gtSetX(-20) $this-gtImage(phppng1705) $this-gtLn (20)

La figura 193 muestra una cabecera con una imagen insertada

Pie de paacutegina

De la misma forma puede sobrescribir el meacutetodo que imprime el pie de paacutegina de la clase FPDF

Este meacutetodo recibe el nombre de F o o t e r () y tiene el mismo tratamiento que la cabecera cada vez que existe un salto de paacutegina se hace una llamashyda al mismo Nuestro pie de paacutegina puede quedar de la siguiente forma

funct ion Footer()

$this-gtSetY (-15) $this-gtSetFont(Arial I 10) $this-gtCell (010 Paacutegina $this-gtPageNo() 00 C )

334 Capiacutetulo 19

S e t Y () nos coloca el cursor a 15 miliacutemetros del borde derecho Seguidashymente escoja el tipo de fuente Aria e imprima el nuacutemero de la paacutegina acshytual con el meacutetodo PageNo ()

Muchos documentos informan ademaacutes del nuacutemero de paacuteginas que tiene el texto Esto es complicado a primera vista porque a priori no podraacute saber cuaacutentas paacuteginas ocuparaacute su texto Existe un meacutetodo que se ejecuta cuando el documento es cerrado y sustituye una marca por el nuacutemero de folios con los que cuenta nuestro proyecto

function FooterO

$this-gtSetY(-15) $this-gtSetFont ( Anal I 10) $this-gtAliasNbPages() $this-gtCell(0 10 Paacutegina $this-gtPageNo()

nb 00 C)

El meacutetodo A l i a s N b P a g e s () cuenta el nuacutemero de paacuteginas cuando el doshycumento estaacute cerrado y sustituye la marca nb por este nuacutemero

Tablas

Una tabla no es maacutes que un conjunto de celdas colocadas en un orden determinado Podemos diferenciar entre la cabecera de la tabla que conshytendraacute las propiedades y los datos Si realiza una clase para escribir tashyblas puede hacer tambieacuten esa diferenciacioacuten cambiando el tipo de letra el tamantildeo o el color El coacutedigo siguiente muestra coacutemo se puede instaurar una clase para la creacioacuten de tablas faacutecilmente

ltphp define(FPDF_FONTPATHfpdffont) require_once(fpdffpdfphp) class PDF extends FPDF function tabla($cabecera$datos)

$this-gtcabecera ($cabecera) $this-gtdatos($datos)

function cabecera($cabecera) Cabecera

$this-gtSetFont(ArialB15)

Creacioacuten de archivos PDF 335

foreach($cabecera as $columna) $this-gtCell(407$columna1 0 C )

$this-gtLn()

function datos($datos) Datos

$this-gtSetFont(Arial12) foreach ($datos as $dato)

foreach ($dato as $columna) $this-gtCell(407$columna10 C )

$this-gtLn ()

$pdf = new PDF () $pdf-gtAddPage ()

$cabecera = array(UsuariosVisitasLocalidadTeleacutefono) $datos = array(array(Luis Miguel 12Badajoz555345678)

array(Mariacutea Fernanda 45 Meacuterida 234234654) array(Pedro Casas3Caacuteceres342123 890))

$pdf-gttabla($cabecera$datos) $pdf-gtOutput () gt

En este caso los datos se sacan de un array de dos dimensiones pero pueshyde utilizar la libreriacutea de bases de datos o la de XML creadas en los capiacutetushylos anteriores para extraerlos

Los datos los recibe el meacutetodo T a b l a ( ) que los enviacutea a sus corresponshydientes meacutetodos para ser tratados El funcionamiento baacutesico consiste en la creacioacuten repetitiva de celdas cuyo nuacutemero coincidiraacute con el nuacutemero de datos existentes en el array Todas las celdas se muestran seguidas dando sensacioacuten de ser una tabla como puede ver en la figura 194 Ahora que es casi un experto en la creacioacuten de tablas para facturas o alba-ranes en PDF puede dar un toque de color al relleno texto o liacuteneas de las celdas

Puede comprobar que con tan soacutelo tres liacuteneas de coacutedigo maacutes el aspecto visual del documento mejora considerablemente

function cabecera($cabecera)

Cabecera $this-gtSetFillColor (25500)

336 Capiacutetulo 19

$this-gtSetTextColor(255) $this-gtSetDrawColor(12 800) $this-gtSetFont(ArialB15) foreach($cabecera as $columna)

$this-gtCell(407$columna10C1)

$this-gtLn()

function datos($datos)

D a t o s $this-gtSetTextColor (1) $thiacutes-gtSetDrawColor (12 800) $this-gtSetFont ( Arial 12) foreach ($datos as $dato)

foreach ($dato as $columna) $this-gtCell(407$columna10C)

$this-gtLn ()

El resultado es mucho maacutes llamativo gracias a los meacutetodos que antildeaden color El meacutetodo S e t F i l l C o l o r () define el color de fondo de las celdas

Creacioacuten de archivos PDF 337

y los rectaacutengulos que no sean transparentes Puede ser expresado con un componente RGB o en escala de grises El valor se mantiene durante todo el documento hasta que se vuelva a invocar el meacutetodo

S e t T e x t C o l o r () y S e t D r a w C o l o r () funcionan de la misma forma actuando esta vez sobre el color del texto o el color de las liacuteneas y bordes de celda La figura 194 muestra los colores (tonos de grises en este caso) distintos que pueden tomar un archivo PDF

Enlaces

Una de las ventajas del formato PDF es que permite hacer enlaces intershynos es decir que si tiene un documento de 500 folios podraacute acceder a cada uno de los capiacutetulos haciendo clic en el iacutendice tal y como funcionan los enlaces en las paacuteginas Web

Un enlace externo es muy faacutecil de crear

$pdf-gtWrite(5wwwluisyfernandanethttpwwwluisyfernandanet)

Los meacutetodos dedicados a texto tienen un argumento para antildeadir un enlashyce que si es externo debe llevar la direccioacuten URL completa

338 Capiacutetulo 19

Crear un enlace interno es algo maacutes complicado Tiene que hacer uso del meacutetodo A d d l i n k ( ) que genera una referencia que debe ponerse en el lugar hacia donde quiere que se produzca el salto En ese lugar utilice el meacutetodo S e t L i n k () para cerrar el enlace

El coacutedigo de ejemplo puede aclarar el concepto

ltphp define(FPDF_FONTPATHfpdffont) require_once(fpdffpdfphp) $pdf = new FPDF() $pdf-gtAddPage () $pdf-gtSetFont(Arial 15) $enLace = $pdf-gtAddLink() $pdf-gtWrite(5Este texto contiene un enlace$enlace) $pdf-gtAddPage) $pdf-gtSetLink($enlace) $pdf-gtWrite (5 Enlace Interno) $pdf-gtOutput () gt

Lo uacutenico a destacar es la creacioacuten del enlace con AddLink ( ) La variable $ e n l a c e recoge el valor de referencia y se antildeade al texto de la liacutenea sishyguiente En este momento el texto contiene un enlace pero no sabemos hacia doacutende La solucioacuten estaacute en llamar al meacutetodo S e t L i n k () en la paacutegishyna de destino con la referencia de paraacutemetro

Resumen

Los archivos PDF se consideran desde hace unos antildeos ideales para la geshyneracioacuten de contenidos on-line As iacute revistas digitales como w w w phparchcom o wwwphpmagnet utilizan este sistema para vender su publicacioacuten

Ademaacutes de revistas digitales podemos encontrar empresas que hacen lleshygar las instrucciones de sus productos en PDF o realizan las facturas de los clientes on-line como el programa de facturacioacuten extrementildeo Galopiacuten (httpgalopinsinuhorg)

La generacioacuten de sus propios archivos ya no es un misterio y puede im-plementar clases muchos maacutes potentes que las mostradas en el libro para sus propios proyectos La inclusioacuten de colores imaacutegenes y tablas de disshytintos tipos haraacuten del lector un profesional de la edicioacuten Web

En este capiacutetulo aprenderaacute a

bull Conocer queacute es un sistema de plantillas con Smarty

bull Independizar el coacutedigo HTML de PHP bull Crear plantillas con variables y bucles bull Crear plugins propios y modificar los ya existentes bull Crear filtros para mejorar el proceso

340 Capiacutetulo 20

Introduccioacuten

Cuando PHP nacioacute fue considerado como un sencillo lenguaje para geneshyrar dinaacutemicamente etiquetas de HTML Tras la versioacuten 3 de PHP se antildeashydioacute un compendio de funciones complejas para el manejo de cadenas arrays y bases de datos lo suficientemente completas como para crear sishytios Web muy extensos

Despueacutes de la creacioacuten de entornos completos en PHP los desarrollado-res comenzaron a pensar que no era muy uacutetil mezclar coacutedigo PHP con coacutedigo HTML e inventaron una forma de independizar los dos lenguajes mediante el uso de plantillas El primer entorno de plantillas que apareshycioacute fue FastTemplate escrito originariamente en Perl

En un periacuteodo corto de tiempo aparecieron muchos programas que facilishytaban el uso de plantillas como vTemplate Xtemplate TemplatePower o SmartTemplate Todos permiten sustitucioacuten de variables bloques repetishytivos inclusioacuten de muacuteltiples plantillas y bloques opcionales con estructushyras del tipo i f La diferencia estaacute en que muchos de estos sistemas utilizan expresiones regulares y hace muy complicado su uso Ademaacutes la velocishydad con la que se generan las plantillas es una propiedad a tener en cuenshyta en un entorno de trabajo en produccioacuten

SmartTemplate aparecioacute en 1999 y es el predecesor de lo que hoy conoceshymos como Smarty Es un entorno muy similar a otros pero incluye caracshyteriacutesticas muy avanzadas que lo hacen uacutenico la compilacioacuten de plantillas Esto significa que Smarty lee la plantilla y crea un script escrito en PHP Una vez creado este script se ejecuta y muestra el resultado en pantalla Lo bueno es que la compilacioacuten soacutelo se hace la primera vez las veces sishyguientes Smarty comprueba si hay nuevos datos que mostrar y si no los hay se utiliza la plantilla escrita en PHP por lo que la ejecucioacuten se hace muy raacutepida Algunas de las caracteriacutesticas generales de Smarty son

bull Extremadamente raacutepido

bull Muy eficiente porque el parse de PHP hace todo el trabajo

bull Soacutelo se compilan las plantillas que cambien los datos

bull Podemos realizar funciones propias y modificadores de variables Esto hace que Smarty sea extensible por el usuario

bull Se pueden utilizar varios delimitadores como j ltmdashmdashgt

bull Las estructuras de control son manejadas directamente por el parse de PHP por lo tanto pueden ser tan complejas como quiera

Plantillas con Smarty 341

bull Se puede incluir coacutedigo PHP dentro de nuestras plantillas

bull Funciones configurables para el manejo de la cacheacute

bull Arquitectura de plugins ampliable

Instalacioacuten de Smarty

La instalacioacuten del entorno de Smarty es muy sencillo y pasa por descargar de la Web httpsmartyphpnet la uacuteltima actualizacioacuten del sistema El archivo comprimido consta de varias carpetas que deberiacutean estar dentro del directorio de libreriacuteas de PHP Tambieacuten es posible guardar la carpeta de Smarty junto con nuestros programas pero no es recomendable

Las libreriacuteas del sistema de plantillas incluidas dentro del directorio l i b s son

Smartyclassphp Smarty_Compilerclassphp Config_Fileclassphp debugtpl

Ademaacutes de estos archivos existen las carpetas c o r e y p l u g i n s que se encargan de controlar el flujo de los objetos de Smarty

Las plantillas que creemos las vamos a guardar en un directorio llamado t e m p l a t e s y las plantillas compiladas deberaacuten estar en t e m p l a t e s _ c

Advertencia

La carpeta t e m p l a t e s _ c debe permitir la escritura porque aquiacute se iraacuten guardando las plantillas compiladas

Utilizacioacuten baacutesica de Smarty

Durante el desarrollo del libro hemos visto algunas teacutecnicas para escribir limpiamente nuestro coacutedigo PHP mezclado con HTML Vamos a ver una clase implementada por nosotros que genera una Web desde PHP y desshypueacutes vamos a ver coacutemo hacer lo mismo desde Smarty

ltphp c l a s s PaginaWeb

342 Capiacutetulo 20

priacutevate $titulo function construct($titulo)

$this-gttitulo = $titulo

priacutevate function cabecera($titulo)

echo lthtmlgt echo ltheadgt -echo lttitlegt$tituloltheadgt echo ltheadgt echo ltbodygt

priacutevate function cuerpo()

echo Este es el cuerpo de nuestra Webltbrgt priacutevate function pie()

echo Pie creado con PaginaWeb class echo ltbodygt echo lthtmlgt

public function creaWeb()

$this-gtcabecera($this-gttitulo) $this-gtcuerpo () $this-gtpie ()

$pagina = new PaginaWeb(Pagina Web generada con PHP) $pagina-gtcreaWeb () gt

Lo que hace cada meacutetodo es generar las etiquetas necesarias para crear una paacutegina Web Imagine ahora un gran sitio Web con cientos de paacuteginas Web con distinto tipo de informacioacuten Cambiar el aspecto visual de esa Web seriacutea un trabajo muy laborioso de varios meses primero buscando doacutende se encuentran las etiquetas junto al coacutedigo PHP y segundo modishyficando todo el coacutedigo HTML para que cambie el aspecto visual Las planshytillas solucionan este problema en muy poco tiempo separando el coacutedigo de la presentacioacuten

El resultado se puede ver en la figura 201

La paacutegina Web siguiente p l a n t i l l a r t p l es la misma que genera la clase anterior pero esta vez creada como plantilla

plantillaltpl

Plantillas con Smarty 343

lthtmlgt ltheadgt lttitlegt$titulolttitlegt ltheadgt ltbodygt $cuerpo $pie ltbodygt lthtmlgt

Todas las etiquetas conservan el estilo de HTML antildeadiendo siacutembolos de llave donde debe aparecer contenido dinaacutemico $ t i t u l o $cuerpo y $pie son variables que reciben su valor desde el programa escrito en PHP

Nota

Todo lo que estaacute entre se considera un comentario

344 Capiacutetulo 20

Para poder asignar valores a la plantilla tiene que hacer una instancia de la clase Smar ty

Puede modificar el objeto anterior para que haga uso de plantillas

ltphp class PaginaWeb

priacutevate $titulo priacutevate $Web function construct($titulo)

$this-gttitulo = $titulo requiacutere_once(Smarty1 ibsSmartyclassphp) $this-gtWeb = new Smarty

priacutevate function cabecera($titulo)

$this-gtWeb-gtassign(titulo$this-gttitulo) priacutevate function cuerpo()

$this-gtWeb-gtassign(cuerpoEste es el cuerpo de nuestra Web)

priacutevate function pie ( )

$this-gtWeb-gtassiacutegn(pie Pie creado con PaginaWeb) public function creaWeb()

$this~gtcabecera($this-gttitulo) $this-gtcuerpo () $this-gtpie()

$this-gtWeb-gtdisplay(plantilla1tpl)

$pagina = new PaginaWeb(Pagina Web generada con PHP) $pagina-gtcreaWeb() gt

La clase es exactamente igual (con los mismos meacutetodos) pero ahora se encuentra libre de etiquetas HTML En su lugar aparecen asignaciones a variables de Smarty El constructor instancia un objeto desde la clase Smarshyty y lo guarda en $ t h i s - gtWeb Las asignaciones de variables se hacen con el meacutetodo a s s i g n () que tiene que recibir como primer paraacutemetro el nombre de la variable escrita en la plantilla y como segundo argumento el texto que debe aparecer en lugar de la variable

Plantillas con Smarty 345

Despueacutes de asignar todos los valores tendremos que llamar al meacutetodo d i s -p l a y () con la plantilla como argumento para que la Web aparezca en el navegador

Si se fija ahora en el directorio de las plantillas compiladas t e m p l a t e s _ c veraacute que ha aparecido un archivo que contiene el siguiente coacutedigo

ltphp Smarty versioacuten 263 created on 2004-08-15 130335

compiled from plantillaltpl gt lthtmlgt ltheadgt lttitlexphp echo $this-gt_tpl_vars [ titulo ] bull gt lttitlegt ltheadgt ltbodygt ltphp echo $this-gt_tpl_vars[cuerpo] gt

ltbrxbrgt ltphp echo $this-gt_tpl_vars[pie] gt

ltbodygt lthtmlgt

Como puede apreciar la compilacioacuten de una plantilla de Smarty consiste en cambiar los valores entre llaves por coacutedigo PHP que hace llamadas a las variables Esto lo convierte en un meacutetodo muy raacutepido porque es el mismo PHP el que se encarga de mostrar la plantilla ya compilada

Cuidado con los estilos CSS

Es muy uacutetil utilizar estilos CSS para definir los colores tipos de letra y demaacutes objetos de presentacioacuten que vamos a utilizar en nuestras paacuteginas Web

El problema surge porque su construccioacuten es de la siguiente forma

lts ty l e t y p e = t e x t c s s gt lt - -P colorgreen - - gt ltstylegt

Este estilo sirve para que los paacuterrafos sean por defecto de color verde El problema es que Smarty parsea todo lo que estaacute entre siacutembolos de llave como c o l o r g r e e n En este caso se produciriacutea un error porque el parse no identificariacutea ninguna funcioacuten estructura o variable de plantilla Para solucionar esto se pueden antildeadir las etiquetas l i t e r a l y l i t e -

346 Capiacutetulo 20

r a l que al ser parseadas su contenido se identifica como un comentashyrio y se salta hasta el siguiente juego de llaves

literal ltstyle type=textcssgt lt --P colorgreen mdash gt ltstylegt literal

Llamada a varias plantillas

Casi todas las paacuteginas Web pueden dividirse en varias partes bien difeshyrenciadas cabecera menuacute cuerpo pie

Con Smarty podraacute crear una Web simple que incluya todas las partes de la Web como un uacutenico archivo HTML o crear 4 plantillas distintas y 1 que las unifique por lo que seriacutea maacutes sencillo cambiar el aspecto de cada una de las partes

La funcioacuten i n c l u d e f i l e de Smarty permite antildeadir plantillas a un fishychero La plantilla principal puede ser de la siguiente forma

lthtmlgt ltheadgt lttitlegt$titulolttitlegt ltheadgt ltbodygt include file=cabeceratpl include file=cuerpotpl include file=$pie ltbodygt lthtmlgt

De esta forma podemos modificar alguna de las plantillas y automaacuteticashymente todas las Web que hagan referencia a la misma cambiaraacuten su asshypecto

Como puede ver la plantilla que genera el pie de paacutegina es una variashyble por lo tanto podemos pasar desde PHP el nombre de cualquier planshytilla en funcioacuten de alguacuten caacutelculo interno o de alguacuten dato de MySQL etceacutetera

Variables

Smarty acepta muchos tipos de variables diferentes

Plantillas con Smarty 347

Pueden ser utilizadas para mostrarse directamente o como paraacutemetro de alguna funcioacuten o modificador dentro de alguna estructura de control etshyceacutetera

$nombre $contactonombre $contacto [0] $persona-gtnombre config_load_file=configuracioacutenconf lttitlegttitulolttitlegt

El coacutedigo anterior contiene diferentes tipos de variables y la forma de imshyprimir el dato que nos interesa Para una variable del tipo array puede utilizar la forma asociativa $ c o n t a c t o nombre o la forma indicativa $ c o n t a c t o [0] Tambieacuten es posible mostrar las propiedades de un objeshyto haciendo referencia asiacute $ p e r s o n a - gtnombre

Por uacuteltimo Smarty posee una funcioacuten que permite cargar una configurashycioacuten de un fichero Con la instruccioacuten c o n f iacute g _ l o a d _ f iacute l e cargaraacute en memoria la configuracioacuten del fichero que deacute como argumento El fichero debe estar escrito de esta forma

titulo = Pagina Web con PHP nombre = Luis Miguel color = FFFFFF

Modificadores

Los modificadores se pueden aplicar a las variables funciones o cadenas de caracteres Eacutestos permiten embellecer el texto recortarlo o adecuarlo a un formato determinado Para utilizar un modificador tiene que especifishycar la variable seguido de un siacutembolo de tuberiacutea ( I ) y el nombre del modificador

lthtmlgt ltheadgt cambia el texto a mayuacutesculas lttitlegt$titulo|upperlttitlegt ltheadgt ltbodygt Recorta el texto a 10 caracteres y le suma tren puntos suspensivos $cuerpoiexcltruacutencate10 ltbrxbrgt $pie ltbodygt lthtmlgt

348 Capiacutetulo 20

La plantilla anterior contiene el modificador upper que convierte todos los caracteres que recibe en mayuacutesculas El modificador t r uacute n c a t e recorshyta el texto dejaacutendolo en 10 caracteres y le antildeade puntos suspensivos como puede apreciar en la figura 202 La tabla 201 contiene un conjunto de modificadores que pueden utilizarse en las plantillas

Tabla 201 Modificadores de Smarty

Modificador Descripcioacuten Paraacutemetros

capitalize Convierte la primera letra Ninguno de cada palabra a mayuacutescula

count_characters Se usa para contar los Ninguno caracteres de una variable

cat Concatena el paraacutemetro 1 El texto a concatenar pasado a la variable

count_paragraphs Cuenta el nuacutemero de paacuterrafos Ninguno que contiene una variable

count_words Cuenta el nuacutemero de palabras Ninguno

Plantillas con Smarty 349

Modificador Descripcioacuten Paraacutemetros

date_format Imprime en un formato 1 Formato de salida 2 Si determinado la fecha y hora la entrada estaacute vaciacutea acep-del sistema este paraacutemetro por defecto

default Valor por defecto de la 1 El valor por defecto variable Si no se asigna ninguacuten valor la variable tendraacute el valor por defecto

escape Antildeade caracteres de escape 1 html htmlall url quo-a la variable tes hex hexentity javas-

cript

indent Antildeade varios caracteres a 1 Nuacutemero de caracteres a la izquierda de la variable indentar 2 Caraacutecter elegishy

do para indentar

lower Convierte a minuacutescula todos Ninguno los caracteres

nl2br Convierte los saltos de liacutenea a ltbrgt

regexreplace Busca y reemplaza una 1 Expresioacuten regular 2 Ca-expresioacuten regular dena de texto a reemplazar

replace Reemplaza una cadena de 1 Cadena a reemplazar caracteres por otra 2 Cadena de texto que susshy

tituiraacute al paraacutemetro 1

spacify Inserta un caraacutecter determinado 1 Caraacutecter entre los caracteres de la variable Por defecto un espacio en blanco

string_format Formatea un texto 1 Formato del texto como lo usa s p r i n t f

strip Reemplaza todos los espacios Ninguno saltos de liacuteneas y fabuladores por un espacio en blanco

strip_tags Elimina todas las etiquetas Ninguno

truacutencate Recorta una variable el nuacutemero 1 Nuacutemero de caracteres a de caracteres que indiquen los recortar 2 Texto que debe paraacutemetros aparecer si se recorta 3

True permite recortar en mitad de una palabra

upper Convierte a mayuacutesculas todos los caracteres de una variable

350 Capiacutetulo 20

Es bueno saber que podraacute aplicar varios modificadores a una misma vashyriable Tiene que antildeadirlos en el orden en el que quiera que se ejecuten de izquierda a derecha

$cuerpo[upper|spacify j truacutencate20

Nota

Si la variable es un array se aplicaraacute el modificador a todos ss valores

Funciones

El gestor Smarty tiene varias funciones que se pueden utilizar dentro del aacutembito de las plantillas Ademaacutes puede crear sus propias funciones o modificar las que ya estaacuten construidas

foreach

El bucle foreach se utiliza para mostrar un array simple La sintaxis es algo distinta al bucle de PHP

lttablegt foreach from=$art is tas i tem=valor lt t r x t d gt $ v a l o r lt t d x t r gt foreach lt t ab legt

Lo puede utilizar para antildeadir los valores de un array a una tabla como en el coacutedigo anterior La construccioacuten maacutes baacutesica de fo reach recibe en el atributo f rom el array que contiene los valores El atributo item crea una variable de Smarty que recoge los valores del array y se puede utilizar para mostrar el valor unas liacuteneas maacutes abajo

Otra construccioacuten un poco maacutes compleja es lttablegt foreach name=buclel from=$artistas key=indice item=valor lttrxtdgt $indice $valor lttdxtrgt foreach lttablegt

Funciona exactamente igual que el anterior El atributo key recoge el vashylor del iacutendice del array y ntildeame da un nombre al bucle para poder acceder a eacutel desde las variables propias de Smarty

Plantillas con Smarty 351

Truco

Se puede acceder al bucle mediante la variable global de Smarty Esta variable es $ smar ty Para acceder al bucle puede hacerlo de la siguiente forma $ s m a r t y f o r e a c h b u c l e 1

El resultado de la ejecucioacuten de la plantilla es

0 Paquito DRivera 1 Michel Camilo 2 Jerry Gonzaacutelez

if elseif else

La construccioacuten i f es tan flexible como la sentencia de PHP Cada i f debe tener una pareja del tipo i f

if $artistas[0] = Michel Camilo El primer artista toca el saxofoacuten alto

else El primer a r t i s t a toca e l piano

i f

Ademaacutes de los operadores baacutesicos de PHP tambieacuten puede utilizar mushychos otros como eq ne neq g t l t l t e l e g t e g e i s even i s odd i s n o t odd no t mod d i v by e v e n by o odd by El coacutedigo siguiente es similar al anterior

if $artistas[0] ne Michel Camilo El primer artista toca el saxofoacuten alto

else

El primer artista toca el piano

if

php incluido en plantillas

Puede antildeadir a una plantilla coacutedigo PHP encerrado entre las etiquetas de Smarty php y phpiexcl Si recuerda la filosofiacutea de las plantillas separar el coacutedigo de la presentacioacuten no se me ocurre ninguna excusa para utilizar esta habilidad en alguacuten proyecto por si acaso alguien le encuentra alguacuten sentido su uso es muy sencillo

php Incluir aquiacute alguacuten coacutedigo escrito en PHP include_once(logotiposphp) Php

352 Capiacutetulo 20

assign

Crea una variable y le asigna un valor determinado

assign var=variable value=Michel Camilo El valor de $variable es $variable

Se utiliza en tiempo de ejecucioacuten de la plantilla

counter

Se utiliza para imprimir un contador en pantalla

counter start=0 skip=3 print=falseltbrgt counterltbrgt counterltbrgt counterltbrgt

El atributo s t a r t indica el nuacutemero desde el que va a empezar el contashydor y s k i p el nuacutemero que debe sumarse al contador cada vez que exista una ocurrencia Cada vez que el parse encuentre c o u n t e r se incremenshytaraacute el contador y el navegador mostraraacute el resultado Para el ejemplo anterior podemos obtener

3

6

9

cycle

Una funcioacuten interesante que permite alternar entre varios valores pasashydos Cada vez que se ejecuta se recupera un valor distinto hasta el final de los valores Cuando se llega al final de la lista se vuelve a empezar Es muy uacutetil cuando queremos mostrar valores en una tabla y que cada liacutenea de detalle muestre un color diferente

lttablegt foreach name=buclel from=$artistas key=indice item=valor lttr bgcolor=cycle valueacutes=EEEEEEd0d0d0gtlttdgt$indice $valorlttdxtrgt foreach lttablegt

En este caso el bucle genera nombres de artistas del Jazz Latino y los inshytroduce en una tabla Gracias a la funcioacuten c y c l e se pueden diferenciar unos de otros por tener los colores de fondo de cada liacutenea distintos

Plantillas con Smarty 353

Opciones avanzadas de Smarty

Existen muchos tutoriales en Internet sobre el sistema de plantillas Toshydos abarcan la forma de utilizar las funciones y variables del entorno pero pocos se ocupan de las caracteriacutesticas que lo hacen uacutenico

La arquitectura de Smarty estaacute escrita en PHP Los ficheros que contienen las funciones baacutesicas para que el parse pueda realizar su trabajo estaacuten dentro de c o r e Pero la mayoriacutea de las funciones de presentacioacuten estaacuten incluidas dentro de la carpeta de p l u g i n s

Plugins

Un plugin dentro de la estructura de Smarty es un pequentildeo programa que realiza una tarea determinada Por ejemplo todos los modificadores son plugins y cada uno se encarga de hacer algo con el texto Veamos la estructura del plugin c a p i t a l i z e que recordemos modifica la primera letra de cada palabra y la convierte a mayuacutescula

ltphp function smarty_modifiacuteer_capitalize($string)

return ucwords($string)

gt

El funcionamiento del plugin es obvio Tan soacutelo hace uso de una funcioacuten existente en PHP para mostrar el resultado Puesto que es tan sencillo vamos a crear un plugin que serviraacute para enfatizar nuestro texto en detershyminadas ocasiones

ltphp function smarty_modifier_enfatizar($string)

re turn ltbgt $ s t r ing ltbgt

gt

Para crear un plugin modi f icador cree un fichero con el nombre modif i e r nombre php y guaacuterdelo en el directorio d e p l u g i n s En este caso tendraacute que crear un archivo con el nombre modi f i e r e n f a t i z a r php El nombre de la funcioacuten tambieacuten debe llevar un nombre estructurado Nuestro modificador se llamaraacute s m a r t y _ m o d i f i e r _ e n f a t i z a r y reci-

354 Capiacutetulo 20

biraacute como paraacutemetro la cadena de caracteres que lo utilice Dentro de la funcioacuten puede antildeadir el coacutedigo que sea necesario para cumplir su propoacuteshysito y despueacutes devolver el valor con la funcioacuten re turn

En nuestro caso devolvemos la misma cadena pero antildeadiendo la etiqueta de HTML para mostrar el texto en negrita por lo que quedaraacute enfatizado Tambieacuten podemos antildeadir alguacuten paraacutemetro para elegir entre distintos tishypos de eacutenfasis

ltphp funetion smarty_modifier_enfatizar($string $parametrol)

switch ($parametrol)

case 1 return ltbgt $striacuteng ltbgt break-

case 2 return ltemgt $string ltemgt break

case 3 return i i iexcl $string break

default return ltbgt $string ltbgt

gt

Ahora tenemos tres formas distintas de mostrar un texto que llame la atenshycioacuten Para invocar desde la plantilla cualquiera de los tipos de eacutenfasis hashybraacute que separar el modificador con un siacutembolo de dos puntos ( )

$valor|enfatizar3

Filtros

Los filtros son funciones que realizan una tarea determinada en nuestra plantilla justo antes o despueacutes de que sea compilada Se pueden consideshyrar los pre-filtros y los post-filtros respectivamente Existe un tercer tipo de filtro que se ejecuta en el momento de la llamada al meacutetododisplay ()

Crear un filtro para Smarty es tan sencillo como crear un plugin Hay que seguir estrictamente la nomenclatura del archivo y del nombre de la funshycioacuten para que funcione correctamente

ltphp function smarty_jostfilter_HechoCon($compiled amp$smarty)

Plantillas con Smarty 355

return $compiled ltbgtHecho con Smartyltbgt

gt

El filtro HechoCon () es una funcioacuten que recibe como paraacutemetros la fuente de la paacutegina Web ya compilada y el objeto Smarty que estamos utilizanshydo Nuestro filtro HechoCon devuelve la Web y antildeade un pequentildeo texto que indica que ha sido creado con Smarty

Para poder utilizar el filtro tenemos que cargarlo antes de utilizar el meacuteshytodo d i s p l a y ( ) en nuestro coacutedigo Esto se hace con la funcioacuten l o a d _ f i l t e r ( )

$this-gtWeb- gtload__f ilter (pre trim) $this-gtWeb-gtload_filter(postHechoCon) $this-gtWeb-gtload_filter(outputcompress)

El primer paraacutemetro del meacutetodo l o a d _ f i l t e r () indica el tipo de filtro que vamos a cargar y el segundo el nombre que recibe

Resumen

Alguacuten lector se preguntaraacute despueacutes de entender correctamente lo bueno que es separar el coacutedigo de la presentacioacuten por queacute he esperado tanto tiempo en contar el secreto de Smarty La verdad es que es mejor aprenshyder PHP paso a paso haciendo pequentildeos programas con HTML embebishydo para despueacutes ir concibiendo la mejor forma de atajar los diferentes proyectos que nos propongan

Con Smarty tiene una viacutea libre de exploracioacuten maacutes porque muchas de sus caracteriacutesticas no han podido ser tratadas en este capiacutetulo Le queda aveshyriguar coacutemo utilizar la cacheacute los recursos (habilidad para leer de una base de datos una plantilla) y las numerosas funciones que hemos dejado en el tintero Una vez que conozca la potencia de Smarty no querraacute mezclar nunca maacutes su coacutedigo con HTML

358 Apeacutendice A

Antes de comenzar

El primer paso para desarrollar programas en PHP 5 es encontrar un sershyvidor donde hacer las pruebas del programa y posteriormente dejarlo almacenado para que los usuarios puedan utilizarlo Este servidor debeshyriacutea estar disponible las 24 horas del diacutea con una conexioacuten fija a Internet

Como esto puede ser algo complicado al principio vamos a ver los pasos necesarios para instalar un servidor de pruebas donde escribir nuestros primeros scripts

PHP 5 se distribuye como coacutedigo fuente listo para compilar en el sistema operativo que quiera El problema es que es algo complicado si nunca ha compilado un programa Por eso he elegido paquetes ya compilados que soacutelo necesitan ser instalados para comenzar a funcionar

Vamos a instalar los siguientes programas

bull Servidor Web Apache

bull PHP 5

bull MySQL 4

Instalacioacuten en MacOSX

Uno de los maacutes excitantes desarrollos Open Source ha sido la apertura parshycial del coacutedigo de la plataforma Macintosh Gracias a esto muchos usuashyrios estaacuten contribuyendo con la creacioacuten de paquetes de instalacioacuten como el de PHP 5

Apache

El servidor Web Apache es necesario para enviar las peticiones HTTP de los clientes

Afortunadamente Apache viene ya instalado en MacOSX Para ponerlo en funcionamiento tendraacute que seguir los siguientes pasos

bull Abra una Terminal

bull Entre como suacuteper usuario con el comando su

bull Introduzca la passzvord de suacuteper usuario

bull Escriba a p a c h e c t l s t a r t

La figura A l muestra los pasos realizados en el terminal para iniciar el servidor Web A partir de ahora puede probar si funciona Apache escribiendo en el nashyvegador la direccioacuten l o c a l h o s t como muestra la figura A2

360 Apeacutendice A

PHP5

Existe una Web dedicada al mundo de MacOSX que se actualiza todos los diacuteas

Su administrador L i y a n a g e es el encargado de crear paquetes con toshydas las versiones de PHP 5 que ven la luz que en el momento de redactar el libro es la 501

Para instalar PHP 5 tendraacute que descargar el paquete de

ht tp www2entropychdownloadEntropy-PHP-5-01-1dmg

Una vez copiado el archivo en su sistema soacutelo tiene que hacer doble clic en eacutel y seguir los pasos de instalacioacuten del sistema operativo como puede ver en la figura A3

MySQL 4

Los pasos son exactamente igual que en la instalacioacuten de PHP 5

El primer paso es descargar el paquete para MacOSXmysql - s t a n d a r d -4 0 2 0 - a p p l e - d a r w i n 7 3 0 -powerpc dmg que se encuentra en la seccioacuten de descargas de la Web wwwmysql com

El paquete se instala como cualquier paquete de MacOSX simplemente haciendo doble clic

Instalacioacuten de PHP 5 y MySQL 361

Comprobacioacuten final

Para comprobar que todo funciona correctamente tendraacute que seguir los pasos siguientes

bull Abra una Terminal

bull Entre como suacuteper usuario con el comando su

bull Introduzca la password de suacuteper usuario

bull Reinicie la ejecucioacuten de Apache para que acepte la nueva configurashycioacuten de PHP 5 con el comando a p a c h e c t l r e s t a r t

bull Inicie MySQL con el comando u s r l o c a l m y s q l - s t a n d a r d -4 0 2 0 - a p p l e - d a r w i n 7 3 O - p o w e r p c b i n m y s q l d - u r o o t

bull Cree una Web de prueba y guaacuterdela en la ruta del usuario para paacutegishynas Web Normalmente es U s e r s u s u a r i o S i t e s

bull Abra el navegador y escriba la direccioacuten del servidor junto con el nomshybre de la Web La direccioacuten seraacute parecida a esta l o c a l h o s t - u s u a shyr i o i n f o r m a c i oacute n php

El programa que hemos escrito para comprobar que todo funciona correcshytamente y muestra el contenido de la figura A4 es

ltphp

362 Apeacutendice A

p h p i n f o ( ) gt

En la figura A4 puede ver el funcionamiento de todo el sistema instalado

Instalacioacuten en Windows

Instalar un sistema completamente funcional en un sistema operativo Windows puede ser tan sencillo o tan complicado como quiera Existe un paquete de aplicaciones llamado XAMPP que contiene todo lo necesario para funcionar con Apache PHP 5 y MySQL

En la Web wwwapachefriendsorg puede encontrar un archivo de instashylacioacuten de Windows

Despueacutes de descargar el archivo tiene que hacer doble clic y seguir las instrucciones impresas en pantalla como muestra la figura A5

Una vez instalado en la ruta lniciogtProgramasgtapachefriendsgtxampp veraacute tres apartados importantes

bull xampp basic start Se encarga de iniciar Apache PHP 5 y MySQL

bull xampp basic stop Para la ejecucioacuten de los servidores

bull xampp httpdoc folder Carpeta donde tiene que guardar todos sus programas escritos en PHP 5

Para probar que todo funciona puede ejecutar el programa xampp bashys i c s t a r t abrir un navegador y escribir como direccioacuten l o c a l h o s t Si

Instalacioacuten en gnuuumlnux

Existen en el mercado varias versiones de gnuLinux como gnuLinEx 2004 SuSe RedHat Gentoo Cada una de ellas posee un sistema de paquetes distinto Puesto que no tenemos espacio para describir 3 formas diferenshytes de instalar PHP 5 nos conformaremos con describir un tema general que sirve para todos los sistemas gnuLinux

Como ya puede imaginar nos vamos a apoyar en X A M P P para gnushyLinux

Una vez descargada la versioacuten para gnuLinux en el disco duro tendraacute que descomprimirla en un directorio El archivo comprimido deberiacutea llamarse x a m p p - l i n u x - 1 4 7 t a r g z Para instalarlo debe seguir los pasos sishyguientes

bull Descomprima con el comando g z i p -d x a m p p - l i n u x - 1 4 7 t a r g z

bull Vuelva a descomprimir el archivo esta vez con t a r x v f x a m p p - l i -n u x - 1 4 7 t a r

Instalacioacuten de PHP 5 y MySQL 363

todo se instaloacute correctamente podraacute ver una Web parecida a la de la figushyra A6

364 Apeacutendice A

bull Se crearaacute una carpeta llamada lampp

bull Copie la carpeta al directorio op t con el comando cp -r lampp opt

bull Ya lo tiene instalado Para ejecutarlo debe ser suacuteper usuario e invocar el comando opt lampp lampp s t a r t

La figura A7 muestra un terminal con el comando de inicio

En la figura A8 puede ver la paacutegina de inicio de XAMPP tras poner en el navegador l o c a l h o s t como direccioacuten Web Todas las paacuteginas Web que genere tendraacute que guardarlas en el directorio op t l ampp h tdocs para poder verlas a traveacutes del navegador

Recomendacioacuten final

La forma maacutes raacutepida y sencilla de hacer funcionar PHP 5 en su sistema es la que hemos visto pero no es la mejor La forma maacutes recomendable que se escapa del enfoque de este libro es compilar su PHP 5 De esta manera tendraacute la posibilidad de antildeadir los

Instalacioacuten de PHP 5 y MySQL 365

moacutedulos y extensiones que realmente vaya a utilizar La recomendacioacuten es que navegue por la Web wwwphpnet e investigue la forma de compishylar su sistema

368 Apeacutendice B

Introduccioacuten

El archivophp i n i contiene informacioacuten de configuracioacuten que puede moshydificar a su antojo Es un fichero de texto que se lee cada vez que se inicia el servidor Web Apache Para averiguar la ruta del disco duro donde se almacena el archivo php i n i soacutelo tiene que fijarse en el apartado Conf i g u r a t i o n F i l e (php i n i ) Path de la Web que recibioacute al ejecutar phpinf o () La configuracioacuten contiene parejas de variables valores separadas por puntos y comas Los valores que tenemos que asignar suelen ser rutas del disco duro 10 Yes No On Off o True False Cada vez que cambie alguna parte de la configuracioacuten tendraacute que reini-ciar Apache para que los cambios surtan efecto

short_open_tag

Permite la forma corta de antildeadir scripts de PHP de la forma lt gt Si quiere utilizar funciones XML es mejor dejarlo a Off

disable_functions

Desactiva funciones que nos resulten peligrosas como el enviacuteo de correos funciones de red etceacutetera

max_execution_time

Tiempo maacuteximo de ejecucioacuten de un script PHP en el servidor

error_reporting

Muestra el nivel de error que configure cuando un script falla Los tipos de errores los puede ver en el capiacutetulo 17

register_globals

Esta configuracioacuten ya no se utiliza a partir de la versioacuten PHP 42 y estaacute destinada a desaparecer

Configuracioacuten de phpini 369

Si la activa todas las variables seraacuten pasadas como globales y no dentro de las variables suacuteper globales

magic_quotes_runtime

Antildeade el siacutembolo de escape cuando se pasan variables con los siacutembolos de comillas simples o dobles

include_path

Antildeade rutas donde puede almacenar libreriacuteas que pueda utilizar sus proshygramas

Resumen

Hemos visto las principales opciones de configuracioacuten del archivo php i n i La configuracioacuten es mucho maacutes extensa pero no merece la pena indagar en otras opciones a menos que vaya a dedicarse a la administrashycioacuten del Sistema

372 Apeacutendice C

Bibliografiacutea

El desarrollo del libro ha sido posible gracias a la consulta de numerosas publicaciones escritas paacuteginas Web y revistas profesionales que han dado una visioacuten actual de la programacioacuten en PHP 5 La bibliografiacutea presente en este libro muestra un compendio de libros revistas y paacuteginas Web que pueden ser uacutetiles al lector si decide ampliar sus conocimientos una vez terminado este libro

Libros de PHP 5

bull PHP5 and MySQL Bible Tim Converse y Joyce Park Completo libro que abarca numerosos temas Especializado en generar bases de datos con MySQL y PHP 5

bull The PHP Anthology Harry Fuecks El mejor libro sobre PHP esshycrito nunca Abarca casi todos los temas importantes a la hora de crear un sitio Web profesional Todos los scripts estaacuten cuidadosashymente pensados y orientados a objetos El autor es uno de los proshypulsores de los patrones de disentildeo

bull Learning PHP5 David Sklar Contenido muy sencillo pero direcshyto Para aprender PHP 5 desde 0

bull PHP5 for Dummies Janet Valade Un buen libro para aprender y profundizar en varias aacutereas Desde luego el teacutermino Dummies no le hace justicia porque a veces se hace algo complicado de seguir

bull Proyectos Profesionales PHP Ashish Wilfred Meeta Gupta Kartik Bhatnagar Proyectos orientados a PHP 4 pero muy bien construidos

bull PHP 4 Esteban Trigos Libro muy sencillo para iniciarse en PHP 4 bull PHP 5 Power Programming Andi Gutmans De uno de los creashy

dores de PHP Muy bien enfocado y con muacuteltiples temas bull Beginning PHP 5 Equipo Wrox Libro extenso sobre PHP 5 Cubre

todo lo que se puede conocer sobre PHP 5 En Octubre saldraacute la seshygunda parte llamada Proffesional PHP 5

Revistas profesionales

bull PHP Solutions Revista polaca traducida al espantildeol Contiene muy buenos artiacuteculos sobre desarrollo actual con PHP

Bibliografiacutea 373

bull PHP Magazine Revista alemana de gran alcance bull PHP Architect Revista canadiense donde habitualmente escriben

desabolladores como Harry Fuecks Marco Tabini o Andi Gutmans La misma editora de esta revista ha sacado el libro de estudio para preshysentarse al examen de Certificacioacuten de PHP

Paacuteginas Web

bull wwwphpsolmagorg Web de la revista PHP Solutions bull wwwphpmagnet Web de la revista PHP Magazine bull wwwphparchcom Web de la revista PHP Architect bull wwwsinuhorg Comunidad GnuLinux de Extremadura

bull wwwphpbuildercom Comunidad de usuarios con mucho coacutedishygo libre

bull wwwluisyfernandanet Web del autor bull wwwphppatternscom La Web de Harry Fuecks bull wwwphpnet Web oficial de PHP

bull wwwzendcom La empresa que hay detraacutes de PHP Ofrece curshysos y seminarios on-line

bull wwwcodewalkerscom Web con mucho coacutedigo libre

Page 2: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo

MANUAL IMPRESCINDIBLE

RESPONSABLE EDITORIAL

Eugenio Tuya Feijooacute

ILUSTRACIOacuteN DE CUBIERTA

Cecilia Poza Melero

REALIZACIOacuteN DE CUBIERTA

Gracia Fernaacutendez-Pacheco

Todos los nombres propios de programas sistemas operativos equipos hardware etc que aparecen en este libro son marcas registradas de sus respectivas compantildeiacuteas u organizaciones

Reservados todos los derechos El contenido de esta obra estaacute protegido por la ley que estashyblece penas de prisioacuten y o multas ademaacutes de las correspondientes indemnizaciones por dantildeos y perjuicios para quienes reprodujeren plagiaren distribuyeren o comunicasen puacuteblishycamente en todo o en parte una obra literaria artiacutestica o cientiacutefica o su transformacioacuten interpretacioacuten o ejecucioacuten artiacutestica fijada en cualquier tipo de soporte o comunicada a traveacutes de cualquier medio sin la preceptiva autorizacioacuten

copy EDICIONES ANA YA MULTIMEDIA (GRUPO ANAYA SA) 2004 Juan Ignacio Luca de Tena 15 28027 Madrid Depoacutesito legal M-44920-2004 ISBN 84-415-1785-1 Printed in Spain Imprime Artes Graacuteficas Guemo SL Febrero 32 Madrid 28022

A mi mujer Mariacutea Fernanda por creer en nuestro Proyecto de vida

Agradecimientos

Finalizar este libro ha sido una odisea donde han intervenido muchas personas y factores mudanza incluida Para empezar me gustariacutea agradecer a Marta Camarero y a Eugenio Tuya su fe en miacute como escritor Me dieron aacutenimos desde el principio y un poquito de prisa A Zeev Suraski y Andi Gutmans creadores de PHP 5 por crear el lenguashyje y tratarme como a uno de los suyos en los iquestseminar de wwwzendcom Ademaacutes tengo que agradecerles la rapidez con la que escribieron el proacuteshylogo del libro A Marco Tabini director de la revista canadiense PHParchitect por enshyviarme el manual de Certificacioacuten PHP en papel y no en PDF A Tim Converse y Joyce Park por escribir PHP5 and MySQL Bible cuyos conocimientos me bebiacute en apenas 3 diacuteas A Harry Fuecks por escribir el mejor libro de PHP de todos los tiempos The PHP Anthology que me hizo reorientar todos los esfuerzos a la innoshyvacioacuten

A la Asociacioacuten Regional de Universidades Populares de Extremadura (AUPEX) por probar todos mis programas escritos en PHP (libros de visita foros nccproject newton etceacutetera) Espero dar alguacuten diacutea con la tecla A mis compantildeeros de trabajo Pako Palomo Javi y Pedro por las largas horas de discusioacuten en torno a Delphi Java C y por supuesto PHP A Justo Cabezas porque todo lo que me regaloacute fueron libros de informaacuteshytica y encima escritos por eacutel Sigo tus pasos A los grupos de usuario de gnuLinux de Extremadura wwwsinuhorg y wwwgulexorg por ser una fuente inagotable de conocimientos Por uacuteltimo A mi padre Ramoacuten que ya no estaacute a mi madre Felisa y a mi hermano Felipe porque nunca entendieron nada de informaacutetica pero me animashyron a seguir adelante con todo lo que me propuse Al resto de la familia porque cada uno de ellos ha tenido algo que ver en miacute vida y forman parte de lo que soy

iacutendice

Coacutemo usar este libro 19 Destinatarios de este libro 20 Organizacioacuten del libro 20 Convenios que emplea este libro 25 Los ejemplos en la Web de Anaya 26

Proacutelogo 27

Introduccioacuten 29 Historia de PHP 30 Nuevas Caracteriacutesticas de PHP 5 31

Faacutecil de usar 31 Embebido en HTML 32 Multiplataforma 33 Licencia Open Source 34 Multitud de Extensiones 34 Velocidad e incorporacioacuten de objetos 34 Popularidad 35 Gran Comunidad de apoyo 35

Objetivos del libro 36

1 Introduccioacuten a PHP 5 39 Introduccioacuten 40

8 iacutendice

HTML estaacutetico 40 Tecnologiacuteas del lado del cliente 42 Tecnologiacuteas del lado del servidor 43 Etiquetas de PHP 45 Nuestro primer programa en PHP 5 46 Repaso de HTML 47

Cabecera y cuerpo de una paacutegina Web 47 Cabecera 48 Cuerpo del documento 48 Paacuterrafos y saltos de liacuteneas 49 Estilo de texto 49 Enlaces de texto 51 Listas 51 Imaacutegenes 52 Tablas 53

Resumen 54

2 Variables constantes y tipos de datos 55 Variables en PHP 5 56

Tipos de Variables 56 Asignacioacuten de variables 57

Tipos simples 57 Enteros (integer) 58 Nuacutemeros de coma flotante (double) 59 Cadena de caracteres (string) 59 Boolean 61 NULL 62

Variables de variables 62 Constantes 63

defined() 63 Constantes predefinidas 64

Funciones relacionadas con variables 65 isset() 65 unsetQ 66 gettype() 66 settype() 67 empty() 67 is_integer() is_double() is_string() 67 intvalQ doublevalQ strvalQ 68

Resumen 68

iacutendice 9

3 Operadores 69

Introduccioacuten 70 Operador de asignacioacuten 70 Operador Unario 71 Operadores Aritmeacuteticos 71 Operadores de comparacioacuten 71 Operadores Loacutegicos 73 Operador Ternario 74 Operadores bit a bit 74 Operadores de asignacioacuten combinados 75 Operador de ejecucioacuten 76 Operador de supresioacuten de errores 77 Precedencia de Operadores 78 Resumen 80

4 Estructuras de control 81

Introduccioacuten 82 Estructuras de eleccioacuten 82

if-else 82 elseif 83 switch 84

Bucles 86 while 86 do-while 89 for 89

break y continueacute 92 Finalizar la ejecucioacuten de un programa 93 Sintaxis alternativa 93 Resumen 94

5 Funciones 95 Introduccioacuten 96 Valores de las funciones 96 Funcioacuten de ejemplo Obtencioacuten de la fecha actual 97 Documentacioacuten sobre funciones 98 Funciones de usuario 99

Definicioacuten de funciones 99 Paraacutemetros insuficientes 101 Paraacutemetros en exceso 102

10 iacutendice

Aacutembito de las variables 102 Variables estaacuteticas 104

Include() y require() 105 Recursividad 105 Funciones con nuacutemero de argumentos variables 106

Argumentos por defecto 106 Argumentos mediante un array 107 Muacuteltiples argumentos con func_num_args() 109

Llamadas por valor 110 Llamadas por referencia 111

Referencia a variables 112 Funciones variables 113 Resumen 114

6 Cadenas de caracteres y expresiones regulares 115 Introduccioacuten 116 Propiedades de las cadenas 116

iacutendices de string 116 Operadores 118 Sintaxis para muacuteltiples liacuteneas 118

Funciones de string 119 Tamantildeo de la cadena 120 Posicioacuten de los caracteres 120 Comparacioacuten 121 Buacutesqueda de caracteres 122 Seleccioacuten de subcadenas 122 Funciones de limpieza de cadenas 124 Sustitucioacuten de cadenas 126 Funciones de mayuacutescula y minuacutescula 126

Expresiones regulares 127 Comprobar expresiones regulares 129 Reemplazar patrones 131

Resumen 131

7 Conjuntos de datos del tipo array 133

Introduccioacuten 134 Creacioacuten de arrays 134

Asignacioacuten directa 134 array() 135 Funciones que devuelven arrays 136

iacutendice 11

Arrays multidimensionales 136 Propiedades de arrays 137

count() 1 3 7

in_array() 137 Borrar ocurrencias 138 Interactuar con arrays 138

Funciones para avanzar en un array 140 Funciones para retroceder en un array 142 Intercambio de valores 143 Inversioacuten del contenido 144 Mezcla de los valores 145

Pilas 145 Ordenacioacuten de los valores 146 Resumen 148

amp Paso de informacioacuten entre formularios 149

Introduccioacuten 150 Argumentos GET 150

Formularios con GET 151 Paso de informacioacuten con GET 155

Argumentos POST 157 Variables suacuteper-globales 158 Resumen 159

9 Programacioacuten orientada a objetos bull bull 1 6 1

Introduccioacuten 162 Definicioacuten de clases 163

Instancia de clase 164 Funcioacuten constructor 165

Herencia 165 Meacutetodos o funciones de objeto 166 Herencia encadenada 168 Valores y alcance de variables 168

Miembros puacuteblicos privados y protegidos 170 Meacutetodos privados 170 Meacutetodos protegidos 171 Meacutetodos puacuteblicos 171

Interfaces 172 Clases abstractas 172 Clases con meacutetodos estaacuteticos 173

12 iacutendice

Llamadas a funciones padre 174 Sobrecarga de meacutetodos 176 Sentildealizacioacuten 176 Funciones de manejo de clases 177 Resumen 179

10 Ficheros y almacenamiento de datos 181 Introduccioacuten 182 Funciones de lectura y escritura de ficheros 182

Abrir el fichero 182 Lectura de ficheros 183 Escritura de ficheros 185

Sistema de ficheros y directorios 188 Copiar borrar y renombrar 188 Funciones de comprobacioacuten 189 Directorios 190

Ficheros de configuracioacuten 191 Manejo de ficheros en el servidor 193

Subida de ficheros 193 Descarga de ficheros 195

Resumen 197

11 Bases de datos con SQL y SQLite 199 Introduccioacuten 200 SQL 200

SELECT 202 Uniones 203

INSERT 205 UPDATE 206 DELETE 207

Definicioacuten de tablas 207 SQLite 208

Creacioacuten de bases de datos 209 Uacuteltimos cambios en una tabla 211 Seleccioacuten de datos 212

SQLite orientado a objetos 213 Seleccioacuten de registros 214 Funciones de Array para recuperar datos 215 Nuacutemero de filas 216 Moverse entre registros 216

Resumen 218

iacutendice 13

12 PHP 5 y MySQL 219 Introduccioacuten 220 Administracioacuten de usuarios 220 Conexioacuten a MySQL 220

Seleccionar datos 222 Manipulacioacuten de datos 224

Insertar una fila 224 Actualizar una fila 225 Borrar una fila 225

Errores con las comillas 226 Contando filas 228

Contar filas con PHP 228 Contar filas con MySQL 229

Contar filas afectadas 230 Uacuteltimo nuacutemero insertado 230 Buacutesquedas dentro de una tabla 231 Definicioacuten de bases de datos 231

Creacioacuten de bases de datos 231 Creacioacuten de tablas 231

Resumen 233

13 Sesiones y Cookies 235 Introduccioacuten 236 Sesiones en PHP 5 237

Instanciando sesiones 237 Variables de sesioacuten 239 Problemas con los navegadores 240 Funciones para el manejo de sesiones 241

Cookies 243 setcookie() 243 Borrar una cookie 244

Cabeceras HTTP laquo 245 Resumen 246

14 Lectura y escritura de archivos XML 247 Introduccioacuten 248 SAXDOMySimpleXML 250 SAX 250 DOM 254

14 iacutendice

Usar DOM para leer archivos 255 Todo es un objeto 255 Atributos 256 Buacutesquedas muacuteltiples 257

Escribir archivos XML con DOM 257 Modificar archivos XML 259

SimpleXML 259 Resumen 261

15 Aplicaciones praacutecticas de XML 263 Introduccioacuten 264 Compartir informacioacuten con RSS 264

Distintos formatos 264 Leer un archivo RSS 268 Escribir archivos RSS 269

Servicios Web XML-RPC 272 Clase IXR 273 Cliente XML-RPC 274 Servidor XML-RPC 275 Usos de XML-RPC 277

Resumen 277

16 Generacioacuten de graacuteficos con PHP 5 279 Introduccioacuten 280 Graacuteficos HTML 280

Graacuteficos de barras 284 Libreriacutea GD 285

Tipos MIME 285 Mostrar una imagen en pantalla 286 Crear imaacutegenes en miniatura 288 Generar una marca de agua 290

Graacuteficos estadiacutesticos profesionales con JpGraph 292 Graacuteficos de barras 292 Graacuteficos en 3D 295

Resumen 297

17 Gestioacuten de errores en PHP 5 299 Introduccioacuten 300 Errores y Excepciones 300

iacutendice 15

La clase Exception 301 Bloque Try Catch 303 Heredar de la clase Exception 304 Limitaciones de PHP 5 305

Control de errores sin excepciones 306 Errores nativos de PHP 306 Controladores de error 307 Errores de usuario con trigger_error() 308

Depuracioacuten de errores 308 Resumen 309

18 Conexiones desde PHP 5 311

Introduccioacuten 312 FTP 312

Mostrar los archivos remotos 314 Descargar y Enviar ficheros 315 Otras funciones de FTP 316

Correo electroacutenico 317 Enviar correo desde PHP 318

PHPMailer 319 Antildeadir un fichero adjunto 320

Resumen 322

19 Creacioacuten de archivos PDF 325

Introduccioacuten 326 Libreriacutea FPDF 326

Nuestro primer documento 327 Funciones de texto 328

Meacutetodo Write() 328 Meacutetodo Cell() 329

Desplazamiento de los cursores 330 Salto de paacutegina automaacutetico 330

Sobrescribir los meacutetodos 331 Cabecera 331 Imagen de cabecera 332 Pie de paacutegina 333

Tablas 334 Enlaces 337 Resumen 338

16 iacutendice

20 Plantillas con Smarty 339

Introduccioacuten 340 Instalacioacuten de Smarty 341 Utilizacioacuten baacutesica de Smarty 341

Cuidado con los estilos CSS 345 Llamada a varias plantillas 346 Variables 346 Modificadores 347

Funciones 350 foreach 350 if elseif else 351 php incluido en plantillas 351 assign 352 counter 352 cycle 352

Opciones avanzadas de Smarty 353 Plugins 353 Filtros 354

Resumen 355

Apeacutendice A Instalacioacuten de PHP 5 y MySQL 357

Antes de comenzar 358 Instalacioacuten en MacOSX 358

Apache 358 PHP 5 360 MySQL 4 360 Comprobacioacuten final 361

Instalacioacuten en Windows 362 Instalacioacuten en gnuLinux 363 Recomendacioacuten final 364

Apeacutendice B Configuracioacuten de phpini 367 Introduccioacuten 368

short_open_tag 368 disable_functions 368 max_execution_time 368 error_reporting 368 register_globals 368 magic_quotes_runtime 369

iacutendice 17

include_path 369

Resumen 369

Apeacutendice C Bibliografiacutea 371 Bibliografiacutea 372

Libros de PHP 5 372 Revistas profesionales 372 Paacuteginas Web 373

Glosario 375

iacutendice alfabeacutetico 381

Coacutemo usar este libro

20 Coacutemo usar este libro

Destinatarios de este libro

Este libro estaacute dirigido a usuarios noveles que no sepan programar en ninshyguacuten lenguaje de desarrollo y a usuarios que ya conocen PHP pero desean tener una base soacutelida sobre la nueva versioacuten

PHP 5 estaacute ligado a Internet por lo tanto todas las aplicaciones praacutecticas del lenguaje estaacuten orientadas a realizar contenidos dinaacutemicos para paacutegishynas Por eso el lector debe conocer los aspectos baacutesicos de disentildeo en HTML

El libro puede dividirse en dos partes Una primera en la que se detallan los conceptos principales del lenguaje como las variables estructuras de control manejo de cadenas de caracteres creacioacuten de objetos y conectivi-dad con bases de datos que daraacute al lector novel una visioacuten general de PHP 5 y le permitiraacute comenzar a desarrollar sus primeras aplicaciones La segundaparte algo maacutes compleja haraacute las delicias del usuario novel y del medio Esta cuenta con teacutecnicas avanzadas para la lectura escritura de archivos XML creacioacuten de imaacutegenes en tiempo de ejecucioacuten conexioshynes de FTP y correo electroacutenico o disentildeo de plantillas con Smarty

El Software Libre estaacute presente en el aacutembito de la programacioacuten Por eso podemos utilizar algunos programas libres como base para construir aplishycaciones maacutes complejas El disentildeo de plantillas o la creacioacuten de llamadas a procedimientos remotos no seriacutea posible sin las libreriacuteas Smarty o IXR para XML-RPC desarrolladas por la comunidad de PHP para su uso libre

Por tanto el libro va dirigido a usuarios noveles que no saben nada de PHP Pero tambieacuten a usuarios medios o avanzados que desean conocer las nuevas caracteriacutesticas de PHP 5 y manejar teacutecnicas avanzadas de coshymunicacioacuten y disentildeo

Organizacioacuten del libro

Este libro estaacute dividido en 20 capiacutetulos con los siguientes contenidos

bull Capiacutetulo 1 Introduccioacuten a PHP 5 La introduccioacuten a PHP hace un reshycorrido por las nociones baacutesicas de HTML Ademaacutes aprenderaacute coacutemo crear su primera paacutegina en PHP y coacutemo mezclar el coacutedigo HTML con PHP

bull Capiacutetulo 2 Variables constantes y tipos de datos Los valores que manejamos en los programas deben ser almacenados en zonas de me-

PHP 5 21

moria reservadas por PHP Estas zonas reciben el nombre de variables y pueden ser tratadas de diferentes forma dependiendo de los valores que guarden (nuacutemeros enteros cadenas de caracteres valores boolea-nos) Este capiacutetulo contiene todo lo necesario para comprender coacutemo maneja PHP 5 las variables y las constantes estableciendo una diferenshycia con otros lenguajes fuertemente tipados como Java o C

bull Capiacutetulo 3 Operadores Otro aspecto de los lenguajes de programashycioacuten tiene que ver con los siacutembolos que se utilizan para realizar operashyciones aritmeacuteticas loacutegicas o de asignacioacuten Cada uno de los siacutembolos recibe el nombre de operador Este capiacutetulo muestra por grupos todos los operadores con los que se puede encontrar en PHP 5 Asiacute podraacute ver operadores especializados en sumas restas multiplicaciones o dishyvisiones (aritmeacuteticos) operadores de igualdad desigualdad o asignashycioacuten (de comparacioacuten) incluso operadores de manejo a nivel de bits (binarios)

bull Capiacutetulo 4 Estructuras de control El flujo de los programas viene deshyterminado siempre por las estructuras de control Estas indican en cada momento el rumbo que debe llevar el coacutedigo y lo que debe mostrar nuesshytra paacutegina basaacutendose en el valor contenido en las variables Las estrucshyturas de control y los operadores estaacuten iacutentimamente relacionados y su unioacuten permite desviar a evolucioacuten del programa en uno u otro sentido Las estructuras de control que veraacute en este capiacutetulo le daraacuten la potencia suficiente para crear sus primeros programas funcionales

bull Capiacutetulo 5 Funciones Si su coacutedigo se hace muy extenso a medida que avanza en la comprensioacuten del libro en este capiacutetulo aprenderaacute a remeshydiarlo Las funciones permitiraacuten al lector agrupar fragmentos de coacutedishygo repetitivo y aislarlo en ficheros independientes Este capiacutetulo no soacutelo cubre los aspectos teoacutericos para la creacioacuten de funciones sino que adeshymaacutes es un compendio de buenas praacutecticas a tener en cuenta para que sus proyectos se desarrollen ordenadamente Los aspectos baacutesicos a trashytar son la creacioacuten de funciones propias y el paso de paraacutemetros entre funciones de varias formas diferentes

bull Capiacutetulo 6 Cadenas de caracteres y expresiones regulares La mayor parte de la informacioacuten que puede encontrar en las paacuteginas es texto Conocer todas las teacutecnicas para concatenar medir cortar y buscar texshytos es baacutesico para crear un proyecto basado en contenido dinaacutemico Un perioacutedico digital un Log o incluso su propio CMS ya no tendraacuten seshycretos despueacutes de leer este capiacutetulo Ademaacutes la gran potencia de buacutesshyqueda de patrones viene de la mano de las expresiones regulares Eacutestas

22 Coacutemo usar este libro

permiten encontrar palabras frases y patrones dentro de un texto deshyterminado para manipularlo a nuestro antojo

bull Capiacutetulo 7 Conjuntos de datos del tipo array Este capiacutetulo trata a fonshydo las colecciones de datos PHP 5 maneja los conjuntos de datos como arrays asociativos Es posible acceder a los valores de un array de forma simple utilizando un iacutendice como en C y de forma asociativa asocianshydo una palabra a un valor determinado dentro del array Los arrays tieshynen un incalculable valor en los posteriores capiacutetulos usaacutendose como valor de retorno de muchas funciones de conectividad de bases de dashytos lectura de archivos XML o creacioacuten de plantillas

bull Capiacutetulo 8 Paso de informacioacuten entre formularios Si en el capiacutetulo 1 pudo ver los conceptos baacutesicos de la creacioacuten de paacuteginas en este podraacute conocer las teacutecnicas para enviar informacioacuten a traveacutes de formularios La mayoriacutea de las paacuteginas utilizan formularios para interactuar con los usuashyrios Aprenderaacute a pasar variables y arrays entre dos paacuteginas y coacutemo recoshyger desde PHP 5 los valores que se enviacutean Ademaacutes podraacute saber la diferencia entre los meacutetodos GET y POST y las variables suacuteper-globales

bull Capiacutetulo 9 Programacioacuten orientada a objetos El gran avance queacute ha sufrido PHP 5 desde su versioacuten anterior ha sido la total incorporacioacuten de la sintaxis y teacutecnica orientada a objetos Esto permite desarrollar proshygramas reutilizables en varios proyectos Una de las ventajas de la proshygramacioacuten orientada a objetos es que nos permite utilizar software de otras personas simplemente conociendo los meacutetodos que implementa no es necesario conocer coacutemo funciona el objeto para utilizarlo En este capiacutetulo el usuario novel y medio aprenderaacute las nuevas caracteriacutesticas de la programacioacuten orientada a objetos de PHP 5 A partir del capiacutetulo 9 casi todos los ejemplos estaraacuten basados en esta metodologiacutea de trabajo

bull Capiacutetulo 10 Ficheros y almacenamiento de datos La forma maacutes natushyral de almacenar datos persistentes es guardarlos en un fichero de dashytos Es una tarea muy sencilla y no dependemos de la instalacioacuten de alguacuten programa externo como una base de datos El capiacutetulo 10 mueacutes- tra coacutemo almacenar variables y textos dentro de un archivo para desshypueacutes recuperarlo en nuestra paacutegina Ademaacutes aprenderaacute una serie de teacutecnicas para recuperar ficheros enviados a traveacutes de un formulario y para poner en descarga archivos del servidor

bull Capiacutetulo 11 Bases de datos con SQL y SQLite Sin duda la mejor forma de almacenar datos masivos es utilizar una base de datos PHP 5 incorshypora una API de gestioacuten de bases de datos SQLite que permite almaceshynar millones de registros de diferentes tipos en un archivo binario Lo

PHP 5 23

mejor de utilizar SQLite es que no necesita instalacioacuten de una base de datos ni su administracioacuten todo estaacute contenido dentro de la API Aunshyque este libro no estaacute dedicado a la programacioacuten con bases de datos se da una referencia de los usos maacutes comunes del lenguaje de consultas estructurado (SQL) para que se pueda iniciar en este complejo mundo

bull Capiacutetulo 12 PHP 5 y MySQL MySQL ha sido siempre la panacea del desarrollo en el aacutembito profesional Es una base de datos robusta que permite administracioacuten de usuarios y seguridad a nivel de tablas y celshydas Es algo compleja de administrar pero muy sencilla de manejar desde PHP 5 Su utilizacioacuten ha sido tal que en el mundo de desarrollo se habla de las paacuteginas LAMP (Linux + Apache + MySQL + PHP) En este capiacutetulo aprenderaacute a manejar las funciones maacutes caracteriacutesticas de MySQL y a utilizarlas por medio de objetos en sus aplicaciones La proacutexima aparicioacuten de MySQL 5 hace prever que la combinacioacuten con PHP seraacute perfecta (MySQL 5 + PHP 5 = 10)

bull Capiacutetulo 13 Sesiones y Cookies En este capiacutetulo se detallan las teacutecnishycas necesarias para grabar informacioacuten en el equipo de los usuarios Estas pequentildeas variables (Cookies) permiten crear un pequentildeo control de asistencia de sus usuarios o guardar configuraciones especiales En cuanto a las sesiones son muy necesarias a la hora de crear espacios de venta de productos Las sesiones identifican a un usuario en concreto dentro de una paacutegina y permiten asociar variables concretas a ese usuashyrio aunque la paacutegina esteacute siendo visitada por muchas personas a la vez

bull Capiacutetulo 14 Lectura y escritura de archivos XML Frente a una inmenshysa cantidad de tipos de archivos propietarios como los documentos DOC o XLS nos encontramos a una serie de archivos basados en el lenguaje XML Este tipo de archivos como SXW (Openoffice) o SVG (graacuteficos vectoriales) estaacuten creados para ser entendidos por las personas y por los ordenadores Por lo tanto crear programas que interpreten estos archivos no es nada complejo El capiacutetulo 14 muestra tres caminos disshytintos para leer archivos XML Dos de ellos que vienen funcionando desde versiones anteriores SAX y DOM Y uno nuevo implementado en PHP 5 para facilitar esta tarea al programados Ademaacutes se incluyen las pautas necesarias para que cree sus propios archivos XML con la metodologiacutea DOM

bull Capiacutetulo 15 Aplicaciones praacutecticas de XML Si en el capiacutetulo anterior sentaacutebamos las bases para la lectura de informacioacuten desde archivos XML en este capiacutetulo crearemos objetos que implementen aplicacioshynes reales y actuales para compartir informacioacuten Es muy habitual hoy

24 Coacutemo usar este libro

en diacutea que las paacuteginas lleven asociados un panel de noticias que se generan en portales diferentes Esta informacioacuten se puede mostrar grashycias a teacutecnicas como RSS

Ademaacutes de crear sus propios objetos de generacioacuten de contenido RSS y su lectura haremos hincapieacute en lo que actualmente se llaman servicios Los servicios son pequentildeos programas almacenados en alguacuten servidor que informan acerca de algo concreto Aquiacute aprenderaacute a crear sus sershyvicios con las teacutecnicas ya adquiridas en el capiacutetulo 14

bull Capiacutetulo 16 Generacioacuten de graacuteficos con PHP 5 La generacioacuten de graacuteshyficos desde PHP 5 es posible gracias a la utilizacioacuten de libreriacuteas extershynas como GD Esto le permite manipular archivos graacuteficos que sus usuarios puedan subir a traveacutes de un formulario Con esta libreriacutea pueshyde generar graacuteficos en miniatura para despueacutes de hacer clic en eacutel antildeashydir una marca de agua a todas las imaacutegenes antildeadiendo el logo de su empresa o asociacioacuten

Otra gran libreriacutea es JpGraph que permite crear todo tipo de graacuteficos estadiacutesticos Esto le serviraacute para conocer el nuacutemero de visitas por diacutea mes o antildeo comparativas anuales de ventas de productos y todo un abanico de posibilidades

bull Capiacutetulo 17 Gestioacuten de errores en PHP 5 Una vez terminada la aplishycacioacuten tendraacute que tener en cuenta las partes del coacutedigo donde puede tener problemas Algunos usuarios pueden introducir caracteres no permitidos o nuacutemeros donde se esperaban letras La gestioacuten de errores permite mostrar al desarrollador y al usuario doacutende aparece el error y el tipo de fallo que se ha producido Una buena gestioacuten de errores haraacute que su programa sea maacutes fiable

bull Capiacutetulo 18 Conexiones desde PHP 5 La conectividad de PHP con otras aplicaciones o servicios ha sido siempre una preocupacioacuten de sus desarrolladores Asiacute desde anteriores versiones puede encontrar coshynectividad con servicios LDAP POP3 SMTP o FTP

Este capiacutetulo trata de abarcar dos servicios muy utilizados por la coshymunidad de usuarios El FTP en primer lugar para enviar y recuperar informacioacuten de otros servidores desde un programa escrito en PHP Y en segundo lugar el manejo de las funciones necesarias para enviar informacioacuten por correo electroacutenico

bull Capiacutetulo 19 Creacioacuten de archivos PDF El formato de texto maacutes difundishydo en Internet es el PDF Tanto se ha extendido este formato que la mayoshyriacutea de las paacuteginas profesionales contienen archivos PDF con diferentes contenidos Desde paacuteginas de contenido tecnoloacutegico hasta las de cocina

PHP 5 25

exportan sus contenidos en PDF para que sus usuarios puedan disfrutar desde su ordenador del manual del video o la receta de la semana

En este capiacutetulo veraacute paso a paso coacutemo generar un archivo PDF comshypleto desde la cabecera hasta el pie de paacutegina pasando por todo tipo de textos e imaacutegenes

bull Capiacutetulo 20 Plantillas con Smarty La uacuteltima aportacioacuten de este libro tiene que ver con la tendencia de separar el coacutedigo PHP de la presentashycioacuten en HTML Smarty provee unos sencillos mecanismos desde PHP que permiten realizar sencillamente esta separacioacuten Ademaacutes de las caracteriacutesticas baacutesicas de las plantillas la potencia de Smarty reside en la compilacioacuten del disentildeo cada vez que cambian los datos hecho que otorga a Smarty el puesto nuacutemero 1 en velocidad en el ranking de sisteshymas de plantillas En este capiacutetulo aprenderaacute a crear plantillas con Smarty que permitiraacuten cambiar el aspecto graacutefico de su aplicacioacuten sin tocar el coacutedigo escrito en PHP 5

bull Apeacutendice A Instalacioacuten de Apache y PHP 5 en distintos Sistemas Opeshyrativos La instalacioacuten de PHP 5 es muy sencilla en gnuLinux MacOSX y Windows El Apeacutendice muestra los pasos necesarios para instalar un servidor Apache con el parse de PHP 5 listo para ser utilizado con los ejemplos En cada caso la instalacioacuten se hace de una forma distinta Hemos buscado para cada Sistema Operativo la opcioacuten maacutes sencilla que es utilizando alguacuten paquete compacto que se instale y deje listo el sistema Puesto que es un libro para principiantes hemos huido de crear PHP 5 desde el coacutedigo fuente compilando el programa

bull Apeacutendice B Configuracioacuten baacutesica de phpini El archivo de configurashycioacuten php i n i contiene aspectos de funcionamiento de PHP 5 que pueshyden cambiarse sin necesidad de compilar el programa Este Apeacutendice contiene algunos paraacutemetros de configuracioacuten que pueden ser uacutetiles

bull Apeacutendice C Bibliografiacutea Este libro estaacute basado en el conocimiento adquirido tras la lectura de numerosos libros sobre la temaacutetica paacutegishynas Web y revistas profesionales del sector Este Apeacutendice cubre todas las posibilidades dando al lector un camino a seguir despueacutes de termishynar el presente libro

Convenios que emplea este libro

El nombre de los comandos funciones meacutetodos u objetos aparecen resalshytados en el libro de la siguiente forma ob j e t o

26 Coacutemo usar este libro

Algunas palabras teacutecnicas que no tienen una traduccioacuten faacutecil al castellano o simplemente estaacute fuertemente asentada en el idioma teacutecnico aparecen de la siguiente forma array true ofalse

En el libro aparecen resaltados una serie de temas circunstancias o aconshytecimientos extraordinarios de la siguiente forma array true ofalse

Nota

Anotaciones sobre el texto

Advertencia

Informacioacuten importante a tener en cuenta a la hora de desarrollar un programa Explican de alguna manera posibles equivocacioshynes o ayudas para no caer en errores frecuentes

Truco

Consejo o informacioacuten importante que puede facilitar el trabajo

Los ejemplos en la Web de Anaya

La mayoriacutea de los ejemplos del libro se pueden obtener en la Web de Anashyya Multimedia en la direccioacuten siguiente

httpwwwanayamultimediaes Seleccionando los menuacutes Atencioacuten a clientegtComplementosgtManuales lmprescindiblesgtManual Imprescindible de PHP 5 Ademaacutes de los ejemplos puede encontrar las aplicaciones externas o enshylaces a las mismas que utilizamos para desarrollar algunos ejemplos como Smarty FPDF JpGraph o la libreriacutea IXR

Todos los ejemplos han sido probados en el servidor Apache para MacOSX con el paquete de PHP 501 y en un servidor Apache sobre gnuLinEx Todas las capturas de pantalla se han realizado con el navegador Grulla (Mozilla Firefox) de gnuLinEx 2004

Proacutelogo

28 Proacutelogo

Una de las preguntas maacutes interesantes que nos hacen es queacute hace que PHP tenga tanto eacutexito Distintas personas nos han dado respuesta a esta preshygunta Algunos sostienen que es su excelente conexioacuten con bases de dashytos otros que se debe al coacutedigo abierto por el contrario otros mantienen que es su funcionamiento Sin embargo nuestra opinioacuten difiere PHP pershymite que cualquier usuario obtenga raacutepidamente resultados de forma senshycilla incluso aquellos que no posean experiencia en programacioacuten Al mismo tiempo a diferencia de las herramientas RAD PHP permite el deshysarrollo de proyectos tan complejos como se desee En nuestra opinioacuten esta combinacioacuten ausente en la mayoriacutea de las plataformas Web actuales es lo que hace que PHP sea especial

Lograr el equilibrio entre estas dos liacuteneas (la potencia y la sencillez) no ha sido faacutecil pero siacute imprescindible para el eacutexito de PHP como tambieacuten lo son las nuevas caracteriacutesticas que permiten al desarrollador aprovechar la uacuteltima tecnologiacutea

PHP 5 es el producto de este importante equilibrio Aunque dotado de muchas funciones nuevas esta versioacuten es tan accesible como lo fueron PHP 3 y PHP 4 con lo que permite un raacutepido aprendizaje para aquellos que se inicien De hecho algunas de las novedades basadas en la interfaz de Zend Engine II como SimpleXML SQLite y SOAP hacen maacutes sencillo el uso de PHP al tiempo que incrementa el potencial de aquellos usuarios noveles pues les permite trabajar con XML SQL y Web Services sin esfuerzo

La nueva generacioacuten PHP tambieacuten supone una buena noticia para desashybolladores experimentados En primer lugar por simplificar todas aqueshyllas funciones que ya se han indicado (al contrario de lo que normalmente se piensa ni siquiera a los desabolladores avanzados les gusta trabajar a menos que sea imprescindible) y en segundo lugar por poner a su disposhysicioacuten funciones mejoradas Las nuevas opciones orientadas a objetos de Zend Engine II son un regalo para el desarrollo de aplicaciones de media y gran escala como la nueva extensioacuten mysqli y el nuevo moacutedulo de inteshygracioacuten NET que permite la creacioacuten de aplicaciones hiacutebridas de PHP que emplean la estructura NET

Este libro es una gran introduccioacuten a PHP en general y de PHP 5 en partishycular Si no tiene experiencia previa con PHP e incluso si no tiene ningushyna experiencia en programacioacuten en breve podraacute trabajar con eacutel

Zeev Suraski Tel A v i v

Andi Gutmans Cupertino

Introduccioacuten

30 Introduccioacuten

Historia de PHP

Rasmus Lerdorf miembro del equipo de desarrollo de Apache creoacute PHP (Personal Home Page) en 1994 Su uacutenica intencioacuten fue la de crear un pequeshyntildeo sistema de control para verificar el nuacutemero de personas que leiacutean su curriculum vitae en la Web

En los meses siguientes a su creacioacuten PHP se desarrolloacute en torno a un grushypo de programadores que comprobaban el coacutedigo y sus revisiones Para dar maacutes potencia al sistema Rasmus creoacute funciones en lenguaje C para permitir conexioacuten a bases de datos Este fue el comienzo de la potencia real del leguaje

En 1995 aparecioacute un conjunto de herramientas sobre PHP Esta biblioteca se llamoacute Herramientas para paacuteginas personales y conteniacutean un analizashydor de coacutedigo muy sencillo un libro de visitas un contador y algunas macros que facilitaban el trabajo de los disentildeadores

A mediados de 1995 aparecioacute una revisioacuten puacuteblica llamada PHPFI 20 Esta nueva versioacuten contaba con un analizador sintaacutectico reescrito desde 0 ademaacutes de unas herramientas escritas para el tratamiento de datos desshyde un formulario (de ahiacute el nombre aacuteeFI Form iacutenterpreter) y conectividad con mSQL (Gestor de bases de datos)

Hacia 1997 PHPFI se estaba usando en maacutes de 50000 paacuteginas en todo el mundo En este periacuteodo de tiempo Zeev Suraski y Andi Gutmans decishydieron crear una nueva versioacuten de PHPFI para solventar unos probleshymas con una aplicacioacuten de comercio electroacutenico que estaban desarrollando PHP 30 nacioacute con suculentas innovaciones como la conectividad con vashyrios gestores de bases de datos protocolos y una API ampliada La vershysioacuten oficial de PHP 30 vio la luz en junio de 1998 donde se contemplaba ya la programacioacuten orientada a objetos

En 1999 se realizoacute la primera revisioacuten del motor Zend (Zend Engine) que aportaba modularidad claridad y herramientas de optimizacioacuten para paacuteshyginas de gran escala Zend viene de la unioacuten de Zeev y Andi

PHP 40 vio la luz en mayo de 2000 dividida en 3 partes El motor Zend la API de servidor y los moacutedulos de funcionas El motor Zend es el responshysable de analizar el coacutedigo PHP definir la sintaxis y del lenguaje de proshygramacioacuten La API permite la comunicacioacuten con el servidor Con esta API es posible utilizar PHP desde varios servidores Los moacutedulos contienen funciones para el manejo de cadenas archivos XML o tratamiento de imaacuteshygenes

PHP 5 31

La orientacioacuten a objetos no estaacute muy lograda en PHP 40 Los objetos tieshynen un tratamiento muy pobre e iloacutegico La definicioacuten de las variables miembro (propiedades) y los meacutetodos son siempre puacuteblicos por lo que la encapsulacioacuten es nula Todos los objetos se pasan por valor por defecto cuando deberiacutean pasarse por referencia

Todas estas propuestas realizadas por el equipo de desarrollo de PHP han desembocado en la creacioacuten del motor Zend 20 y su consecuencia PHP 5

PHP 5 incorpora una verdadera orientacioacuten a objetos Antildeadiendo las pashylabras reservadas public protected y priacutevate a la definicioacuten de las propiedashydes y meacutetodos de los objetos se permite una verdadera encapsulacioacuten Ademaacutes del considerable avance con respecto a los objetos PHP 5 incorshypora un control de errores muy mejorado al estilo de los lenguajes de proshygramacioacuten maacutes avanzados

Nota

Despueacutes de una encuesta entre desarrolladores y usuarios de PHP se decidioacute cambiar el significado de PHP a PHP Hypertext Pre-processor Este cambio sigue los pasos de Richard Stallman al nombrar a su sistema operativo GNU (GNU is not Unix) doshytando a la palabra PHP de recursividad Es un juego de palabras muy utilizado en el ambiente hacker

Nuevas Caracteriacutesticas de PHP 5

Existen muchas razones para elegir PHP 5

Faacutecil de usar

PHP 5 es un lenguaje muy faacutecil de aprender con respecto a otros lenguashyjes utilizados para el mismo propoacutesito como JAVA o ASP Debido a esto no es necesario hacer un estudio muy concienzudo de sus funciones para realizar programas sencillos que nos resuelvan la mayoriacutea de los probleshymas diarios

La mayoriacutea de las funciones maacutes usuales estaacuten disponibles por defecto como la conexioacuten a bases de datos o la utilizacioacuten de servidores IMAP Existe una gran cantidad de paacuteginas con documentacioacuten y programas heshychos por desarrolladores que se pueden leer y modificar libremente

32 Introduccioacuten

Embebido en HTML

Las paacuteginas escritas en PHP son simples paacuteginas en HTML que contieshynen ademaacutes de las etiquetas normales el programa que queremos ejecushytar Por ejemplo

ltHTMLgt ltBODYgt ltHEADgt ltTITLEgtEjemplo de PHP5 embebidoltTITLEgt ltHEADgt ltBODY ltPgtEsto es HTML del buenoltPgt ltphp Aquiacute comienza el coacutedigo PHP Lo siguiente es una simple asignacioacuten de variables y su salida por pantalla $nombre=Luis Miguel $apellidos=Cabezas Granado $fecha_hoy=date(d-ra-Y1) gt ltPgtEste paacuterrafo contiene HTML y PHP El autor del script es ltphp echo ($nombre $apellidosgt gtlt Pgt ltPgtLa fecha de ejecucioacuten del script es ltphp echo($fecha_hoy)gtltPgt ltBODYgt ltHTMLgt

Cuando un cliente solicita esta paacutegina el servidor preprocesa los datos y ejecuta las instrucciones de PHP En este caso las variables (las palabras que tienen el signo $ delante) se llenan con los valores que hay a la dereshycha del signo igual Una vez resuelto todo el proceso el servidor le enviacutea al cliente una paacutegina soacutelo con etiquetas de HTML La figura 11 muestra este proceso

Si inspeccionamos ahora el coacutedigo que tenemos en el navegador nos dareshymos cuenta de que las etiquetas de PHP han desaparecido

ltHEAD ltTITLEgtEjemplo de PHP5 embebido-TITLEgt ltHEADgt ltBODYgt ltPgtEsto es HTML del buenoltPgt ltPgtEste paacuterrafo contiene HTML y PHP El autor del script es Luis Miguel Cabezas GranadoltPgt ltPgtLa fecha de ejecucioacuten del script es 05-07-2004ltPgt ltBODYgt ltHTMLgt

higura ii Kesuitaao ae ejecutar un scnpi sencillo

La consecuencia maacutes inmediata es que no es necesario compilar el prograshyma en coacutedigo binario antes de poder testar si funciona o no PHP es un lenshyguaje interpretado como otros muchos en el mercado (ASP Python o JSP)

Multiplataforma

PHP 5 se ejecuta en multitud de plataformas Sistemas Operativos y Sershyvidores existentes Es compatible con los tres servidores liacutederes del mershycado Apache Microsoft Internet Information Server y Netscape Enterprise Server

Tabla 11 Sistemas Operativos y Servidores para PHP 5

Basados en UNIX Windows

Sistema Operativo AIX AUX BSDI Digital UNIXTru64 FreeBSD HP-UX IacuteRIX MacOS X gnuLinux gnuLinEx NetBSD OpenBSD SCO UnixWare Solaris SunOS Ultrix Xenix y muchos maacutes Windows 98Me Windows NT 2000XP2003

Servidores Apache fhttpd Netscape US PWS Netscape Apashyche Omni

Puesto que PHP se ejecuta en todos los Sistemas Operativos indicados en la tabla 11 y en la mayoriacutea de las plataformas hardware existentes (Intel

PHP 5 33

34 Introduccioacuten

A M D PowerPc SPARC etceacutetera) nos seraacute muy sencillo conseguir un lashyboratorio de pruebas para nuestros script

Licencia Open Source

La licencia de Coacutedigo Abierto implica que el coacutedigo fuente de PHP 5 es libre de ser descargado e inspeccionado por nosotros La consecuencia principal es que el coste del producto en la mayoriacutea de los casos es de 0 Euros Tener el coacutedigo fuente de PHP 5 sirve entre otras cosas para poshyder hacer nuestro servidor a medida es decir podemos compilar el proshygrama con las opciones que realmente utilicemos (base de datos LDAP)

Si acompantildeamos Apache el servidor maacutes popular a la instalacioacuten de PHP 5 y antildeadimos alguna base de datos Open Source como PostgreSQL tendreshymos un sistema completo de script de servidor cuyo coste es nulo frente a otras opciones en las que es necesario el uso de licencias

Multitud de Extensiones

PHP 5 se desarrolla para dar la mayor versatilidad y flexibilidad a los usuashyrios que lo utilizan Es por esto por lo que existen muchas extensiones del lenguaje que permiten utilizar nuevas bases de datos protocolos enlaces a libreriacuteas etceacutetera

El acceso a bases de datos tiene una gran potencia implementando soporshyte nativo para 15 Sistemas Gestores de Bases de Datos muy populares En cuanto a los protocolos podemos contar con extensiones que controlan el acceso a LDAP IMAP o POP3 Tambieacuten se ha cuidado el soporte para crear imaacutegenes en tiempo de ejecucioacuten gracias a la libreriacutea GD

Dada la importancia del desarrollo del lenguaje XML en los uacuteltimos antildeos PHP 5 incorpora tres meacutetodos de acceso a este tipo de archivos SAX D O M y simpleXML Ademaacutes se incorpora a PHP 5 la gestioacuten de errores mediante el manejo de excepciones

En esta versioacuten se han antildeadido facilidades para utilizar los repositorios de coacutedigo de PEAR

Velocidad e incorporacioacuten de objetos

El nuevo motor Zend 20 acelera los procesos de ejecucioacuten del coacutedigo Ademaacutes incorpora un nuevo modelo de objetos que permite crear ciacutea-

Figura 12 Uso de PHP desde el antildeo 2000

Gran Comunidad de apoyo

PHP 5 se ha escrito bajo el auspicio del Coacutedigo Abierto Por lo tanto exisshyte una comunidad que apoya su desarrollo en colaboracioacuten La ventaja principal es que existen multitud de paacuteginas listas de correo y foros de debate cuyo tema de conversacioacuten es el manejo de este lenguaje de proshygramacioacuten

Esta comunidad sirve de apoyo para todos los que necesitamos conocer desde los aspectos maacutes baacutesicos hasta las implementaciones maacutes complishycadas Tan pronto como hagamos uso de esta ayuda nos sentiremos oblishygados a prestar la nuestra a usuarios principiantes y asiacute la Comunidad se

PHP 5 35

ses y meacutetodos privados protegidos y puacuteblicos clases abstractas e inter-faces

Popularidad

El uso de PHP se ha disparado desde el antildeo 1999 como puede verse en la figura 12

36 Introduccioacuten

iraacute ampliando Si nuestros conocimientos llegan a superar alguacuten diacutea los objetivos de este libro podemos pensar en contribuir enviando fallos en el lenguaje respondiendo a mensajes de las listas de correo participando en foros de debate o escribiendo extensiones en lenguaje C

Objetivos del libro

A la hora de seleccionar este libro o cualquier otro sobre PHP 5 creo que es esencial que conozca los objetivos que marcan sus capiacutetulos Este libro en concreto estaacute pensado para

bull Tener una visioacuten general de los lenguajes de script para desarrollo

bull Conocer las ventajas de PHP 5 frente a otros lenguajes similares Tener una visioacuten general de las nuevas caracteriacutesticas que ofrece PHP 5

bull Aprender los conceptos baacutesicos para empezar a desarrollar aplicacioshynes sencillas que muestren contenido dinaacutemico

bull Identificar claramente todas las caracteriacutesticas de la orientacioacuten a objeshytos y aprender a desarrollar aplicaciones divididas en partes con moacuteshydulos reutilizables en distintos proyectos

bull Sacar partido de la API SQLite y del gestor de bases de datos MySQL para crear aplicaciones maacutes profesionales que nutran de contenido las paacuteginas

bull Crear formularios que enviacuteen informacioacuten y ficheros entre varias paacuteshyginas de distinta forma

bull Aprender a generar archivos para Internet de distintos formatos Los archivos XML o PDF se han vuelto indispensables en esta era y muy uacutetiles para exportar informacioacuten a los usuarios

bull Conocer las funciones baacutesicas para la creacioacuten de paacuteginas que controshylen y manipulen imaacutegenes Ademaacutes conoceraacute herramientas para geshynerar en el momento graacuteficos estadiacutesticos de diferentes formas

bull Controlar todos los errores que puedan producir los programas evishytando mostrar en el navegador mensajes de error geneacutericos para mosshytrar errores controlados por nosotros

bull Generar plantillas con libreriacuteas para separar el coacutedigo escrito en PHP de la presentacioacuten creada con HTML o alguacuten programa de disentildeo

El libro crea una base muy fuerte para comenzar a realizar aplicaciones profesionales Es evidente que la creacioacuten de archivos XML PDF genera-

PHP 5 37

cioacuten de graacuteficos o plantillas Smarty necesitan un libro entero para cubrir todas las caracteriacutesticas que ofrecen Este libro da una visioacuten general a los lectores y permite conocer las herramientas que actualmente se utilizan para que cada uno pueda investigar por su cuenta las que maacutes le interese

Capiacutetulo 1

Introduccioacuten aPHP5

En este capiacutetulo aprenderaacute a

bull Diferenciar entre scripts de cliente y servidor bull Utilizar diferentes tipos de etiquetas de inicio de PHP bull Escribir su primer programa en PHP bull Conocer las etiquetas HTML

40 Capiacutetulo 1

Introduccioacuten

El mundo de los desarrolladores de paacuteginas ha cambiado de forma vertishyginosa en los uacuteltimos antildeos En poco tiempo han surgido tecnologiacuteas y reshyvisiones de esas tecnologiacuteas que hacen que los programadores tengamos que reciclarnos continuamente

Hace unos antildeos el desarrollo de grandes paacuteginas era complicado de manshytener El lenguaje existente era uacutenicamente HTML y solo permitiacutea crear las paacuteginas y subirlas a un servidor El problema de esto es que modificar alguacuten dato de una de las paacuteginas implicaba un trabajo extra que incluiacutea descargarla modificarla maquetarla de nuevo y subirla al servidor

Actualmente existe un conjunto de lenguajes que permiten desarrollar paacutegishynas Web dinaacutemicas es decir que el contenido puede variar muy raacutepidamente sin ninguacuten esfuerzo por parte de los desarrolladores Eacutestos se denominan lenguajes de script de servidor porque la ejecucioacuten del programa se realiza en el servidor Web donde se encuentra alojada la paacutegina Existe un largo compendio de lenguajes que se pueden utilizar para la creacioacuten de paacuteginas Web dinaacutemicas ASP de Microsoft Java y JSP de Sun Perl Python PHP

HTML estaacutetico

El tipo maacutes baacutesico de paacutegina Web es completamente estaacutetico basado en texto plano y completamente escrito en HTML La paacutegina siguiente es un ejemplo de Web estaacutetica

ltHTMLgt ltHEADgt

ltTITLEbLibros sobre PHP 5 y gnuLinuxltTITLEgt ltHEADgt ltBODYgt ltTABLE BORDER-lgt ltTRgt

ltTDgtTiacutetulo de libros americanos sobre PHP 5ltTDgt ltTRgt ltTABLEgt ltulgt ltlixbgt Advanced PHP Programmingltbxbrxligt ltlixbgtPHP5 and MySQL bibleltbxbrxligt ltlixbgtLearning PHP 5ltbgtltbrxligt ltlixbgtUpgrading to PHP 5ltbxbrxligt ltlixbgtBeginning PHP 5 and MySQLltbxbrxligt

Introduccioacuten a PHP 5 41

ltlixbgtPHP 5 Power Programmingltfcgtgtltbrgtltligt lt u lgt ltTABLE border=lgt ltTRgt ltTDgtTiacutetulo de libros americanos sobre gnuLinuxltTDgt ltTRgt ltTABLEgt ltulgt ltlixbgtRunning Linuxltbxbrxligt ltlixbgtLinux in a Nutshellltbxbrxligt ltlixbgtHow Linux Worksltbxbrxligt ltlixbgtLinux for Non-Geeksltbxbrxligt ltulgt ltBODYgt ltHTHLgt

Figura 11 Ejemplo de paacutegina Web estaacutetica

La figura 11 muestra el ejemplo de una Web estaacutetica El funcionamiento de Internet es algo complejo para explicarlo en este capiacutetulo pero vamos a dar vinas nociones baacutesicas sobre lo que pasa tras la peticioacuten de una paacutegina Web por un cliente Los pasos que sigue nuestro navegador de Internet son

bull Nuestro ordenador solicita al servidor una paacutegina Web a traveacutes de Inshyternet

bull El servidor enviacutea los datos solicitados en formato de texto

42 Capiacutetulo 1

bull El navegador recibe estos datos interpreta la paacutegina Web enviada y la muestra en la pantalla de acuerdo con la resolucioacuten del monitor las preferencias del usuario y alguacuten otro factor

En la figura 12 podemos ver todo el proceso

Figura 12 Esquema de peticioacuten de una Web estaacutetica

Las paacuteginas Web estaacuteticas no permiten apenas una interactividad con el usuario final Por eso han aparecido numerosas tecnologiacuteas que hacen maacutes usable las paacuteginas y eliminan algunas restricciones o limitaciones Los lenshyguajes Javascript Vbscript CSS o los ap-plet de Java ofrecen una mayor interactividad pero son dependientes del navegador que utilicemos o de programas externos

Tecnologiacuteas del lado del cliente

Muchas de las mejoras antildeadidas al lenguaje HTML pertenecen a tecnoloshygiacuteas del lado del cliente es decir que se descargan junto con la paacutegina Web solicitada al servidor y se ejecutan en nuestro ordenador local La tabla 11 todas las tecnologiacuteas aparecidas hasta ahora del lado del cliente Estas tecnologiacuteas aunque son maacutes llamativas y permiten desarrollar la imashyginacioacuten en pro del disentildeo dependen totalmente de las caracteriacutesticas del navegador Por ejemplo si tiene un ordenador ibook de Apple con un Sisshytema Operativo gnuLinux Debiacutean (como el autor) le seraacute complicado obshytener una maacutequina virtual de Java y un inteacuterprete de Flash Las tecnologiacuteas de cliente no pueden rescatar datos de servidores porque su ejecucioacuten es uacutenicamente en local Eacutesto los imposibilita para recuperar informacioacuten de bases de datos o servicios

introduccioacuten a PHP 5 43

Tabla 11 Tecnologiacuteas del lado del cliente

[Tecnologiacutea Descripcioacuten Efecto de ejemplo

CSS HTML Sirve para dar formato a las Enlaces con movi-Dinaacutemico paacuteginas color tamantildeo capas efectos miento Javascript Manejo de eventos del navegador Imaacutegenes que Vbscript cambian cuando

se aproxima el ratoacuten Applets Aplicaciones pequentildeas Puzzles conectivi-de Java dad con bases de

datos Animaciones Animaciones graacuteficas Peliacuteculas iexclnteracti-Flash vas

Tecnologiacuteas del lado del servidor

Los lenguajes del lado del servidor son invisibles para los clientes Las paacuteginas que utilicen scripts de este tipo contienen el coacutedigo entre etique-fas parecidas a las de HTML pero eacutestas desaparecen cuando el cliente reshycibe la paacutegina

Los pasos que debe seguir nuestro navegador de Internet son

bull Nuestro ordenador solicita al servidor una paacutegina Web a traveacutes de Inshyternet

bull El servidor comprueba si la paacutegina solicitada contiene scrvpt del lado del servidor (PHP ASP JSP etceacutetera)

bull Ejecuta los posibles scripiacutes y antildeade el resultado final a la paacutegina Web resultante

bull El navegador recibe estos datos interpreta la paacutegina Web enviada y la muestra en la pantalla de acuerdo con la resolucioacuten del monitor las preferencias del usuario y alguacuten otro factor

La figura 13 muestra el proceso Los lenguajes del lado del servidor necesitan un motor (un programa) que interprete el coacutedigo Este programa puede formar parte o no del servidor Web En nuestro caso utilizaremos el motor Zend Engine 20 para parsear (interpretar) los proshygramas escritos en PHP 5

Figura 14 Zend Studio 351 para MacOSX

Suponiendo que ya tiene un servidor para probar los programas o ha leiacuteshydo el Apeacutendice A para instalar su propio servidor Web con PHP 5 vamos a crear nuestro primer programa del lado del servidor Para escribir los programas puede utilizar cualquier editor de texto plano

44 Capiacutetulo 1

Introduccioacuten a PHP 5 45

En gnuLinux tiene algunos editores libres que funcionan muy bien Sus nombres son Bluefish o Anjuta En entornos propietarios como Windows o MacO^X existen editores proshyfesionales que ademaacutes de disentildear paacuteginas Web permiten antildeadir todo tipo de coacutedigo PHP eso siacute los programas no son gratuitos y hay que pagar una elevada licencia por su uso Para los tres sistemas operativos tenemos una impresionante herramienta de edicioacuten y depuracioacuten creada por los programa^ores de PHP 5 La herramienta Zend Studio tiene dos versiones una de pago bajo licenshycia con muacuteltiples opciones de depuracioacuten y otra gratuita con opciones de desarrollo tan interesantes como el auto completado de funciones y variables

Etiquetas de PHP

Lo primero que debe saber es que todo prograrr1^ escrito en PHP debe empezar por unas etiquetas determinadas

ltphp gt

Ademaacutes aacutee esta iacuteoxma oacutee iacutemciax xm programa pu^dt ^urf^cam -iquesti -hiti iquesti-vo php i n i para que sus programas puedan empezar entre

lt gt

Nota

El archivo php i n i contiene la configuracioacuten de PHP en ese moshymento Cambiando algunos paraacutemetros podraacute cambiar la forma de funcionar del parser

El paraacutemetro s h o r t - o p e n - t a g puede igualarse a off o a on Si contiene el valor on PHP permitiraacute el uso de la etiqueta cofta Otra forma posible de empezar un programa escrito en PHP es utilizando las etiquetas de ASP Mucha gente que desarrolla con programas de Microsoft como Fron-tPage para generar paacuteginas Web utiliza esta forma de empezar el coacuteshydigo

lt gt

46 Capiacutetulo 1

Nuestro primer programa en PHP 5

Despueacutes de estas pequentildeas nociones ya estaacute preparado para crear su prishymer programa Eacuteste le va a permitir tener una visioacuten de la configuracioacuten global de PHP 5

Puede escribir el programa siguiente en cualquier editor de texto como vimos anteriormente

ltHTMLgt

ltHEADgt ltTITLEgtMi primer programa en PHP 5ltTITLEgt ltHEADgt ltBODYgt ltphp echo Este es el tiacutepico Hola Mundo ltbrxbrgt phpinfo() gt ltBODYgt ltHTMLgt

Como puede ver el programa contiene la estructura normal de una paacutegishyna Web La etiqueta ltHTMLgt define el comienzo y el final de la paacutegina Esta puede dividirse en dos partes La primera estaacute separada por la etishyqueta ltHEADgt y contiene informacioacuten sobre el autor tiacutetulo y meta datos que pueden servir para antildeadir coacutedigo Javascript o CSS La segunda parte es el cuerpo de la paacutegina Web es decir contiene todos los datos que veraacute el usuario en el navegador Estaacute separada entre etiquetas ltBODYgt

Dentro del BODY puede ver que empleamos las etiquetas de inicio y fin de programa PHP Dentro de estas etiquetas hay dos funciones que hacen cosas distintas Las funciones son programas ya creados y funcionales que pueden utilizarse en el transcurso de nuestro programa Existen en PHP 5 una infinidad de funciones uacutetiles para el manejo de cadenas de caracteshyres funciones aritmeacuteticas o funciones para mostrar texto en pantalla La funcioacuten echo ) se encarga de mostrar los datos en pantalla en este caso se encargaraacute de mostrar la frase Este es el tiacutepico Hola Mundo Ademaacutes imprime dos etiquetas ltbr gt que no se muestran porque tienen sentido dentro de HTML La etiqueta ltbrgt antildeade un salto de liacutenea a la paacutegina Web

La funcioacuten phpinf o () enviacutea al navegador la configuracioacuten de PHP que estamos utilizando en el servidor Aquiacute aparece la configuracioacuten que se ha utilizado para compilar el parser las libreriacuteas auxiliares que contiene el sistema que se estaacute utilizando etceacutetera

Introduccioacuten a PHP 5 47

Nota r Durante el proceso de aprendizaje del libro conoceraacute muchas funshyciones y sus aplicaciones inmediatas En el capiacutetulo 5 del libro aprenderaacute a crear sus propias funciones

El resultado de la ejecucioacuten del programa lo muestra la figura 15

Figura 15 Resultado de nuestro primer script

Repaso de HTML

El lenguaje de marcas de hipertexto se ha convertido en el principal refeshyrente de la Web Para seguir adecuadamente los contenidos del libro neshycesitaraacute conocer el funcionamiento de HTML para insertar sus programas escritos en PHP 5

Cabecera y cuerpo de una paacutegina Web

Todo documento escrito en HTML estaacute contenido entre las etiquetas ltHTMLgt y ltHTMLgt Se pueden estructurar en

bull Cabecera Entre las etiquetas ltHEADgt y ltHEADgt Contiene informashycioacuten relativa al documento

48 Capiacutetulo 1

bull Cuerpo Entre las etiquetas ltBODYgt y ltBODYgt Debe contener la inshyformacioacuten que el usuario veraacute en el navegador

Cabecera

El tiacutetulo del documento debe ir entre las etiquetas ltTITLEgt y ltTITLEgt Este tiacutetulo se mostraraacute en la parte superior del navegador Ademaacutes se utiliza como descripcioacuten si guarda la paacutegina en el apartado de Favoritos

Para antildeadir informacioacuten sobre el autor fecha de expiracioacuten o el programa con el que hemos disentildeado la Web puede utilizar la etiqueta ltMETAgt

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODYgt ltBODYgt

ltHTMLgt

Algunas etiquetas permiten la inclusioacuten de atributos La etiqueta ltMETAgt contiene el atributo NtildeAME y CONTENT para sentildealar en el documento el autor de la paacutegina Los buscadores haraacuten buen uso del contenido de estas etishyquetas para enlazarlas en sus motores de buacutesqueda

Cuerpo del documento

La etiqueta ltBODYgt tambieacuten puede contener atributos que modifiquen el aspecto exterior de la paacutegina

Los principales atributos son

bull BGCOLOR Indica el color de fondo de la Web

bull TEXT Color general del texto

bull LINK Color del texto de los enlaces

bull VLINK Color de los enlaces que ya han sido utilizados

bull ALINK Color de activacioacuten del texto

bull BACKGROUND Imagen de fondo de un documento

En el siguiente ejemplo puede ver la utilizacioacuten de los atributos de la etishyqueta del cuerpo

ltHTMLgt ltHEADgt

introduccioacuten a PHP 5 49

ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODY BGCOLOR=FF0 0 00 LINK=000000 VLINK=FF00FFgt ltBODYgt ltHTMLgt

Nota

El color se escribe en formato RGB Esto quiere decir que un color puede dividirse en tres componentes (rojo verde y azul) y elishygiendo la intensidad de cada componente se forma el color deseashydo Cada componente tiene 2 cifras en hexadecimal Asiacute el color FF0000 tiene al nuacutemero FF hexadecimal (255 en decimal) en su componente rojo y los demaacutes a 0 por lo tanto el color resulshytante seraacute Rojo intenso

Paacuterrafos y saltos de liacuteneas

Los textos pueden escribirse dentro de la etiqueta ltBODYgt en el orden que quiera los navegadores no interpretan los saltos de liacuteneas o liacuteneas en blanshyco eliminando todos los espacios vaciacuteos Para crear un salto de liacutenea tiene que utilizar ltBRgt escrito despueacutes del texto Para crear paacuterrafos tendraacute que escribir el texto entre las etiquetas ltPgt ltpgt

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltHEADgt ltB0DYgt ltPgt Esto es paacuterrafo y tambieacuten un salto de liacuteneasbrgt ltPgt ltBODYgt ltHTMLgt

Estilo de texto

Podemos resaltar partes del texto con algunas etiquetas

bull ltBgt Bloque de texto en negrita bull ltIgt Texto en cursiva

Figura 16 Diferentes estilos de textos

Ademaacutes puede elegir el formato de las fuentes de cada bloque de texto

50 Capiacutetulo 1

bull ltUgt Bloque de texto subrayado bull ltBIGgt Texto con su mayor tamantildeo bull ltSMALLgt Texto con m tamantildeo pequentildeo bull ltCENTERgt Texto centrado

bull ltSUPgtSuperiacutendice bull ltSUBgt Subiacutendice

El ejemplo siguiente que tambieacuten se muestra en la figura 16 muestra la utilizacioacuten de alguna de las etiquetas anteriores

ltHTMLgt

ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODYgt ltCENTERgtTexto centrado-CENTERxBRgt ltUxIxBIGgtTexto subrayado y cursivaltBIGxIgtltUxBRgt ltBgtTexto en negritaltBxBRgt ltSUPgtTexto superiacutendiceltSUPxBRgt Este cont iene un ltSUBgtsubiacutendiceltSUBgt ltBRgt ltBODYgt ltHTMLgt

Introduccioacuten a PHP 5 51

La etiqueta ltFONTgt permite seleccionar entre varios atributos para utilishyzar distintas fuentes colores o tamantildeos Entre los atributos que podemos utilizar

bull COLOR Color de la fuente

bull SIZE Tamantildeo de la fuente

bull FACE Tipo de fuente ltFONT SIZE=1 FACE=ComicgtTexto con tamantildeo y fuente determinadosltFONTgt

Enlaces de texto

Un enlace es un mecanismo que permite dirigirse a una paacutegina determishynada despueacutes de hacer clic en el texto Si entre las etiquetas ltAgt y ltAgt aparece alguacuten contenido (texto o imagen) al hacer clic en la situacioacuten denshytro de navegador la paacutegina seraacute dirigida a la nueva direccioacuten

El atributo HREF contiene la direccioacuten del enlace

ltA HREF=pagina2htmgtenlaceltAgt

Listas

Las listas son capaces de presentar ordenadamente una serie de concepshytos Los tipos de lista son

bull ltULgt Lista desordenada

bull ltOLgt Lista ordenada

bull ltDLgt Lista de definicioacuten

La diferencia entre los tipos de lista radica en el caraacutecter que aparece en la zona izquierda de cada liacutenea de la lista Las listas desordenadas tendraacuten un graacutefico formal (una forma geomeacutetrica) las ordenadas tendraacuten un nuacuteshymero de orden y las listas de definicioacuten una letra

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltHEADgt ltBODYgt ltBgtLiacutesta desordenada-BxBRgt ltULgt

ltLIgtLiacutenea 1 laquoLis-Liacutenea 2 ltLIgtLiacutenea 3

Figura 17 Listas ordenadas y desordenadas

52 Capiacutetulo 1

ltUI-igt

ltLIgtLiacutenea 31 ltLIgtLiacutenea 32

ltULgt ltLIacutegtLiacutenea 4

ltULgt ltBgtLiacutesta ordenadaltBgtltBRgt ltOLgt

ltLIacutegtLiacutenea 1 ltLJgtLiacutenea 2 ltLlgtLiacutenea 3 ltotgt

ltLIgtLiacutenea 31 ltLIgtLiacutenea 32

ltOLgt ltLIacutegtLiacutenea 4

ltOLgt ltBODYgt ltHTMLgt

Cada liacuteitea de una lista debe estar precedida de la etiqueta ltLIgt El coacutedishygo anterior genera la Web de la figura 17

Imaacutegenes

La etiqueta lt IMGgt utiliza el atributo SRC para insertar la imagen seleccioshynada en el documento

Introduccioacuten a PHP 5 53

Ademaacutes puede utilizar ALT para antildeadir una descripcioacuten a la imagen Entre las imaacutegenes que se pueden incluir en la Web estaacuten los tipos de archishyvos GIF PNG y JPG

ltIMG SRC=fo to l jpg ALIGN=centergt

La alineacioacuten de la imagen con respecto a la pantalla se puede controlar con el atributo ALIGN

Tablas

El elemento estrella en una paacutegina Web es la tabla Actualmente las tashyblas se utilizan para colocar en lugares determinados de la pantalla texshytos imaacutegenes o el menuacute de seleccioacuten Para definir u n a tabla tiene que insertar todos los datos entre las etiquetas ltTABLEi y ltTABLEgt

A continuacioacuten antildeada las filas y las columnas de nuestras tablas Para antildeadir una fila tendraacute que utilizar la etiqueta ltT^gt y para incluir una nueva columna la etiqueta ltTDgt

Para disentildear una tabla de 3 filas y 4 columnas siga los pasos que muestra el ejemplo

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author COMTENT=Luis Miguel Cabltbzas Granadogt ltHEADgt ltBODYgt ltTABLE B0RDER=1gt ltTRgt ltTDgtColumna 11ltTDgt ltTDgtColumna 12ltTDgt ltTDgtColumna 13ltTDgt ltTDgtColumna 14ltTDgt ltTRgt ltTRgt ltTDgtColumna 2 1ltTDgt ltTDgtColumna 2 2ltTDgt ltTDgtColumna 2 3ltTDgt ltTDgtColumna 24ltTDgt ltTRgt ltTRgt ltTDgtColumna 31ltTDgt ltTDgtColumna 3 2ltTDgt ltTDgtColumna 33ltTDgt ltTDgtColumna 34ltTDgt ltTRgt

Figura 18 Tabla de 3 filas y 4 columnas

54 Capiacutetulo 1

ltTABLEgt ltBODYgt ltHTMLgt

Como muestra el coacutedigo la etiqueta ltTABLEgt puede contener atributos como BORDER que antildeade un borde a todas las celdas de la tabla Esta forshyma de actuar la vemos en la figura 18

Resumen

Es muy importante para la lectura de los capiacutetulos del libro que conozca el lenguaje HTML en profundidad PHP 5 se encarga de generar datos dinaacutemicamente desde una base de datos archivos o haciendo caacutelculos complejos pero al final seraacute una etiqueta HTML la que muestre esos dashytos en pantalla Puesto que el objetivo de este libro no es conocer los asshypectos de HTML invito al lector a indagar en otras publicaciones o en Internet para suplir las posibles carencias que pueda tener

Los ejemplos del libro se han escrito directamente en un editor de textos pero esta no es la uacutenica posibilidad Tambieacuten puede utilizar para realizarshylos alguacuten programa de disentildeo Web con la ventaja de que las etiquetas HTML seraacuten antildeadidas a golpe de clic

Capiacutetulo 2

Variables constantes y tipos

de datos

En este capiacutetulo aprenderaacute a

bull Almacenar informacioacuten en variables bull Manejar variables constantes y constantes predefinidas por PHP 5

bull Utilizar funciones de manejo de datos

56 Capiacutetulo 2

Variables en PHP 5

Como en todos los lenguajes de programacioacuten PHP 5 permite almacenar datos de distintos tipos en memoria Estas zonas de memoria se llaman variables Las variables comienzan por el siacutembolo de doacutelar ($) y no necesishytan ser declaradas antes de comenzar el programa como en otros lenguashyjes

Tipos de Variables

Existen varios tipos de variables

bull Entero (integer) Almacena nuacutemeros sin decimales Se puede utilizar la notacioacuten decimal (83) octal (0123) o hexadecimal (0x12)

bull Coma Flotante (double) Nuacutemeros con decimales bull Caraacutecter (string) Texto o informacioacuten numeacuterica escrita entre comillas

dobles () o simples () bull Bootean Soacutelo tiene dos posibles valores Verdadero o Falso bull Nulo NULL) Es un tipo especial que solo contiene un valor NULL bull Vectores (array) Colecciones de datos

bull Objetos (object) Conjunto de datos y funciones independientes

Los 5 primeros tipos son simples y los 2 siguientes (array y object) son comshypuestos Trataremos los tipos compuestos en capiacutetulos sucesivos

ltphp Asignacioacuten de nuacutemeros enteros de coma flotante y cadenas de caracteres $numero_entero = 12343 $numero_flotante = 12343123 $cadena_caracter = 12 34 3 Asignacioacuten de los tipos especiales boolean y NULL $verdadero = TRUE $vacio = NULL gt

Hay que tener en cuenta que el nombre de las variables no puede empeshyzar por un nuacutemero pero siacute puede contenerlos Tambieacuten pueden empezar por un guioacuten bajo (__) Puesto que PHP 5 es sensible a las mayuacutesculas y minuacutesculas las variables $numero y $NUMERO seraacuten distintas

ltphp $4numero = 23 Esta liacutenea da error

Variables constantes y tipos de datos 57

$_numero = 45 Las liacuteneas siguientes muestran que PHP 5 es sensible a mayuacutesculas $numero = 23 $NUMERO = 24 $Numero = 25 echo (numero es $numeroltbrgt) echo (NUMERO es $NUMEROltbrgt ) echo (Numero es $Numeroltbrgt) gt

Nota

Es una buena praacutectica de programacioacuten llamar a las variables de una forma descriptiva Si tenemos un formulario que intenta pashysar datos sobre el nombre y apellido de una persona lo maacutes coshyrrecto es llamar a las variables $nombre y $ ape l l i do en vez de $n y $a Hay que buscar siempre la similitud entre el dato que pasamos y el nombre de la variable para que el programa resulte legible

Asignacioacuten de variables

La asignacioacuten es simplemente dar un valor a la variable Esto se hace poshyniendo un siacutembolo = entre la variable y el dato que queremos asignar

ltphp $numero_pi = 314159 Aproximadamente gt

Si se fija en el ejemplo acabamos de asignar un nuacutemero de coma flotante a la variable $numero_pi En este momento podemos cambiar el valor de la variable asignando un nuevo valor que puede ser de un tipo difeshyrente

ltphp $numerojiacute = 314159 El tipo se convierte a cadena de caracteres gt

Tipos simples

Los tipos de variables simples (enteros coma flotante cadenas de caracteshyres boolean y NULL) deberiacutean ser familiares si conocemos alguacuten lenguaje

58 Capiacutetulo 2

de programacioacuten como C Puesto que la base de la programacioacuten consiste en almacenar datos correctamente vamos a ver las peculiaridades de los diferentes tipos

Enteros (integer)

Corresponde a un nuacutemero entero sin decimales pudiendo ser negativo o el nuacutemero cero Pueden ser almacenados en diferentes formatos corresshypondiendo con las bases decimal (base 10) octal (base 8) y hexadecimal (base 16) Por defecto se utiliza la numeracioacuten decimal Para utilizar base 8 debe ponerse un 0 delante del nuacutemero asignado y un Ox si queremos utilizar base 16 Para antildeadir un nuacutemero negativo basta con poner el signo menos (-) delante del nuacutemero

ltphp $entero_baselO = 1234 $entero_base8 = 01234 $entero_basel6 = 0x1234 $entero_negativo = -1234 echo (Decimal $entero_baselOltbrgt) echo (Octal $entero_base8ltbrgt) echo (Hexadecimal $entero_basel6ltbrgt) echo (Negativo $entero_negativoltbrgt) gt

La salida del navegador es

Figura 21 Asignacioacuten de enteros en decimal octal y hexadecimal

Variables constantes y tipos de datos 59

La salida de los nuacutemeros se hace en decimal aunque la asignacioacuten se haya hecho en hexadecimal o en octal Esto es asiacute porque PHP trabaja internashymente en binario y hace la conversioacuten a decimal de todos los nuacutemeros enteros y de coma flotante

Nuacutemeros de coma flotante (double)

Este tipo de dato contiene nuacutemeros enteros con decimales Se almacenan de forma diferente a los nuacutemeros enteros por lo que las sumas de cantishydades de coma flotante con cantidades enteras daraacuten como resultado un nuacutemero de coma flotante

ltphp Nuacutemeros de coma flotante $numero__double = 1234123 $numero_double2 = 01213 $numero_double3 = -12 3 40 echo (Salida de la funcioacuten echo() $numero_double3ltbrgt) gt

La salida en el navegador seriacutea S a l i d a de echo -1234

Como puede comprobar parece que el nuacutemero que se muestra en pantashylla es del tipo entero Esto es porque la funcioacuten echo 0 no muestra el forshymato del dato Para que esto ocurra debemos utilizar otro tipo de funcioacuten

ltphp $numero_double3 = -12340 echo (Salida de printft) ) printf(f$numero_double3) gt

El coacutedigo anterior muestra ahora una salida por pantalla maacutes coherente Salida de printf() es -1234000000

Cadena de caracteres (string)

Es un conjunto de caracteres encerrados entre comillas dobles () o sim-pies ( )bull

ltphp Definicioacuten de variables de tipo string $cadenal = Esto es una cadena de caracteres $cadena2 = Esto es una cadena entre comillas simples $cadena3 = Cadena con 0 caracteres gt

60 Capiacutetulo 2

La diferencia entre las comillas simples y las comillas dobles radica en

bull Comillas simples Permiten imprimir el contenido iacutentegro de caracteshyres que esteacute entre las dos comillas

bull Comillas dobles Permiten incluir variables para imprimirlas junto al texto ltphp $dato = IMPRIMIBLE $texto_simple = No puede imprimir la variable $dato $texto_doble = Imprime la variable dato como $dato echo ($texto_simpleltbrgt) echo ($texto_doble) gt

Existen algunos caracteres especiales que no pueden ser antildeadidos a una variable de tipo string a menos que avisemos antes a PHP para que tenga cuidado a la hora de manejar el dato Este aviso se conoce como secuenshycia de escape y no es maacutes que la inclusioacuten delante del caraacutecter especial de un siacutembolo Asiacute si quiere insertar unas comillas dobles entre un texto tendraacute que escribir para que no se produzca un error

ltphp Secuencias de escape $cadenal = Aquiacute se pueden antildeadir comillas doblesltbrgt $cadena2 = Aquiacute se pueden antildeadir comillas simplesltbrgt $cadena3 = Esta cadena da errores por las comillas doblesltbrgt $cadena4 = Esta cadena no da errores por las comillas doblesltbrgt echo $cadenal echo $cadena2 echo $cadena3 echo $cadena4 gt

El resultado muestra la impresioacuten de las cadenas excepto la cadena3 que da un error por no incluir la secuencia de escape para las comillas

Tabla 21 Secuencias de escape comunes

Secuencia Valor

$ Signo de doacutelar $

Comillas dobles

V Comillas simples

Bar ra invert ida

Variables constantes y tipos de datos 61

Secuencia Valor

n Nueva liacutenea

r Retorno de carro

t Tabulador

Boolean

Una variable de tipo boolean soacutelo puede contener dos valores Verdadero o Falso Se suelen utilizar para comprobar si se cumple una condicioacuten en el programa

ltphp $variable_booleana = TRUE if ($variable_booleana) echo (El resultado es VERDADERO)

gt

El resultado se muestra en la figura 22

Aunque todaviacutea no hemos visto las estructuras de control podemos adshyvertir que la salida del programa anterior da como resultado la impresioacuten en pantalla del texto que contiene la funcioacuten echo () Ademaacutes de las vashyriables boolean podemos tomar otros tipos de datos como Verdaderos o Falsos para hacer nuestras comprobaciones

62 Capiacutetulo 2

bull Los nuacutemeros enteros o decimales positivos o negativos son todos Verdashyderos El 0 se considera Falso En cualquier caso se recomienda no utilishyzar variables de coma flotante para comprobar si son Verdaderos o Falsos

bull Las cadenas de caracteres son Verdaderas excepto cuando no contieshynen ninguacuten dato o contienen uacutenicamente el caraacutecter 0

bull Las variables del tipo NULL son siempre Falsas

NULL

Es un tipo especial de datos que soacutelo contiene el valor NULL Aunque se suele utilizar por norma en mayuacutescula PHP 5 lo acepta escrito de divershysas formas NULL nuil NuLl

ltphp $variable_nula = NuLl if ($variable_nula) echo (La comprobacioacuten es VERDADERA)

else echo (La comprobacioacuten es FALSA) gt

Variables de variables

Las variables son en definitiva nombres descriptivos que asocian un esshypacio en memoria del servidor con una palabra entendible por nosotros En ese espacio de memoria podemos almacenar diferentes tipos de datos Podemos definir una variable de la siguiente forma

ltphp $variablel = hola gt

En este momento tenemos un espacio de memoria llamado $ v a r i a b l e l donde se aloja el dato hola iquestQueacute pasa si queremos tratar la palabra hola como una variable Podemos hacerlo antildeadiendo un signo de $ delante de $ v a r i a b l e l por lo que se reservaraacute otro espacio en memoria para aloshyjar el nuevo contenido esta vez con el nombre $hola

ltphp $variablel = hola $$variablel = mundo

Variables constantes y tipos de datos 63

Las dos liacuteneas siguientes producen la misma salida echo ($variablel $$variablelltbrgt) echo ($variablel $holaltbrgt) gt

La salida por pantalla nos da el siguiente resultado hola mundo hola mundo

Constantes

Las constantes son tipos de datos que no variacutean en el desarrollo de un programa En la vida real existen muchos tipos de constantes el nuacutemero pi la temperatura de congelacioacuten del agua el nombre de la Empresa etshyceacutetera Para crear una constante tiene que usar la funcioacuten de f ine () de la siguiente forma

ltphp define(EMPRESAZendSA) define(AutorLuis Miguel Cabezas Granado) gt

Para mostrar el valor de las constantes uacutenicamente hay que invocar su nombre esta vez sin utilizar el siacutembolo de $

ltphp Definimos primero la constante define (COLOR_ROJO FF0000) Y ahora escribimos en pantalla su resultado echo COLOR_ROJO Hay que destacar que el signo de $ no hace falta ponerlo Existe otra funcioacuten que nos permite averiguar el valor de la constante echo constant ( C0L0R_R0JO) gt

defined()

Puede utilizar def ined () para averiguar si una constante ya se ha creado

ltphp define(EditorialAnaya) if (defined(Editorial) ) echo La Editorial es Editorial

gt

64 Capiacutetulo 2

Constantes predefinidas

PHP 5 define varias constantes cada vez que se ejecuta un script y que son accesibles por nosotros

Tabla 22 Algunas constantes definidas por PHP 5

Nombre Descripcioacuten

PHP_VERSION Versioacuten del parse de PHP que estamos utilizando

PHP_OS Sistema operativo del servidor de PHP

PEAR_EXTENSION_DIR Ruta donde estaacute instalada la extensioacuten PEAR

PHP_LIBDIR Ruta donde estaacuten almacenadas las libreriacuteas de PHP 5

Finalmente tenemos 5 constantes maacutegicas tal y como las definen en el sishytio Web wwwphpnet que cambian de valor dependiendo del lugar donshyde se usen Por ejemplo el valor de la constante LINE depende de la liacutenea donde la estemos usando en nuestro programa

Tabla 23 Constantes maacutegicas

Nombre Descripcioacuten

LINE Indica el nuacutemero de liacutenea desde la que imprimimos el

valor

FILE Ruta completa al fichero

FUNCTION Nombre de la funcioacuten que la contiene

CLASS Nombre de la clase

_ M E T H O D _ Nombre del meacutetodo

Advertencia

Hay que tener cuidado con el nombre de las constantes maacutegicas Los siacutembolos que hay a la izquierda y ala derecha del nombre son dos guiones bajos seguidos (_)

ltphp echo LINE - VERSIOacuteN de PHP 5PHP_VERSION echo ltbrgt

Variables constantes y tipos de datos 65

echo LINE - SISTEMA Operativo Servidor PHP_OS echo ltbrgt echo LINE - Ruta de las extensiones PHP_EXTENSION_DIR echo ltbrgt echo LINE - API de Servidor PHPJ3API gt

Funciones relacionadas con variables

PHP 5 brinda al programador una serie de funciones para el manejo de variables

isset()

Con esta funcioacuten podemos averiguar si una funcioacuten existe dentro de nuesshytro programa Si existe devuelve true y si no existe false

ltphp $DNI = 8868543-Z if (isset($DNI)) echo (La variable DNI existe)

66 Capiacutetulo 2

gt

unset()

Libera la memoria ocupada por una variable destruyendo su nombre y su contenido Despueacutes de usar unset () la variable destruida apareceraacute comoase al utilizar la funcioacuten i s s e t ()

ltphp $Nombre = Mariacutea Fernanda if (isset($Nombre)) echo (El nombre existe)

Podemos comprobar queacute pasa si liberamos la variable $Nombre unset($Nombre)iexcl if (isset($Nombre)) echo (El nombre existe) else echo (El nombre ya no existe) gt

El resultado es el siguiente El nombre e x i s t e El nombre ya no e x i s t e

gettype()

Con esta funcioacuten podemos averiguar el tipo de dato almacenado en la variable Nos puede devolver uno de los siguientes valores

bull integer

bull double

bull string

bull array

bull object

bull class

bull unknown type ltphp $correo = luisnccextremaduraorg echo la variable correo es del tipo

Variables constantes y tipos de datos 67

echo g e t t y p e ( $ c o r r e o ) gt

settype()

Convierte el tipo de la variable al especificado en la funcioacuten El tipo debe especificarse eligiendo uno de los siguientes array double integer object o string Si la funcioacuten no es capaz de convertir el tipo de la variable devuelshyve el valor false

ltphp $correo = luisnccextremaduraorg if (settype($correointeger))

echo (Variable correo convertida a Enteroltbrgt)

else

echo (Imposible convertir al tipo Enteroltbrgt)

echo (Valor actual de correo es $correo) gt

Al tratar de convertir un tipo string (una cadena de caracteres) a un enteshyro PHP 5 comprueba si existe alguacuten nuacutemero Si no existe cambia el valor a O y la funcioacuten s e t t y p e () la evaluacutea como correcta

empty()

Comprueba si una variable estaacute vaciacutea no existe o su valor es 0 ltphp $correo = luisnccextremaduraorg if (empty($nombre))

echo (La variable nombre no existe)

$numero_entero = O if (empty($numero_entero))

echo (La variable numero_entero no existe o tiene el valor O) gt

isjntegerf) is_double() is_string()

Estas funciones devuelven true si la variable pasada coincide con el tipo que indica la funcioacuten

68 Capiacutetulo 2

Si la variable $numero_en te ro se evaluacutea con la funcioacuten i s _ i n t e g e r ( ) devolveraacute true

ltphp $numero_entero = 0 if (is_integer()($numero_entero))

echo (numero_entero es del tipo integer)

gt

intval() doublevalQ strval()

Convierte el valor de una variable al tipo indicado en la funcioacuten Esta funshycioacuten no permite la conversioacuten a tipos object o array

ltphp Conversioacuten de un tipo string a un integer $cadena = 232 echo El tipo de la variable cadena es gettype($cadena)ltbrgt $numero = intval($cadena) echo (el numero es $numero) gt

Resumen

La base de la programacioacuten reside en la creacioacuten de datos y su procesashymiento En este capiacutetulo hemos visto coacutemo declarar variables de diferenshytes tipos y coacutemo utilizar funciones para averiguar las propiedades de cada una de ellas Ademaacutes de las variables las constantes juegan un papel muy importante sobre todo las predefinidas por PHP 5 que nos dan informashycioacuten muy uacutetil con la que poder trabajar

En este capiacutetulo aprenderaacute a

bull Utilizar los diferentes tipos de operadores existentes bull Distinguir entre operadores unarios binarios y ternarios

bull Comprender la preferencia de ejecucioacuten entre operadores

70 Capiacutetulo 3

Introduccioacuten

En el capiacutetulo anterior hemos visto ejemplos de coacutedigo escrito en PHP que utilizan siacutembolos muy comunes en el ambiente matemaacutetico e inforshymaacutetico Estos siacutembolos que aparecen entre variables o dentro de funciones son conocidos como operadores Existen varios tipos de operadores

bull De asignacioacuten bull Unario bull Aritmeacuteticos bull De comparacioacuten bull Loacutegicos bull Ternario bull Bit a bit bull Asignacioacuten combinados bull De ejecucioacuten bull Supresioacuten de errores

Operador de asignacioacuten

El maacutes baacutesico es el siacutembolo de asignacioacuten (=) utilizado para dar valores a las variables que usamos en nuestro coacutedigo

ltphp $variable = 34 $variable2 = Asignacioacuten de valores gt

Las variables que estaacuten a la izquierda del operador toman el valor que se encuentra en la expresioacuten de la derecha

Advertencia

No hay que confundir el operador de asignacioacuten (=) con el operashydor de comparacioacuten (==) sobre todo en bucles de control donde seriacutea difiacutecil encontrar alguacuten fallo

Operadores 71

Operador Unario

El signo menos (-) se utiliza delante de un nuacutemero o variable numeacuterica Este operador tiene la propiedad de hacer a los nuacutemeros negativos o poshysitivos dependiendo del signo actual

ltphp $entero = 23 $entero_negativo = -$entero El valor es ahora -23 entero2 = -$entero__negativo El valor cambia ahora a 23 gt

Operadores Aritmeacuteticos

Este tipo de operadores forman parte de la aritmeacutetica baacutesica Nos resultashyraacute familiar porque son siacutembolos muy utilizados en el aprendizaje de las matemaacuteticas

Tabla 31 Operadores aritmeacuteticos

Ejemplo Nombre Resultado

$a + $b suma Suma las dos variables $a - $b resta Hace la diferencia de las dos variables Sa $b multiplicacioacuten Producto de las variables $a $b divisioacuten Cociente entre las dos variables $a $b Moacutedulo Resto de la divisioacuten de $a entre $b

Nota

-rr PHP 5 ignora los espacios en blanco entre las variables y los opeshyradores Aunque $a + $b es equivalente a $a + $b es preferible utilizar la primera forma de escribir porque se hace maacutes legible

Operadores de comparacioacuten

En algunos ejemplos del capiacutetulo anterior puede ver que se utiliza la esshytructura de control if el se Como veremos maacutes adelante esta estructu-

72 Capiacutetulo 3

ra compara dos valores y elige el camino a seguir El valor de la comparashycioacuten siempre es true ofalse

Tabla 32 Operadores de comparacioacuten

Ejemplo Nombre Resultado

$a == $b Igualdad Devuelve true si $a y $b son iguales $a === $b Identidad Verdadero si son iguales y del mismo tipo $a = $b Distinto True si son distintos $a ltgt $b Distinto True si son distintos $a lt $b Menor que Cierto si $a es menor que $b $a gt $b Mayor que Cierto si $a es mayor que $b $a lt= $b Menor o igual Correcto si $a es menor o igual que $b $a gt= $b Mayor o igual Correcto si $a es mayor o igual que $b

ltphp $a = 23 Asignacioacuten de los valores $b = 75 if ($a gt= $b) La condicioacuten no se cumple El resultado es false

echo Esta parte no se ejecuta else

echo La comparacioacuten es false porque $a es menor que $b

gt

Operadores 73

Operadores Loacutegicos

Durante el desarrollo de su proyecto puede encontrarse con situaciones en las que necesite hacer varias comparaciones seguidas para que se cumshypla una determinada condicioacuten PHP 5 permite unir todas las comparashyciones en una mediante el uso de los operadores loacutegicos

Tabla 33 Operadores loacutegicos

Ejemplo Nombre Resultado

expresionl and expresion2 Y Si las dos expresiones son vershydaderas el valor es true

expresionl or expresion2 O Si una de las expresiones es vershydadera el valor es true

expresionl xor expresion2 O exclusivo True si una expresioacuten es verdashydera y la otra falsa

expresionl Negacioacuten Verdadero si la expresioacuten no es cierta

expresionl ampamp expresion2 Y Si las dos expresiones son vershydaderas el valor es true

expresionl || expresion2 O Si una de las expresiones es vershydadera el valor es true

El listado siguiente muestra dos condiciones anidadas lt php $a = 2 3 Sb = 75 $c = true if ($a lt $b)

if ($c) echo (Se cumplen las dos condiciones)

gt gt

Egtta expresioacuten se puede hacer maacutes legible utilizando alguacuten operador loacuteshygico

ltphp $a = 23 3b = 75 $c = t rue

74 Capiacutetulo 3

i f ($a lt $b and $c) echo Se cumplen l a s dos cond ic iones

gt

Operador Ternario

Los operadores que hemos visto hasta ahora son capaces de manejar un operando (Unarios) o dos operandos (binarios) El operador ternario o de comparacioacuten evaluacutea un operando y dependiendo de si es falso o vershydadero evaluacutea el segundo operando o el tercero La expresioacuten que se quiere evaluar se escribe delante de un siacutembolo () despueacutes la expresioacuten que tiene que ejecutarse si la evaluacioacuten anterior es true seguida del siacutembolo () con la expresioacuten que debe ejecutarse si es false

ltphp $valor = false $valor == true $resultado = OK $resultado = FALLO Si $value es true $resultado seraacute OK Si es false $re sultado seraacute FALLO echo $resultado gt

Operadores bit a bit

Estos operadores son complicados de entender si no conoce la loacutegica bishynaria Afortunadamente se utilizan en muy pocas ocasiones Los operashydores de bit utilizan las variables a nivel bajo tal y como se almacenan en memoria fiacutesica y comparan bit a bit los valores Lo mejor es verlo con un ejemplo

ltphp bull$a = 4 Valor binario 100 $b = 5 Valor binario 101 $c = $a amp $b echo $c El valor de c es 100 gt

El operador binario Y (siacutembolo amp) compara bit a bit las variables $a y $b Si los bits de una misma posicioacuten son true (tienen el valor 1) el bit resultashydo es 1 En este caso soacutelo existe una pareja de bits que es igual a true (sus

Operadores 75

dos valores son 1) por lo tanto el valor de la variable $c es 4 (en binario 100)

Tabla 34 Operadores bit a bit

Ejemplo Nombre Resultado

$a amp $b Y Si las parejas de bits son verdaderas el resultado es

verdadero

$a | $b O Si alguacuten bit de la pareja es verdadero el resultado es

verdadero

$a A $b O Si un bit de la pareja es true y el otro false el resultado exclusiva es verdadero

~$a No Los bits 1 se vuelven 0 y viceversa Tambieacuten cambia el bit que se refiere al signo positivo o negativo

$a ltlt $b Desplaza- Desplaza a la izquierda los bits de la variable $a tantos miento a bits como indique la variable $b la izquierda de bits

$a gtgt $b Desplaza- Desplaza a la derecha los bits de la variable $a tantos miento a bits como indique la variable $b la derecha

Nota

Puesto que la notacioacuten binaria se escapa del enfoque de este libro le recomiendo algunas lecturas posteriores referidas a la loacutegica de bit si es que tiene curiosidad Probablemente no utilizaraacute estos operadores nunca pero eso depende de la magnitud de los proyecshytos a los que se enfrente

Operadores de asignacioacuten combinados

En numerosas ocasiones se nos presentan situaciones en las que una va-riable debe incrementar o disminuir su valor en 1

ltphp

$a =23

$a = $a +1 Incrementamos en 1 el valor de la variable gt

HP 5 provee operadores combinados que permiten asignar raacutepidamente crementos de valor concatenaciones de caracteres etceacutetera

76 Capiacutetulo 3

Tabla 35 Operadores de asignacioacuten combinados

Ejemplo Nombre Equivalencia

$a++ Incremento $a = $a +1

$a~ Decremento $a = $a -1

++$a Incremento $a = $a +1

~$a Decremento $a = $a -1

$a += $b Suma $a = $a + $b

$a -= $b Resta $a = $a - $b

$a = $b Multiplicacioacuten $a = $a $b

$a = $b Divisioacuten $a = $a $b

$a = $b Moacutedulo $a = $a $b

$a amp= $b Y $a = $a amp $b

$a |= $b O $a = $a | $b

$a A= $b O exclusiva $a = $a A $b

$a = $b Concatenacioacuten $a = $a $b

$a gtgt= $b Desplazamiento a la derecha $a = $a gtgt $b

$a ltlt= $b Desplazamiento a la izquierda $a = $a ltlt $b

Advertencia

Como vemos en la tabla 35 iexclos operadores de incremento y deshycremento pueden aparecer a la derecha o a la izquierda de un vashyriable La posicioacuten del operador influye en el orden en el que la variable se asigna o se incrementa Mejor verlo en un ejemplo ltphp $a = 23 $b = $a++ $b es igual a 23 porque $a se incrementa despueacutes de la asignacioacuten

$a = 2 3 $c = + + $a $c es igual a 24 porque $a se incrementa antes de la asignacioacuten

echo la variable b es $b y c es $c gt

Operador de ejecucioacuten

Si tiene experiencia con la programacioacuten en shell de Unix o gnuLinux sabraacute que el apostrofe invertido sirve para ejecutar comandos del sis-

Operadores 77

tema PHP 5 ha adoptado esta nomenclatura y funciona exactamente igual

ltphp $listado_archivos = Is -la~ Hacemos un listado de los ficheros del directorio actual echo $listado_archivos y lo sacamos por pantalla gt

Nota

El comando ls del ejemplo anterior es propio de sistemas Unix y gnuLinux Siacute hace pruebas sobre un sistema basado en el Sistema Operativo Windows el ejemplo anterior no funcionariacutea tendriacutea que cambiar el comando por dir

Operador de supresioacuten de errores

La mayoriacutea de las funciones que se utilizan en PHP 5 muestran errores en el navegador cuando algo falla

Si intenta abrir un fichero que no existe PHP mostraraacute un mensaje de error v continuaraacute la ejecucioacuten del programa

78 Capiacutetulo 3

El operador () colocado delante de una funcioacuten evitaraacute que se muestre el error

ltphp $fichero = fopen(pruebatxt r) Muestra un error en el navegador echo (El programa sigue ejecutaacutendose) gt

El coacutedigo siguiente oculta la salida de error por pantalla

ltphp $fichero = fopen(pruebatxtr) echo (El programa sigue ejecutaacutendose) gt

Precedencia de Operadores

Vamos a echar un vistazo al coacutedigo siguiente

ltphp $resultado = 20 + 10 10 echo $resultado gt

Aparentemente es un coacutedigo muy simple pero encierra un problema mashytemaacutetico

Existen dos resultados posibles en funcioacuten del operador que debe ejecushytarse antes

Si la suma se ejecuta antes la variable $ r e s u l t a d o tendraacute el valor 300 y si la multiplicacioacuten se ejecuta antes tendremos q u e $ r e s u l t a d o equivashyle a 120

Si comprobamos el coacutedigo el resultado que nos muestra es 120 por lo tanto el operador de multiplicacioacuten () es preferente con respecto al operador de suma (+)

Si los operadores que aparecen son ideacutenticos existe un orden de ejecushycioacuten que puede ser desde la izquierda a la derecha o derecha a izquierda

ltphp $resultado = 2 0 1 0 2 echo $resultado gt

El valor de $ r e s u l t a d o es ahora 1 porque primero se calcula 20 10 y despueacutes ese mismo resultado se divide entre 2 es decir la asociacioacuten enshytre operadores de divisioacuten es desde la izquierda

Operadores 79

Tabla 36 Orden de preferencia de los operadores

Operador Operacioacuten Asociacioacuten

() Pareacutentesis de preferencia NA

new Instancia de objeto NA

[] array Derecha

NO loacutegico Derecha

Signo menos Derecha

++ -- Incremento decremento Derecha

Supresioacuten de errores Derecha

Multiplicacioacuten divisioacuten y moacutedulo Izquierda

+ - Suma resta concatenacioacuten Izquierda

ltlt gtgt Desplazamiento izquierda y derecha Izquierda

lt lt = gt gt = Menor que menor o igual NA

mayor que mayor o igual

== = Igual no igual NA

amp Y izquierda A O exclusivo Izquierda

| O Izquierda

ampamp Y loacutegico Izquierda

|| O loacutegico Izquierda

condicional Derecha = += = = = Asignacioacuten Derecha = = amp= = -= ltlt= gtgt=

and Y loacutegico Izquierda

xor O exclusivo loacutegico Izquierda

or O loacutegico Izquierda

El operador pareacutentesis tiene la propiedad de dar preferencia en la evaluashyron a todos los operadores que contiene El siguiente ejemplo muestra oacutemo podemos utilizar correctamente el operador pareacutentesis

ltphp $resultado = 2 0 1 0 + 2 echo $resultado El resultado es 4 $resultado = 20 (10 + 2) echo $resultado El resultado es 166666667 gt

Resumen

Los operadores son responsables de todas las operaciones que realizamos en nuestros programas Por eso es importante conocer las propiedades v los casos de uso de cada uno de ellos para poder sacarles el maacuteximo partishydo Sin embargo si ya conoce alguacuten lenguaje de programacioacuten la intuishycioacuten le haraacute utilizarlos adecuadamente sin pararse a pensar en el tipo de operador

Por uacuteltimo debe prestar un especial intereacutes a la preferencia de uso ya que una mala utilizacioacuten redundaraacute en un error muy difiacutecil de controlar

En este capiacutetulo aprenderaacute a

bull Utilizar las estructuras de control de eleccioacuten simple y muacuteltiple bull Crear bucles de diferentes tipos bull Crear sus primeros programas bull Conocer las sentencias para interrumpir un bucle

82 Capiacutetulo 4

Introduccioacuten

Es difiacutecil imaginar un programa sin estructuras de control Eacutestas nos permishyten elegir diferentes caminos en funcioacuten de los datos que evaluamos en cada momento En este capiacutetulo trataremos dos tipos de estructuras de control

bull Estructuras de eleccioacuten

bull Estructuras de bucle

Las estructuras de eleccioacuten permiten evaluar una condicioacuten o varias y eleshygir el camino correcto Las de bucle repiten un nuacutemero determinado de veces un conjunto de instrucciones

Estructuras de eleccioacuten

Existen dos tipos

bull Eleccioacuten simple bull Eleccioacuten muacuteltiple

if-else

La sintaxis de esta estructura es if (condicioacuten) instruccioacuten

Si se cumple la condicioacuten se ejecuta la instruccioacuten que le sigue Si quiere que se ejecuten varias instrucciones debe utilizar el siacutembolo llave ( insshytrucciones iexcl )

if (condicioacuten) instruccionl instruccion2iexcl

instruccion3

La estructura if puede ampliarse para que se pueda elegir entre condishycioacuten verdadera y falsa

if (condicioacuten) instruccionl instruccioacuten2 instruccion3

else

Estructuras de control 83

instruccionl -instruccioacuten2 instruccion3

Si la condicioacuten es verdadera se ejecutan las instrucciones inmediatamente despueacutes del if y si la condicioacuten es falsa se ejecutan las instrucciones disshypuestas despueacutes de la palabra e l s e Puede ver un ejemplo completo

ltphp $valor = 23 $valor2 = 27 if ($valor lt $valor2)

echo La variable valor es menor que valor2 else

echo La variable valor es mayor que valor2

gt

elseif

Es muy comuacuten hacer comparaciones en cascada para comprobar varios valores

ltphp $ d i a = 4 if ($d ia == 1)

84 Capiacutetulo 4

echo El diacutea es Lunes else

if ($dia == 2) echo El diacutea es Martes

else if ($dia == 3)

echo El diacutea es Mieacutercoles else

if ($dia == 4) echo El diacutea es Jueves

gt

El patroacuten anterior es tan comuacuten que existe una estructura especial para manejarlo

Puede escribir el ejemplo anterior con la palabra reservada e l s e i f de la siguiente forma

ltphp $dia=4

if ($dia == 1) echo El diacutea es Lunes

elseif ($dia == 2) echo El diacutea es Martes

elseif ($dia == 3) echo El diacutea es Mieacutercoles

elseif ($dia == 4) echo El diacutea es Jueves

gt

El ejemplo anterior evaluacutea la variable $dia hasta que encuentra el valor correcto y ejecuta las instrucciones

switch

La construccioacuten swi t ch comprueba el valor de una expresioacuten y permite elegir entre un conjunto de instrucciones El formato es el siguiente switch (expresioacuten)

case valorl instruccionl instruccion2 instruccion3 break

Estructuras de control 85

case valor2 instruccionl instruccion2 instruccion3 break

case valor3 instruccionl instruccion2 instruccion3 break

default instruccionl instruccion2

instruccion3

La expresioacuten puede ser de cualquier tipo siempre que devuelva un valor de tipo entero de coma flotante o de cadena de caracteres Una vez evashyluada la expresioacuten se busca el valor en la instruccioacuten case y si coincide se ejecutan todas las instrucciones hasta la palabra reservada break Si no coincide ninguacuten valor se ejecutan las instrucciones por defecto Veamos un ejemplo completo

ltphp $dia = 4 switch ($dia)

case 1

echo El diacutea es Lunes break

case 2 echo El diacutea es Martes break

case 3 echo El diacutea es Mieacutercoles break

case 4 echo El diacutea es Jueves break

case 5 echo El diacutea es Viernes break

case 6 echo El diacutea es Saacutebado break

case 7 echo El diacutea es Domingo break

default

Bucles

Los bucles son estructuras de control que permiten repetir varias veces las mismas instrucciones

while

El bucle while es el maacutes baacutesico de todos La construccioacuten baacutesica es la sishyguiente

while (condicioacuten) instruccioacutenlbull instruccioacuten2 instruccioacuten3

La condicioacuten se evaluacutea al principio

Si es verdadera se ejecutan las instrucciones que estaacuten dentro del bucle y se vuelve a evaluar la condicioacuten

86 Capiacutetulo 4

echo El diacutea de la semana es incorrecto

gt

Estructuras de control 87

Si la condicioacuten es falsa no se ejecutan las instrucciones y se continuacutea con el desarrollo del programa

Puesto que la condicioacuten se evaluacutea antes de ejecutar las instrucciones es posible que algunos bucles no se ejecuten ninguna vez

El siguiente ejemplo muestra una instruccioacuten while que no se ejecuta nunshyca porque la condicioacuten es falsa

ltphp $variable = false while ($variable)

echo Esta linea no se ejecuta nunca

gt

Existe la posibilidad de que un bucle se ejecute infinitas veces si dentro de las instrucciones no existe nada que cambie la condicioacuten que se evaluacutea al principio

ltphp $variable = true while ($variable)

echo CUIDADO Esta liacutenea se ejecuta siempre

gt

88 Capiacutetulo 4

El bucle while se puede utilizar para ejecutar un nuacutemero determinado de veces las instrucciones que implica

Veacutease el ejemplo de la serie de Fibonacci

ltphp $numero_anterior = 1 $numero_posterior = 1 $serie = 1 $fin = 10000 echo Serie de Fibonacci while ($serie lt $fin) echo $serie $serie = $numero_anterior + $numero_posterior $numero_anterior = $numero_posterior $numero_posterior = $serie

gt

Cada nuacutemero de la serie de Fibonacci se forma sumando los dos nuacutemer -anteriores

En el ejemplo la condicioacuten es que el nuacutemero de la serie sea menor que t

nuacutemero que marca la variable $f i n es decir si el nuacutemero que indica iquest serie es mayor que 10000 el bucle finaliza

La variable $f in sirve de valor maacuteximo y puede cambiarlo en funcioacuten la cantidad de nuacutemeros que quiera tener en pantalla

Estructuras de control 89

do-while

Este bucle es igual que el anterior pero la condicioacuten se evaluacutea al final de las instrucciones Por lo tanto el coacutedigo que estaacute entre las llaves se ejecuta al menos una vez El formato baacutesico es el siguiente

do instruccioacutenl instruccioacuten2 instruccioacuten3

while (condicioacuten)

Puede comprobar que la diferencia es miacutenima cuando utiliza esta estrucshytura de control para la serie de Fibonacci

ltphp $numero_anterior = 1 $numero_posterior = 1 $serie = 1 $fin = 6765 echo Serie de Fibonacci do

echo $serie $serie = $numero_anterior + $numero_posterior $numero_anterior = $numero_posterior $numero_posterior = $serie

whi le ($ser ie lt $ f i n ) gt

for

La construccioacuten de bucle maacutes complicada es la del for Tiene la siguiente sintaxis

for (expresioacuten inicial condicioacuten de fin expresioacuten de fin) instruccioacutenl instruccioacuten2

instruccioacuten3

El funcionamiento es muy sencillo La expresioacuten inicial se ejecuta una sola vez al principio del bucle La condicioacuten de fin se evaluacutea cada vez que se ejecuta el bucle Si es verdashydera se continuacutea la ejecucioacuten y si es falsa se sale del bucle Al final de cada interaccioacuten se ejecuta la expresioacuten de fin

90 Capiacutetulo 4

Puede simular la instruccioacuten f or con una instruccioacuten w h i l e de esta forma

expresioacuten inicial

while (condicioacuten de fin)

instruccioacutenl

instruccioacuten2

instruccioacuten3

expresioacuten de fin

Otra forma poco corriente es eliminar alguna o todas las expresiones de bucle Si quita todas las expresiones se crea un bucle infinito

fOr ( )

instruccioacutenl

instruccioacuten2

instruccioacuten3

equivale a

while (true)

instruccioacutenl

instruccioacuten2

instruccioacuten3

El caso contrario es antildeadir maacutes de una condicioacuten en cada clase de expreshysioacuten separadas por comas En este caso la condicioacuten de fin se evaluara falso si alguna de las claacuteusulas es falsa En realidad funciona como un C loacutegico

ltphp

for ($x = 1 $y = 1 $z = 1 $y lt 10 $z lt 10 $x++ $y = $y -

2 $z = $z + 3)

echo ($x $y $zltbrgt)

gt

Un ejemplo claacutesico es la tabla de multiplicar lthtmlgt ltbodygt ltbgtTABLA DE MULTIPLICARltbgt lttable border=lgt ltphp echo (lttrgt) echo (ltthxthgt ) for ($cabecera = 1 $cabecera lt= 10 $cabecera++)

echo (ltthgt) echo $cabecera

Estructuras de control 91

echo (ltthgt)

echo (lttrgt) for ($x = l$x lt= 10 $x++ )

echo (lttrgt) echo (ltthgt) echo $x echo (ltthgt) for ($y = l$y lt= 10 $y++ )

$multiplicacion = $x $y echo (lttdgt) echo ($multiacutepliacutecaciacuteon) echo (lttdgt)

echo (lttrgt) gt gt lttablegt ltbodygt lthtmlgt

[ ejemplo se sirve de un bucle for que crea una cabecera de tabla con la queta especial ltthgt donde inserta los nuacutemeros del uno al diez Estos umeros escritos en horizontal se podraacuten cruzar con los verticales para atener asiacute el resultado de una multiplicacioacuten

92 Capiacutetulo 4

El siguiente paso es un conjunto de dos bucles anidados El primer bucle almacena en la variable $x los valores numeacutericos que apareceraacuten como cabecera de la columna uno El segundo bucle seraacute el encargado de multishyplicar el valor actual de $x por los valores del 1 al 10

Cada vez que se ejecuta el segundo f o r se obtiene una celda nueva con un valor determinado por la multiplicacioacuten y cada vez que se ejecuta el primer bucle aparece una nueva fila cuya cabecera es un nuacutemero del 1 al 10

break y continueacute

El camino ordinario para salir de un bucle es que la condicioacuten se evaluacutee a false Existe una forma especial de salir de un bucle utilizando las palashybras reservadas b r e a k y c o n t i n u eacute Su forma de actuar es la siguiente

bull break Sale del bucle actual y continuacutea el programa

bull continueacute Salta hasta el final de la interaccioacuten y continuacutea la ejecucioacuten desde el principio del bucle

El coacutedigo siguiente muestra la forma de utilizar b r e a k

ltphp for ($x = 1 $x lt 20 $x++)

if ($x == 10) break

else echo $xltbrgt

La salida por pantalla es una sucesioacuten de nuacutemeros del 1 al 9 Al llegar la variable $x al nuacutemero 10 la condicioacuten del if se cumple y se ejecuta la instruccioacuten b r e a k saliendo del bucle Veamos ahora el mismo ejemplo pero utilizando c o n t i n u eacute

ltphp for ($x = 1 $x lt 20 $x++)

if ($x == 10) continueacute

else echo $xltbrgt

gt

Estructuras de control 93

En este caso cuando $x alcanza el valor 101o que hace la instruccioacuten conshyt i n u eacute es ir hacia el final de bucle y volver al principio comprobando la condicioacuten

El resultado por pantalla es una sucesioacuten de nuacutemeros desde el 1 hasta el 19 sin incluir el nuacutemero 10

Finalizar la ejecucioacuten de un programa

Hay veces que necesitamos parar la ejecucioacuten de un programa por divershysas causas ha ocurrido un error un fallo en la entrada del nombre y la conshytrasentildea La funcioacuten para la ejecucioacuten es e x i t () o d i e () Estas dos funciones aceptan un paraacutemetro que se imprime en pantalla Por ejemplo considere el siguiente coacutedigo que asume la conexioacuten a una base de datos

ltphp $conexion = conectar_base_datos(libros) if ( $conexion)

die (Se ha producido alguacuten error en la conexioacuten)

gt

Se puede apreciar que si la variable $ c o n e x i oacute n se evaluacutea false (no se ha conseguido la conexioacuten) se detiene la ejecucioacuten del programa Una vershysioacuten maacutes compacta se consigue utilizando el operador or

ltphp $conexion = conectar_base_datos(libros) or die (Se ha producido alguacuten error en la conexioacuten) gt

Nota

e x i t () y d i e () eran iexclas uacutenicas alternativas para el control de errores criacuteticos en versiones anteriores de PHP En PHP 5 aforshytunadamente se ha incluido un potente manejo de excepciones que hace la ejecucioacuten maacutes flexible

Sintaxis alternativa

Algunas estructuras de control pueden escribirse de una forma distinta Las estructuras i f w h i l e f or y s w i t c h pueden escribirse sustituyen-

94 Capiacutetulo 4

do la llave de inicio por un siacutembolo de dos puntos () y la llave de cierre por e n d i f e n d w h i l e endf or y e n d s w i t c h respectivamente

Como ejemplo podemos ver la estructura i f

ltphp $variable = 10 if ($variable == 10)

echo Nueva estructura de control gt

El coacutedigo siguiente es equivalente al anterior

ltphp $variable = 10 if ($variable == 10)

echo Nueva estructura de control end i f

gt

Resumen

Si ha llegado hasta aquiacute ya conoceraacute los secretos baacutesicos de la programashycioacuten en PHP 5 Como puede darse cuenta lo uacutenico necesario para hacer un programa es tener claro la forma de utilizar las variables los operadoshyres y las estructuras de control Una vez dominado esto lo demaacutes es aprenshyder funciones de PHP y teacutecnicas de recuperacioacuten e insercioacuten de datos

Los capiacutetulos siguientes hacen un estudio maacutes concienzudo de las variashybles y las funciones que facilitan el proceso de interaccioacuten entre ellas

En este capiacutetulo aprenderaacute a

bull Crear sus propias funciones bull Utilizar paraacutemetros fijos y variables

bull Realizar funciones recursivas bull Separar el coacutedigo fuente en varios ficheros

96 Capiacutetulo 5

Introduccioacuten

Las funciones son grupos de instrucciones independientes que tienen un propoacutesito determinado

Asiacute tenemos funciones que calculan la raiacutez cuadrada de un nuacutemero nos dan un nuacutemero aleatorio o permiten contar los caracteres de una palabra La sintaxis baacutesica de una funcioacuten es la siguiente

nombre_funcioacuten (paraacutemetrol paraacutemetro2 paraacutemetro3paraacutemetro_n)

Las funciones pueden ser llamadas con varios paraacutemetros o con ninguno dependiendo de su definicioacuten

Cuando PHP encuentra en el coacutedigo la llamada a una funcioacuten primero evaluacutea cada argumento y los utiliza como paraacutemetro de entrada Despueacutes ejecuta la funcioacuten y devuelve el valor solicitado o realiza alguna accioacuten sin enviar ninguacuten valor de salida

El siguiente ejemplo contiene un conjunto de llamadas a funciones con 01 oacute 2 paraacutemetros de entrada

ltphp echo sqrt(9) Raiacutez cuadrada de 9 es 3 echo rand(1020) Nuacutemero aleatorio entre 10 y 20 echo pi() Nuacutemero pi gt

Valores de las funciones

Cada funcioacuten en PHP se considera como una expresioacuten Se pueden utilishyzar las funciones para lo mismo que se utilizan las expresiones como alshymacenar su resultado en una variable o formar parte de una expresioacuten maacutes compleja

ltphp $numero_aleatorio = rand (1100) Se almacena en una variable $numero_aleatorio = rand (1100) + rand (1100) sqrt(9) Expresioacuten compleja gt

No todas las funciones devuelven un valor numeacuterico Tambieacuten pueden devolver caracteres array o truefalse si la funcioacuten ha tenido eacutexito o no Este tipo de funciones se utiliza para conectar a bases de datos escribir a ficheros de texto manipular imaacutegenes etceacutetera

Funciones 97

Funcioacuten de ejemplo Obtencioacuten de la fecha actual

Existen un conjunto de funciones que permiten averiguar la fecha actual del sistema Una de estas funciones es d a t e ( ) que permite recuperar el antildeo diacutea mes etceacutetera del momento en el que se hace la consulta Para averiguar el diacutea de hoy podemos utilizar la construccioacuten

lt d a t e (d) gt

El paraacutemetro que pasamos entre pareacutentesis indica a la funcioacuten el formato de fecha que queremos obtener En este caso la d indica que queremos obtener el diacutea en formato numeacuterico La siguiente tabla relaciona los caracshyteres dentro de la funcioacuten d a t e () con su aplicacioacuten praacutectica

Tabla 51 Formato de fecha con date()

Caraacutecter Valor

a Imprime am o pm

A AM o PM

h La hora en formato (01-12)

H Hora en formato 24 (00-23)

g Hora de 1 a 12 sin un cero delante

G Hora de 1 a 23 sin cero delante

i Minutos de 00 a 59

s Segundos de 00 a 59

d Diacutea del mes (01 a 31)

j Diacutea del mes sin cero (1 a 31)

w Diacutea de la semana (0 a 6) El 0 es el domingo

m Mes actual (01 al 12)

n Mes actual sin ceros (1 a 12)

Y Antildeo con 4 diacutegitos (2004)

y Antildeo con 2 diacutegitos (04)

z Diacutea del antildeo (0 a 365)

t Nuacutemero de diacuteas que tiene el mes actual

98 Capiacutetulo 5

Se pueden utilizar varios caracteres dentro de la funcioacuten indicando el forshymato de fecha que nos interesa

ltphp $meses = array (Enero Febrero Marzo Abril Mayo

Junio Julio Agosto Septiembre Octubre Noviembre Diciembre)

echo Fecha actual date(d-m-Y) ltbrgt echo Diacutea del antildeo date(z) ltbrgt echo Estamos en el mes $meses[date(n) ] ltbrgt gt

El resultado en pantalla es el siguiente

Documentacioacuten sobre funciones

Desde sus inicios PHP se disentildeoacute para que fuera sencillo de utilizar y de extender por la comunidad de desarrolladores La potencia reside en la gran cantidad de funciones escritas de todo tipo Este libro cubre las funciones maacutes utilizadas en el desarrollo de un proshyyecto profesional pero seriacutea imposible cubrir todas las funciones existenshytes con detalle Por esta razoacuten es imprescindible tener como referencia la

Funciones 99

guiacutea on-line de PHP en wwwphpnet donde podemos encontrar clasifishycadas por temaacutetica todas las funciones existentes hasta ahora

Ademaacutes contamos con un buscador de apoyo que nos permite buscar la definicioacuten de una funcioacuten y ejemplos de uso escritas por usuarios de PHP

Para los usuarios que no conocen la forma de trabajar con el lenguaje C se hace necesario explicar coacutemo aparecen las funciones descritas en el mashynual de wwwphpnet El formato es el siguiente

tipo_devuelto nombre_funcioacuten (tipol argl tipo2 arg2) -

El t i p o - d e v u e l t o es el tipo de valor que la funcioacuten daraacute como salida Puede ser un integer double array etceacutetera El nombre de la f u n c i oacute n es la forma correcta de ejecutar el coacutedigo Los p a r aacute m e t r o s de e n t r a d a (arshygumentos) deben pertenecer al tipo que define la funcioacuten Un ejemplo de definicioacuten es

string substr (string string int start[ int length] )

Puede ver que la funcioacuten s u b s t r () devolveraacute como resultado una cadeshyna de caracteres y que tiene 2 argumentos de entrada como miacutenimo El paraacutemetro que se encuentra entre dos corchetes es opcional y puede decishydir usarlo o no

Funciones de usuario

Para realizar programas complejos en PHP 5 no es necesario escribir funshyciones Se pueden escribir programas utilizando todo lo aprendido hasta ahora

A medida que el proyecto se haga maacutes complejo el coacutedigo se haraacute maacutes extenso y menos legible En este punto deberiacutea comenzar a pensar en crear funciones que realicen determinadas tareas

Definicioacuten de funciones

El formato es el siguiente

function nombre_funcioacuten($argumentol $argumento2 )

instruccioacutenl instruccioacuten2 instruccioacuten3

100 Capiacutetulo 5

Como puede ver se comienza con la palabra reservada f u n c t i o n seguishyda del nombre de la f u n c i oacute n y el nuacutemero de p a r aacute m e t r o s n e c e s a shyr i o El bloque de coacutedigo que pertenece a nuestra funcioacuten debe introducirse entre dos siacutembolos de llave ( ) Un ejemplo claacutesico consiste en calcular el factorial de varios nuacutemeros El factorial del nuacutemero x se obtiene multishyplicando el nuacutemero x por el factorial de (x-1) teniendo en cuenta que el factorial de 1 es 1 Por ejemplo el factorial de 3 seriacutea 3 por el factorial de 2 es decir 3 2 1 El coacutedigo sin utilizar funciones es

ltphp $resultado = 1 $factorial = 3 Queremos calcular el factorial de 3 for ($x = $factorial $x gt 0 $x--)

^resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt bull

$resultado = 1 $factorial = 4 Queremos calcular el factorial de 4 for ($x = $factorial $x gt 0 $x--)

$resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt

$resultado = 1 $factorial = 5 Queremos calcular el factorial de 5 for ($x = $factorial $x gt 0 $x--)

$resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt

gt

Si se fija en el coacutedigo anterior podraacute comprobar que sigue un patroacuten muy evidente El caacutelculo del factorial se realiza en un bucle que va disminushyyendo el valor de una variable y multiplicando todos los valores entre siacute Aprovechando este patroacuten puede crear una funcioacuten que realice el factoshyrial del nuacutemero x ahorrando liacuteneas de coacutedigo

ltphp function factorial($numero)

$resultado = 1 for ($x = $numero $x gt 0 $x--)

$resultado = $resultado $x return $resultado

echo El factorial de 3 es factorial(3)ltbrgt

Funciones 101

echo El factorial de 4 es factorial(4)ltbrgt echo El factorial de 5 es factorial(5) ltbrgt gt

Si comparamos los dos ejemplos podemos llegar a la conclusioacuten de que el segundo es mucho maacutes legible y maacutes sencillo de realizar Como puede ver la funcioacuten f a c t o r i a l () hace uso de la palabra reservada r e t u r n que es la encargada de devolver el valor que estamos solicitando cuando se invoca la funcioacuten

Nota

Aunque en el ejemplo la funcioacuten f a c t o r i a l () recibe como pashyraacutemetro el nuacutemero 3 4 oacute 5 tambieacuten es posible llamarla con una variable del tipo integer o double

Paraacutemetros insuficientes

Si llama a una funcioacuten con menos paraacutemetros de los que debe utilizar por definicioacuten apareceraacute el siguiente error por defecto

Warning Missing argument 1 for factorial()

Este tipo de error no es criacutetico y puede controlarse con excepciones como veremos en capiacutetulos sucesivos Ademaacutes de las excepciones podemos utilishyzar el operador de supresioacuten de error delante de la funcioacuten de esta forshyma f a c t o r i a l ( )

No se recomienda eliminar los mensajes de error en este caso ya que hace complicado la correccioacuten de los posibles fallos

Paraacutemetros en exceso

Si al contrario que en el apartado anterior le pasa a una funcioacuten maacutes paraacuteshymetros que los definidos eacutestos seraacuten omitidos y la ejecucioacuten continuaraacute normalmente sin ninguacuten mensaje de error Esta propiedad de PHP 5 pershymite utilizar variables con un nuacutemero de paraacutemetros variable

Aacutembito de las variables

Las variables definidas en un archivo de PHP permanecen declaradas en todo el fichero menos en las funciones Las funciones crean un entorno de ejecucioacuten donde soacutelo pueden ver las variables que estaacuten dentro de las mismas Aunque no parece muy loacutegico esto nos permite tener variables

Funciones 103

con el mismo nombre en diferentes funciones haciendo el coacutedigo reutili-zable

Si nos fijamos en el ejemplo

ltphp $pi = 3 1 4 funct ion v a l o r _ p i ( )

if ( uuml s s e t ($pi) ) $pi = p i ()

re turn $pi

echo v a l o r _ p i ( ) gt

Se puede observar que definimos al comienzo del coacutedigo la variable $pi como un valor aproximado del nuacutemero pi (314) La funcioacuten v a l o r _ p i () comprueba si la variable $pi estaacute definida y si no lo estaacute recupera ese valor con una funcioacuten de PHP 5 Para entender el alcance de las variables vamos a ir paso a paso viendo queacute es lo que ocurre

bull Se define $pi a nivel global en el programa

bull Se define la funcioacuten v a l o r _ p i () que por ahora no se utiliza

bull Se lanza la ejecucioacuten de la funcioacuten

bull La funcioacuten evaluacutea si existe la variable $pi y da como resultado false Esto es asiacute porque la variable estaacute definida fuera de la funcioacuten y no dentro de ella por lo tanto se considera que la variable $p i dentro de la funcioacuten es distinta (entorno local) a la variable $pi definida fuera de la funcioacuten (entorno global)

bull El resultado por pantalla es 31415926535898

Esta forma de programar se considera la correcta en la comunidad de de-sarrolladores de PHP Auacuten asiacute existen mecanismos que permiten que una variable definida fuera de una funcioacuten pueda ser utilizada dentro de la misma simplemente anteponiendo la palabra reservada g l o b a l a la vashyriable definida dentro de la funcioacuten

Utilizando el ejemplo anterior tenemos

ltphp $pi = 3 1 4 funct ion v a l o r _ p i ( )

g l o b a l $pi if ( Uuml s s e t ($pi) )

$pi = pi ()

104 Capiacutetulo 5

re turn $pi

echo v a l o r _ p i ( )

gt

Si vemos paso a paso el ejemplo

bull Se define $pi a nivel global en el programa bull Se define la funcioacuten v a l o r _ p i () que por ahora no se utiliza bull Se lanza la ejecucioacuten de la funcioacuten

bull Dentro de la funcioacuten la variable $pi se define como global es decir se utiliza la variable creada al principio del coacutedigo

bull La funcioacuten evaluacutea si existe la variable $p i y da como resultado true

bull El resultado por pantalla es 314

Variables estaacuteticas

Por defecto las funciones que creamos en PHP 5 no retienen en memoria el valor de las variables que se utilizan Cada llamada a una funcioacuten imshyplica la nueva creacioacuten de las variables locales con su valor inicial La deshyclaracioacuten static antildeadida a una variable causa que la funcioacuten retenga en memoria el valor de esa variable en cada llamada Como puede ver en el ejemplo las 100 llamadas a la funcioacuten c o n t a d o r () dan siempre el misshymo resultado porque la variable $ c o n t a d o r se crea con cada llamada

ltphp function contador()

$contador = 0 $contador = $contador +1 return $contador

for ($x = 1 $X lt= 100 $x++)

echo contador() gt

Sin embargo podemos hacer que la funcioacuten recuerde los valores antildeadienshydo la palabra s t a t i c a la definicioacuten de la variable

ltphp function contador()

static $contador = 0 $contador = $contador + 1 return $contador

for ($x = 1 $x lt= 100 $x++)

Funciones 105

echo contador()

gt

iacutenclude() y require()

A medida que su proyecto se hace maacutes complejo comenzaraacute a crear funshyciones muy uacutetiles para conectar a bases de datos crear imaacutegenes al vuelo conectar por FTP etceacutetera y seguramente quiera emplear estas funcioshynes en otros proyectos distintos para ahorrar tiempo El camino para hashycer esto es muy sencillo Soacutelo tiene que guardar las funciones necesarias en un fichero con extensioacuten php htm c s s i n c etceacutetera y utilizar las directivas i n c l u d e () o r e q u i r e f ) desde la Web que vaya a utilizarlas

En PHP 5 no existen apenas diferencia entre ambas funciones salvo que la funcioacuten i n c l u d e () es maacutes tolerante a fallos que r e q u i r e () y permishyte continuar la ejecucioacuten del programa aunque se haya encontrado un fashyllo

La conclusioacuten es que debe utilizarse r e q u i r e () para aplicaciones que necesiten obligatoriamente alguacuten archivo criacutetico y no pueda continuarse la ejecucioacuten sin eacutel

Si en el desarrollo de nuestro proyecto nos encontramos con que vamos a utilizar varios archivos que hacen llamadas unos a otros podriacutea pasar que hagamos varias inclusiones del mismo archivo en distintos puntos proshyvocando alguacuten fallo difiacutecil de detectar Las funciones r e q u i r e _ o n c e () e i n c l u d e _ o n c e () solucionan eacuteste problema ya que si se intenta incluir un fichero varias veces con dichas funciones PHP 5 simplemente ignorashyraacute las llamadas El formato es el siguiente

require base_datosphp include contador_vistasphp require_once test php-include_once visitasphp

Recursividad

El paradigma de la programacioacuten nos lleva a los desarrolladores a invenshytar foacutermulas que minimicen el esfuerzo en nuestros programas pecando

106 Capiacutetulo 5

algunas veces de complejidad Las funciones recursivas son aquellas cashypaces de llamarse a siacute mismas Como uacutenico requisito es que haya una forshyma de salir en la llamada recursiva Si volvemos al ejemplo del nuacutemero factorial nos encontramos en que se puede escribir de la siguiente forma

ltphp function factorial($numero)

if ($numero == 1) return $numero

else return $numero factorial($numero-l)

echo El factorial de 7 es factorial(7) ltbrgt gt

Lo primero que llama la atencioacuten es que carece de un bucle f or para ir disminuyendo los nuacutemeros implicados en el factorial Lo que hace la funshycioacuten es multiplicar el nuacutemero que se pasa por el factorial del nuacutemero-1 Si el nuacutemero que se pasa es igual a 1 la funcioacuten deja de hacer llamadas reshycursivas y comienza a devolver los valores hasta llegar al resultado final

Funciones con nuacutemero de argumentos variables

Es habitual que el nuacutemero de paraacutemetros que se le pase a una funcioacuten dependa de la situacioacuten en la cual es llamada Hay tres formas de hacer esto en PHP

bull Definiendo la funcioacuten con argumentos por defecto Este meacutetodo pershymite hacer llamadas con menos paraacutemetros sin que aparezca un error

bull Usando un array para pasar las variables

bull Usando las funciones de argumento variable f unc_num_args () f u n c _ g e t _ a r g () y f u n c _ g e t _ a r g s () ya utilizadas en PHP 4

Argumentos por defecto

Para definir paraacutemetros de este tipo se sustituyen las variables por exshypresiones de asignacioacuten El formato es el siguiente

function nombre_funcioacuten($argumentol=valorl $argumento2=valor2 )

Funciones 107

De esta forma al llamar a la funcioacuten podemos hacerlo con varios paraacutemeshytros Si alguno de los paraacutemetros es obviado la variable tendraacute como vashylor el valor por defecto de la definicioacuten

ltphp function capitales($Pais$Capital = Madrid$habitantes = muchos)

re turn (La c a p i t a l de $Pais es $Capi ta l y t i ene $habi tantes hab i tan tes ltbrgt)

echo capitales(Espantildea) echo capitales(PortugalLisboa) echo capitales(FranciaParismuchiacutesimos) gt

La salida por pantalla es la siguiente

La capital de Espantildea es Madrid y tiene muchos habitantes La capital de Portugal es Lisboa y tiene muchos habitantes La capital de Francia es Paris y tiene muchiacutesimos habitantes

La funcioacuten c a p i t a l e s () tiene un paraacutemetro fijo y dos paraacutemetros por defecto El paraacutemetro $ P a i s es obligatorio pero los demaacutes pueden queshydarse en blanco recibiendo el valor por defecto La limitacioacuten de este meacutetodo es que los argumentos tienen un orden y no podemos saltarnos ninguno es decir no podemos dar los valores $ C a p i t a l y $ h a b i t a n -t e s porque en medio hay otro paraacutemetro

Argumentos mediante un array

Si no encontroacute alguna utilidad a la anterior forma de pasar valores variashybles quizaacutes necesite utilizar un array para pasarlos El ejemplo siguiente usa esta estrategia y algunos trucos maacutes como el operador ternario y los array asociativos

ltphp function capitales($datos)

$Pais = isset ($datos[Pais ] ) $datos [Pais] Espantildea $Capital = isset ($datos[Capital] ) $datos [Capital] Madrid $habitantes = isset ($datos[habitantes] ) $datos [habitantes] muchos return (La capital de $Pais es $Capital y tiene $habitantes habitantesltbrgt)

Introducimos en el array los datos uno por uno para que sea maacutes faacutecil de entender $datos [Pais] = Espantildea echo capitales($datos) $datos [Pais] = Portugal

108 Capiacutetulo 5

$datos [Capital] = Lisboa echo capitales($datos) $datos [Pais] = Francia $datos [Capital] = Paris $datos [habitantes] = muchiacutesimos echo capitales($datos) gt

Como puede ver la funcioacuten tiene un uacutenico argumento que contiene toshydos los datos que nuestro programa necesita Esta vez los valores por defecto los introducimos mediante el operador ternario que chequea si existe el dato referido al P a i s C a p i t a l o h a b i t a n t e s y si no existe se antildeaden los datos E s p a ntilde a Madr id y muchos El ejemplo utiliza la funcioacuten con 0 2 y 3 paraacutemetros La ventaja de este meacutetodo es que podraacute utilizar los argumentos que quiera y en el orden que necesite sin encasishyllarse en una forma especial de pasar los datos

Nota

Jgt Aunque todaviacutea no hemos visto el capiacutetulo 7 que trata con detalle el manejo dearrays el lector puede hacerse una idea de coacutemo funshycionan en el aacutembito de los paraacutemetros defunciones Si queda alshyguna duda de coacutemo utilizarlos siempre puede echar un breve vistazo al capiacutetulo 7 para aclarar esas lagunas

Funciones 109

Muacuteltiples argumentos con func_num_args()

Desde la versioacuten 4 PHP ofrece algunas funciones que pueden ser utilizashydas para recuperar los argumentos

Son muy similares al lenguaje C

bull func_num_args() Devuelve el nuacutemero de argumentos que recibe la funcioacuten desde la que es llamada

bull func_get_arg() Devuelve uno a uno los argumentos pasados de la sishyguiente forma func_get_arg(0) func_get_arg(l) func_get_arg(5)

bull func_get_args() Devuelve un array con todos los argumentos pasashydos a la funcioacuten con los iacutendices del array empezando desde 0

Cualquiera de estas funciones daraacute un error si son llamadas fuera del enshytorno de una funcioacuten y f u n c _ g e t _ a r g () produciraacute un fallo si es llashymada con un nuacutemero maacutes alto que los argumentos que se reciben

Las funciones anteriores dan una ventaja a largo plazo ya que si durante el periacuteodo de vida de una funcioacuten necesita antildeadir alguacuten argumento maacutes puede capturar sin necesidad de cambiar el coacutedigo de las llamadas o el de definicioacuten de la funcioacuten

En el ejemplo siguiente puede comprobar coacutemo se utiliza este meacutetodo

ltphp function capitales()

$numero_argumentos = func_num_args() $Pais = $numero_argumentos gt 0 func_get_arg(0) Espantildea $Capital = $numero_argumentos gt 1 func_get_arg(1) Madrid $habitantes = $numero_argumentos gt 2 func_get_arg (2) muchos return (Nuacutemero de argumentos es $numero_arguraentos La capital de $Pais es $Capital y tiene $habitantes habitantesltbrgt)

echo capitales() echo capitales(Portugal Lisboa) echo capitales(Francia Paris muchiacutesimos) gt

Esta forma de utilizar los argumentos sigue teniendo una limitacioacuten Los argumentos deben ser pasados en un lugar determinado sino la funcioacuten no haraacute bien su trabajo Utilizar los paraacutemetros como array es el meacutetodo maacutes flexible y el maacutes utishylizado en los programas PHP Auacuten asiacute es muy uacutetil cuando no sepa cuaacutentos datos necesita manejar una funcioacuten Podemos utilizarlo para funciones que sumen todos los parame-

110 Capiacutetulo 5

tros que introduzca o concatenen todas las palabras como el ejemplo sishyguiente

ltphp function concatenar()

$resultado = $numero_argumentos = func_num_args() $array_parametros = func_get_args() for ($x = 0 $x lt= $numero_argumentos $x++)

$resultado = $resultado $array_parametros[$x]

return $resultadoltbrgt

echo concatenar(Hola Mundo) echo concatenar(Esto es una prueba dela potencia de este meacutetodo) gt

Llamadas por valor

Por defecto las llamadas a funciones se hacen por valor Esto quiere decir que las variables que se utilizan como paraacutemetros se copian al entorno de la funcioacuten

Todos los cambios de valor que sufra la variable en este entorno no afecshytaraacuten al programa fuera de la funcioacuten

ltphp function elevado($nuraero$ iacutendice)

$resultado = $numero for ($x = $indice $x gt 0 $x--)

$resultado = $resultado $nuraero

$numero = $resultado return $numero

$numero = 2 $indice = 5 echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt echo $numero elevado a $indice es igual a elevado ($numero$ indice) ltbrgt gt

El resultado por pantalla es

2 elevado a 5 es igual a 64 2 elevado a 5 es igual a 64

Funciones 111

El ejemplo anterior calcula el resultado de $numero elevado a $ Iacute n d i c e La funcioacuten e l e v a d o () crea un bucle para multiplicar $numero por las veces que indica el $ iacute n d i c e y lo va almacenando en la variable temporal $resultado

Cuando el bucle termina este resultado se vuelve a pasar a la variable $ numero que es devuelta como salida de la funcioacuten Cuando volvemos a ejecutar la funcioacuten con los mismos paraacutemetros vemos que la variable $nu-mero no ha cambiado en la ejecucioacuten anterior porque en realidad lo que se pasa es una copia del valor y todas las modificaciones se hacen sobre la copia y no sobre la variable original

Llamadas por referencia

PHP 5 ofrece actualmente dos caminos diferentes para cambiar sus argushymentos en la definicioacuten de la funcioacuten y en la llamada a la misma

Las variables pasadas por referencia pueden ser modificadas durante el proceso de una llamada porque lo que se pasa no es una copia sino la variable en siacute misma

Para pasar variables por referencia hay que utilizar el operador (amp) deshylante de la variable

Lo mejor es verlo en un ejemplo

ltphp function elevado(amp$numeroamp$indice)

$resultado = $numero for ($x = $iacutendiacutece $x gt 0 $x--)

$resultado = $resultado $numero

$numero = $resultado return $numero

$numero = 2 $ iacutendice = 5 echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt gt

El resultado por pantalla es ahora

2 elevado a 5 es igual a 64 64 elevado a 5 es igual a 68719476736

El funcionamiento es exactamente igual pero el resultado es distinto El operador (amp) hace que la variable $numero pueda ser modificada dentro de la funcioacuten y guarde este nuacutemero fuera de ella

Tambieacuten puede forzar a una funcioacuten a tomar argumentos por referencia aunque esta capacidad de PHP puede desaparecer en futuras versiones del lenguaje Las llamadas pueden hacerse de la siguiente forma

$numero = 2 $indice = 5 echo $numero elevado a $indice es igual a elevado(amp$numeroamp$indice)ltbrgt echo $numero elevado a $indice es igual a elevado(amp$numeroamp$indice)ltbrgt

El resultado es exactamente igual que al poner la referencia en la definishycioacuten de la funcioacuten

Referencia a variables

Las referencias pueden usarse tambieacuten fuera de las funciones en el aacutembishyto de las variables El ejemplo siguiente muestra coacutemo trabaja el operador (amp) con las variables

ltphp $nombre = Luis Miguel

Funciones 113

$apelliacutedos = Cabezas Granado $nombre auxiliar es simplemente una copia de $nombre $nombre_auxiliar = $nombre-$nombre_referencia es una referencia a la variable $nombre_referencia = amp$nombre echo $nombre $apellidosltbrgt $nombre_auxiliar = Alberto echo $nombre $apellidosltbrgt $nombre_referencia = Felipe echo $nombre $apellidosltbrgt gt

$nombre__aux i l i a r es una copia de la variable $nombre y por mucho que la cambiemos $nombre permaneceraacute con el mismo valor En cambio la variable $nombre_ref e r e n c i a es un alias de $nombre por lo tanto todos los cambios que se hagan en cualquiera de las dos variables les afecshytaraacute por igual

Funciones variables

Uno de los trucos que se pueden hacer con PHP es utilizar variables para almacenar el nombre de funciones Si una variable almacena el nombre de una funcioacuten simplemente tendraacute que antildeadir unos pareacutentesis al final de la variable para hacer la llamada correctamente

ltphp function saludo_maniana()

return (Buenos Diacuteas)

function saludo_tarde()

return (Buenas Tardes)

function saludo_noche()

return (Buenas Noches) $horario = tarde $funcion_variable = saludo_$horario echo $funcion_variable () gt

En el ejemplo anterior tenemos tres funciones que nos saludan depenshydiendo del horario en el que ejecutemos el programa Este valor se recoge en la variable $ h o r a r iacute o Sabemos que todas las funciones comienzan con la palabra saludo_ Si a la variable $f u n c i o n _ v a r iacute a b l e le concatenashymos el valor de $ h o r a r i o tenemos como resultado el nombre de la fun-

1 1 4 Capiacutetulo 5

cioacuten que nos daraacute el saludo Para que esto funcione antildeadimos dos siacutemboshylos de pareacutentesis al final de la expresioacuten

Resumen

Si el capiacutetulo anterior daba rienda suelta a su imaginacioacuten para comenzar con el desarrollo de pequentildeos scripts despueacutes de leer este capiacutetulo estaraacute en situacioacuten de realizar un gran proyecto Ahora que conoce el secreto para almacenar en distintos archivos funciones y partes de un programa escrishyto en PHP podraacute crear aplicaciones maacutes extensas y complejas

Ahora bien debe tener en cuenta que hay que tener cuidado con el alcanshyce de las variables y los pasos por valor y referencia aspecto muy relevanshyte en el capiacutetulo referido a los objetos

En este capiacutetulo aprenderaacute a

bull Diferenciar entre las comillas simples y las comillas dobles bull Trabajar con cadenas de muacuteltiples liacuteneas bull Concatenar varias cadenas bull Generar nuevas cadenas de caracteres a partir de una original bull Eliminar los espacios en blanco de las cadenas bull Convertir a mayuacutesculas o minuacutesculas bull Definir patrones de verificacioacuten de cadenas

116 Capiacutetulo 6

Introduccioacuten

Si pensamos en los tipos de datos que circulan por la red llegaremos a la conclusioacuten de que una gran porcioacuten la ocupan las imaacutegenes animaciones en Macromedia Flash videos o subprogramas escritos en Java La otra gran porcioacuten mayoritaria son los textos o las cadenas de caracteres

Las cadenas de caracteres o string son secuencias de caracteres que pueshyden ser tratadas como una unidad asignadas a variables pasadas como paraacutemetros a funciones o enviadas como salida al navegador Un string se diferencia de otro tipo de dato en PHP 5 porque va encerrado entre comishyllas dobles ( ) o simples ( )

Cadena entre comillas dobles Cadena entre comillas simples

PHP interpreta de distinta forma las cadenas que van entre comillas doshybles y las que van entre comillas simples Losstrings entre comillas dobles pueden sustituir ciertos siacutembolos por acciones como la inclusioacuten del vashylor de una variable Las comillas simples simplemente muestran todo el contenido sin atender a caracteres especiales Podemos ver un ejemplo donde sucede esto

ltphp $variable = Domingo $frase_l = Hoy es $variable el cielo estaacute gris $frase_2 = Hoy es $variable el cielo estaacute gris echo $frase_l echo $frase_2 gt

El resultado en el navegador es

Hoy es Domingo el cielo estaacute gris Hoy es $variable el cielo estaacute gris

Como se puede observar la cadena $f r a s e _ l es capaz de sustituir la vashyriable por su valor por el simple hecho de estar entre comillas dobles

Propiedades de las cadenas

iacutendices de string

Si pensamos en las cadenas como una sucesioacuten de caracteres en un orden determinado podemos llegar a desear acceder libremente a parte de los

Cadenas de caracteres y expresiones regulares 117

caracteres Esto es posible gracias a los siacutembolos de llave ( ) y un iacutendice numeacuterico que se corresponderaacute con la posicioacuten del caraacutecter que buscamos El ejemplo muestra coacutemo crear una funcioacuten que duplica las letras de una cadena aprovechando esta forma de acceder a los caracteres

ltphp function duplicar_caracteres($cadena)

$tamanio = strlen ($cadena) $cadena_auxiliar = for ($x = 0$x lt $tamanio $x++)

$cadena_auxiliar = $cadena_auxiliar $cadena$x $cadena$x

return $cadena_auxiliar

$cadena = Duplicar las letras echo duplicar_caracteres($cadena)iexcl gt

La salida por pantalla como puede adivinar es

118 Capiacutetulo 6

Operadores

En este punto aprovecharemos para hacer un breve repaso de los operashydores de string vistos en el capiacutetulo 3 En otros lenguajes como Java se utiliza el operador suma (+) para unir dos cadenas En PHP este mismo resultado se obtiene con el operador punto ( ) Asiacute podemos concatenar varias cadenas de la forma siguiente

ltphp $cadenal = Hola $cadena2 = Mundo $cadena3 = iexclQueacute tiacutepico $supercadena = $cadenal $cadena2 $cadena3 echo $supercadena gt

Es faacutecil intuir que el operador puede concatenar caracteres y variables de tipo string de forma conjunta Es posible que desee ahora antildeadir texto a una cadena ya existente esto se puede hacer de dos formas muy similashyres La primera es asignando a la variable su valor maacutes el valor a antildeadir de la siguiente forma

ltphp $cadenal = Hola $cadena2 = Mundo $cadenal = $cadenal $cadena2 echo $cadenal gt

O utilizando el operador de concatenacioacuten y asignacioacuten ( = ) como en el ejemplo

ltphp $cadenal = Hola $cadena2 = Mundo $cadenal = $cadena2 echo $cadenal gt

Sintaxis para muacuteltiples liacuteneas

Existe en PHP una forma maacutes de introducir cadenas aparte de las comishyllas muy recomendable para largos textos o un considerable conjunto de etiquetas HTML La sintaxis es muy sencilla y comienza con el operador (ltltlt) seguido de una etiqueta que indica el principio del texto Despueacutes de esto podemos escribir un conjunto de caracteres muy numerosos y para

Cadenas de caracteres y expresiones regulares 119

finalizar la etiqueta de fin El ejemplo muestra coacutemo almacenar un forshymulario en una variable

ltphp $formulario = ltltltINICIO ltformgt ltiacutenput type=text name=Nombre value=Luiacutes Miguel Cabezasgt ltbrgt ltinput type=submit name=submit value=Enviar gt ltformgt INICIO echo $formulario gt

Siempre debe comenzar por el operador (ltltlt) seguido de un identifica-dor por ejemplo INICIO Despueacutes se incluye el texto en este caso un forshymulario y para finalizar la misma etiqueta de inicio Esta forma de almacenar datos permite utilizar indistintamente comillas simples o doshybles dentro de una variable La imagen 62 muestra el resultado del script

Funciones de string

Si conoce el lenguaje C podraacute comprobar que las funciones de manejo de caracteres son muy parecidas en nombre y uso Los desarrolladores de PHP

120 Capiacutetulo 6

siempre han querido que exista esta similitud para facilitar el aprendizaje del lenguaje

La mayoriacutea de las funciones existentes en PHP 5 tienen una homologa en C

Tamantildeo de la cadena

La funcioacuten s t r l e n () devuelve como resultado el tamantildeo en caracteres de la cadena que pasemos de paraacutemetro Este valor puede asignarse a una variable como indica el ejemplo

ltphp $cadena = Esta cadena tiene muchas letras $numero_letras = strlen($cadena) echo cadena tiene $numero_letras caracteres gt

Simplemente imprime

cadena tiene 31 caracteres

Posicioacuten de los caracteres

Para crear buenos motores de buacutesqueda en nuestros sitios Web necesitashyremos potentes herramientas que sean capaces de buscar caracteres cashydenas o patrones coincidentes dentro de textos extensos La funcioacuten s t r p o s () encuentra en un string la posicioacuten de un caraacutecter determinado

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de a es strpos($cadena a) ltbrgt echo La primera ocurrencia de m es strpos($cadena m) ltbrgt gt La s a l i d a en el navegador no es o t ra que La primera ocur renc ia de a es 3 La primera ocur renc ia de m es 18

Si s t r p o s () se utiliza para averiguar la posicioacuten de la primera L mashyyuacutescula de $ cadena vemos que nos devuelve un 0 esto es asiacute porque el iacutendice de caracteres comienza en 0 como pasa en muchos lenguajes de programacioacuten Si no se encuentra ninguna ocurrencia del caraacutecter buscashydo el resultado seraacutease

Cadenas de caracteres y expresiones regulares 121

La funcioacuten s t r p o s () tambieacuten puede utilizarse para buscar varios caracshyteres seguidos en una misma cadena

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de tiene es strpos($cadenatiene) ltbrgt gt

Si lo que nos interesa es encontrar caracteres buscando desde el final de la cadena la funcioacuten que tenemos que utilizar es s t r r p o s () (la letra r que se antildeade viene del ingleacutes reverse) El ejemplo anterior nos sirve para comshyprobar el funcionamiento de la funcioacuten

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de a es strpos($cadena a ) ltbrgt echo La primera ocurrencia desde atraacutes de a es strrpos($cadena a) ltbrgt gt

siendo el resultado

La primera ocurrencia de a es 3 La primera ocurrencia desde atraacutes de a es 29

Comparacioacuten

El operador (==) nos puede servir para evaluar si dos cadenas de caracteshyres son iguales dentro de una estructura de control Ademaacutes tenemos la funcioacuten s t r c m p ( ) que compara bit a bit dos cadenas de caracteres Atenshydiendo al valor de salida de la funcioacuten podemos obtener los siguientes resultados

bull Si el valor que se obtiene es 0 las dos cadenas son exactamente igual

bull Si obtenemos un valor negativo el primer string es maacutes pequentildeo que el segundo

bull Si obtenemos un valor positivo el primer string es maacutes grande que el segundo ltphp $cadenal = Prueba $cadena2 = Prueba if (strcmp($cadenal$cadena2) == 0)

echo Las dos cadenas son iguales elseif (strcmp($cadenal$cadena2) lt 0)

echo La cadenal es menor que la cadena2

122 Capiacutetulo 6

else echo La cadenal es mayor que la cadena2

gt

La comparacioacuten anterior soacutelo da como resultado dos cadenas iguales si las dos cadenas son exactamente iguales haciendo distincioacuten entre mashyyuacutesculas y minuacutesculas

Para evitar este problema podemos utilizar la funcioacuten s t r c a s e c m p ( ) que no es sensible a mayuacutesculas Asiacute s t r c a s e c m p (HoLa hOlA) da como resultado 0 es decir las dos cadenas son iguales

Buacutesqueda de caracteres

Siguiendo con las buacutesquedas de texto la funcioacuten s t r s t r () recibe como paraacutemetros una cadena de caracteres donde buscar y otra con un conjunshyto de caracteres que queremos encontrar Si se encuentra el patroacuten de buacutesshyqueda el resultado seraacute una cadena de caracteres que comenzaraacute justo en el patroacuten hasta el final del string primero Si no se encuentra el patroacuten el resultado seraacutefalse

lt php $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de cadena es strstr ($cadenacadena) ltbrgt

gt

Como cabe esperar el resultado es La primera ocurrencia de cadena es cadena tiene muchas letras

Seleccioacuten de subcadenas

La funcioacuten s u b s t r () permite seleccionar un conjunto de caracteres de una cadena quedando intacto el string original Puede tomar varios paraacuteshymetros

bull s u b s t r ( c a d e n a iacute n d i c e ) Cadena es el conjunto de caracteres que queremos cortar e iacute n d i c e la posicioacuten a partir de la cual se cortaraacute la cadena hasta el final

bull s u b s t r ( cadena iacute n d i c e numero) Cadena es el conjunto de cashyracteres que queremos cortar e iacute n d i c e la posicioacuten a partir de la cual se cortaraacute la cadena tantas posiciones como indique el nuacutemero

Cadenas de caracteres y expresiones regulares 123

Por ejemplo

ltphp $cadena = Esta cadena tiene muchas letras Devuelve la cadena completa echo substr($cadena 0) echo ltbrgt Desde el caraacutecter 12 hasta el final echo substr($cadena 12) echo ltbrgt Devuelve 6 caracteres desde el caraacutecter 18 echo substr($cadena 186) echo ltbrgt Devuelve los 6 uacuteltimos caracteres echo substr($cadena -6) echo ltbrgt Desde la posicioacuten 26 contando desde atraacutes 6 caracteres echo substr($cadena -266) echo ltbrgt Empezando en el caraacutecter 4 y terminando en el 7 desde atraacutes echo substr($cadena 4-7) gt

El resultado lo podemos ver maacutes abajo Recuerde que la variable $ cade -na queda intacta

124 Capiacutetulo 6

Dependiendo de la posicioacuten del nuacutemero negativo s u b s t r () actuaraacute de una forma u otra

Tabla 61 Respuestas de la funcioacuten substr ()

Ejemplo Resultado

substr(Hola2) Devuelve la cadena completa empezando por el caraacutecter 2 substr(Hola-2) Devuelve la cadena completa empezando por el caraacutecter

2 esta vez empezando a contar desde atraacutes

substr(Hola13) El resultado son 3 caracteres empezando desde el caraacutecshyter 1

substr(Hola-32) Doscaracteres empezando desde el caraacutecter 3 contando desde la uacuteltima letra

substr(Hola2-1) Devuelve un conjunto de caracteres que estaacuten desde la posicioacuten 2 a la posicioacuten 1 comenzando desde atraacutes

substr(Hola-2-3) No tiene aplicacioacuten posible

Funciones de limpieza de cadenas

Sirven para limpiar espacios en blanco al principio de la cadena al final o en cualquier parte desde el principio al final y son respectivamente l t r i m ( ) chop () y t r i m () Su aplicacioacuten es tan sencilla que bastaraacute un ejemplo para entender su funcionamiento

ltphp $salto_linea = n $cadena = cadena con varios espacios en blanco echo $salto_linea $cadena tamantildeo strlen($cadena) echo ltbrgt echo $salto_linea ltrim($cadena) tamantildeo strlen(ltrim($cadena)) echo ltbrgt echo $salto_linea chop($cadena) tamantildeo strlen(chop($cadena)) echo ltbrgt echo $salto_linea trim($cadena) tamantildeo strlen(trim($cadena)) gt

Cada liacutenea realiza una de las operaciones vistas e imprime el resultado de la cadena en el navegador junto con el tamantildeo de la cadena

La figura 64 muestra el resultado por pantalla

126 Capiacutetulo 6

Sustitucioacuten de cadenas

La funcioacuten s t r _ r e p l a c e () toma como paraacutemetros un conjunto de cashyracteres a buscar un grupo que debe sustituirse por el anterior y una cashydena de caracteres sobre la que actuar

ltphp $cadena = Esta cadena tiene muchas letras $cadena = str_replace(EstaEste$cadena) echo str_replace(cadenaconjunto$cadena) gt

Si en la cadena existiera maacutes de una instancia del conjunto buscado todas las ocurrencias quedariacutean cambiadas

ltphp cadena = Esta cadena tiene muchas letras y cadenas $cadena = str_replaceacute(EstaEste$cadena) echo str^replace(cadenaconjunto$cadena) gt

El resultado es Este conjunto tiene muchas letras y conjuntos

Truco

Puede probar esta funcioacuten para cambiar todos iexclos caracteres de un tipo de una cadena de iexcla siguiente forma s t r _ r e p l a c e (h j hola h o l a )

Funciones de mayuacutescula y minuacutescula

Las funciones s t r t o l o w e r () y s t r toupper () devuelven la cadena que se pasa como argumento completamente en minuacutescula o mayuacutescula resshypectivamente

ltphp $cadena = Hay palabras en MAYUacuteSCULAS y en minuacutesculasltbrgt echo strtolower($cadena) echo strtoupper($cadena) gt

El resultado es hay palabras en mayuacutesculas y en minuacutesculas HAY PALABRAS EN MAYUacuteSCULAS Y EN MINUacuteSCULAS

Si lo que realmente nos interesa es que la primera letra de un texto apashyrezca como letra Capital o que letras iniciales de cada palabra en una fra-

Cadenas de caracteres y expresiones regulares 127

se aparezcan en mayuacutescula tenemos las funciones u c f i r s t ( ) y u c w o r d s ( )

ltphp $cadena = habiacutea una vezltbrgt echo ucfirst($cadena) $cadena2 = linux user group echo LUG significa ucwords($cadena2) gt

Expresiones regulares

Las funciones vistas anteriormente basan su potencia en la buacutesqueda o susshytitucioacuten de los caracteres de una cadena pero son poco uacutetiles cuando tratashymos de comprobar si un conjunto de caracteres cumple un formato determinado Si solicitamos mediante un formulario un correo electroacutenico necesitamos saber a priori si ese correo por lo menos estaacute bien construido

luisnccextremaduraorg luiszendcom

La idea es poder descartar de alguna forma los correos escritos de esta manera

l u i s (Snccextremaduraorg E s p a c i o en medio

128 Capiacutetulo 6

LUISzendcom En mayuacutesculas luisaupexorg Dos

Las expresiones regulares son patrones de buacutesqueda dentro de cadenas Estos patrones se construyen mediante caracteres especiales que cumplen unas reglas determinadas

Tabla 62 Reglas de expresiones regulares

Ejemplo Regla

aabb Los caracteres no especiales como un grupo de letras se escriben como de costumbre

A Indica que hay que buscar el patroacuten desde el principio de la cadena $ Este simbolo obliga al patroacuten a cumplirse hasta el final de la

cadena Simboliza cualquier caraacutecter

Indica que puede haber O o maacutes instancias de una expresioacuten + Indica que puede haber 1 o maacutes instancias de una expresioacuten [ab] Indica que se puede encontrar el caraacutecter a o el b y la expresioacuten

seriacutea correcta Lo podemos acompantildear de [ab] para evaluar si hay varias letras seguidas del tipo a o b

[a-z] Indica que se puede elegir entre un rango de caracteres que va desde la a hasta la z

Si queremos utilizar cualquiera de los anteriores caracteres como parte del patroacuten tendremos que utilizar eacuteste siacutembolo para indicarle a PHP que es un literal

Como ejemplo vamos a intentar hacer un patroacuten que verifique si un coshyrreo electroacutenico estaacute correctamente construido o no Seriacutea faacutecil pensar en una expresioacuten parecida a la siguiente

[ a - z ] + [ a - z ] + o r g

La primera parte [ a - z ] + nos dice que aceptaraacute una letra o conjunto de letras sin espacios y en minuacutesculas que pueden corresponderse con el nombre de usuario de la cuenta de correo Despueacutes aceptaraacute un siacutembolo seguido de otro conjunto de caracteres correspondientes al servidor de correo La uacuteltima parte de la expresioacuten la componen los siacutembolos que indican que tiene que aparecer un punto que separe la descripcioacuten del servidor del dominio y la cadena o r g que obliga a que todos los correos sean de dominio no gubernamental

Cadenas de caracteres y expresiones regulares 129

La expresioacuten anterior tiene algunas limitaciones que veremos como solshyventar La primera es que se puede aplicar a cualquier texto con indepenshydencia del tamantildeo Si en alguna parte de ese texto aparece un conjunto de caracteres que cumpla con la expresioacuten la validacioacuten seriacutea true Esto no es bueno cuando queremos chequear si un correo es introducido correctashymente La solucioacuten es aplicar las reglas de inicio y fin que obligan a que el comienzo de la cadena y el final sean parte de la expresioacuten

[ a - z ] + [ a - 2 ] + o r g $

Tambieacuten podemos encontrarnos con que existen correos introducidos coshyrrectamente pero el dominio es otro distinto a org Esta vez la solucioacuten es introducir el operador O loacutegico | que permite elegir entre varias opcioshynes

^ [ a - z ] + [ a - z ] + ( o r g | c o m | n e t ) $

Por uacuteltimo un problema menor aunque habitual en el aacutembito de los coshyrreos electroacutenicos es la utilizacioacuten de signos de puntuacioacuten para separar nombres y apellidos y servidores de servidores virtuales Por ejemplo el correo siguiente es correcto pero no seriacutea evaluado por la expresioacuten anteshyrior

l u iacute s c a b e z a s n c c a u p e x o r g

Una posible solucioacuten es

[ a - z | ] + [ a - z | ] + ( o r g | c o m ( n e t ) $

Comprobar expresiones regulares

La funcioacuten e reg () es capaz de comprobar si una cadena se corresponde con el patroacuten que se pasa como paraacutemetro Toma dos argumentos obligashytorios una expresioacuten regular y una cadena de caracteres donde buscar el patroacuten Seguidamente puede ver un ejemplo completo de utilizacioacuten de expresiones regulares y la funcioacuten

ltphp $correo = luiscabezasnccaupexorg $correol = LUISnccaupexorg $correo2 = luiscabezasnccaupexorg if (ereg ( [a-z|]+[a-z|]+ (org|com|net)$$correo))

echo El correo $correo se aceptaltbrgt else

echo El correo $correo no cumple el patroacutenltbrgt

iacutef (ereg(^ [a-z|]+ [a-z|]+ (org|comjnet)$$correol) )

echo El correo $correol se aceptaltbrgt

130 Capiacutetulo 6

else echo El correo $correol no cumple el patroacutenltbrgt

if (ereg(A [a-zj]+ [a-zj]+ (org|com|net)$$correo2))

echo El correo $correo2 se aceptaltbrgt else

echo El correo $correo2 no cumple el patroacutenltbrgt gt

El resultado por pantalla es

Puesto que hay muchos usuarios acostumbrados a escribir su correo elecshytroacutenico completamente en mayuacutesculas se hace necesario comprobar este contratiempo tambieacuten Lo maacutes raacutepido es utilizar la funcioacuten e r e g i () que funciona exactamente igual que e r e g ( ) pero no es sensible a mayuacutescula o minuacutescula El ejemplo anterior lo podemos arreglar de la siguiente forma

ltphp $correo = LUISnccaupexorg if (ereg([a-z|]+[a-z|]+(org|com|net)$$correo$pepe))

echo El correo $correo se aceptaltbrgt else

echo El correo $correo no cumple el patroacutenltbrgt

gt

Cadenas de caracteres y expresiones regulares 131

Nota

e reg () y e r e g i () tienen un tercer argumento opcional del tipo array Si iexcla expresioacuten regular la dividimos en pequentildeas parshytes entre pareacutentesis cada ocurrencia encontrada en la cadena se va almacenando como un elemento del array

Reemplazar patrones

e r e g _ r e p l a c e () y e r e g i _ r e p l a c e () tiene tres paraacutemetros El prishymero es una expresioacuten regular el segundo un string por el que se cambiashyraacuten todas las ocurrencias del patroacuten y por uacuteltimo una cadena donde buscar Como antes la diferencia entre las dos es uacutenicamente que la prishymera es sensible a mayuacutesculas El siguiente ejemplo muestra el funcionashymiento

ltphp $texto = El correo es de luisnccaupexorg echo ereg_replace([a-z|]+[a-z|]+(org|com|net)Luis Miguel$texto) gt

Asiacute da como resultado el cambio del correo electroacutenico por el nombre de la persona asociada

Resumen

Desde hace unos antildeos se ha puesto de moda una serie de productos donshyde prima el contenido frente al disentildeo Los CMS (Content Manager System) son programas la mayoriacutea escritos en PHP que permiten gestionar mushycho contenido escrito por diferentes personas El tratamiento de los textos se agudiza al maacuteximo en este caso siendo indispensable la utilizacioacuten de expresiones regulares para verificar los datos nuevos que puedan incor- porarse Ademaacutes suelen llevar un buscador capaz de encontrar patrones determishynados dentro de las noticias expuestas Este capiacutetulo le ha servido para conocer funciones para concatenar recorshytar o verificar cadenas Con esto bien aprendido ya puede comenzar a crear su propio CMS

En este capiacutetulo aprenderaacute a

bull Comprender queacute es un array y coacutemo se define bull Trabajar con funciones que definen listas de datos bull Diferenciar entre los distintos meacutetodos para recorrer los array

bull Ordenar los conjuntos de datos con diferentes meacutetodos bull Crear pilas y colas

134 Capiacutetulo 7

Introduccioacuten

Un array es una coleccioacuten de valores con un uacutenico nombre Para acceder a los distintos valores de la variable se utiliza un iacutendice numeacuterico o alfanu-meacuterico Nos vamos a servir de la definicioacuten de un array en el lenguaje C para ver la potencia de este tipo de datos en PHP La definicioacuten es la siguiente

int mi_array[100] Esto es C

Lo primero que debe llamarnos la atencioacuten es que la variable estaacute predefishynida como i n t (entero) En PHP los arrays no tienen que definirse de una forma concreta sino que pueden tomar distintos tipos de valores enteshyros caracteres objetos etceacutetera Lo siguiente es que en C se necesita sashyber de antemano el nuacutemero de valores maacuteximo que podraacute tomar el array Esto no es necesario en PHP ya que podraacute ir creando valores nuevos a medida que lo vaya necesitando Lo uacuteltimo es que en C el iacutendice para acshyceder a los 100 valores distintos debe ser numeacuterico en cambio en PHP el iacutendice puede ser numeacuterico o alfanumeacuterico

ltphp $mi_array[l] = 23 $mi_array[2] = Este valor es un string $mi_array[ejemplo] = Esto es un array asociativo gt

Creacioacuten de arrays

Vamos a ver tres formas distintas de crear un array dentro de un script de PHP

Asignacioacuten directa

El camino maacutes simple y por otro lado loacutegico es asignar valores cuando se necesiten La primera vez que asignemos un valor el array se crearaacute en el entorno

ltphp $mi_array[l] = 23 Asignacioacuten directa gt

De esta forma tenemos un valor asignado al iacutendice 1 del array Puede asigshynar cualquier iacutendice en la creacioacuten de este tipo de dato e incluso no asig-

Conjuntos de datos del tipo array 135

nar ninguno de forma que PHP se encarga de asociar un iacutendice distinto para cada valor

ltphp $mi_array[] = 23 Empieza en el iacutendice 0 $mi_array[] = 54 iacutendice 1 gt

array()

Esta funcioacuten crea un array con los valores que pase como datos de entrashyda Los iacutendices seraacuten antildeadidos automaacuteticamente empezando desde 0

Si no asigna paraacutemetros a a r r a y ( ) la funcioacuten le devolveraacute un array vaciacuteo

ltphp $mi_array = array(2345762365) gt

El meacutetodo es similar a

ltphp $mi_array[0] = 23 $mi_array[l] = 4 5 $mi_array[2] = 76 $mi_array[3] = 23 $mi_array[4] = 65 gt

La funcioacuten a r r a y () permite tambieacuten antildeadir iacutendices a los valores que se introducen

Para ello se utiliza el operador =gt de esta forma

ltphp $mi_array = array0 =gt 23 1 =gt 45 2 =gt 76) gt

Tambieacuten es posible antildeadir iacutendices que no sean correlativos o iacutendices alf-anumeacutericos incluso mezclar los dos tipos

ltphp $mi_array = a r r a y ( c e r o =gt 23 uno =gt 45 2 =gt 7 6 ) gt

Para recuperar cualquier valor se utiliza el iacutendice dentro de los corchetes

ltphp $mi_array = array(cero =gt 23 uno =gt 45 2 =gt 76) echo $mi_array [ uno] ltbrgt echo $mi_array[2] gt

136 Capiacutetulo 7

Funciones que devuelven arrays

La uacuteltima forma de obtener un array es utilizando alguna de las funcioshynes que devuelven este tipo de datos

Es muy frecuente que las funciones que manejan bases de datos devuelshyvan las ocurrencias dentro de un array

Por ejemplo la funcioacuten r a n g e () devuelve un array con valores numeacuterishycos que van desde un nuacutemero de inicio hasta un nuacutemero final tal y como se muestra en el ejemplo

ltphp $mi_array = range(120130) gt

Esta funcioacuten crea un array empezando desde el iacutendice 0 y el valor 120 hasta el iacutendice 10 y el valor 130

Arrays multidimensionales

Hasta aquiacute hemos visto ejemplos de arrays de una sola dimensioacuten PHP soporta el uso de arrays de varias dimensiones faacutecilmente aunque son complejos de entender y de usar El array siguiente es de 5 dimensiones

ltphp $ m i _ a r r a y [ l ] [ 1 ] [ 2 3 ] [ 4 3 ] [ 0 ] = A r r a y de 5 d i m e n s i o n e s gt

Cada iacutendice encerrado entre corchetes corresponde a una dimensioacuten disshytinta En realidad cada dimensioacuten es un array que se introduce como vashylor dentro de la dimensioacuten anterior

Asiacute podraacute crear un array multidimensional de la siguiente forma

ltphp $colores = array(fuertessuaves) $colores [fuertes] = array ( rojo =gt FF0000 verde =gt 00FF00 azul =gt 0000FF)

$ c o l o r e s [ s u a v e s ] = a r r a y ( r o s a =gt FE9ABC a m a r i l l o =gt FDF189 malva =gt 9 A 2 F 6 8 ) echo $colores[fuertes] [rojo] gt

Para recuperar los valores se utilizan un iacutendice del primer array (fuertes o suaves) y un iacutendice de alguno de los dos arrays secundarios

Conjuntos de datos del tipo array 137

Otra forma de definir el array anterior es

ltphp

$colores = array( fuertes =gt array ( rojo =gt FF0000 verde =gt 00FF00 azul =gt 0000FF)

suaves =gt array ( rosa =gt FE9ABC amarillo =gt FDF189 malva =gt 9A2F68))

echo $colores[fuertes] [rojo] gt

Propiedades de arrays

Existen numerosas funciones que son capaces de averiguar datos de los arrays tales como el tamantildeo si un valor forma parte del conjunto o si un determinado iacutendice estaacute registrado

count()

Cuenta el nuacutemero de elementos que contiene un array

ltphp echo elementos de 1 dimensioacuten count ($colores) ltbrgt echo elementos de 2 dimensiones count ($colores[fuertes]) gt

El ejemplo anterior se basa en la definicioacuten del array de colores inicializa-do antes Para contar el nuacutemero de elementos debe ponerse tambieacuten la dimensioacuten Si el array es de una sola dimensioacuten no hace falta La funcioacuten s i z e o f () actuacutea de la misma forma

in_array()

Busca dentro de un array un valor pasado como paraacutemetro y si lo encuenshytra devuelve el valor true si no devuelve false Toma dos argumentos el valor a buscar y el array doacutende buscar

ltphp $colores = array (rojoverdeamarilloazul) if (in_array(rojo$colores))

echo Se ha encontrado el valor rojo

138 Capiacutetulo 7

e l s e echo No se ha encontrado

gt

Borrar ocurrencias

Para borrar un elemento simplemente se utiliza la misma funcioacuten que borra las variables definidas unset ()

ltphp $colores = array (rojoverdeamarilloazulrosa) echo El nuacutemero de elementos de colores es count ($colores) ltbrgt unset ($colores[2]) echo El nuacutemero de elementos de colores es count ($colores) ltbrgt gt

Se puede observar que para borrar un elemento hay que conocer el iacutendishyce El resultado del ejemplo por pantalla es

El nuacutemero de elementos de colores es 5 El nuacutemero de elementos de colores es 0

Advertencia

Debe tener cuidado el lector con utilizar unset () con el nombre de un array sin iacutendice pues esto causaraacute el borrado del conjunto de datos en su totalidad Unset ($colores) borra el array comshypleto unset ($colores [2] borra soacutelo el iacutendice 2 del conjunto

Interactuar con arrays

Anteriormente tuvo la oportunidad de conocer las estructuras de control existentes en PHP La estructura f oreach quedoacute en el aire para tratarlo a fondo en el presente capiacutetulo El uso es asiacute

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) foreach ($colores as $valor)

echo (El valor es $valorltbrgt)

gt

Conjuntos de datos del tipo array 139

La construccioacuten anterior recorre el array desde el principio En el ejemplo se puede ver que f oreach toma el array a recorrer y sus valores los va almacenando en la variable $ v a l o r a medida que el bucle se ejecuta Existe una segunda construccioacuten que permite recuperar el iacutendice y el valor Veashymos un ejemplo de esto

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) foreach ($ciacuteudades as $iacutendiacutece =gt $valor)

echo (El iacutendice $indice tiene el valor $valorltbrgt)

gt

La salida en el navegador nos la muestra la figura 71

Es un meacutetodo muy bueno para imprimir los valores de un array que tiene iacutendices numeacutericos y alfanumeacutericos

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia] = Paris foreach ($ciudades as $indice =gt $valor)

echo (El Iacutendice $indice tiene el valor $valorltbrgt)

gt

140 Capiacutetulo 7

Funciones para avanzar en un array

Cada vez que creamos un array dentro de un programa PHP se crea un puntero que permite recorrer en su totalidad el conjunto de valores Este puntero se inicializa al valor inicial del array La funcioacuten c u r r e n t () deshyvuelve el valor al que apunta el puntero La funcioacuten n e x t () hace avanshyzar el puntero una posicioacuten en el conjunto de datos

Si el puntero se encuentra al final del conjunto n e x t () devuelve un vashylor false El ejemplo siguiente muestra coacutemo utilizar estas funciones para recorrer un array

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia] = Paris do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

while (next($ciudades) ) gt

Podemos crear una funcioacuten que realice este traacutemite

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) Sciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia ] = Paris

function recorre($ciudades) do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

Jwhile (next($ciudades))

recorre($ciudades) recorre($ciudades) gt

La funcioacuten r e c o r r e () utiliza un array como paraacutemetro y va utilizando las funciones de introspeccioacuten para sacar los resultados Puesto que los valores son pasados por valor la funcioacuten r e c o r r e () crea una copia de los datos que recibe y genera el resultado de la figura 72

De esta forma no hay manera de controlar el puntero porque siempre que pase la variable $ c i u d a d e s el puntero comenzaraacute desde el principio

Conjuntos de datos del tipo array 141

La forma de arreglar esto es hacer las llamadas por referencia r e c o r r e (Sc$ciudades) r e c o r r e (amp$ciudades)

142 Capiacutetulo 7

Ahora ya no es una copia de $ c iudades lo que se pasa como paraacutemetro sino una referencia al valor real Esto hace posible tener una memoria de la situacioacuten del puntero Una vez recorrido elarray el puntero queda fijado al final del conjunto de datos Para volver al principio se puede utilizar la funcioacuten r e s e t () que enviacutea al puntero al principio La funcioacuten puede quedar asiacute

function recorre($ciudades) if (current($ciudades))

reset($ciudades)

do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

Jwhile (next($ciudades))

Ahora lo que hacemos es comprobar si el puntero estaacute al final del array si esto es asiacute se llama a la funcioacutenreset 0 y el puntero se coloca al prinshycipio

Funciones para retroceder en un array

La funcioacuten prev () retrocede una posicioacuten el puntero y la funcioacuten end () se coloca al final de una lista de valores Esto puede ser uacutetil para mostrar el contenido en sentido inverso como puede ver en la nueva funcioacuten que hemos creado

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal ] = Lisboa $ciudades[Francia ] = Paris function recorre($ciudades)

if ( lcurrent($ciudades)) reset($ciudades)

do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

jwhile (next($ciudades))

function recorre_atras($ciudades)

end($ciudades) do

$valor = current($ciudades)

Conjuntos de datos del tipo array 143

echo (El valor es $valorltbrgt) while (prev($ciudades))

recorre(amp$ciudades) recorre_atras(amp$ciudades) gt

El navegador muestra El valor es Badajoz El valor es Meacuterida El valor es Caacuteceres El valor es Plasencia El valor es Madrid El valor es Lisboa El valor es Paris El valor es Paris El valor es Lisboa El valor es Madrid El valor es Plasencia El valor es Caacuteceres El valor es Meacuterida El valor es Badajoz

Por uacuteltimo para obtener el valor del iacutendice puede utilizar la funcioacuten key() La funcioacuten r e c o r r e () la puede actualizar de la siguiente forma

function recorre($ciudades) if ( current($ciudades) )

reset($ciudades)

do

$valor = current($ciudades) $indice = key($ciudades)

echo ($indice valor $valorltbrgt)

while (next($ciudades))

Intercambio de valores

La funcioacuten a r r a y _ f l i p () intercambia los valores de iacutendices y datos es decir los iacutendices seraacuten guardados como datos y los valores seraacuten sus nueshyvos iacutendices

ltphp function recorre ($numero)

foreach ($numero as $indice =gt $valor) echo $indice $valorltbrgt -

144 Capiacutetulo 7

$numero = array(uno =gt ldos =gt 2 tres =gt 3cuatro =gt 4) echo (Nuacutemerosltbrgt ) recorre($numero) echo (Nuacutemeros intercambiadosltbrgt) recorre(array_fliacutep$numero)) gt

El resultado es el esperado

Nuacutemeros uno 1 dos 2 tres 3 cuatro 4 Nuacutemeros intercambiados 1 uno 2 dos 3 tres 4 cuatro

Puede ver el resultado en la figura 74

Inversioacuten del contenido

Tambieacuten es posible ordenar a la inversa una lista de datos Esto se consishygue con la funcioacuten a r r a y _ r e v e r s e ()

Conjuntos de datos del tipo array 1 4 5

Si modifica el coacutedigo anterior tendraacute

echo (Nuacutemeros intercambiadosltbrgt ) recorre(array^reverse($numero))

Dando como resultado

Nuacutemeros uno 1 dos 2 tres 3 cuatro 4 Nuacutemeros intercambiados cuatro 4 tres 3 dos 2 uno 1

Mezcla de los valores

Si necesita alguna vez elegir un valor aleatorio de un array la funcioacuten shu-f f le () puede ser de gran ayuda ya que mezcla todos los valores cada vez que se ejecuta Parte del coacutedigo puede ser este

echo (Nuacutemeros mezcladosltbrgt ) shuffle($numero) recorre($numero)

Pilas

Las pilas son estructuras de datos que se utilizan mucho en el mundo de la informaacutetica La filosofiacutea baacutesica de las pilas es que todos los valores deshyben introducirse en un orden especiacutefico y soacutelo podemos recuperar esos valores en el orden inverso estricto al que fueron insertados Las pilas LIFO (Last ln First Out el uacuteltimo en entrar es el primero en salir) utilizan unas funciones especiacuteficas que permiten manejar todos los datos A r r a y _ p u s h () permite insertar en la pila un dato y a r r a y _ p o p () exshytrae un valor Es necesario antes que nada definir la variable como array pues ninguna de las funciones descritas lo hace

A r r a y _ p u s h () y a r r a y _ p o p () toman como argumento la variable array y los valores a introducir

lt php $pila = array() array_push($pilaunodostres)

146 Capiacutetulo 7

array_jpush($pilacuatrocinco) while ($valor = arrayjop($pila) )

echo valor extraiacutedo es $valorltbrgt

gt

El resultado por pantalla muestra que la extraccioacuten de los valores se hace en orden inverso del que fueron introducidos

valor extraiacutedo es cinco valor extraiacutedo es cuatro valor extraiacutedo es tres valor extraiacutedo es dos valor extraiacutedo es uno

Ordenacioacuten de los valores

Finalmente PHP ofrece una gran variedad de funciones para ordenar arrays Las funciones pueden verse en la tabla siguiente

Tabla 71 Funciones de ordenacioacuten

Funcioacuten Explicacioacuten

asort() Ordena de forma ascendente el array pasado como argumento Ordena las parejas iacutendicevalor atendiendo al dato Es un buen meacutetodo para los arrays asociativos

arsort() Igual que asort () pero ordena en sentido descendente ksort() Ordena de forma ascendente el array pasado como argumento

Ordena las parejas iacutendicevalor atendiendo esta vez al iacutendice

krsort() Igual que ksort () pero ordena en sentido descendente

sort() Ordena de forma ascendente el array pasado como argumento Se pierde el valor asociativo entre el iacutendice y el valor

rsort() Igual pero en orden descendente

Puede ver actuar todas las funciones de ordenacioacuten en el ejemplo sishyguiente

ltphp function recorre ($numero)

foreach ($numero as $indice =gt $valor) echo $indice $valorltbrgt

Conjuntos de datos del tipo array 147

$pi la = array(cinco = gt5uno = gtl cuatro = gt4dos = gt2 tres = gt3) echo Array sin ordenarltbrgt recorre($pila) echo Ordenacioacuten asort()ltbrgt asort($pila) recorre($pila) echo Ordenacioacuten arsort)ltbrgt arsort($pila) recorre($pila) echo Ordenacioacuten ksort()ltbrgt ksort($pila) recorre ($pila) echo Ordenacioacuten krsort()ltbrgt krsort ($pila) -recorre($pila) echo Ordenacioacuten sort()ltbrgt sort($pila) recorre($pila) echo Ordenacioacuten rsort()ltbrgt rsort($pila) recorre($pila) gt

La figura 75 muestra todos los tipos de ordenacioacuten que puede utilizar sobre un array

148 Capiacutetulo 7

Resumen

En este capiacutetulo ha conocido el tipo de variable estrella de PHP el array Controlar los meacutetodos y las funciones para extraer la informacioacuten le daraacute ventaja en los capiacutetulos posteriores Muchas funciones que tienen que ver con el manejo de datos como funciones de bases de datos XML o generashycioacuten de plantillas devuelven un array como respuesta El tipo array es el vehiacuteculo estaacutendar para la recuperacioacuten de datos estrucshyturados como veremos en los proacuteximos capiacutetulos

En este capiacutetulo aprenderaacute a

bull Crear formularios para pasar datos entre paacuteginas

bull Utilizar las variables suacuteper-globales para recibir la informacioacuten de un formulario

bull Diferenciar entre los meacutetodos de enviacuteo GET y POST

bull Encontrar posibles errores revisando las variables suacuteper-globales

150 Capiacutetulo 8

Introduccioacuten

Hasta ahora en los capiacutetulos anteriores hemos visto coacutemo construir dishyversos programas en PHP con un limitado radio de accioacuten La verdadera potencia del lenguaje reside en la aplicacioacuten de las teacutecnicas aprendidas a traveacutes de varias paacuteginas Web pasando informacioacuten de unas a otras Como veremos maacutes adelante las dos teacutecnicas principales son el uso de formulashyrios y la utilizacioacuten de la barra de direccioacuten para pasar los valores

Argumentos GET

Los argumentos GET pasan la informacioacuten como parte de la URL Cuando utilice esta forma de trabajar las parejas de variable valor podraacuten verse en la casilla de direccioacuten del navegador Para probar esto podemos escrishybir un pequentildeo script que guardaremos como paacutegina Web

lthtmlgt ltbodygt ltphp echo Variables pasadas mediante GETltbrgt foreach ($_GET as $indice =gt $valor)

echo $indice $valor

gt ltbodygt lthtmlgt

Si ejecuta el coacutedigo anterior veraacute que uacutenicamente se imprime en pantalla el texto que muestra la orden echo En realidad esto es correcto puesto que no hemos introducido ninguna variable tipo GET a la Web Para hashycerlo debemos escribir el nombre de la paacutegina Web seguido de un siacutembolo de interrogacioacuten () y el conjunto de parejas de variable valor separadas del siacutembolo (amp)

La direccioacuten queda algo asiacute f o r m u l a r i o php v a r i a b l e l = H o l a M u n d o amp v a r i a b l e 2 = 1234 Ahora el resultado es diferente El bucle f o shyr e a c h inspecciona el array $_GET e imprime en pantalla

Variables pasadas mediante GET variablel Hola Mundo variable2 1234

El array $_GET es considerado en PHP 5 una variable suacuteper-global Este en concreto almacena todas las variables pasadas entre paacuteginas mediante

Paso de informacioacuten entre formularios 151

el meacutetodo GET Para extraer el valor de una variable pasada por este meacuteshytodo soacutelo hay que escribir $_GET [ n o m b r e _ v a r i a b l e ] en la paacutegina que recibe los datos

Advertencia

En versiones anteriores de PHP para recuperar el valor de una variable simplemente habiacutea que escribir un siacutembolo $ delante del nombre como $ n o m b r e _ v a r i a b l e Esto es porque el paraacutemeshytro register_globals del fichero de configuracioacuten php i n i estaacute en PHP 5 a off

Formularios con GET

La forma maacutes utilizada para recabar informacioacuten acerca de los usuarios es emplear formularios HTML Los formularios pueden hacerse escribiendo en un editor de texto las etiquetas HTML o utilizando alguacuten editor Web profesional como Macromedia Dreamweaver Netscape Composer o Nvu La siguiente paacutegina Web llamada f o r m u l a r i o php muestra coacutemo reshycoger informacioacuten

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt

ltpgtIntroduzca sus datos personales ltpgt ltform name=formulario method=GET action=formulario2 php gt lttable width=50 border=0 cellspacing=0 cellpadding=0gt lttrgt lttd width=24gtNombrelttdgt lttd width=76xinput name=nombre type=text id=nombrextdgt

lttrgt lttrgt lttdgtApellidoslttdgt lttdxiacutenput name=apellidos type=text id=apellidos2gtlttdgt

lttrgt lttrgt lttdgtCorreolttdgt lttdxinput name=correo type=text id= correo xtdgt

lttrgt lttrgt lttdgtEstado civil lttdgt lttdxselect name= estado id= estado gt ltoption value=SolterogtSolteroltoptiongt ltoption value=CasadogtCasadoltoptiongt

152 Capiacutetulo 8

bullcoption value=DivorciadogtDivorciadoltoptiongt ltoption value=ViudogtViudoltoptiongt

ltselectgtlttdgt lttrgt lttrgt lttdgtNampuacutemero hijos lttdgt lttdgt 0 ltinput name=hijos type=radio value=0 checkedgt

1 ltinput name=hijos type=radio value=lgt 2 ltinput name=hijos type=radio value=2gt 3 ltinput name=hijos type=radio value=3gtlttdgt

lttrgt lttrgt lttdgtGustoslttdgt lttdgt Informampaacutetica ltinput type=checkbox name=gustos []

value=Informaacuteticagt Buceo ltinput type=checkbox name=gustos [] value=Buceogt Magia ltinput type=checkbox name=gustos [ ] value=Magiagt Jazz ltinput type=checkbox name=gustos [] value=Jazzgtlttdgt

lttrgt lttrgt lttdxinput type=submit name=Submit value=Enviargtlttdgt lttdgtampnbsplttdgt

lttrgt lttablegt

ltformgt ltpgtampnbsp ltpgt ltbodygt lthtmlgt

La figura 81 muestra el aspecto en el navegador Hay varios aspectos a tener en cuenta Lo primero es que el apartado a c t i o n de la etiqueta ltFORMgt contiene la paacutegina Web a la que se enviaraacuten los datos y el apartashydo method permite seleccionar el meacutetodo de enviacuteo por ahora utilizareshymos el meacutetodo GET La paacutegina f o r m u l a r i o 2 php recoge la informacioacuten del formulario y la imprime en pantalla utilizando un bucle f o r e a c h a la variable suacuteper-global $_GET

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidosltpgt ltphp foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

gt ltbodygt lthtmlgt

Para sacar los datos hemos utilizado un bucle que busca todos los valores dentro de $__GET Otra forma de hacerlo es imprimir los datos uno a uno

154 Capiacutetulo 8

si sabemos el nombre de las variables definidas en el formulario anterior de la siguiente forma $_GET [ n o m b r e ] $_GET [ a p e l l i d o s ] $_GET [ c o r r e o ]

Existen en el formulario visto varias teacutecnicas de recogida de informacioacuten Los cuadros de texto que permiten escribir valores alfanumeacutericos lista de seleccioacuten y botones de opcioacuten es donde podemos elegir una de las opciones existentes y casillas de verificacioacuten que permiten elegir 0 o maacutes opciones existentes Todas estas partes del formulario tienen una variable asociada que puede buscarse en $_GET

El uacutenico meacutetodo que puede plantear alguacuten problema es el que utiliza cashysillas de verificacioacuten Puesto que podemos elegir varias opciones eacutestas son enviadas como un array y deben recuperarse atendiendo a esta razoacuten

Advertencia

Para que los valores de las casillas de verificacioacuten sean enviados como array hay que declararlas en el formulario como tal escrishybiendo dos siacutembolos de corchetes en la propiedad ntildeame asociada a las casillas por ejemplo lt i n p u t t y p e = c h e c k b o x n a m e = g u s t o s [] v a l u e = I n f o r m aacute t i c a gt

La paacutegina f o r m u l a r i o 2 php queda de esta forma para que pueda recishybir los gustos de los usuarios

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidos ltpgt ltphp foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

echo ltbrgtGUSTOSltbrgt $gustos = $_GET[gustos] foreach ($gustos as $indice =gt $valor)

echo $indice $valorltbrgt gt ltbodygt lthtmlgt

La figura 83 muestra la mejora incluida en el programa Ahora es capaz de recuperar los gustos de los usuarios e imprimirlos en pantalla Para esto

Paso de informacioacuten entre formularios 155

hemos antildeadido un bucle nuevo que inspecciona los valores enviados al array $gustos

Paso de informacioacuten con GET

Si se fija en la barra de direccioacuten de los navegadores cuando visita paacutegishynas Web sobre noticias o carritos de la compra en la URL van aparecienshydo variables que tienen que ver con los distintos menuacutes que existen en la Web

El siguiente ejemplo muestra una pequentildea revista digital escrita en pocas liacuteneas y en una sola paacutegina Web que cambia sus noticias eligiendo las disshytintas opciones del menuacute

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitIacuteonalEN

httpwwww3orgTRhtml4loosedtdgt lthtmlgt ltbodygt ltphp $menu = array (1 =gt Editorial 2 =gt Opinioacuten 3 =gt Regional 4 =gt Nacional) echo (--Revista Digital --ltbrxbrgt) echo (--MENU--ltbrgt ) foreach ($menu as $indice =gt $valor)

echo (lta href = Iacutendexphpmenu=$indicegt$valorltaxbrgt)

156 Capiacutetulo 8

j

echo ( ltbrgt--NOTICIAS--ltbrgt) switch ($_GET[menuacute])

case 1 echo (Editorial) break

case 2 echo (Opinioacuten) break

case 3 echo (Regional) break

case 4 echo (Nacional) break

default echo (Noticias de Portada) break

gt ltbodygt lthtmlgt

El array $menu se carga de los distintos valores que podemos ir seleccioshynando

En la actualidad estos valores se suelen extraer de una base de datos

Para mostrar el menuacute se hace un bucle donde se extraen todos los valores e iacutendices del array y se ponen como valores en los enlaces

echo (lta href=Iacutendexphpmenu=$indicegt$valorltaxbrgt)

Los enlaces siempre se dirigen a la paacutegina principal pero con un valor distinto en la variable menuacute

La segunda parte de la Web es una eleccioacuten muacuteltiple mediante la estrucshytura s w i t c h donde en funcioacuten del valor de la variable menuacute pasada por GET se eligen unas noticias vi otras

Puede ver el resultado en la figura 84

echo (lta href=Iacutendexphpmenu=$indicegt$valorltaxbrgt)

Los enlaces siempre se dirigen a la paacutegina principal pero con un valor distinto en la variable menuacute

La segunda parte de la Web es una eleccioacuten muacuteltiple mediante la estrucshytura s w i t c h donde en funcioacuten del valor de la variable menuacute pasada por GET se eligen unas noticias u otras

Puede ver el resultado en la figura 84

Argumentos POST

La utilizacioacuten del meacutetodo GET es totalmente inseguro porque no hay forshyma de ocultar datos privados en la direccioacuten Web tales como la contraseshyntildea de entrada o el nuacutemero de cuenta bancaria

El meacutetodo POST arregla estos problemas siendo el preferido de los desa-rrolladores Este meacutetodo es tan sencillo como cambiar en el formulario el meacutetodo de enviacuteo de datos

ltpgtIntroduzca sus datos personalesltpgt ltform name=formulario method=POST action=formulario2 php gt

lttable width=50 border=0 cellspacing=0 cellpadding=0gt

En cuanto a la recuperacioacuten de los datos tambieacuten debe cambiar el nombre de la variable suacuteper-global $_GET por $_POST de esta manera

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidosltpgt ltphp foreach ($_POST as $indice =gt $valor)

echo $indice $valorltbrgt

e c h o ltbrgtGUSTOSltbrgt $ g u s t o s = $ _ P O S T [ g u s t o s ]

158 Capiacutetulo 8

foreach ($gustos as $indice =gt $valor) echo $indice $valorltbrgt

gt ltbodygt lthtmlgt

Variables suacuteper-globales

Desde PHP 4 se vienen utilizando los arrays suacuteper-globales para almaceshynar los valores que pasan de unas paacuteginas a otras se almacenan en el orshydenador del usuario o en el servidor En PHP 5 el uso de estas variables se hace obligatorio para recuperar todos los valores Las variables a utilizar son

bull $_GET Almacena las variables que se pasan desde un formulario meshydiante el meacutetodo GET

bull $_POST Almacena las variables pasadas por POST

bull $_COOKIE Guarda los valores que estaacuten almacenados en cookies Ya veremos en capiacutetulos sucesivos coacutemo utilizarlo

bull $_SESSlON bull Guarda las variables que se pasan entre sesiones

bull $_SERVER Contiene numerosos valores relativos al servidor

bull $_FILES Los archivos que enviemos a traveacutes de un formulario seshyraacuten recogidos en este array

Una equivocacioacuten en el nombre de una variable puede llevarle a dar vuelshytas sobre el coacutedigo hasta encontrar el error Por eso es necesario conocer el contenido de las variables suacuteper-globales asiacute podraacute averiguar si estaacute pasando los datos correctamente La funcioacuten siguiente se puede utilizar cada vez que le surja un error de este tipo La funcioacuten muestra todos los valores de los arrays suacuteper-globales

ltphp function depuracioacuten() echo --Variables GET--ltbrgt foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

echo --Variables POST--ltbrgt foreach ($_POST as $indice =gt $valor)

echo $indice $valorltbrgt

echo --Variables COOKIES--ltbrgt

Paso de informacioacuten entre formularios 159

foreach ($_COOKIE as $indice =gt $valor) echo $iacutendiacutece $valorltbrgt

echo --Variables SESSION--ltbrgt foreach ($_SESSION as $indice =gt $valor)

echo $iacutendiacutece $valorltbrgt

echo --Variables SERVER-~ltbrgt foreach ($_SERVER as $indice =gt $valor)

echo $indice $valorltbrgt

depuracioacuten () gt

La figura 85 muestra los valores de todas las variables suacuteper-globales

Resumen

Hasta ahora soacutelo habiacuteamos tenido la oportunidad de crear programas en PHP que realizaran tareas en una uacutenica paacutegina Web

Este capiacutetulo ha dado una visioacuten praacutectica de coacutemo utilizar los conceptos aprendidos para escribir programas distribuidos en varias paacuteginas

160 Capiacutetulo 8

Aunque no ha aprendido ninguna funcioacuten nueva ha descubierto el vershydadero secreto del disentildeo de una Web dinaacutemica el paso de variables

Si viene de otras versiones de PHP tendraacute que tener en cuenta que la forshyma de recuperar las variables es a partir de la versioacuten 43 a traveacutes de las variables suacuteper-globales

En este capiacutetulo aprenderaacute a

bull Diferenciar entre clase y objeto bull Crear clases que hereden de otras clases bull Utilizar los modificadores pr iacutevate protected ypubl ic

bull Crear meacutetodos estaacuteticos y finales bull Guardar el estado de un objeto mediante la sentildealizacioacuten bull Recuperar informacioacuten referente a las clases meacutetodos y propiedades

162 Capiacutetulo 9

Introduccioacuten

PHP comenzoacute su andadura como un simple lenguaje de scripts A medishyda que las versiones avanzaban se fueron incluyendo algunas caracteshyriacutesticas que permitiacutean programar con orientacioacuten a objetos Con la aparicioacuten de PHP 5 los desabolladores tenemos una verdadera platashyforma de programacioacuten orientada a objetos gracias a la potencia del nuevo engine Zend 20 que permite ejecutar maacutes raacutepido y eficientemenshyte este tipo de programas

La programacioacuten orientada a objetos utiliza los elementos c l a s e y o b shyj e t o con punto de inicio Actualmente en las carreras teacutecnicas es posishyble encontrar ensentildeanzas sobre lenguajes orientados a objetos como Java o C++

Nota

En realidad Java y C++ son considerados como seudo lenguajes orientados a objetos Un ejemplo de lenguaje puro es SmallTalk o su versioacuten graacutefica Squeak (httpsqueaklinexorg) con muchos antildeos de antiguumledad

La programacioacuten orientada a objetos en PHP 5 no necesita una sintaxis muy diferente sino que es una aproximacioacuten a la realidad en otro camino diferente al acostumbrado Por ejemplo si piensa en un programa que tenga que averiguar la letra del DNI de un cliente lo normal es que cree una funcioacuten con un paraacutemetro al que le pase el nuacutemero de DNI y le deshyvuelva la letra buscada

Un desarrollo orientado a objetos pensariacutea en cada problema como una idenshytidad uacutenica como un objeto Puesto que el DNI siempre va asociado a una persona puede crear un objeto que identifique a personas y dentro de ese objeto programar una funcioacuten (meacutetodo en este caso) que calcule la letra La aproximacioacuten procedural (crear una funcioacuten) no asocia esa funcioacuten a persoshynas directamente y le podriacutea pasar cualquier nuacutemero entero recibiendo una respuesta vaacutelida En cambio la aproximacioacuten de objetos crea la funcioacuten dentro del objeto c l i e n t e y soacutelo permite mediante teacutecnicas que veremos maacutes adelante recuperar la letra del DNI de una persona

La programacioacuten orientada a objetos desarrolla nuevos conceptos y termishynologiacuteas que deben aprenderse correctamente para generar buen coacutedigo

Programacioacuten orientada a objetos 163

Definicioacuten de clases

Una clase es un tipo de dato que contiene en una misma estructura vashyriables y funciones Una clase es una especie de plantilla desde la que los objetos son instanciados y toman su valor Desde una clase se pueden consshytruir varios objetos del mismo tipo La definicioacuten es la siguiente

class pagina_Web

var $titulo function getTitulo()

return $this-gttitulo

Mediante la palabra reservada c l a s s definimos una clase completa Utishylizando va r podemos definir las variables que utilizaremos en el desarroshyllo del programa La palabra reservada va r desapareceraacute en versiones siguientes de PHP a favor de las palabras publ ic p r iacute v a t e y p r o t e c -ted Las funciones se definen como en el capiacutetulo 5 siempre que esteacuten dentro de la construccioacuten de la clase En este capiacutetulo vamos a definir una clase completa cuya misioacuten seraacute mostrar una paacutegina Web Podemos seshyguir con el ejemplo ampliando las funciones

ltphp class pagina_Web

var $titulo function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

function getTitulo() return $this-gttitulo

function cabecera() echo (lthtmlxheadxtitlegt) echo $this-gttitulo echo ( lttitlexheadxbodygt) bull

function cuerpo() echo(Este es el cuerpo de la paacutegina Web)

164 Capiacutetulo 9

function pie ( )

echo (ltbodyxhtmlgt)

function mostrar_pagina()

echo $thiacutes-gtcabecera () echo $this-gtcuerpo()

echo $this-gtpie()

Como puede ver la clase se divide en varias funciones y en una sola vashyriable La variable $ ti t u l o guardaraacute el tiacutetulo deacute la paacutegina Web Las funshyciones c a b e c e r a ( ) c u e r p o () y p i e () son las encargadas de mostrar las distintas partes de una Web

Estas funciones se llaman desde la f u n c i oacute n m o s t r a r _ p a g i n a ( ) Es inteshyresante observar que en unas pocas liacuteneas de coacutedigo hemos definido un objeto que podriacutea utilizarse como base de muchas aplicaciones El operador $ t h i s es una variable que contiene el objeto actual desde el que la invocamos Para acceder dentro de un objeto a funciones o variashybles propias debe anteponerse al nombre de eacutestas la expresioacuten $ t h i s - gt Para acceder desde la funcioacuten m o s t r a r _ p a g i n a () a cualquiera de las funciones de la clase tendraacute que escribir

$this-gtcabecera () $this-gtcuerpo ( ) $this-gtpie ()

Instancia de clase

Para que el coacutedigo funcione necesita crear el objeto Esto se hace utilizanshydo el operador new seguido del nombre de la clase

$ p a g i n a = new p a g i n a _ W e b ( )

Con el coacutedigo anterior hemos creado un objeto que contiene todas las vashyriables y funciones de la clase pag ina_Web ( ) La variable que contiene ese objeto es $pag ina

Para acceder a las funciones desde el nuevo objeto creado tenemos que utilizar la variable que contiene al objeto en este caso $ p a g i n a seguido del operador - gt y el nombre de la funcioacuten Para mostrar la Web tenemos que seguir estos sencillos pasos

$ p a g i n a = new p a g i n a _ W e b ( )

Programacioacuten orientada a objetos 165

$pagina-gtsetTitulo(Paacutegina Web nueva) $pagina- gtmostrar__pagina ( )

Funcioacuten constructor

Existen algunas funciones especiales en la definicioacuten de una clase La maacutes importante es el constructor Esta se ejecuta cada vez que se crea un nueshyvo objeto y permite crear las variables iniciales que se necesitan como el tiacutetulo de la Web o el autor El nombre de la funcioacuten debe ser c o n s -t r u c t () Nuestro constructor se encargaraacute de crear el tiacutetulo de la paacutegina Web que estamos creando

funct ion c o n s t r u c t ( $ t i t u l o )

$this-gtsetTitulo($titulo)

Herencia

La programacioacuten orientada a objetos permite heredar de otras clases Con esta teacutecnica puede ahorrar mucho tiempo de trabajo La clase hija (clase que hereda de otra) adquiere estas propiedades

bull Automaacuteticamente obtiene todas las variables miembro de la clase padre

bull Tambieacuten obtiene todas las funciones miembro de la clase padre que funcionaraacuten exactamente de la misma forma

bull La clase hija puede a su vez definir nuevas variables y funciones

La sintaxis es la siguiente

class pagina_Web_formulario extends pagina_Web

function formulario_inicio() Escribir el coacutedigo necesario

La palabra reservada e x t e n d s indica que la nueva clase creada seraacute una extensioacuten (heredaraacute) de la clase que se escribe justo a la derecha de la deshyfinicioacuten Puede crear un objeto formulario a partir de la clase pagina_Web de la siguiente forma

class pagina_Web_formulario extends pagina_Web

166 Capiacutetulo 9

function formulariacuteo_inicio($accion)

echo (ltform action=$acciongt)

function formulario_fin() echo (ltformgt)

function formulario_caj a_texto($nombre) echo ($nombre ltinput type=text name=$nombregt)

function formulario_boton() echo (ltinput type=submit name=Submit

valuacutee = Enviargt )

function mostrar_pagina () $this-gtcabecera () $this- gtf ormulario__inicio ( Iacutendex php) $this- gtf ormulario__caj a_texto (Nombre) $this-gtformulario_boton() $this-gtformulario_fin()

$this- gtpie ()

Si ahora ejecuta el coacutedigo instanciando la clase que hemos creado puede ver que las funciones c a b e c e r a () p i e ( ) incluso el constructor pueshyden ser utilizadas auacuten no perteneciendo a la clase p a g i n a _ W e b _ f o r -m u l a r i o

$formulario = new pagina_Web_formularioPagina con f o r m u l a r i o ) $formular io-gtmostrar_pagina ( )

La figura 91 muestra la ejecucioacuten del objeto anterior

Meacutetodos o funciones de objeto

Cuando definimos una clase hija las funciones de la clase padre son autoshymaacuteticamente heredadas Se llama redefinicioacuten de meacutetodos a la creacioacuten de funciones en la clase hija con el mismo nombre que en la clase padre En el ejemplo anterior la funcioacuten m o s t r a r _ p a g i n a ( ) de la clase pag ina_Web_f o r m u l a r i o estaacute redefinida ya que existe una funcioacuten con

Programacioacuten orientada a objetos 167

el mismo nombre en la clase pag ina_Web Al instanciar el objeto y ejecushytar el meacutetodo m o s t r a r _ p a g i n a ( ) el meacutetodo que se ha definido es la clase hija

PHP 5 con su nuevo motor Zend Engine 2 introduce la palabra reservashyda f i n a l

Si en la clase padre ponemos delante de cualquier funcioacuten la palabra f i n a l eacutesta funcioacuten no podraacute ser sobrecargada en las clases que la heshyreden

Tambieacuten podemos declarar clases completas como f i n a l lo que signifishycaraacute que no podraacuten ser heredadas

final function mostrar_pagina()

echo $this-gtcabecera() echo $this-gtcuerpo()

echo $this-gtpie()

Si definimos la funcioacuten anterior como f i n a l en la clase pag ina_Web la clase p a g i n a _ W e b _ f o r m u l a r i o no podraacute tener una funcioacuten con este mismo nombre y mostraraacute un error en pantalla La figura 92 muestra el error que se produce al intentar sobrecargar un meacutetodo que estaacute marcado como f i n a l

Herencia encadenada

Algunos lenguajes de programacioacuten permiten heredar de varias clases a la vez esto es conocido como herencia muacuteltiple PHP 5 no permite herenshycia muacuteltiple pero siacute herencia encadenada es decir permite heredar de varias clases padres correlativamente Un ejemplo es

class A

class B extends A

class C extends B

class D extends C

Valores y alcance de variables

En versiones anteriores de PHP los objetos eran pasados por valor a otras funciones por lo tanto el estado de los objetos no se conservaba En PHP 5 los objetos son pasados por defecto por referencia gracias al Zend Engine 2

ltphp

Programacioacuten orientada a objetos 169

class Nombre

i var $nombre function setNombre($nombre)

$this-gtnombre = $nombre

function getNombre() return $this-gtnombre

function cambiaNombre($obj eto$nombre)

$objeto-gtsetNombre($nombre)

$luis = new Nombre $luis-gtsetNombre(Luis Miguel) echo El nombre del objeto es $luis-gtgetNombre() ltbrgt cambiaNombre($luisPedro) eche El nombre del objeto es $luis-gtgetNombre() ltbrgt gt

El coacutedigo muestra coacutemo cambiar las propiedades de un objeto desde una funcioacuten con PHP 5 El resultado en el navegador puede comprobarlo en la figura 93

170 Capiacutetulo 9

Dentro de los objetos debe tener tambieacuten cuidado con el alcance de las variables Las variables definidas fuera del entorno del objeto no son acshycesibles desde los meacutetodos de las clases a menos que anteponga la palashybra g l o b a l

Miembros puacuteblicos privados y protegidos

Mientras no se especifique otra cosa los meacutetodos y propiedades de una clase son siempre puacuteblicos es decir son accesibles desde fuera del objeto de la forma o b j e t o - gtf u n c i oacute n Pero existe un camino para que las vashyriables y los meacutetodos no puedan ser accedidos desde fuera del objeto Eche un vistazo ahora al objetopagina_Web Su variable $ t i t u l o es puacuteblico porque no lo hemos definido de alguna forma especial Para cambiar el valor de esta variable podriacutea utilizar la funcioacuten asociada o directamente haciendo $ o b j e t o - gt t i t u l o = nuevo v a l o r Esta forma de actuar rompe con la filosofiacutea de la programacioacuten orientada a objetos Como norshyma general las propiedades de los objetos deben estar ocultas al entorno exterior y tomar sus valores desde funciones definidas dentro del objeto

Meacutetodos privados

Si declaramos un meacutetodo o propiedad como privada soacutelo se podraacute acceshyder a eacutel desde la clase que lo define Las clases que hereden de una clase con meacutetodos privados no tendraacuten acceso a eacutestos meacutetodos y tampoco seraacute posible desde fuera del objeto hacer llamadas Para hacer un meacutetodo o propiedad privado soacutelo hay que anteponer la palabra p r iacute v a t e delante de la declaracioacuten

class pagina_Web

priacutevate $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

priacutevate function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

De esta manera la clase p a g i n a _ W e b _ f o r m u l a r i o que hereda de pagina_Web no puede acceder directamente a la funcioacuten s e t T i t u l o ()

Programacioacuten orientada a objetos 171

de la siguiente forma $ t h i s - gt s e t T i t u l o ( T i t u l o n u e v o ) porque obtenemos un error de acceso ilegal Despueacutes de esta modificacioacuten soacutelo es posible dar un tiacutetulo a la paacutegina Web a traveacutes del constructor que como siacute estaacute dentro de la clase tiene potestad para utilizarla

Meacutetodos protegidos

Los meacutetodos protegidos son menos restrictivos que los privados Cuando declaramos un meacutetodo como protegido su visibilidad es en la clase que lo declara y en todas las clases que lo heredan El ejemplo anterior puede modificarse de la siguiente forma

c l a s s pagina_Web

protected $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

protected function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

Meacutetodos puacuteblicos Por defecto todos los meacutetodos y propiedades que se declaren en un objeshyto son puacuteblicos a menos que lleven asociados la palabra p r o t e c t e d o p r iacute v a t e Como buena praacutectica de programacioacuten las variables deben deshyfinirse como privadas o protegidas para que no puedan modificarse desshyde fuera del objeto Ademaacutes deben llevar dos meacutetodos puacuteblicos asociados s e t V a r i a b l e () para dar un nuevo valor a la variable y g e t V a r i a b l e () para recibir el valor actual de la propiedad Veamos el ejemplo

class pagina_Web

private $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

public function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

172 Capiacutetulo 9

public function getTitulo()

return $this-gttitulo

Interfaces

En proyectos profesionales a veces es necesario que un equipo de varias personas trabajen juntas En este caso se hace imprescindible definir unas pautas generales de trabajo para que el resultado final sea el esperado Si el desarrollo consiste en programar varios objetos el analista de la aplicashycioacuten puede definir la estructura baacutesica en papel o crear una pequentildea planshytilla con meacutetodos que el objeto final deberiacutea tener obligatoriamente Esta plantilla es un i n t e r f a c e y permite definir una clase con funciones deshyfinidas pero sin desarrollar que obliga a todas las clases que lo imple-menten a declarar estos meacutetodos como miacutenimo

i n t e r f a c e Web

public function setTitulo($titulo = Titulo por defecto)

public function getTitulo()

La interface anterior define la estructura baacutesica que queremos para el obshyjeto declarando las funciones setTitulo y getTitulo Para que una clase haga uso de la i n t e r f a c e se declara de la siguiente forma

class pagina_Web implements Web

Clases abstractas

Un i n t e r f a c e no permite crear el cuerpo de ninguna funcioacuten dejando esta tarea a las clases que la implementen Las clases abstractas permiten definir funciones que deben implementarse obligatoriamente en los objetos que hereden y ademaacutes permiten definir funciones completas que pueden heredarse Las clases abstractas deben llevar la palabra rese rvadaabs t rac t en la declaracioacuten de la clase y en todos los meacutetodos que soacutelo definan su nombre

abstract class Web

protected $titulo

Programacioacuten orientada a objetos 173

public function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

a b s t r a c t pub l i c funct ion g e t T i t u l o ( )

En lugar de un i n t e r f a c e hemos optado por utilizar una clase abstracshyta porque tenemos claro que el meacutetodo s e t T i t u l o () tiene que funcioshynar asiacute Tambieacuten se define el meacutetodo abstracto g e t T i t u l o () que obligatoriamente debe ser declarado en la clase que herede de eacutesta En realidad un i n t e r f a c e es una clase que tiene todos sus meacutetodos absshytractos

Clases con meacutetodos estaacuteticos

En PHP 5 puede declarar funciones dentro de una clase que no utilicen propiedades o meacutetodos de la misma Estos meacutetodos pueden calcular valoshyres numeacutericos hacer una conexioacuten a una base de datos o comprobar que un correo electroacutenico esteacute bien definido Aunque no existe ninguna palashybra reservada para definirlo son conocidos como meacutetodos estaacuteticos y pueshyden ser utilizados sin necesidad de instanciar un objeto

ltphp class Nombre

protected $nombre public function getNombre(

return $this-gtnombre

public function setNombre($nombre)

$this-gtnombre = $nombre

public function NombreDefecto()

return Luis Miguelltbrgt

$luis = new Nombre echo $luis-gtNombreDefecto() Tambieacuten se puede acceder al nombre por defecto echo NombreNombreDefecto() gt

174 Capiacutetulo 9

Para acceder a un meacutetodo estaacutetico desde el cuerpo del programa se escrishybe el nombre de la clase que lo implementa seguido del operador ( ) y el nombre del meacutetodo En el ejemplo vemos que se puede acceder al meacutetoshydo NombreDef e c t o () creando un objeto o mediante la construccioacuten Nombre NombreDef e c t o Si intenta llamar a un meacutetodo que no es estaacutetico de esta forma se imprimiraacute un error en pantalla La figura 94 muestra el error que recibe si intenta llamar a un meacutetodo no estaacutetico desshyde fuera de un objeto

Llamadas a funciones padre

El operador ( ) se puede utilizar tambieacuten dentro de una clase para hacer llamadas a funciones de la clase padre que esteacuten sobrecargadas Si define un constructor para la clase padre y otro para la clase hijo cuando cree el objeto el constructor que se ejecuta es el de nivel infeshyrior el constructor hijo Para llamar al constructor padre debe utilizarshyse la nomenclatura N o m b r e _ c l a s e _ p a d r e c o n s t r u c t ()

ltphp class Nombre

protected $nombre

Programacioacuten orientada a objetos 175

f unet ion construct ( $nombre)

$this-gtnombre = $nombre

publie function getNombre() return $this-gtnombre

publie function setNombre($nombre) $this-gtnombre = $nombre

publie function NombreDefecto() return Luis Miguelltbrgt

class Apellido extends Nombre

protected $apellidos function construct($nombre$apellidos)

$this-gtapellidos = $apellidos Nombre construct(Snombre)

publie function getApellidos () return $this-gtapellidos

$luis = new Apellido(Luis MiguelCabezas Granado) echo $luis-gtgetNombre() ltbrgt echo $luis-gtgetApellidos() gt

Puede ver que el constructor de la clase Ape l l ido inicializa la variable $ape-11 idos y seguidamente llama al constructor de la clase padre Nombre Esta forma de actuar puede resultar complicada si no conoce el nombre de la clase padre La solucioacuten a este pequentildeo inconveniente la tenemos en la palabra parent que hace alusioacuten a la clase de la que heredamos El coacutedigo anterior puede quedar de esta forma

class Apellido extends Nombre

protected $apellidos function construct($nombre$apellidos)

$this-gtapellidos = $apellidos

176 Capiacutetulo 9

p a r e n t cons t ruc t ($nombre) public function getApellidos()

return $this-gtapellidos

Sobrecarga de meacutetodos

Algunos lenguajes de programacioacuten orientados a objetos permiten declashyrar maacutes de un meacutetodo con el mismo nombre La definicioacuten de estos meacutetoshydos variacutea en el nuacutemero de paraacutemetros o en los tipos de datos de los argumentos PHP 5 no permite sobrecarga de meacutetodos pero puede simushylar esta actuacioacuten empleando la teacutecnica de las funciones con un nuacutemero variable de paraacutemetros El constructor de la clase A p e l l i d o puede queshydar de la siguiente forma

class Apellido extends Nombre

protected $apellidos function construct($nombre)

if (func_num_args()= = 2 ) $apellidos = func_get_arg(1) $this-gtnombre = $nombre $this-gtapellidos = $apellidos parent construct($nombre)

else $this-gtnombre = $nombre $this-gtapellidos = $apellidos parent construct($nombre)

public function getApellidos()

return $this-gtapellidos

Sentildealizacioacuten

Los objetos son en realidad un conjunto de datos y funciones que guarshydan una serie de estados de ejecucioacuten Este conjunto de bits se pueden al-

Programacioacuten orientada a objetos 177

macenar en un momento dado y recuperar justo en el mismo estado en el que se encontraba cuando lo guardamos Esta teacutecnica se llama sentildealizashycioacuten y permite almacenar y recuperar el conjunto de bits que forman un objeto

PHP 5 ofrece dos funciones s e r i a l i ze () y u n s e r i a l i z e ( ) que toshyman como paraacutemetro un objeto y devuelven una cadena de caracteres Los objetos serializados los podemos almacenar en base de datos ficheros etshyceacutetera

$luis = new Apellido(Luis Miguel) echo $luis-gtgetNombre() ltbrgt echo $luis- gtgetApellidos () -$manuel = serialize($luis) $pedro = unserialize($manuel) echo $pedro-gtgetNombre ()

El coacutedigo anterior crea el objeto $ l u i s y utiliza los meacutetodos propios de la clase y los heredados Despueacutes utilizamos la funcioacuten s e r i a l i z e () para grabar el estado del objeto como un conjunto de caracteres en la variable $manuel La variable $pedro contiene el resultado de aplicar u n s e r i a shyl i z e () a $manuel

De esta forma conseguimos recuperar el objeto $ l u i s con los datos que ya habiacuteamos almacenado

Funciones de manejo de clases

Las funciones siguientes son uacutetiles para recuperar informacioacuten sobre la herencia de las clases sobre meacutetodos o variables miembro o llamadas a las funciones

Tabla 91 Funciones de clases

Funcioacuten Descricioacuten

ge t c l a s s () Devuelve el nombre de la clase que iexclmplementa el objeto pasado como paraacutemetro

g e t _ p a r e n t _ c l a s s 0 Devuelve el nombre de la clase padre

c l a s s _ e x iacute s t ( ) Si el paraacutemetro es el nombre de una clase devuelve un true

g e t _ d e c l a r e d _ c l a s s () Devuelve un array con el nombre de todas las clases definidas en el coacutedigo actual

178 Capiacutetulo 9

Funcioacuten Descricioacuten

i s _ s u b c l a s s _ o f () Toma dos paraacutemetros Si el primer paraacutemetro es una subclase del segundo paraacutemetro la funcioacuten devuelve un true

i s _ a ( ) g e t _ c l a s s _ v a r s ( ) Devuelve un array con parejas variable valor de una clase que tengan valores por

defecto

g e t _ o b j e c t _ v a r s () Devuelve un array con parejas variable valor de un objeto que tengan valores por defecto

method_ex is ts () Toma dos paraacutemetros Si el objeto pasado tiene un meacutetodo con el nombre del segundo paraacutemetro la funcioacuten devuelve true

ge t_c lass_method () Devuelve un array de meacutetodos definidos en una clase

Puede ver el funcionamiento de la funcioacuten g e t _ c l a s s () en el ejemplo siguiente y el resultado en la figura 95

$luis = new Nombre echo $luis-gtNombreDefecto() echo La variable $luis es un objeto del tipo get_class($luis)

Programacioacuten orientada a objetos 179

Resumen

Existe en el mundo de los desabolladores de PHP una antigua disputa sobre la mejor forma de afrontar un proyecto Web Unos opinan que la forma maacutes raacutepida de crear una Web es realizar funciones separadas en ficheros y desde las paacuteginas del proyecto hacer las llamadas necesarias

La otra vertiente opina que merece la pena dedicar un poco maacutes de tiemshypo al desarrollo de objetos porque despueacutes redundaraacute en un gran benefishycio en futuros programas En realidad depende del proyecto Si soacutelo necesita crear un formulario para recibir datos de un usuario quizaacute no merezca la pena crear un objeto y siacute algunas funciones de control Si su proyecto va a ser muy extenso la recomendacioacuten es que prepare un comshypendio de objetos que se interrelacionen para llevar a buen teacutermino el programa

Puesto que el libro versa sobre PHP 5 y sus mejoras con respecto a las vershysiones anteriores intentaremos en los capiacutetulos siguientes realizar la mashyyoriacutea de los ejemplos en metodologiacutea orientada a objetos

En este capiacutetulo aprenderaacute a

bull Abrir y cerrar ficheros de lectura y escritura

bull Utilizar funciones para leer el contenido de un fichero

bull Realizar programas para la escritura de informacioacuten en un fichero

bull Gestionar los ficheros y directorios de un sistema operativo

bull Crear ficheros de configuracioacuten

bull Generar cabeceras para la descarga de archivos

182 Capiacutetulo 10

Introduccioacuten

Antes de que la proliferacioacuten de los gestores de bases de datos se hiciera efectiva los lenguajes de programacioacuten utilizaban el acceso a ficheros para almacenar sus datos Asiacute los lenguajes COBOL Pascal o incluso C comenshyzaron a utilizar el manejo de archivos en aquellos programas que necesishytaban guardar datos para recuperarlos posteriormente

Actualmente la informacioacuten puede almacenarse en ficheros o en bases de datos Los ficheros pueden almacenar textos que pueden ser leiacutedos faacutecilshymente por nosotros y por un ordenador Ademaacutes existe una serie de utishyl idades que permiten al sistema operat ivo (gnuLinux o MacOSX) interactuar con ellos hacer buacutesquedas etceacutetera

Nota

El sistema operativo Windows tiene algunas restricciones con resshypecto al manejo de ficheros y no se recomienda para gestionar los archivos

Funciones de lectura y escritura de ficheros

Existen en PHP 5 un conjunto muy numeroso de funciones que permishyten manejar ficheros de diferentes formas La idea baacutesica para trabajar con ficheros es la siguiente

bull Abrir el fichero para su lectura escritura

bull Leer el fichero

bull Cerrar el fichero (puede hacerse maacutes tarde)

bull Realizar las operaciones necesarias en el contenido

bull Escribir los datos

Abrir el fichero

La funcioacuten f open () asigna a una variable un puntero (un descriptor) al fichero que quiera abrir La variable puede utilizarse despueacutes para hacer cualquier tipo de operacioacuten Si el fichero que intenta abrir no existe o no puede utilizarse en ese momento f open () devolveraacute un valor false

Ficheros y almacenamiento de datos 183

Los ficheros pueden abrirse en varios modos tal y como indica la tabla 101

Tabla 101 Modos de apertura de los ficheros

Modo Explicacioacuten

Soacutelo lectura (r) Soacutelo permite leer el fichero Si intenta hacer otra cosa le saldraacute un error

Lectura y escritura si existe el Permite leer y escribir un fichero que exis-fichero (r+) ta El contenido del fichero no se borra

sino que se escribe a continuacioacuten Soacutelo escritura (w) Soacutelo se puede escribir Sobrescribe cualshy

quier fichero afectado Escritura y lectura (w+) Si el fichero no existe intenta crearlo Escritura al final (a) Escribe siempre al final del fichero tanto si

existe como si no Lectura y escritura al final (a+) Escribe al final del fichero y permite leer

Desde la versioacuten 4 de PHP puede abrir ficheros remotos que esteacuten almashycenados en servidores Asiacute podraacute utilizar el protocolo HTTP o FTP para recuperar datos remotamente Puede ver como ejemplo varias formas de abrir un fichero con f open ()

ltphp Los ficheros HTTP solo pueden abrirse de lectura $descriptor = fopen(httpwwwluisyfernandanet noticiastxtr) FTP permite abrir ficheros de lectura y escritura $descriptor2 = fopen(ftp usuariocontrasentildealuisyfernandanetnoticiastxtr) Apertura normal de un fichero guardado en el ordenador local $descriptor3 = fopen(noticiastxt a+) gt

Lectura de ficheros

f r e a d () tiene como paraacutemetro un descriptor de fichero devuelto por la funcioacuten f o p e n () y el tamantildeo del bloque de datos que queremos leer

$variable = fread($descriptor 4000)

Normalmente no conoceraacute el tamantildeo del fichero y por lo tanto debe utishylizar alguna teacutecnica para leerlo correctamente Lo maacutes sencillo es apoyar-

184 Capiacutetulo 10

se en la funcioacuten f i l e s i z e () que devuelve el tamantildeo en bytes del fichero que pase como argumento Asiacute la lectura anterior quedariacutea

$variable = fread($descriptor filesize(noticiastxt))

Advertencia

Tiene que notar que el lector f i l e s i z e () no toma como paraacuteshymetro el descriptor devuelto por la funcioacuten f o p e n O sino el nombre del fichero que estamos tratando

La funcioacuten anterior devuelve un bloque completo de caracteres leiacutedos desde un fichero y puede hacerse poco manejable cuando intente buscar alguacuten dato especiacutefico PHP 5 posee algunas funciones para leer liacutenea a liacuteshynea desde un fichero f r e a d () tiene como paraacutemetros el descriptor del fichero y un bloque maacuteximo de caracteres a leer La utilizacioacuten praacutectica es la siguiente

ltphp $descriptor = fopen (librotxta +) $linea_numero = 1 while (feof($descriptor))

$linea = fgets ($descriptor4096) echo liacutenea nuacutemero $numero_linea es $linea $linea_numero++

f c l o s e ($desc r ip to r ) gt

El bucle actuacutea hasta que la funcioacuten f e o f () encuentra el final del fichero apuntado por el descriptor Mientras que no sea el fin del fichero la funshycioacuten f g e t s () iraacute leyendo liacutenea a liacutenea todo el contenido e imprimieacutendoshylo en pantalla

La forma ideal de trabajar con ficheros es ir leyendo poco a poco su conshytenido para poder buscar datos que nos interesen en cada liacutenea o conshyjunto de caracteres Existe una funcioacuten que nos permite almacenar todo el contenido de un fichero en un array para su posterior proceso con las funciones propias de las colecciones de datos La funcioacuten e x p l o d e () toma como paraacutemetros un caraacutecter por donde cortar la cadena y el nomshybre de la variable que contiene los datos Podemos ver su funcionamienshyto en el ejemplo

ltphp $descriptor = fopen (librotxta+) $linea__numero = 1

Ficheros y almacenamiento de datos 185

$archivo = while ( feof($descriptor) )

$linea = fgets($descriptor4096) $archivo = $archivo liacutenea nuacutemero $numero__linea es

$linea $1inea_numero++

fclose($descriptor) $lista = explode( $archivo) gt

En este caso e x p l o d e () busca en la variable $ a r c h i v o todos los espashycios en blanco y va almacenando en el array caracteres que esteacuten entre dos ocurrencias (entre dos espacios) Asiacute obtenemos una gran lista de palashybras almacenadas por separado que hacen muy faacutecil buscar ordenar o borrar cualquier contenido

Por uacuteltimo la funcioacuten f ge te () permite leer un fichero caraacutecter a caraacutecshyter Esto es muy uacutetil cuando construimos un parse (un programa que inshyterpreta el contenido de un fichero) y debemos ir evaluando las palabras letra por letra para actuar en consecuencia

Escritura de ficheros

Las funciones para escribir ficheros son tan sencillas de utilizar como las de lectura La funcioacuten principal f w r i t e () escribe en un fichero apuntashydo por un descriptor una cadena de caracteres Es imprescindible que el fichero esteacute abierto en uno de los modos de escritura para que no deacute error

Veamos ahora un ejemplo completo El coacutedigo siguiente es un pequentildeo libro de visitas donde todo aquel que navegue por nuestra Web puede dejar mensajes de agradecimiento y aacutenimo Aunque no es el mejor libro de visitas escrito nunca siacute es un buen ejemplo de coacutemo utilizar la lectura v escritura de archivos dentro de un entorno orientado a objetos

ltphp class libro_visitas

priacutevate $tamano priacutevate $nombre priacutevate $descriptor priacutevate $contenido function construct($nombre)

$this-gtnombre = $nombre

i

186 Capiacutetulo 10

public function leer_libro)

$this-gtdescriptor = fopen ($this-gtnombrea+) $this-gttamano=filesize($this-gtnombre) if ($this-gttamano gt 0)

$this-gtcontenido = fread($this-gtdescriptor $this-gttamano)

fclose ($this-gtdescriptor) return $this-gtcontenido

pub l i c funct ion esc r ib i r__ l ib ro ($riombre $texto)

$ t h i s - gt d e s c r i p t o r = fopen ($this-gtnombrea+) $nombre = lt t r x t d bgcolor=CCCCCCgt$nombrelttdgtlttrgt $texto = lt t r x t d bgcolor=FFFFFFgt$textolt tdx t rgt f w r i t e ( $ t h i s - gt d e s c r i p t o r $ n o m b r e ) f w r i t e ( $ t h i s - gt d e s c r i p t o r $ t e x t o ) f c l o s e ($ th i s -gtdesc r ip to r )

gt ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtralgt ltheadgt lttitlegtLibro de visitaslttitlegt ltmeta http-eguiv=Content-Type content=texthtml charset=iso-8859-lgt ltheadgt ltbodygt ltp align=centerxstronggtLibro de visitas ltstrongxpgt lttable width=100 border=0 cellspacing=0 cellpadding=0gt

ltphp if (isset ($_POST[nombre ] ) |] isset($_POST[texto]))

$libro = new libro_visitas(librotxt) $librogtescribir_libro($_POST[nombre]$_POST[texto])

$libro_ver = new libro__visitas(librotxt) echo $libro_ver-gtleer_libro() gt lttablegt ltform action=librophp raethod=POST gt Nombre ltinput name=nombre tYpe=text id=nombregt

ltpgt ltpgtTexto

Ficheros y almacenamiento de datos 187

lttextarea name=texto id= tex togtlt tex ta reagt ltpgt ltpgt

ltinput type=submit name=Submit value=Enviar gt ltpgt ltformgt ltbodygt lthtmlgt

La figura 101 muestra el resultado del libro de visitas Como puede ver el coacutedigo tiene dos partes diferenciadas La primera es la definicioacuten de una clase con tres meacutetodos que es la encargada de almacenar y recuperar los datos La segunda parte es el coacutedigo HTML que nos permite visualizar los comentarios de las personas que nos visitan Lo maacutes recomendable es seshyparar ambas partes en dos ficheros distintos y hacer uso de la funcioacuten r e q u i r e _ o n c e () para utilizar el coacutedigo PHP

Si se fija en el coacutedigo HTML hay una parte central escrita en PHP que comprueba si existen datos pasados mediante el meacutetodo POST es decir si existen datos para escribir en el fichero Si es asiacute creamos el objeto $1 lishyb r o y llamamos al m eacute t o d o e s c r i b i r _ l i b r o ( ) que se encarga de guarshydar los datos correctamente Si no hay datos que guardar simplemente se crea un objeto y se lee el archivo donde estaacuten los comentarios

188 Capiacutetulo 10

La clase l i b r o _ v i s i t a s escribe en el fichero filas de una tabla que desshypueacutes se interpretan en el HTML colocando todo correctamente

Sistema de ficheros y directorios

Existe un conjunto de funciones que permiten manejar ficheros y directoshyrios del sistema Estas funciones son muy parecidas a comandos de Unix gnuLinux y seguramente le resulten familiar al lector

Copiar borrar y renombrar

Las operaciones baacutesicas de manejo de ficheros y que se aprenden cuando comenzamos a utilizar un sistema operativo concreto son las de copia borrado y modificacioacuten

Para copiar un fichero se utiliza la funcioacuten copy ( ) que toma como paraacuteshymetros el fichero que quiere copiar y el destino donde quiere guardar la copia

Puede antildeadir un meacutetodo nuevo a la clase l i b r o _ v i s i t a s para que reashylice funciones de copia de seguridad

public function copia_seguridad()

c o p y ( $ t h i s - gt n o m b r e c o p i a t x t )

La siguiente funcioacuten u n l i n k ( ) toma como paraacutemetro el nombre de un fichero y lo borra Puede hacer uso de esta funcioacuten para ampliar su clase y permitir que se puedan borrar los ficheros que almacenan los libros de visitas

public function borrar_libro()

unlink($this-gtnombre)

Como el meacutetodo c o p i a _ s e g u r i d a d () soacutelo permite almacenar un fichero puede ampliar su gama de meacutetodos y antildeadir uno que le deacute la posibilidad de renombrar el fichero c o p i a t x t a otro nombre

public function renombrar_copia($nuevo_nombre)

rename ($this- gtnombre $nuevo__nombre)

Ficheros y almacenamiento de datos 189

Funciones de comprobacioacuten

Es necesario antes de borrar copiar o renombrar un fichero hacer una comprobacioacuten miacutenima para saber si el fichero existe

De esta forma evitaraacute errores innecesarios y tendraacute maacutes control en el flujo de su programa

La funcioacuten f i l e _ e x i s t s () comprueba si un fichero existe dando el valor tnte en caso afirmativo yfalse en caso contrario

El meacutetodo b o r r a r _ l i b r o () puede quedar de la siguiente forma

public function borrar_libro()

if (file_exists($this-gtnombre))

unlink($this-gtnombre)

En los sistemas operativos UNIX gnuLinux todos los recursos hardware se corresponden con un fichero Puede que alguna vez necesite saber el tipo de fichero con el que va a tratar (fichero directorio recurso) La funshycioacuten f i l e t y p e () devuelve un valor que indica el tipo de fichero que coshyrresponde al valor pasado como paraacutemetro

Tabla 102 Tipos de ficheros

Valor Descripcioacuten

fifo Es de tipo FIFO

char Dispositivo de caraacutecter

dir Directorio

block Dispositivo especial de bloques

link Enlace

file Fichero

unknown Tipo desconocido

Ademaacutes de la funcioacuten anterior existe un conjunto de funciones que preshyguntan directamente al archivo por su tipo y el resultado es true ofalse en funcioacuten de la veracidad de la pregunta Las funciones i s _ d i r ( ) i s__execu tab le () i s _ f i l e () y i s _ l i n k ( ) preguntan a su argumento si es del tipo directorio ejecutable fichero o enlace respectivamente

190 Capiacutetulo 10

Directorios

Es muy uacutetil disponer de un gestor de ficheros Web que nos permita naveshygar entre los archivos y directorios Para hacer esto en PHP existen dos meacutetodos El primero utiliza las funciones o p e n d i r ( ) r e a d d i r () y c l o -s e d i r ( ) muy parecidas en su funcionamiento a f open () f r e a d () y f c i oacute s e ( ) Lo mejor es ver coacutemo trabajan juntas con un ejemplo

ltphp $directorio = $descriptor = opendir($directorio) while ($entrada = readdir($descriptor) )

if (is_dir($directorio$entrada) ) echo [Directorio] $entrada ltbrgtbull

elseif ( is__f ile ($directorio $entrada) ) echo [Fichero] $entrada ltbrgt

closedir($descr iptor) gt

Como puede intuir no existe ninguna diferencia significativa entre abrir un fichero o abrir un directorio Lo primero es crear un puntero hacia el directorio que quiera observar y guardarlo en $ d e s c r i p t o r El bucle va leyendo entrada por entrada con la funcioacuten r e a d d i r () y dependiendo

Ficheros y almacenamiento de datos 191

del resultado de las funciones i s _ d i r () o i s _ f i l e () se imprimiraacute el directorio o el fichero pertinente

Existe una segunda forma de visualizar lo mismo pero utilizando proshygramacioacuten orientada a objetos PHP 5 provee un objeto que implementa toda la loacutegica vista anteriormente La funcioacuten d i r () devuelve un objeto que permite examinar el directorio pasado como paraacutemetro El objeto poshysee un meacutetodo llamado r e a d () que va leyendo todas las entradas y un meacutetodo c i oacute s e ( ) que cierra el objeto El ejemplo anterior puede verse asiacute

ltphp $directorio = $fichero = dir(directorio) while ($entrada = $fichero-gtread())

if (is_dir(directorioentrada)) echo [Directorio] $entrada ltbrgt

elseif (is_file($directorio$entrada)) echo [Fichero] $entrada ltbrgt

$ f i c h e r o - gt c l o s e ( ) gt

Ficheros de configuracioacuten

Cuando sea un excelente programador en PHP 5 necesitaraacute conocer teacutecshynicas para almacenar datos de configuracioacuten en un fichero Una teacutecnica habitual es crear un fichero con variables de PHP que toman los valores adecuados y en el transcurso del programa utilizar una llamada a la funshycioacuten r e q u i r e j o n e e () para poder utilizarlas De esta forma podriacuteamos utilizar el siguiente ejemplo como configuracioacuten para conectar a una base de datos

ltphp servidor = localhost usuario = luis $password = secreta $base_datos = anaya gt

Otra alternativa es utilizar un tipo de fichero de configuracioacuten que utiliza la misma estructura que el fichero php i n i La estructura es la siguiente

Los comentarios van despueacutes de un punto y coma

192 Capiacutetulo 10

[Base__datos] servidor=localhost usuario=luis password=secreta base_datos=anaya Creamos un nuevo apartado [Preferencias] color=rojo tamanio=medio fuente=verdana

Este archivo almacena las variables que necesite en el transcurso del proshygrama

Para leerlo existe una sentencia especial que almacena el resultado en un array Para acceder a cada uno de los campos hay que utilizar la notacioacuten de un array de dos dimensiones como muestra el ejemplo La figura 103 muestra el resultado de leer un archivo de configuracioacuten

ltphp $configuracion = parse_ini_file(configuracioacuteniniTRUE) Ejemplos de variables echo $configuracion[Base__datos] [servidor] echo $configuracion[Preferencias] [fuente] gt

Ficheros y almacenamiento de datos 193

Manejo de ficheros en el servidor

Conociendo todas las posibilidades que ofrece PHP 5 a la hora de controshylar archivos llega la hora de aplicar a la praacutectica casos reales de funcionashymiento Los dos usos maacutes comunes de manejo de ficheros en la Web tienen que ver con la subida de los mismos a un servidor o con la descarga desshyde una paacutegina Web

Subida de ficheros

Cuando utilice un formulario Web puede introducir los datos solicitados a traveacutes de cajas de texto listas desplegables o botones de seleccioacuten Adeshymaacutes existe una etiqueta HTML que permite elegir un fichero de nuestro ordenador local y subirlo al servidor Puede crear un formulario miacutenimo que contenga la etiqueta en el siguiente ejemplo

ltHTMLgt ltBODYgt ltform action=subirphp method=POST enctype=multipartform-datagt Introduce el fichero ltinput type=file name=fichero gtltbrgt ltinput type=hidden ntildeameTAMANIO valueacute = 1000gt ltinput type=subraitgt ltformgt ltBODYgt ltHTMLgt

Como puede ver el atributo e n c t y p e debe tener el valor m u l t i p a r t = f o r m - d a t a para que el formulario trabaje correctamente Ademaacutes heshymos antildeadido una etiqueta llamada TAMANIO que guarda el valor maacutexishymo en bytes que nuestro script va a permitir subir Esto debe controlarse en la Web que reciba los datos mediante PHP Puede ver el aspecto graacutefishyco en la figura 104

Cuando el formulario se enviacutea PHP detecta automaacuteticamente que hemos enviado un fichero y lo almacena en un directorio temporal del servidor La Web que recibe los datos introduce dentro de la variable suacuteper-global 3_FILES [ nombre_f i c h e r o ] un conjunto de propiedades tales como el nombre del fichero subido el nombre temporal del recurso el tamantildeo o si ha tenido alguacuten error la subida Vamos a ampliar el formulario con coacuteshydigo para el manejo de ficheros

ltHTMLgt ltBODYgt ltform action=subirphp method=POST enctype=multipartform-datagt

194 Capiacutetulo 10

Introduce el fichero ltinput type=file name=ficherogtltbrgt ltinput type=submit gt ltformgt ltPHP

$fichero = $_FILES[fichero] foreach ($_FILES[fichero] as $indice =gt $valor)

echo $indice $valorltbrgt if ($_POST[TAMANIO]lt$_FILES[fichero] [size])

echo ltbrgtEl fichero tiene un tamantildeo adecuado copy ($_FILES[fichero] [tmp_name]archivotxt)

else echo ltbrgtEl fichero es demasiado grande

gt

ltBODYgt ltHTMLgt

i n L )T^ M ^ ir 7~n l a

L- I r

1 1 1 4 t r 1 c c - 1 r

f - 1 tlf 1 4 4

1 l 1 1 4 4 1

directorios ocultos Cenes ar

Terminado

f f t Eacute f l U B M I - B [luis] v Moziacutella Firefc V E l GIMP bull $ ^ C 7

Figura 104 Formulario de entrada de ficheros

El resultado muestra un formulario donde debe introducir un fichero que puede ver en la figura 105

Cuando activa el botoacuten de subida la paacutegina vuelve a cargar pero esta vez muestra informacioacuten sobre el fichero y si el tamantildeo es adecuado o no para su almacenamiento Nos hemos apoyado en la construccioacuten foreach para averiguar las proshypiedades del fichero subido

Ficheros y almacenamiento de datos 195

Si el tamantildeo en bytes que tenemos puesto como liacutemite en el formulario es menor que el tamantildeo del archivo se utiliza la funcioacuten c o p y () para coshypiar el fichero y guardarlo en el servidor

Descarga de ficheros

Normalmente dejamos al lenguaje HTML el trabajo de enlazar los archishyvos que deseamos que los usuarios de nuestra Web puedan descargar Esto se puede hacer simplemente con un enlace del tipo

lthtmlgt ltBODYgt lta href=ejemplozipgtPincha aquiacute para descargarltagt ltBODYgt ltHTMLgt

Cuando hacemos clic en el enlace normalmente el navegador averigua el tipo de fichero que vamos a descargar (ZIP PDF imagen) y nos muestra una pequentildea ventana con informacioacuten sobre el fichero

Imagine ahora que los ficheros que queremos poner en descarga se geneshyran en ese mismo instante como los archivos PDF Tenemos que seguir una pauta distinta para permitir la descarga desde el sitio Web utilizanshydo cabeceras HTTP La figura 106 muestra la ventana del navegador que recibe la cabecera MIME

196 Capiacutetulo 10

ltphp $fichero = ejemplozip $mimeType = appliacutecationzip Si el navegador es Explorer u Opera cambiamos el tipo de cabecera if (strpos($_SERVER[HTTP_USER_AGENT]MSIE 5) |[

strpos($_SERVER[HTTP_USER_AGENT]Opera 7)) $mimeType = applicationx-download

Se genera la cabecera header(content-disposition attachment f ilename = ej emplo__personal zip) header(content-type $mimeType) header(content-length filesize($fichero)) Se enviacutea el archivo al navegador readfile($fichero) gt

Los tipo MIME identifican el tipo de fichero y lo asocian a una aplicacioacuten determinada en un sistema operativo determinado Si utiliza el tipo MIME de PDF en un sistema Windows la aplicacioacuten asociada puede ser Acrobat Reader de Adobe Casi todos los archivos llevan asociado un tipo MIME y sirve entre otras cosas para que el navegador reconozca el tipo de archishyvo que estaacute descargando y optar por mostrarlo directamente en pantalla o guardarlo en alguna ubicacioacuten del disco duro Si comprueba antes el nomshybre del navegador que ha solicitado la descarga puede cambiar el tipo para que sea compatible con distintas versiones Las cabeceras HTTP deshyben generarse con la funcioacuten h e a d e r () y debe ser lo primero que se enshyviacutea al navegador Si enviacutea alguacuten dato o etiqueta antes que la cabecera obtendraacute un error

Ficheros y almacenamiento de datos 197

La cabecera que utilizamos en este caso es la de enviacuteo de un fichero del tipo MIME indicado y tamantildeo calculado con la funcioacuten f i l e s i z e ( ) No es necesario que el archivo que vaya a enviar tenga el mismo nombre en la descripcioacuten de la cabecera que en el servidor

Finalmente la funcioacuten r e a d f i l e () lee el fichero completamente y lo enviacutea al navegador

Resumen

Situados ya en el ecuador del libro podemos asegurar que estaacute preparado para enfrentarse a programas serios Los conceptos baacutesicos los aprendioacute en los capiacutetulos 1 2 3 4 5 6 y 7 El capiacutetulo 8 le mostroacute la forma de utilishyzar las variables entre varias paacuteginas Web y el 9 la verdadera potencia de uso de PHP 5

Este capiacutetulo le ha mostrado la forma de guardar datos para que permashynezcan almacenados indefinidamente y meacutetodos para abrir cerrar copiar o borrar los ficheros que utilice Aunque no es el mejor meacutetodo para guarshydar los datos muchas aplicaciones existentes se sirven de las funciones de archivos en vez de la utilizacioacuten de bases de datos

Los dos capiacutetulos siguientes le guiaraacuten por el apasionante mundo de los gestores de bases de datos La potencia de estos gestores le permitiraacute errashydicar de sus scripts la gestioacuten de datos mediante ficheros A partir de enshytonces la gestioacuten de archivos quedaraacute relegada al manejo de ficheros graacuteficos copias o gestioacuten de la configuracioacuten

En este capiacutetulo aprenderaacute a

bull Crear sus propias bases de datos con el lenguaje SQL bull Realizar consultas con SQL para insertar modificar o borrar registros

bull Conocer las funciones baacutesicas de SQLite

bull Recuperar los datos de una tabla y el nuacutemero de registros bull Moverse entre los registros de una base de datos

200 Capiacutetulo 11

Introduccioacuten

Este capiacutetulo pretende ser una introduccioacuten al lenguaje estructurado de consulta (SQL) que es primordial conocer a la hora de utilizar alguna base de datos relacional Puesto que no es un libro dedicado a SQL soacutelo vereshymos las estructuras baacutesicas del lenguaje para poder realizar nuestros ejemshyplos por eso recomiendo leer alguacuten libro deciicado a consultas SQL para sacar el maacuteximo partido a las bases de datos

Tambieacuten conoceremos la nueva implementacioacuten de PHP 5 para bases de datos SQLite Lejos de ser un gestor de bases de datos es sencillamente una libreriacutea que nos permite tratar un fichero de iexcla misma forma que utishylizamos una base de datos SQLite viene instalado en los binarios de PHP 5 y no utiliza ninguacuten puerto de conexioacuten externo tan soacutelo funciona cuanshydo se hace una llamada a las funciones de SQLite

SQL

La estructura baacutesica de una base de datos SQL es muy sencilla Los datos de una base de datos se almacenan en tablas donde cada fila identifica uniacutevocamente a un elemento distinto Por ejemplo la tabla de usuarios tendraacute tantas filas como usuarios tenga la paacutegina Web Cada tabla puede definir varias columnas Las columnas hacen referencia a las propiedades de cada fila Por ejemplo la tabla de usuarios podriacutea tener como columshynas el coacutedigo de usuario el nombre los apellidos y la direccioacuten postal

Nota

Hoy en diacutea tedas las aplicaciones profesionales escritas en PHP se basan en la interaccioacuten entre el coacutedigo y los datos almacenados en alguna base de datos Recomiendo al lector que no escatime esfuerzos en aprender el lenguaje SQL pues le seraacute muy uacutetil para realizar despueacutes aplicaciones basadas en cualquier base de datos MySQL SQLite SQL Server o incluso Oracle

El lenguaje SQL nos permite elegir varias filas atendiendo a un criterio insertar nuevas filas actualizar los datos o borrarlas con las sentencias SELECT INSERT UPDATE y DELETE respectivamente Este lenguaje per-

Bases de datos con SQL y SQLite 201

mite soacutelo manipular los datos contenidos en las tablas Si quiere modificar la estructura tiene que apoyarse en el lenguaje de definicioacuten de datos que le permite crear nuevas tablas o bases de datos insertar nuevas propiedashydes en forma de columnas o borrar tablas con las sentencias CREacuteATE ALTER v DROP respectivamente Para seguir los ejemplos vamos a basarshynos en una pequentildea base de datos con tres tablas

Tabla 1 1 1 Usuario

id_usuario nombre cuenta

1 Luis Miguel 7011

2 Mariacutea Fernanda 3454

3 Pedro 3445

4 Javier 1123

La tabla de U s u a r i o s tiene 4 filas Cada una de ellas es diferente a las demaacutes y el paraacutemetro que las identifica uniacutevocamente es i d _ u s u a r i o En Espantildea todas las personas tienen un coacutedigo numeacuterico el DNI que las identifica y las hace distintas frente a otras personas que tengan el mismo nombre y apellidos En las tablas ocurre lo mismo Necesitamos un coacutedigo numeacuterico que nos identifique personas distintas Las dos propiedades sishyguientes son el nombre y la c u e n t a del banco para hacer los pagos

Tabla 112 Producto

id_producto nombre precio

1 ratoacuten 6

2 portaacutetil 1000

3 libro PHP5 20

La tabla de P r o d u c t o s es muy similar a la de U s u a r i o s e identifica toshydos los productos que se pueden encontrar en nuestra Web de venta

Tabla 113 Carrito

id_compra id_usuario Jd_producto

1 1 1

202 Capiacutetulo 11

idcompra iexcldusuario id_producto

2 1 2

3 2 1

4 3 3

La tabla C a r r i t o de la compra mantiene un listado que relaciona los usuashyrios con los productos que han comprado Si se fija en la primera fila el i d_compra es el nuacutemero de factura que debe ser distinto siempre en el antildeo actual el i d _ u s u a r i o es 1 lo que quiere decir que el usuario 1 Luis Miguel ha comprado el producto 1 un ratoacuten de PC Si ha entendido esto ya podemos empezar a ver las sentencias SQL para manejar los datos

SELECT

Este es el comando principal que usaraacute en todas sus aplicaciones de bases de datos La sintaxis baacutesica es la siguiente

SELECT campol campo2 campo3 FROM tabla WHERE condicioacuten

La sentencia SELECT permite escoger los campos que especifiquemos de un conjunto de filas que cumplan una condicioacuten escrita despueacutes de la claacuteushysula WHERE Por ejemplo para recuperar todos los nombres de los usuashyrios almacenados en la tabla U s u a r i o tendriacuteamos que hacer

SELECT nombre FROM Usuario

El resultado es una columna con todos los nombres

Luis Miguel Maria Fernanda Pedro Javier

Advertencia

Si se fija iexcla claacuteusula WHERE no aparece porque estamos seleccioshynando todas iexclas filas Si quisieacuteramos seleccionar todas las filas cuyo i d _ u s u a r i o sea mayor que 2 tendriacuteamos que antildeadir WHERE i d_usua r io gt 2

Bases de datos con SQL y SQLite 203

Si necesita utilizar todos los campos de una tabla puede utilizar el siacutemboshylo para seleccionar todos

SELECT FROM U s u a r i o

Un uacuteltimo truco permite conocer el nuacutemero de filas que cumplen la conshydicioacuten Si despueacutes de la sentencia SELECT escribimos c o u n t ( ) el gesshytor de bases de datos nos contaraacute el nuacutemero de filas implicadas en la seleccioacuten

SELECT c o u n t ) ) FROM U s u a r i o

El resultado devuelto es 4 el nuacutemero de usuarios dados de alta

Uniones

Imagine ahora que queremos conocer el nombre de los usuarios que han comprado un producto determinado Si nos fijamos en la tabla C a r r i t o soacutelo podemos sacar el i d _ u s u a r i o con lo aprendido hasta ahora

Existe la posibilidad de cruzar varias tablas Cuando unimos dos tablas lo que realmente pasa es que obtenemos como resultado una tabla mayor con la suma del nuacutemero de columnas de las tablas y tantas filas como inshydique la multiplicacioacuten de las filas de las tablas implicadas

Si hacemos algo asiacute

SELECT FROM Usuario Carrito

El resultado es la unioacuten de las tablas Usuario y Carrito cuyo resultado tiene la suma de las columnas (3 + 3) y la multiplicacioacuten de las filas (4 x 4)

Tabla 114 UsuarioxCarrito

idusuario nombre cuenta id_carrito id_usuario idproducto

1 Luis Miguel 7011 1 1 1

1 Luis Miguel 7011 2 1 2

1 Luis Miguel 7011 3 2 1

1 Luis Miguel 7011 4 3 3

2 Ma Fernanda 3454 1 1 1

2 Ma Fernanda 3454 2 1 2

2 Ma Fernanda 3454 3 2 1

2 Ma Fernanda 3454 4 3 3

204 Capiacutetulo 11

idusuario nombre cuenta id_carrito id_usuario id_producto

3 Pedro 3445 1 1 1

3 Pedro 3445 2 1 2

3 Pedro 3445 3 2 1

3 Pedro 3445 4 3 3

4 Javier 1123 1 1 1

4 Javier 1123 2 1 2

4 Javier 1123 3 2 1

4 Javier 1123 4 3 3

Aquiacute es donde realmente se necesita utilizar la claacuteusula WHERE Lo que queshyremos conocer es el nombre de los usuarios que han comprado el producto nuacutemero 1 Al hacer una unioacuten lo primero que tenemos que hacer es eliminar las filas repetidas mediante una sentencia que relacione las dos tablas Si se fija bien puede ver que la columna i d _ u s u a r i o aparece en las dos tablas por lo tanto es una buena referencia Observe la siguiente sentencia SQL

SELECT FROM Usuario Carrito WHERE Usuario id_usuario = Carrito id__usuario

Lo que hemos hecho es crear una unioacuten de dos tablas donde cada fila debe tener las dos columnas i d _ u s u a r i o iguales

Como las dos tablas tienen el mismo nombre para la columna i d _ u s u a r i o es necesario anteponer la tabla a la propiedad para que la consulta funshycione de la siguiente forma U s u a r i o i d _ u s u a r i o o C a r r i t o i d _ u s u a r i o

El resultado de la sentencia anterior es

Tabla 115 UsuarioxCarrito

idusuario nombre cuenta id_carrito idusuario id_producto

1 Luis Miguel 7011 1 1 1

1 Luis Miguel 7011 2 1 2

2 Ma Fernanda 3454 3 2 1

3 Pedro 3445 4 3 3

Bien ahora tenemos un conjunto de datos que nos da el nombre de los usuarios que han comprado algo en nuestra tienda Si queremos averi-

Bases de datos con SQL y SQLite 205

guar quieacuten ha comprado el producto nuacutemero 1 tendremos que modificar la sentencia

SELECT FROM Usuario Carrito WHERE Usuarioid_usuario - Carritoid_usuario AND id_producto = 1

El resultado ahora se acerca maacutes a la realidad de lo que necesitamos

Tabla 116 UsuarioxCarrito

id_usuario nombre cuenta id_carrito id_usuario id_producto

1 Luis Miguel 7011 1 1 1

2 Ma Fernanda 3454 3 2 1

Acotando un poquito maacutes la sentencia

SELECT nombre FROM Usuario Carrito WHERE Usuarioid_usuario = Carritoid_usuario AND id_producto = 1

Ahora el resultado siacute es el esperado

Tabla 117 Nombre de los usuarios que han comprado el producto 1

nombre

Luis Miguel

Ma Fernanda

Dominar la sentencia SELECT con todas sus variaciones es un trabajo duro de varios meses o antildeos pero la recompensa se recoge en los primeros pashysos cuando comenzamos a ver la potencia del lenguaje y el uso en los disshytintos gestores de bases de datos

INSERT

Para poder seleccionar los datos primero hay que poder insertarlos en las tablas La sentencia necesaria para introducir nuevos datos es

INSERT INTO tabla (columnal columna2 columna3) VALUacuteES (valorl valor2 valor3)

206 Capiacutetulo 11

El resultado de esta operacioacuten es la inclusioacuten de un registro nuevo en la tabla en las columnas indicadas y con los valores dados Aquellas columshynas que no aparezcan no tomaraacuten valor en ese registro o tomaraacuten el vashylor NULL Para insertar un nuevo cliente en la tabla de U s u a r i o puede utilizar la sentencia

INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (5 Feo Joseacute 78 98)

La tabla resultante quedaraacute de esta forma

Tabla 118 Usuario

idusuario nombre cuenta

1 Luis Miguel 7011

2 Ma Fernanda 3454

3 Pedro 3445

4 Javier 1123

5 Feo Joseacute 7898

UPDATE

Se utiliza para editar informacioacuten que ya estaacute almacenada en la base de datos En otras palabras podemos cambiar selectivamente cierta informashycioacuten sin tener que borrar un registro e insertarlo de nuevo

La sintaxis baacutesica es

UPDATE tabla SET carapol = valorl campo2 = valor2 campo3 = valor3 WHERE condicioacuten

La condicioacuten se utiliza para seleccionar el nuacutemero de filas a las que afectashyraacute el cambio Si no ponemos nada se supone que la actualizacioacuten de datos se hace sobre todas las filas de una tabla por eso es necesario poner algushyna condicioacuten

Podemos utilizar UPDATE para cambiar el nuacutemero de cuenta de uno de los usuarios

UPDATE Usuario SET cuenta = 4455 WHERE id_usuario = 2

Lo que hemos hecho es cambiar el nuacutemero de cuenta de Mariacutea Fernanda de 3454 a 4455

Bases de datos con SQL y SQLite 207

DELETE

Eacutes la sentencia maacutes peligrosa de las vistas Permite borrar de uno a varios registros de una tabla La sintaxis es

DELETE FROM tabla WHERE condicioacuten

Si se omite la claacuteusula WHERE se borran todas las filas de una tabla Es aconsejable no precipitarse en el uso de esta opcioacuten y detenerse antes un momento a recapacitar si se necesita realmente dejar la tabla vaciacutea La fila que contiene al usuario Javier puede borrarse de la siguiente forshyma

DELETE FROM Usuario WHERE nombre=Javier

Definicioacuten de tablas

El primer paso para poder interactuar con los datos de una tabla es su creacioacuten Para este fin se utiliza la sentencia CREacuteATE que define los campos y el tipo de datos que se va a almacenar en cada columna

Ll formato simplificado es CREacuteATE TABLE tabla (columnal tipo_dato columna2 tipo_dato columna3 tipo_dato)

Los tipos de datos de SQL estaacutendar pueden variar dependiendo del gesshytor de bases de datos que utilice pero baacutesicamente pueden ser

Tabla 119 Tipos de datos en SQL 92

Especificacioacuten Tipo de dato

INT INTEGER Entero grande

SMALLINT Entero pequentildeo

REAL FLOAT Coma flotante

DEC DECIMAL Decimal

CHAR(n) CHARACTER(n) Alfanumeacuterico de longitud fija n

208 Capiacutetulo 11

Especificacioacuten Tipo de dato

VARCHAR(n) Alfanumeacuterico de longitud variable como maacutexishy

mo n caracteres

DATE Fecha

TIME Hora

TIMESTAMP Instante Conjunto de Fecha y Hora de un momento determinado

Con estos datos podemos ver la definicioacuten de la tabla de U s u a r i o

CREacuteATE TABLE Usuario (id_usuario INTEGER nombre CHAR(255)

cuenta INTEGER)

Si alguno de los campos es obligatorio es decir si siempre que realice una insercioacuten de nuevos datos necesita que ciertos campos sean introducidos obligatoriamente puede utilizar la sentencia NOT NULL despueacutes de la deshyfinicioacuten del campo

El campo nombre es obligatorio en la tabla U s u a r i o ya que un registro de usuarios sin almacenar su nombre no tiene sentido

CREacuteATE TABLE Usuario (id_usuario INTEGER nombre CHAR(255) NOT

NULL cuenta INTEGER NOT NULL)

El i d _ u s u a r i o identifica un registro y soacutelo uno No puede haber en la misma tabla dos nuacutemeros iguales en esta columna La forma de encontrar raacutepidamente una fila determinada es preguntar por este dato

La clave primaria de una tabla es un identificador uacutenico en cada tabla y que puede utilizarse para relacionar una tabla con otra En nuestro ejemshyplo podemos ver claramente que i d _ u s u a r i o es la clave primaria de la tabla U s u a r i o

CREacuteATE TABLE Usuario (id_usuario INTEGER PRIMARY KEY nombre

CHAR(255) NOT NULL cuenta INTEGER NOT NULL)

SQLite

SQLite es una libreriacutea que implementa un conjunto de sentencias bastanshyte amplio de SQL 92 estaacutendar La libreriacutea es muy pequentildea y 2 oacute 3 veces maacutes raacutepida que los gestores de bases de datos MySQL o PostgreSQL Neshycesita muy poco tiempo de ejecucioacuten y muy poca memoria para el proceshyso No se necesita administrar la base de datos fuera del entorno de

Bases de datos con SQL y SQLite 209

programacioacuten ya que no es un servidor Existe un problema derivado de esto

SQLite se basa en el almacenamiento de datos en un fichero por lo tanto cada vez que se almacenan datos el fichero que contiene los registros se bloquea durante el tiempo de la actualizacioacuten y no permite a otros usuashyrios interactuar Si la base de datos se utiliza solamente para leer la veloshycidad seraacute muy elevada pero si la utilizamos para actualizar constanteshymente los datos SQLite perderaacute maacutes tiempo negociando los bloqueos del fichero que dando servicio

Entre las caracteriacutesticas de SQLite tenemos

bull Implementa muchas funcionalidades de SQL 92 incluido disparadoshyres y transacciones

bull Proteccioacuten de integridad de datos con cominit y r o l l b a c k

bull Los ficheros de datos pueden moverse de servidor y seguiraacuten funcioshynando

bull Soporta bases de datos de 2 Terabytcs

bull El coacutedigo fuente es de dominio puacuteblico

Creacioacuten de bases de datos

La interfnce de programacioacuten de la extensioacuten SQLite es muy similar al gesshytor de bases de datos MySQL y PostgeSQL La diferencia principal es que SQLite aunque acepta la definicioacuten de datos con la sentencia CREacuteATE internamente soacutelo diferencia entre valores alfanumeacutericos o valores numeacuteshyricos es decir que podemos omitir el tipo de los campos en la definicioacuten de las tablas

La funcioacuten s q l i t e _ o p e n () recibe como paraacutemetro el nombre de una base datos Si la base de datos no existe la crea Ademaacutes de esta funcioacuten neceshysitaremos otra para poder enviar consultas a la base de datos La funcioacuten s q l i t e _ s i n g l e _ q u e r y () toma como paraacutemetros la base de datos creada con s q l i t e _ o p e n () y un literal con la sentencia SQL que queremos ejeshycutar

El ejemplo siguiente crea la base de datos de usuario e inserta las filas que estamos utilizando para aprender el lenguaje SQL

ltphp

$base_datos = sqlite_single_open(Usuariodb) $consulta = CREacuteATE TABLE Usuario

(id_usuario PRIMARY KEY

210 Capiacutetulo 11

nombre CHARIacute2 55) NOT NULL

cuenta INTEGER NOT NULL)

sqlite__query ( $base_datos $ consulta)

$consultal = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (1 Luis Miguel7011)

$consulta2 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (2 Mariacutea Fernanda3454 )

$consulta3 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (3 Pedro3445)

$consulta4 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (4 Javier1123)

sqlite_single_query($base_datos$consultal)

sqlite_ single_query($base_datos$consulta2 )

sqlite_ single_query($base_datos$consulta3)

sqlite_ single_query($base_datos$consulta4)

gt

De esta forma se ha creado la tabla U s u a r i o pero hemos necesitado hashycer 4 consultas adicionales para antildeadir los datos Esto se puede simplifishycar utilizando la funcioacuten s q l i t e _ q u e r y ( ) que acepta maacutes de una liacutenea de SQL Vamos a crear de esta forma la tabla P r o d u c t o y C a r r i t o

ltphp

$consulta = CREacuteATE TABLE Producto

(Iacuted_producto INTEGER PRIMARY KEY

nombre CHAR(255) NOT NULL

precio INTEGER NOT NULL)

INSERT INTO Producto (id_producto nombre precio)

VALUacuteES (1 Ratoacuten 6)

INSERT INTO Producto (idjroducto nombre precio)

VALUacuteES (2 Portaacutetil1000)

INSERT INTO Producto (id_producto nombre precio)

VALUacuteES (3 Libro PHP520)

sqlite_query($base_datos$consulta)

consulta = CREacuteATE TABLE Carrito

(id^compra INTEGER PRIMARY KEY

id^usuario INTEGER NOT NULL

id^producto INTEGER NOT NULL)

INSERT INTO Carrito (id^compra id_usuario id_producto)

VALUacuteES (1 1 1)

INSERT INTO Carrito (id^compra id_usuario id_producto)

VALUacuteES (2 1 2)

INSERT INTO Carrito (id_compra id_usuario id_producto)

VALUacuteES (3 2 1)

INSERT INTO Carrito (id_compra id_usuario idjroducto)

VALUacuteES (4 3 3)

sqlite_query($base_datos$consulta)

gt

Bases de datos con SQL y SQLite 211

Algunos gestores de bases de datos necesitan antildeadir una sentencia espeshyciacutefica para que uno de los campos sea auto incremental es decir que su valor aumente poco a poco sin necesidad de antildeadirlo nosotros en realishydad es gestionado por la propia base de datos

Los campos enteros que llevan asociada la sentencia PRIMARY KEY autoshymaacuteticamente son tratados como campos auto incremeacutentales y en las oacutershydenes INSERT se puede omitir la inclusioacuten del valor porque SQLite le daraacute el valor correlativo de la fila que le corresponda

Uacuteltimos cambios en una tabla

Hay veces que necesitamos saber el uacuteltimo valor auto incremental que SQLite ha generado para asociar una imagen o un archivo a un registro de una tabla Para aver iguar este dato p o d e m o s usar la funcioacuten sqlite_last_insert_rowid()

ltphp $base_datos = sqlite_open(Usuariodb) sqlite_single_query($base_datosINSERT INTO Usuario (nombre cuenta) VALUacuteES (Joseacute A2677)) $ultimo_usuario = sqlite_last_insert_rowid($base_datos) sqlite_single_query($base_datosINSERT INTO Producto (nombre precio) VALUacuteES (Ibook1200)) $ultimo_producto = sqlite_last_insert__rowid($base_datos) sqlite_single_query($base_datosINSERT INTO Carrito (id_usuario id_producto) VALUacuteES ($id_usuario$id_producto)) gt

En el ejemplo puede ver la posible utilizacioacuten de la funcioacuten Con ella exshytraeraacute el uacuteltimo usuario y el uacuteltimo producto introducido y aprovecharaacute para insertarlos en la tabla de compras

Otra funcioacuten muy uacutetil es s q l i t e _ _ c h a n g e s ( ) que devuelve el nuacutemero de filas afectadas por una consulta anterior

Si borra varias filas esta funcioacuten le devolveraacute el nuacutemero de filas que han sido borradas como puede ver en la figura 1 1 1

lt php $base_datos = sqlite_open(Usuariodb)

sqlite_single_query($base_datosUPDATE Usuario set cuenta =

2 2 2 2) echo Nuacutemero de filas afectadas

sqlite_changes($base_datos) gt

Seleccioacuten de datos

Como hemos visto antes la funcioacuten s q l i t e _ q u e r y () da la posibilidad de hacer cualquier tipo de consulta vista al principio del capiacutetulo

Las sentencias CREacuteATE INSERT DELETE o UPDATE no necesitan devolshyver ninguacuten dato pero la sentencia SELECT tiene que devolver los datos requeridos

La variable que obtiene los datos se considera como un recurso y debe aplicarse una funcioacuten para recuperar las filas una a una

Lo podemos comprobar con un ejemplo cuyo resultado se muestra en la figura 112

lt php $base_datos = sqlite_open(Usuariodb) ^resultado = sqlite_query($base_datosSELECT FROM Usuario) if ( $resultado)

echo Parece que hay un error else

while ($fila = sqlite_fe tch__array ($resu l taaacuteo) ) foreach ($fila as $indice =gt $valor)

echo $indice $valorltbrgt

gt

Despueacutes de hacer una consulta con la funcioacuten s q l i t e _ q u e r y ( ) la vashyriable $ r e s u l t a d o recibe un tipo de dato que no es manejable La funshycioacuten s q l i t e _ f e t c h _ a r r a y () extrae de la variable $ r e s u l t a d o todas las filas devueltas en forma de array Para ello hemos construido un bucle w h i l e donde la variable $f i l a va recibiendo los registros

Para acceder a cada columna de un registro simplemente tenemos que hacer uso de la variable como si fuera un array y como iacutendice el nombre de la columna o el nuacutemero de registro de esta forma $f i l a [nombre] $ f i l a [ c u e n t a ] $ f i l a [ 0 ] $ f i l a [ l ]

Dentro del bucle hemos utilizado otro bucle f o r e a c h para mostrar por pantalla todos los valores del array

SQLite orientado a objetos

Puesto que la potencia de PHP 5 radica en la fuerte orientacioacuten a objetos es de agradecer que SQLite provea alguacuten objeto para la interaccioacuten con bases de datos SQLite tiene una potente interface orientada a objetos que puede ser usado para un eficaz manejo de los datos librando al progra-mador de crear su propio objeto con las funciones procedurales El objeto se llama S Q L i t e D a t a b a s e () y el constructor recibe como paraacutemetro la base de datos

214 Capiacutetulo 11

El ejemplo muestra coacutemo utilizarlo aunque el lector ya conoceraacute el funshycionamiento baacutesico de los objetos

lt php $base_datos = new SQLiteDatabase(Usuariodb) $consulta = CREacuteATE TABLE Usuario

(id^usuario INTEGER PRIMARY KEY nombre CHAR(2 55) NOT NULL cuenta INTEGER NOT NULL) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (1 VLuis Miguel7 011) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (2 VMariacutea Fernanda3454) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (3 Pedro3445) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (4 Javier1123)

$base_datos-gtquery($consulta) gt

El meacutetodo q u e r y ( ) funciona exactamente igua l que la funcioacuten s q l i t e _ q u e r y ( ) pero soacutelo recibe como paraacutemetro la consulta ya que la base de datos va impliacutecita en el objeto

Seleccioacuten de registros

Las consultas SELECT se tratan de manera parecida a lo visto anteriorshymente Puesto que estamos utilizando un objeto para recibir el resultado de una consulta tendremos que utilizar meacutetodos que nos permitan maneshyjarlos En la figura 113 puede ver el resultado

ltphp

$base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtquery($consulta) while ($resultado-gtvalid() )

$fila = $resultado-gtcurrent() echo $fila[0] ltbrgt echo $fila[l] ltbrgt echo $fila[2] ltbrgt $ resultado- gtnext () bull

gt

El meacutetodo v a l id () da un resultado true si existen valores que no se han mostrado si devuelve false es que ya hemos extraiacutedo todas las filas El meacutetodo c u r r e n t () nos da la fila actual deacutela consulta La variable $f i l a

Bases de datos con SQL y SQLite 215

obtiene un array con los datos del registro actual Para avanzar de registro en la consulta se utiliza el meacutetodo n e x t ( )

Funciones de Array para recuperar datos

SQLite ofrece tambieacuten un nuacutemero de nuevas funciones que simplifican y aceleran la recogida de informacioacuten de la base de datos Por ejemplo el meacutetodo A r r a y Q u e r y () devuelve un array de dos dimensiones donde la primera dimensioacuten indica el nuacutemero de la fila y la segunda dimensioacuten el nuacutemero de columna de esa fila Si la variable $ r e s u l t a d o recoge el resultado de A r r a y Q u e r y ( ) puede acceder a los registros de la siguienshyt e forma $ r e s u l t a d o [ 0 ] [ 0 ] $ r e s u l t a d o [ l ] [ 0 ] $ r e s u l t a -do [2] [3] Puede utilizar alguacuten bucle foreach para sacar todos los datos

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtArrayQuery($consulta) $filas = 0 while (isset ($resultado [$filas] ) )

foreach ($resultado[$filas] as $indice =gt $valor) echo $indice $valorltbrgt

$filas++

216 Capiacutetulo 11

gt

Ademaacutes de esta forma de trabajar puede hacer que el resultado de la consulshyta se devuelva en forma de objeto PHP 5 permite utilizar la construccioacuten fo-reach para interactuar con objetos v recuperar los datos de la siguiente forma

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario bullresultado = $base_datos-gtunbufferedQuerv($consulta) foreach ($resultado as $valor)

echo Svalor[0]ltbrgt echo $vaior[1]ltbrgt echo $valor[2]ltbrgt

gt

La construccioacuten unbuf f e r edQuery () devuelve las filas en forma de objeshyto y ademaacutes no almacena el resultado en buffer por lo que es muy raacutepida

Nuacutemero de filas

La extensioacuten SQLite posee un meacutetodo para determinar el nuacutemero de camshypos devueltos en una consulta en un resultado El meacutetodo n u m F i e l d s () se encarga de devolver este resultado Para poder utilizarlo debe recupeshyrar los datos con la funcioacuten unbuf f e r e d Q u e r y () y el objeto devuelto seraacute el que le indique el nuacutemero de campos que almacena

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtunbufferedQuery($consulta) $numero_filas = $resultado-gtnumFields() echo El nuacutemero de filas es $numero_filas foreach ($resultado as $valor)

echo $valorf0]ltbrgt echo $valor[1]ltbrgt echo $valor[2]ltbrgt

gt

Moverse entre registros

En muchos casos querraacute utilizar la menor memoria posible y se haraacute inshydispensable utilizar el meacutetodo unbuf f e r e d Q u e r y ( ) aunque esto hace perder funcionalidad y puede no resultar la mejor eleccioacuten

Bases de datos con SQL y SQLite 217

Por ejemplo imagine que quiere saber cuaacutentas filas devuelve un resulshytado

Usando unbuf f e r e d Q u e r y () tenemos que hacer un bucle para contar una a una las filas del resultado Con la funcioacuten q u e r y () tan soacutelo hay que llamar al meacutetodo numRows () para conocer el nuacutemero de registros implicados en la consulta

Las consultas con q u e r y () permiten ademaacutes recuperar la informacioacuten en el orden que queramos y no secuencialmente

El ejemplo siguiente muestra coacutemo utilizar una consulta para ver los reshygistros empezando desde el uacuteltimo hasta el primero

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtquery($consulta) $numero_filas = $resultado-gtnumRows() $resultado-gtseek($numero_filas-1) do

$fila = $resultado-gtcurrent () foreach ($fila as $valor)

echo $valorltbrgt

while ($resultado-gthasPrev() ampamp $resultado-gtprev()) gt

218 Capiacutetulo 11

El meacutetodo s e e k () se mueve a traveacutes del resultado y permite posicionar-nos en el registro que pasemos como paraacutemetro El meacutetodo h a s P r e v () es true si existe un registro previo y p r e v () es true si ha sido posible moshyverse a un registro anterior La figura 114 es un fiel reflejo del funcionashymiento

Resumen

SQLite es una de las caracteriacutesticas estrella de PHP 5 Se ha incluido para que no necesite instalar un gestor de bases de datos para sus proyectos Esto hace maacutes sencillo distribuir aplicaciones porque no dependen de un software adicional tan soacutelo de PHP 5

SQLite es a la vez un servidor de bases de datos y un cliente La libreriacutea permite operar con la mayor parte de las instrucciones de SQL posee un mayor juego de instrucciones que MySQL 4

Pero como todo lo bueno tiene una pequentildea pega Como SQLite trata las bases de datos como ficheros del sistema operativo cuando un usuario hace una conexioacuten para escribir datos el fichero queda bloqueado para inclusiones de otros usuarios Cuando termina la insercioacuten del primer usuario el segundo tendraacute acceso a escribir los datos Por lo tanto SQLite es muy recomendable cuando realice proyectos donde la mayor parte de las veces se hacen lecturas de la base de datos como un perioacutedico digital o un WebLog En otro caso es mejor utilizar un gestor de bases de datos como MySQL que veraacute en el siguiente capiacutetulo

En este capiacutetulo aprenderaacute a

bull Conocer la forma de conectarse a un servidor de bases de datos bull Realizar consultas y recuperar los datos de distintas formas bull Recuperar el nuacutemero de filas que intervienen en una consulta

bull Crear nuevas bases de datos y tablas

220 Capiacutetulo 12

Introduccioacuten

PHP 5 soporta muchos de los gestores de bases de datos relacioacutenales exisshytentes en el mercado Las dos alternativas maacutes comunes son ProstgreSQL y MySQL

Aunque PostgreSQL es mucho mejor en cuanto a caracteriacutesticas y funcioshynes soportadas del SQL 92 estaacutendar MySQL se ha hecho maacutes popular en el ambiente de los servidores Web Cuando los servidores Web ofrecen su sershyvicio como LAMP se refieren a Linux + Apache + MySQL + PHP

Este capiacutetulo cubre las operaciones maacutes comunes que los desarrolladores de PHP pueden hacer con MySQL desde recuperar o modificar datos buscar textos o hacer una copia de seguridad de la base de datos

Administracioacuten de usuarios

Una gran parte del uso de la seguridad y efectividad de MySQL tiene que ver con comprender el sistema de privilegios MySQL permite dar permishysos al detalle basaacutendose en grupos usuarios conexiones y comandos a utilizar En teoriacutea se puede dar privilegios a ciertos usuarios para que soacutelo puedan escribir en algunas columnas de varias tablas Es una buena idea dar a cada usuario los permisos miacutenimos necesarios para que pueda inte-ractuar con su base de datos En realidad en un mundo ideal no deberiacutea preocuparse por dar permisos a los usuarios o crear bases de datos Si su trabajo profesional se basa en el desarrollo de aplicaciones su adminisshytrador de bases de datos deberiacutea poner a punto el servidor de MySQL para facilitar su trabajo Si se estaacute interesado en conocer los entresijos del servishydor de bases de datos recomiendo al lector que lea la documentacioacuten o-line de la Web wwwmysql com o consiga uno de los muchos libros que tratan el tema

En el Apeacutendice A puede ver coacutemo instalar MySQL y dar los permisos neshycesarios para que pueda probar los ejemplos

Conexioacuten a MySQL

La conexioacuten no puede ser maacutes sencilla Es un proceso de dos pasos

bull Se conecta con el servidor de MySQL

PHP 5 y MySQL 221

bull Se solicita la conexioacuten a una base de datos especiacutefica Es importante recordar que MySQL es un servidor que puede estar alojashydo en el mismo ordenador que PHP 5 o en otro diferente Por eso la coshynexioacuten se hace de forma distinta a SQLite

Para conectar a MySQL es necesario enviar como paraacutemetros la direccioacuten del servidor el usuario y la contrasentildea

ltphp $servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras Conexioacuten al servidor de bases de datos $descriptor = mysql_connect($servidor$usuario $pass) Se selecciona la base de datos mysql_select_db($base_datos$descriptor) Se cierra la conexioacuten cuando terminemos mysql__close ( $descriptor) gt

La funcioacuten m y s q l _ c o n n e c t () permite conectar a un servidor En este caso hemos puesto como servidor a l o c a l h o s t porque estamos utilizanshydo nuestro ordenador local para hacer las pruebas

Otra cuestioacuten importante es que el servidor MySQL puede almacenar varias bases de datos de un mismo usuario por eso tenemos que utilizar la f u n c i oacute n m y s q l _ s e l e c t _ d b ( ) para seleccionar la que queremos utishylizar

Por uacuteltimo tenemos la funcioacuten m y s q l _ c l o s e () que se encarga de ceshyrrar una conexioacuten con el servidor

El ejemplo siguiente muestra coacutemo se puede crear una clase reutilizable en todos los proyectos que sirva para conectarse a una base de datos

ltphp class Servidor_Base_Datos

private $servidor private $usuario private $pass private $base_datos private $descriptor function construct($servidor$usuario$pass$base_datos)

$this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtpass = $pass

222 Capiacutetulo 12

$this-gtbase_datos = $base_datos $this-gtconectar_base_datos()

priacutevate function conectar_base_datos()

$this-gtdescriptor = mysql__connect($this-gtservidor$this-gtusuario$this-gtpass) mysql_select_db($this-gtbase_datos$this-gtdescriptor)

$servidor = localhost $usuario = luis $pass = secreto $base_datos = Usuario $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) gt

Nota

No he antildeadido al objeto ninguacuten tipo de control de errores ya que veremos ese tema con profundidad en el capiacutetulo 17

Seleccionar datos

Existen diferentes formas de recuperar datos desde MySQL pero los maacutes usados son seguramente m y s q l _ f e t c h _ q u e r y () y m y s q l _ q u e r y () Si leyoacute el capiacutetulo anterior sobre S Q L i t e no tendraacute ninguacuten problema para asimilar el funcionamiento de estas funciones

Vamos a antildeadir dos meacutetodos nuevos a la definicioacuten de la clase anterior para que nos pueda servir en otras aplicaciones

public function consulta($consulta)

$this-gtresultado = mysql_query($consulta$this-gtdescriptor)

public function extraer_registro ()

if ($fila = mysql_fetch_array($this-gtresultadoMYSQL_ASSOC)) bull return $fila

else return false

PHP 5 y MySQL 223

El meacutetodo c o n s u l t a () recibe una sentencia SQL que debe ejecutarse en la base de datos apuntada por el descriptor $ t h iacute s- gt d e s c r i p t o r

El meacutetodo e x t r ae r _ r eg i s t r o ( ) comprueba con la funcioacuten m y s q l _ f e t c h _ a r r a y () si existen ficheros en el resultado de la conshysulta

En caso afirmativo devuelve un arraxj con los datos de ese registro En el capiacutetulo anterior vimos que un registro pasado comoarray permitiacutea acceder a las columnas mediante un iacutendice numeacuterico ($f i la [0] ) o meshydiante el nombre de la columna (($f i l a [ i d _ u s u a r i o ]))

La directiva MYSQL_ASSOc elimina la posibilidad de extraer los datos con un Iacutendice numeacuterico mejorando la recuperacioacuten en Jos bucles del foreach El ejemplo siguiente muestra coacutemo utilizar los nuevos meacutetodos

ltphp Primero se antildeade el fichero que contiene la clase require_once(MySQLphp) $servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $usuario-gtconsulta (seslect from Usuario) while ($fila = $usuario-gtextraer_registro() )

foreach ($fila as $indice =gt $valor) echo $indice $valorltbrgt

gt

El coacutedigo anterior recupera la clase del fichero MySQL php e inicializa las variables necesarias para conectar con la base de datos

Tambieacuten podemos utilizar un fichero de configuracioacuten como el que vishymos en el capiacutetulo 10 para almacenar los datos de la conexioacuten

La variable $ u s u a r i o recoge la creacioacuten del objeto de conexioacuten y utiliza el meacutetodo c o n s u l t a () para recuperar el nombre de los usuarios de nuesshytra Web

Para extraer todos los datos nos encontramos con un bucle que va recupeshyrando un arraxj por registro almacenaacutendolo en $f i l a

Utilizando f o r e a c h podemos extraer todas las columnas de la fila indishycada

La figura 121 presenta el resultado del script

Manipulacioacuten de datos

Seleccionar datos de una base de datos es soacutelo el principio la potencia de SQL nos permite tambieacuten insertar actualizar y borrar filas de una tabla Con el objeto que hemos creado es muy sencillo hacer consultas del tipo INSERT UPDATE o DELETE llamando al meacutetodo c o n s u l t a ()

Insertar una fila

Para insertar una fila con nuestro objeto tendremos que definir la consulshyta y ejecutar el meacutetodo c o n s u l t a ()

ltphp require_once(MySQLphp) $servidor = localhost -$usuario = root $pass = $base_datos = Compras $insertar = INSERT INTO Usuario (nombrecuenta) VALUacuteES (Cristina2119) $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) ^usuario-gtconsuIta($insertar) gt

PHP 5 y MySQL 225

Actualizar una fila

Antes de actualizar una fila necesita identificar la fila o filas de la tabla que quiere cambiar En este ejemplo se ha utilizado una sentencia SE-LECT para averiguar primero el valor id_usuar io de Luis Miguel y desshypueacutes proceder a cambiar su cuenta bancaria

ltphp require_once(MySQLphp) $serviacutedor = localhost $usuario = root $pass = $base_datos = Compras $consulta = SELECT id_usuario FROM Usuario WHERE nombre=Luis Miguel $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $id_usuario = $fila[id_usuario] $actualizar = UPDATE Usuario SET cuenta=9999 WHERE id_usuario=$id_usuario $usuario-gtconsulta($actualizar) gt

En un caso praacutectico UPDATE puede utilizarse para modificar los datos introducidos en un formulario Web

Borrar una fila

Para borrar una fila puede seguir el mismo camino que se ha utilizado antes para actualizar Primero averiguumle el registro que quiere eliminar y despueacutes ejecute la consulta con la sentencia DELETE

ltphp require_once(MySQLphp) $servidor = localhost usuario = luis $pass = secreto $base_datos = Compras $consulta = SELECT id_usuario FROM Usuario WHERE nombre=Luis Miguel $usuario = new Servidor_Base_Datos$servidor$usuario$pass$base_datos) $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $id_usuario = $fila[id_usuario ]

226 Capiacutetulo 12

$borrar = DELETE FROM Usuario WHERE id_usuario = 1$id_usuario $usuario-gtconsulta($borrar) gt

Errores con las comillas

Examinemos ahora el coacutedigo siguiente ltPHP require_once(MySQLphp) if (isset ($_POST[nombre] ) ]| isset ($_POST[cuenta ]) )

$servidor = localhost $usuario = root $pass = $base_datos = Compras $nombre = $_POST[nombre ] $cuenta = $_POST[cuenta] $usuario = new Servidor_Base_Datos($servidor$usuario $pass$base_datos) $insertar = INSERT INTO Usuario(nombrecuenta) VALUacuteES ($nombre$cuenta) $usuario-gtconsulta ($insertar)

gt ltHTMLgt ltBODYgt ltform action=formulario_Usuario php method=POSTgt Nombre ltINPUT type=text name=nombregtltbrgt Cuenta ltINPUT type=text name=cuentagtltbrgt ltinput type=submit name=Enviar gt ltformgt ltBODYgt ltHTMLgt

El pequentildeo formulario que muestra la figura 122 permite insertar en la tabla Usuario nuevos clientes Los campos de texto que recogen el nombre y la cuenta pueden recibir cualquier tipo de caraacutecter hay ciertos siacutembolos que pueden provocar que un programa falle y son utilizados malintencionadamente por hackers para corromper el sistema Si en la casilla destinada a escribir el nombre escribe un nombre y en medio una comilla simple y otra doble tal y como muestra el ejemplo

Luis Migue1 Cabezas Granado

PHP 5 y MySQL 227

El meacutetodo c o n s u l t a () intentaraacute ejecutar

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Migue1 Cabezas Granado))

iquestPuede ver el problema Cuando MySQL lee la sentencia cree que es

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Migue

El resto de la sentencia causaraacute un error y fallaraacute la consulta La solucioacuten es antildeadir el siacutembolo de escape delante de la comilla simple para que MySQL tome el siacutembolo como un simple caraacutecter

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Miguel Cabezas Granado))

Existen tres soluciones para antildeadir el siacutembolo de escape a todas las comishyllas que aparezcan en campo de texto

bull Lo primero que puede hacer es configurar el archivo phpini activanshydo la opcioacuten m a g i c _ q u o t e s _ g p c Con esta opcioacuten a todos los datos pasados entre paacuteginas Web por los meacutetodos GET y POST se les inserta automaacuteticamente siacutembolos de escape en las comillas que aparezcan

bull Si m a g i c _ q u o t e s no estaacute activo en su servidor PHP 5 tiene la funshycioacuten a d d s l a s h e s ( ) que tiene el mismo cometido que la opcioacuten anshyterior Si m a g i c _ q u o t e s estaacute activo no podraacute utilizar esta funcioacuten porque se antildeadiriacutean dos siacutembolos de escape

228 Capiacutetulo 12

bull El tercer camino muy similar a a d d s l a s h e s usa la funcioacuten m y s q l _ e s c a p e _ s t r i n g Esta funcioacuten antildeade siacutembolo de escape a las comillas simples comillas dobles caracteres de final de fichero y reshytorno de carro Es un meacutetodo implementado por MySQL por eso es maacutes recomendable utilizar a d d s l a s h e s

Para saber si el fichero phpini tiene activado m a g i c _ q u o t e s existe la funcioacuten g e t _ m a g i c _ q u o t e s _ g p c ( ) Puede antildeadir algunas liacuteneas de coacutedigo a su formulario para que controle este tipo de error de la siguiente forma

ltphp require_once(MySQLphp) if (isset($_POST[nombre]) || isset($_POST[cuenta ]))

$servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras if (get_magic_quotes_gpc())

$nombre = $_POST[nombre] $cuenta = $__POST [cuenta ]

else $nombre = addslashes($_POST[nombre]) $cuenta = addslashes($_POST[cuenta])

$usuario = new Servidor_Base_Datos($servidor$usuario $pass$base_datos) $insertar = INSERT INTO Usuario(nombrecuenta) VALUacuteES ($nombre$cuenta ) $usuario-gtconsulta($insertar)

gt

Contando filas

A menudo es uacutetil conocer el nuacutemero de filas devueltas por una consulta antes de hacer cualquier cosa con el resultado Puede averiguar el nuacutemeshyro de filas mediante el uso de alguna funcioacuten de PHP o la utilizacioacuten de MySQL para obtener el nuacutemero de registros

Contar filas con PHP

La funcioacuten mysql_num_rows () devuelve el nuacutemero de filas seleccioshynadas

PHP 5 y MySQL 229

Su uso puede ampliar el objeto de bases de datos

public function numero_filas()

return mysql_num_rows($this-gtresultado)

Ademaacutes de esta funcioacuten tenemos mysql_num_f i e l d s ( ) que devuelve el nuacutemero de campos del una tabla es necesaria cuando hacemos una conshysulta de datos y no sabemos cuaacutentas columnas hemos seleccionado

Contar filas con MySQL

La alternativa es utilizar una consulta de SQL con la sentencia c o u n t ( ) Esto requiere hacer dos consultas una para obtener el nuacutemero de filas y otra para obtener el resultado

Utilicemos el objeto para realizar la operacioacuten

ltphp

require_once(MySQLphp) $servidor = localhost $usuario = root $pass = $base_datos = Compras $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $consulta = select count() as numero_filas from Usuario $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $numero_filas = $fila[numero_filas] $consulta = select from Usuario $usuario-gtconsulta($consulta) echo El nuacutemero de filas es $numero__f ilasltbrgt while ($fila = $usuario-gtextraer_registro())

foreach ($fila as $indice =gt $valor) echo $indice $valorltbrgt

gt

La primera sentencia SELECT cuenta el nuacutemero de filas y al resultado le da el nombre numero__f i l a s

Para acceder al nuacutemero se hace como siempre leyendo el resultado del irray $f i l a [ numero_f i l a s ]

La figura 123 muestra el resultado

Contar filas afectadas

Es posible que sea necesario saber cuaacutentas filas han sido afectadas desshypueacutes de antildeadir actualizar o borrar algunas filas

La funcioacuten m y s q l _ a f f e c t e d _ r o w s () devuelve el nuacutemero de registros afectados despueacutes de un cambio en las filas de una tabla Actualizando nuestra clase tenemos

public function filas_afectadas()

return mysql_affected_rows($this-gtdescriptor)

Uacuteltimo nuacutemero insertado

Cuando utilice campos auto numeacutericos en una tabla e inserte un nuevo registro seraacute uacutetil conocer el nuacutemero de la uacuteltima fila insertada

Para obtener este nuacutemero tan solo t iene que u t i l izar la funcioacuten m y s q l _ i n s e r t _ i d ( ) Se puede utilizar de la siguiente forma

public function ultima_fila()

PHP 5 y MySQL 231

return mysql_insert_id($this-gtdescriptor)

Buacutesquedas dentro de una tabla

La forma de buscar ocurrencias en una columna es utilizar la sentencia LIKE de SQL

SELECT FROM Usuario WHERE nombre LIKE Luis

El siacutembolo es un comodiacuten es decir puede sustituir a cualquier caraacutecter dentro de la columna donde busque

Definicioacuten de bases de datos

Como indicamos antes lo ideal es que un administrador de MySQL le genere las bases de datos y las tablas Despueacutes de esto con su usuario y contrasentildea podraacute hacer las consultas que tenga autorizadas

En muchos casos la figura del administrador de bases de datos no existe y es el desarrollador el que asume este papel En este caso le interesaraacute conocer la forma de crear desde un script sus bases de datos

Creacioacuten de bases de datos

Para crear una base de datos tiene que utilizar la funcioacuten m y s q l _ c r e a t e _ db () Recibe dos paraacutemetros el primero es el nombre de la base de datos que quiere crear y el segundo el descriptor devuelto por la funcioacuten m y s q _ c o n n e c t () La funcioacuten m y s q l _ d r o p _ d b () borra la base de dashytos del gestor de MySQL

ltphp $descriptor = mysq_connect($servidor $usuario $clave) mysql_create_db(Nueva_Base $descriptor) gt

Creacioacuten de tablas

La creacioacuten de tablas debe hacerse a traveacutes del lenguaje de consultas SQL como vimos en el capiacutetulo anterior Como ya sabe la funcioacuten m y s q l _

232 Capiacutetulo 12

q u e r y () acepta consultas de distintos tipos Aprovechando esto puede incluir una consulta para crear una tabla nueva

SQLite es una base de datos poco tipada es decir que soacutelo es capaz de almacenar dos tipos de datos nuacutemeros o caracteres En cambio MySQL es fuertemente tipada porque tiene un elevado conjunto de tipos para aplicar a sus columnas La tabla 121 muestra algunos tipos de datos que puede aplicar en la sentencia CREacuteATE

Tabla 121 Tipos de datos de MySQL

Nombre Tamantildeo Uso

BIT BOOLEAN 1 byte Almacena valores desde 0 a 255 sin

signo o -128 a 127 con signo SMALLINT 2 bytes De 0 a 65535 sin signo y de -32768 a

32767 con signo

MEDIUMINT 3 bytes De 0 a 16777215 sin signo o-8388608 a 8388607

INT INTEGER 4 bytes De0a4294967295ode-2147483648a 2147483647

BIGINT 8 bytes De 0 a 18446744073709551615 o -9223372036854775808a 9223372036854775807

FLOAT(precisioacuten) De 4 a Nuacutemero de coma flotante con precisioacuten

8 bytes

DATE 3 bytes Almacena una fecha

DATETIME 8 bytes Almacena una fecha con la hora y minutos

VARCHAR(nuacutemero) Nuacutemero Almacena tantos caracteres como indi-bytes ca el nuacutemero El tamantildeo es menor que

255 caracteres

TINYBLOB TINYTEXT Mayor que Almacena caracteres 255 bytes

BLOB TEXT Maacutes de Almacena un nuacutemero elevado de carac-64 kb teres

Como ejemplo puede ver el siguiente coacutedigo

lt $descriptor = mysq_connect($servidor $usuario $clave) mysql_create_db(Concesionario $descriptor) mysql_ select_db ( Concesionario) -

PHP 5 y MySQL 233

$consulta = CREacuteATE TAELE vehiacuteculos ( Iacuted_vehicul0 INT NOT NULL AUTO_INCREMENT PRIMARY KEY color VARCHAR(25) fecha_compra DATETIME)

$resultado = mysql_query($consulta) $mensaje = mysql_drop_db(Concesionario) gt

La columna i d _ v e h i c u l o identifica a un uacutenico vehiacuteculo de la tabla Como puede ver en MySQL tiene que antildeadir algunos modificadores a la columshyna para identificar sus caracteriacutesticas Estos modificadores son obligatoshyrios en MySQL Por ejemplo en SQLite no hace falta antildeadir ninguna propiedad para que el valor se incremente automaacuteticamente En MySQL es necesario especificar la propiedad AUTO_lNCREMENT Es obligatorio ademaacutes que todas las columnas tengan un tipo de dato definido

Resumen

MySQL es sin duda el sistema maacutes utilizado a escala mundial La mayor parte de las aplicaciones en PHP estaacuten escritas para MySQL porque da una fiabilidad y velocidad absolutas Hay que decir tambieacuten que la vershysioacuten 4 tiene bastantes restricciones con respecto a otros gestores de bases de datos como PostgreSQL pero se iraacuten solventando en las futuras vershysiones

Si terminoacute el capiacutetulo con eacutexito todaviacutea le queda un paso por andar La extensioacuten de MySQL que hemos utilizado es la que viene por defecto funshycionando con PHP 5 Recientemente se ha creado desde cero una nueva forma de interactuar con MySQL que permite hacer transacciones o conshysultas almacenadas (de la forma que lo hace Oracle) La extensioacuten se llashyma MySQLi y por su leve dificultad se escapa del objetivo de este libro

En este capiacutetulo aprenderaacute a

bull Diferenciar entre sesiones cookies y cabeceras HTTP bull Utilizar sesiones para ocultar variables entre usuarios y paacuteginas Web bull Almacenar la configuracioacuten de un usuario con cookies

bull Enviar informacioacuten de cabecera viacutea Web

236 Capiacutetulo 13

Introduccioacuten

Una sesioacuten es un periacuteodo de tiempo durante el cuaacutel una persona detershyminada ve un nuacutemero de diferentes paacuteginas Web de un determinado doshyminio

El protocolo HTTP no tiene forma alguna de distinguir un usuario que se conecte desde Espantildea de otro que se conecte desde Japoacuten PHP 5 proshyvee un mecanismo que permite antildeadir cierto nivel de diferenciacioacuten enshytre usuarios

Miremos un ejemplo

ltHTMLgt ltBODYgt ltphp switch ($_GET[opcioacuten ] )

case 1 echo La opcioacuten es 1 break

case 2 echo La opcioacuten es 2 break

case 3 echo La opcioacuten es 3 break

gt ltBODYgt ltHTMLgt

Esta paacutegina elige una de las opciones en funcioacuten del paraacutemetro GET que obtenga Como ya sabe GET pasa todos los valores junto a la direccioacuten Web y es visible para nosotros

El meacutetodo GET no es muy funcional cuando necesite pasar datos comproshymetidos a traveacutes de varias paacuteginas Web POST resuelve en parte este proshyblema

Este meacutetodo permite pasar entre paacuteginas las variables que quiera queshydando ocultas para el usuario A priori parece una buena forma de oculshytar datos pero nos encontramos que es necesario un formulario en cada paacutegina para utilizarla

Las sesiones y las variables de sesioacuten permiten pasar datos entre paacuteginas sin necesidad de utilizar formularios y es la mejor forma para ocultar dashytos comprometidos

Sesiones y Cookies 237

Sesiones en PHP 5

Las sesiones deben soportar

bull Detectar que durante el transcurso de la navegacioacuten por varias paacutegishynas Web la sesioacuten permanece invariable

bull Almacenar informacioacuten que formaraacute parte de una sesioacuten en concreto

PHP trabaja con una combinacioacuten de meacutetodos que son capaces de ocultar variables y cookies de las que hablaremos en un apartado posterior

Instanciando sesiones

El primer paso que nuestro script debe realizar es la llamada a la funcioacuten s e s s i o n _ s t a r t () Esta funcioacuten registra una sesioacuten en el servidor y la identifica con una cadena de 32 caracteres Cada persona que entre en ese mismo instante en la Web desde un ordenador diferente obtendraacute un iden-tificador distinto

La funcioacuten s e s s i o n _ s t a r t () debe incluirse en todas las paacuteginas Web que formen parte de la aplicacioacuten porque no soacutelo se encarga de iniciali-zar la sesioacuten sino que tambieacuten se encarga de mantener la misma sesioacuten durante el proceso La funcioacuten actuacutea de la siguiente forma

bull Si no existe una sesioacuten activa crea una nueva con un identificador

bull Si existe una sesioacuten que puede ser recuperada se extrae la sesioacuten y las variables asociadas ltphp session_start() gt ltHTMLgt ltBODYgt ltphp echo La variable de sesioacuten es SID gt ltBODYgt ltHTMLgt

La figura 131 muestra la variable de sesioacuten En el momento en que elscript escribe cualquier cosa el servidor termina de enviar las cabeceras HTTP y empieza a enviar el contenido No se puede enviar una nueva cabecera cuando ya estamos enviando el cuerpo de la Web Puesto que la funcioacuten s e s s i o n _ s t a r t () utiliza cabeceras para pasar la informacioacuten de sesioacuten

Sesiones y Cookies 239

La primera vez que instanciamos una sesioacuten seacute crea una constante llamashyda S ID que contiene el identificador de 32 caracteres que nos identifica

Variables de sesioacuten

Existe una variable suacuteper-global que se encarga de almacenar las variashybles que quiere pasar entre paacuteginas de una sesioacuten El array $_SESSION permite almacenar datos de cualquier tipo para recuperarlos en otras paacuteshyginas que tengan la misma sesioacuten El coacutedigo para propagar variables de sesioacuten puede ser tan sencillo como la paacutegina s e s i o n l php

ltphp session_start () gt ltHTMLgt ltBODYgt ltphp $_SESSION[nombre] = Luis Miguel Caberas $_SESSION[edad] = 29 echo lta href = sesion2phpgtPasar variablesltagt gt ltBODYgt ltHTMLgt

La vatvabie suacutepex-^toacutebal almacena valores de d-feteate tupo y creamas UTJ enlace a la paacutegina s e s i o n 2 php para poder recuperarlos

ltphp session_start () gt ltHTMLgt ltBODYgt ltphp echo Mostrar las variables de sesioacutenltbiacutegt foreach ($_SESSION as $indice =gt $valor)

echo $indice $valorltbrgt

echo Mostrar las COOKIESltbrgt foreach ($_COOKIE as $indice =gt $valor)

echo $indice $valorltbrgt gt ltBODYgt ltHTMLgt

Si se apoya en el bucle foreach podraacute extraer todos los valores pasados desde la Web s e s i o n l php Como curiosidad hemos introducido un bucle que extrae las variables almacenadas en c o o k i e s y puede ver en

Nota

Como veremos maacutes adelante iexclas cookies son pequentildeos contenishydos que se almacenan en el ordenador local Las cookies son muy utilizadas por los servidores Web para guardar las preferencias de un usuario o alguacuten dato interesante En realidad son variables que se guardan en el ordenador local del usuario y pueden ser resshycatadas por PHP en alguna otra ocasioacuten en la que se necesite

Problemas con los navegadores

Un problema muy comuacuten es que el usuario tenga por razones de segurishydad desactivada la opcioacuten de permitir c o o k i e s en su navegador El proshyb lema es que el o rdenador local no va a aceptar nuestra variable PHPSESSID y todas las paacuteginas creeraacuten que no existe sesioacuten activa y no podraacuten recuperar las variables Se puede resolver con unas pocas liacuteneas de coacutedigo para la paacutegina s e s i o n l php

ltphp

Sesiones y Cookies 241

session_start() gt ltHTMLgt ltBODYgt ltphp $_SESSION[nombre] = Luis Miguel Cabezas $_SESSION[edad] = 29 $id_sesion = SID echo lta href=sesion2php$id_sesiongtPasar variablesltagt gt ltBODYgt ltHTMLgt

Esta forma de trabajar implica tener que pasar en todos los enlaces el iden-tificador de sesioacuten La forma correcta de hacerlo es la que muestra el ejemshyplo ya que produce una URL de este tipo s e s i o n 2 phpPHPSESSID = 9 0 9 7 c 4 3 a a 8 6 d 3 4 5 9 b l 6 6 d 7 1 c 4 e a 4 c 9 3 0

Nota

Si quiere que PHP sea transparente manejando el paso de variashybles a traveacutes de c o o k i e s o viacutea el meacutetodo GET necesita tener configurado PHP 5 con las directivas - e n a b l e - t r a n s - s i d y - e n a b l e - t r a c k - v a r s Si estas opciones no estaacuten activashydas el uacutenico traacutemite para utilizar variables es pasar mediante GET o POST el identificado de sesioacuten corno en el ejemplo anterior

Funciones para el manejo de sesiones

La tabla 131 muestra algunas funciones interesantes con la descripcioacuten de uso

Tabla 131 Funciones relacionadas con las sesiones

Funcioacuten Descripcioacuten

session_start() Inicia una sesioacuten y permite almacenar variables en la

estructura $ _ S E S S I O N

session_destroy() Elimina todas las variables de sesioacuten

session_name() Devuelve el nombre de la sesioacuten normalmente PHPSES-SID

session_id() Devuelve los 32 caracteres que forman el identificador de sesioacuten

242 Capiacutetulo 13

Con las funciones relacionadas en la tabla anterior podemos construir un objeto que nos facilite el manejo de sesiones en nuestras aplicaciones

ltphp class sesioacuten

function constructor()

session_start() public function set($nombre$valor)

$_SESSION[$nombre] = $valor public function get($nombre)

if (isset ($_SESSION[$nombre] ) ) return $_SESSION[$nombre]

else return false

public function borrar_variable($nombre)

unset ($_SESSION[$nombre] ) public function borrarsesiacuteon()

$_SESSION = a r r a y O s e s s i o n _ d e s t r o y ( )

gt

Las paacuteginas s e s i o n l php y s e s i o n 2 php pueden manejarse ahora con la clase que hemos creado de la siguiente forma

ltphp require_once (clase__sesion php) $sesioacuten = new sesioacuten() gt ltHTMLgt ltBODYgt ltphp $sesioacuten-gtset(nombreLuis Miguel Cabezas) $sesioacuten-gtset(edad29) $id_sesion = SID echo lta href=sesion2php$id_sesiongtPasar variablesltagt gt ltBODYgt ltHTMLgt

Sesiones y Cookies 243

Cookies

Una cookie es una pequentildea parte de informacioacuten que queda almacenashyda en el ordenador local de los usuarios de una paacutegina Web Debe conteshyner siempre un nombre y un valor Es muy usual utilizar cookies para guardar preferencias de cada usuario en el uso de una Web pero hay que tener cuidado con el nuacutemero de variables que se pueden almacenar pues norshymalmente hay un maacuteximo de 20 por dominio seguacuten el navegador

En PHP 5 la funcioacuten s e t c o o k i e () se encarga de registrar las cookies durante el enviacuteo de las cabeceras Para recuperar el valor tiene que utilizar la variable suacuteper-global $_COOKIE

setcookie()

La funcioacuten s e t c o o k i e () normalmente tiene 2 argumentos el nombre de la variable y el valor Ademaacutes podemos pasar varios paraacutemetros que permiten dar un tiempo de vida a las variables asociar un dominio o aseshygurar el enviacuteo mediante HTTPS

La tabla 132 muestra en orden todos los argumentos que puede recibir una cookie

Tabla 132 Argumentos de la funcioacuten setcookie()

Argumento Tipo Descripcioacuten -

nombre caraacutecter El nombre de la variable cookie valor caraacutecter El valor que debe almacenar la variable Si este

valor no se indica la cookie seraacute automaacuteticashymente borrada

tiempo de vida entero Indica el tiempo de vida de unacookie Si el valor es 0 la variable nunca expiraraacute Si indica un nuacutemero entero tendraacute el tiempo que la variable permaneceraacute activa El valor hay que asignarlo en tiempo absoluto (como el devuelto por la funcioacuten mkt ime ())

ruta entero Permite distinguir entre dos variables con el mismo nombre pero llamadas desde distinta ruta en el servidor La cookie nombre llamada desde la ruta fo ro seraacute distinta a la cookie nombre llamada desde la ruta usuario

244 Capiacutetulo 13

Argumento Tipo Descripcioacuten

dominio caraacutecter Asegura el dominio de servidor que puede leerla cookie

Secure entero (0 Si el argumento es 1 la cookie soacutelo seraacute enviada oacute 1) a traveacutes de una conexioacuten segura HTTPS

Borrar una cookie

Borrar una cookie es faacutecil Si llama a la funcioacuten s e t c o o k i e () con los misshymos argumentos que para habilitarla excepto el valor la variable se elimishynaraacute del sistema local del usuario Si usa los paraacutemetros r u t a y dominio deben aparecer tambieacuten y con los mismos valores

Como de costumbre vamos a implementar una pequentildea clase para maneshyjar las cookies

ltphp

class Cookie

function constructor()

El constructor no hace nada

public function set($nombre$valor$expire=0$ruta= $dominio=$seguro=0)

setcookie($nombre$valor$expire$ruta$dominio$seguro)

public function get($nombre)

if (isset ($_COOKIE [$nombre] )) return $_COOKIE[$nombre] else return false

public function borrar_cookie($nombre)

setcookie($nombre$valor$expire$ruta$dominio$seguro

gt

El argumento tiempo de vida debe proporcionarse en valor de tiempo absoluto Esto a veces puede resultar incoacutemodo y seriacutea maacutes sencillo pro-

Sesiones y Cookies 245

porcionar el tiempo de vida de la variable en minutos o segundos La clase anterior solicita el tiempo en segundos y se encarga de antildeadir esos segundos al valor absoluto haciendo maacutes simple la asignacioacuten

Para ver coacutemo funciona podemos utilizar la Web c o o k i e l php

ltphp require_once(clase_cookiephp) $cookie = new CookieO $cookie-gtset(nombreLuis Miguel10) gt ltHTMLgt ltBODYgt ltphp echo La COOKIE es $cookie-gtget(nombre) echo lta href = cookie2phpgtPasar variablesltagt gt ltBODYgt ltHTMLgt

Como puede ver es muy sencilla la asignacioacuten de cookies y su recupeshyracioacuten

Cabeceras HTTP

Las funciones s e t c o o k iacute e () o s e s s i o n _ s t a r t () introducen su conteshynido en una cabecera HTTP sin necesidad de especificacioacuten por el usuashyrio Es posible enviar cabeceras desde PHP con la utilizacioacuten de la funcioacuten h e a d e r () La funcioacuten h e a d e r () es muy simple tan soacutelo toma como arshygumento un conjunto de caracteres que seraacute la cabecera a enviar Por ejemshyplo una forma muy uacutetil de redirigir una paacutegina a otra es utilizando la cabecera Location

lt php if (isset($_GET[usuario] ) ampamp $_GET[usuario] == Luis)

header(Location httpwwwluisyfernandanet)

gt lthtmlgt ltbodygt Si ve esta paacutegina su nombre no es Luis ltbodygt lthtmlgt

Este script evaluacutea si en la variable suacuteper-global $_GET existe un identifi-cador llamado u s u a r i o y si su valor es L u i s En caso afirmativo se enviacutea

246 Capiacutetulo 13

la cabecera al navegador que invita a cargar la Web especificada En caso negativo se enviacutea la paacutegina Web que hay despueacutes de la estructura if

Este tipo de uso de las cabeceras puede servir para redireccionar a una paacutegina de error cuando un usuario intente entrar sin permiso o cometa un fallo en la entrada de un nombre o correo electroacutenico

Resumen

Las sesiones resuelven los problemas muy comunes de seguridad El uso conjunto de sesiones cookies y cabeceras HTTP permiten un control absoshyluto sobre las variables de la aplicacioacuten Casi todos los programas que necesitan autentificar un usuario (como una tienda on-line) se sirven de estas teacutecnicas Pero el lector no debe quedarse aquiacute hay muchas cabeceras distintas que pueden ser uacutetiles en diferentes momentos como la autenticacioacuten viacutea HTTP

248 Capiacutetulo 14

Introduccioacuten

XML (Lenguaje de Marcas eXtensible) forma parte de SGML (Lenguaje de Marcas Generalizado eStandar) Auacuten asiacute no es necesario saber nada de SGML para utilizar XML El lenguaje XML define una estructura de documentos que pueden ser leiacutedos por personas y por ordenadores

El camino maacutes sencillo para comprender XML es pensar en coacutemo se utilishyzan los documentos HTML Estos documentos estaacuten estructurados y funshycionan con etiquetas y atributos Las etiquetas van encerradas entre siacutembolos de mayor y menor (ltbgt) y deben cerrarse de la misma forma antildeadiendo un siacutembolo de barra invertida (ltbgt) Los documentos HTML tienen una ortografiacutea especiacutefica es decir unas reglas que definen la forshyma correcta de estructurar un documento por ejemplo la etiqueta ltBODYgt debe ir siempre despueacutes de ltHEADgt o s ino existe eacutesta de ltHTMLgt Adeshymaacutes HTML contiene un diccionario cerrado de etiquetas que definen el lenguaje y no podemos utilizar otras que no esteacuten especificadas

En cambio XML no tiene un diccionario de etiquetas Las etiquetas que aparecen son las que nosotros mismos creamos La uacutenica norma que teneshymos que seguir es que toda etiqueta de inicio (ltcoche gt) debe tener una etiqueta de fin ( lt c o c h e gt )

El documento siguiente muestra un archivo XML bien formado

ltxml version=10 gt ltbibliotecagt lttema id=informaacuteticagt

ltlibrogt lttitulogtManual Imprescindible de PHP 5lttitulogt ltautorgtLuis Miguel Cabezas Granadoltautorgt

ltlibrogt ltlibrogt

lttitulogtDelphi 7lttitulogt ltautorgtMarco Cantultautorgt

ltlibrogt ltlibrogt

lttitulogtDelphi 6 y Kylixlttitulogt ltautorgtFrancisco Charte Ojedaltautorgt

ltlibrogt lttemagt

ltbibliotecagt

Como puede ver la estructura del documento es muy similar a la de una paacutegina Web Estaacute formado por etiquetas y atributos cuya definicioacuten pueshyde inventarse sobre la marcha es decir las etiquetas lt l i b r o gt lt t i t u -

Lectura y escritura de archivos XML 249

l o gt o lt s e c c i o n gt podriacutean tener un nombre totalmente diferente pero no asiacute en HTML que estaacute obligado a mantener el lenguaje definido Algushynos navegadores como Mozilla interpretan los ficheros XML como en la figura 141

Un documento XML estaacute obligado a cumplir ciertas normas que permishyten definir un texto bien formado

bull Debe tener un uacutenico elemento raiacutez Soacutelo puede haber un par de etishyquetas que diferencien el inicio y el final del documento como en HTML donde se utiliza ltHTMLgt y lt HTMLgt

bull Los elementos deben ser hereditarios La estructura lt A x B x B gt lt Agt se permite pero no la siguiente lt A x B x A x B gt En la primera forma la etiqueta ltAgt envuelve a la etiqueta ltBgt que es la forma coshyrrecta de escribir un documento XML HTML sin embargo permite la segunda forma de componer un documento ltA HREF=indexphpgt ltBxAx Bgt

bull Todos los elementos tienen que tener una etiqueta de cierre La pareja ltt i tulogtltt i tulo es correcta HTML permite etiquetas sin cerrar como ltBgt o ltLIgt

bull Los elementos pueden tener entre las dos etiquetas cualquier tipo de contenido como lttitulogtManual imprescindible de PHP 5lttitulogt

250 Capiacutetulo 14

bull Los caracteres amp lt gt las comillas simples y las comillas dobles estaacuten prohibidas como contenido y deben utilizarse siacutembolos de escape para utilizarlas

SAX DOM y SimpleXML

Lo primero que tenemos que hacer antes de leer archivos XML es conocer las tres formas existentes con sus ventajas e inconvenientes

bull SAX Es maacutes ligero y faacutecil de aprender trata los archivos XML como un flujo de datos que se leen poco a poco

bull DOM Lee el fichero completo y crea un objeto en memoria Permite crear archivos desde cero

bull SimpleXML Es el maacutes sencillo de utilizar Los elementos se pueden leer con un simple f o r e a c h

SAX

Se utiliza para parsear elementos XML Estaacute basado en eventos lo que sigshynifica que el parse hace llamadas a determinadas funciones dependiendo de los elementos que examina

Los eventos de SAX son proporcionados por PHP en forma de funcioacuten Al parsear se reconocen piezas de XML como etiquetas de inicio o fin datos o entidades externas y cada una de estas piezas hace una llamada a un evento El procedimiento para parsear un archivo XML con SAX debe seshyguir los siguientes pasos

bull Determinar queacute clase de eventos queremos manejar

bull Escribir una funcioacuten que maneje cada evento Es muy comuacuten escribir una funcioacuten para manejar los datos y las etiquetas de inicio y de fin

bull Crear el parse usando la funcioacuten x m l _ p a r s e r _ c r e a t e () y hacer la llamada con x m l _ p a r s e ()

bull Liberar la memoria usada con la funcioacuten x m l _ p a r s e r _ f r e e ( )

Hemos creado un objeto para leer archivos XML En principio no hace gran cosa tan solo examina las etiquetas de inicio y fin y las imprime en pantalla pero con esto bastaraacute para aprender la peculiar estructura de un parse SAX

ltphp

Lectura y escritura de archivos XML 251

class xml

function construct($fichero_xml)

$this-gtfichero_xml = $fichero_xml $this-gtxml_parser=xml_parser_create()

Puesto que el parse lo creamos desde un objeto debemos registrar la incidencia con xml_set_object

xml_set_obj ect($this~ gtxml_parser$this) Funciones de callback para manejar XML mediante SAX

xml_set_element_handler($this-gtxml_parserelemento_ inicioelemento_fin) if (($fp = fopen($this-gtfichero_xmlr)))

die (Error de Entrada y Salida)

while ($datos = fread($fpfilesize($this-gtfichero_xml)))

if (xml_parse($this-gtxml_parser$datos feof($fp)))

die (Fallo en el XML) xml_error_string(xml_get_error_ code($this-gtxml_parser))

xml_parser_free($this-gtxml_parser)

function elemento_inicio ($parser$nombre$atributos)

echo $nombreltbrgt

function elemento_fin ( $parser$nombre)

echo $nombreltbrgt

$biblioteca = new xml(bibliotecaxml) gt

Si guarda la clase en un archivo llamado c l a s e _ x m l php podraacute usarla en sus proyectos tan soacutelo con instanciar el objeto Si comienza por el consshytructor veraacute que el paraacutemetro que recibe es el archivo que quiere par-sear Debe crear el parse con la f u n c i oacute n x m l _ p a r s e _ c r e a t e () y despueacutes registrarlo en PHP como un objeto mediante la funcioacuten x m l _ s e t _ o b -j e c t () Si crea un parse fuera de la estructura de un objeto no haraacute falta hacer la llamada a la funcioacuten anterior

252 Capiacutetulo 14

La funcioacuten x m l _ s e t _ h a n d l e r () indica al parse que los eventos encarshygados de encontrar las etiquetas de inicio y de fin seraacuten manejadas con las funciones que se pasan como paraacutemetro En este c a s o e l e m e n t o _ i n i c i o ( ) se ejecutaraacute cada vez que se encuentre una etiqueta de inicio y e l e m e n t o _ f in ) cuando se encuentre la etiqueta de cierre

La uacuteltima parte del constructor lee el archivo pasado como argumento y analiza los datos a traveacutes de la funcioacuten x m l _ p a r s e ( ) que inicia la seshycuencia de anaacutelisis Si ejecuta una instancia de la clase comprobaraacute que el navegador muestra todas las etiquetas de inicio y de fin con una rigurosa herencia La figura 142 muestra las etiquetas leiacutedas del archivo XML

Para poder ver los datos tiene que antildeadir una nueva funcioacuten que maneje ese evento La f u n c i oacute n x m l _ s e t _ c h a r a c t e r _ d a t a _ _ h a n d l e r () permite manejar el evento que se dispara cada vez que se encuentra un dato entre dos etiquetas Esta funcioacuten tendraacute que antildeadirla al constructor despueacutes del meacutetodo que maneja los eventos de etiquetas

xml_set_character_data_handler($this-gtxml_parserdatos)

Ademaacutes de esto tendraacute que incluir una nueva funcioacuten que se encargaraacute de mostrar los datos

function datos($parser$valor)

Lectura y escritura de archivos XML 253

echo $v9lorltbrgt

Nota

Los eventos antildeadidos deben iexcllevar Jos argumentos necesarios para recuperar los datos Cada vez que cree un par se del tipo SAX las funciones tienen que tener los paraacutemetros que indicamos en nuesshytra clase de ejemplo

Despueacutes de comprobar el funcionamiento de la clase puede modificarla para que haga algo realmente uacutetil como mostrar ordenadamente los dashytos del fichero Las funciones de la clase pueden quedar de esta forma

function elemento_inicio ($parser$nombre$atributos)

switch($nombre) case TEMA

$tema = $atributos [ ID ] bull echo Tema $temaltbrgt break

case TITULO echo ltbgt break

case AUTOR echo - break

function elemento_fin ($parser$nombre)

switch($nombre) case TITULO

echo ltbgt break

case AUTOR echo ltbrgt break

function datos($parser$valor)

echo $valor

En este caso el parser iraacute analizando las etiquetas que nos interesan y reashylizaraacute una accioacuten determinada Por ejemplo cuando se comprueba la exis-

254 Capiacutetulo 14

tencia de una etiqueta TITULO escribimos en HTML la etiqueta de negrishyta ltBgt para resaltar este dato como muestra la figura 143

Elaborando un poco maacutes la clase obtendraacute un objeto de gran utilidad que podraacute recuperar informacioacuten de bases de datos o archivos de configurashycioacuten

DOM

Esta API define un completo camino para crear definir y parsear archivos XML D O M es una recomendacioacuten del consorcio World Wide Web

La idea baacutesica consiste en que todos los archivos XML pueden verse como un conjunto de nodos que forman parte de un aacuterbol Empezando desde el elemento raiacutez del que todos los elementos nacen como hijos cualquier programa deberiacutea ser capaz de crear una estructura loacutegica del documento

La API puede utilizarse para leer archivos en memoria modificarlos y volver a escribir el archivo con los nuevos datos

DOM estaacute escrito en metodologiacutea orientada a objetos y todos los nodos son instancias de diferentes objetos

Lectura y escritura de archivos XML 255

Usar DOM para leer archivos

El siguiente coacutedigo muestra un archivo XML muy simple

ltxml version=l0 gt lttema id=informaacuteticagt

lttitulogtManual Imprescindible de PHP 5lttitulogt lttemagt

Si parseamos este documento con DOM la etiqueta t i t u l o seraacute consideshyrada un nodo y ademaacutes un hijo del nodo raiacutez que en este caso es tema Esta parte queda maacutes o menos clara debido a la jerarquiacutea de etiquetas que tiene XML La controversia llega con el texto que hay en el nodo tema que no se considera como una parte sino como un nodo independiente cuyo valor es el texto Manual I m p r e s c i n d i b l e de PHP 5 Este nodo permite recuperar el valor con el meacutetodo n o d e V a l u e

Vamos a ver los pasos necesarios para leer el archivo b i b l i o t e c a xml ya que difiere bastante la metodologiacutea con respecto a SAX

Todo es un objeto

PHP 5 implementa una clase DOM para representar los archivos XML llashymada domDocument Como ya sabe para instanciar la clase soacutelo tiene que hacer uso del operador de objetos

$biblioteca = new domDocument

La extensioacuten D O M sigue las especificaciones de XML y trata los espacios en blanco como contenido Esto significa que si entre dos etiquetas existe un espacio el contenido seraacute tratado como un objeto de texto Para evitar fallos de este tipo puede ejecutar el siguiente meacutetodo

preserveWhiteSpace = f a l s e

Lo siguiente que tendraacute que hacer es leer el archivo b i b l i o t e c a xml con el meacutetodo l o a d () del objeto $ b i b l i o t e c a Si el contenido XML se almacena en una variable puede utilizar el meacutetodo loadXML ()

$biblioteca-gtload(bibliotecaxml)

A partir de aquiacute ya puede recuperar el contenido del fichero atendienshydo a sus preferencias En SAX teniacutea que leer el documento completo e ir preguntando etiqueta por etiqueta para averiguar todos los autores que estaban dados de alta en el archivo XML En D O M puede recupeshyrar esta informacioacuten usando g e t E l e m e n t s B y T a g n a m e () que devuelshyve un conjunto de objetos que coinciden con la etiqueta que pase como paraacutemetro

256 Capiacutetulo 14

ltphp Instanciamos el objeto $biblioteca = new domdocument Anulamos la posibilidad de que un espacio en blanco sea un obj eto $biblioteca-gtpreserveWhiteSpace = false Leemos el archivo XML $biblioteca-gtload(bibliotecaxml) Buscamos todas las etiquetas libro $libros = $biblioteca-gtgetElementsByTagname(libro) Imprimimos todos los libros foreach ($libros as $libro)

echo $libro-gtfirstChild-gtnodeVaiue ltbrgt

gt

La variable $ l i b r o s es en realidad un objeto de la clase d o m n o d e l i s t y guarda una relacioacuten de nodos cuya etiqueta es l i b r o es decir hemos seleccionado todos los libros del archivo Con un bucle f o r e a c h podeshymos sacar todos los valores Antes vimos que el texto asociado a un nodo es un nodo hijo con un valor determinado por eso debe llamar al meacutetodo f i r s t C h i l d

El hijo de la etiqueta l i b r o es el texto asociado y su valor lo podemos recibir llamando a n o d e V a l u e

El resultado es la lista de libros

Manual Imprescindible de PHP 5 Delphi 7 Delphi 6 y K y l i x

Atributos

Para recuperar los atributos de los nodos estaacute el meacutetodo g e t A t t r i b u -te ( ) al que tiene que pasar como argumento el nombre del atributo El archivo b i b l i o t e c a xml tiene una uacutenica etiqueta con el atributo id pero nos sirve para mostrar coacutemo funciona el meacutetodo

ltphp $biblioteca = new domdocument -$biblioteca-gtpreserveWhiteSpace = false $biblioteca-gtload(bibliotecaxml) $temas = $biblioteca-gtgetElementsByTagname(tema) foreach ($temas as $tema)

echo $tema-gtgetAttribute(id)

gt

El resultado es el nombre del tema o temas que esteacuten almacenados

Lectura y escritura de archivos XML 257

Buacutesquedas muacuteltiples

Nuestro objetivo final es mostrar todos los tiacutetulos con sus autores ordeshynados por temaacutetica Conociendo ya los meacutetodos principales para recorrer los objetos DOM es sencillo pensar en un coacutedigo que implemente lo que pedimos

ltphp $biblioteca = new domdocument Sbiblioteca-gtpreserveWhiteSpace = false $biblioteca-gtload(bibliotecaxml) $biblioteca-gtdocumentElement $temas = $biblioteca-gtgetElementsByTagname(tema)bull foreach ($temas as $tema)

echo Tema $tema-gtgetAttribute(id) ltbrgt $libros = $tema-gtgetElementsByTagname(libro) foreach ($libros as $libro)

echo ltbgt $libro-gtfirstChild-gtnodeValue ltbgt - $autores = $libro-gtgetElementsByTagname(autor) foreach ($autores as $autor)

echo $autor-gtfirstChild-gtnodeValue ltbrgt

gt

Aunque es un poco maacutes complejo el fundamento baacutesico es ir utilizando bucles para leer los hijos de un nodo determinado hasta recuperar todos los datos necesarios

Escribir archivos XML con DOM

D O M permite hacer maacutes cosas que la simple impresioacuten de los datos en pantalla Se puede utilizar para crear nuevos documentos con el nivel de jerarquiacutea que quiera Para hacer esto debe apoyarse en la creacioacuten de obshyjetos de la clase domElement ()

Vamos a crear un script para crear el siguiente archivo XML ltxml ve r s ion=1 0gt lt b i b l i o t e c a gt

lttemagtTextolttemagt lt b i b l i o t e c a gt

Para crearlo necesita instanciar una serie de objetos que empieza por la creacioacuten de un documento DOM mediante la utilizacioacuten del objeto d o shymdocument ()

ltphp

258 Capiacutetulo 14

$biblioteca = new doradocument(10) $raiz = new domelement(biblioteca) $raiz = $biblioteca-gtappendChild($raiz) $tema = new domelement(temaTexto) $tema = $raiz-gtappendChild($tema) $biblioteca-gtsave(bibliotecaxml) gt

La variable $ r a i z es el objeto que contendraacute todo el documento Para crear las etiquetas tiene que utilizar el meacutetodo a p p e n d C h i l d ( ) El objeto que llama al meacutetodo contendraacute como hijo al elemento que se pasa como paraacuteshymetro

Si se fija en el ejemplo $tema es un nuevo elemento que tendraacute la etiqueshyta tema

Para que $tema sea un hijo de la raiacutez debe hacer que el objeto padre $ r a i z llame al meacutetodo a p p e n d C h i l d () con el paraacutemetro $tema

Para grabar el resultado final el objeto D O M tiene que llamar al meacutetodo s a v e ( ) El fichero b i b l i o t e c a xml lo puede crear con el coacutedigo sishyguiente

ltphp $biblioteca = new domdocument(10) $raiz = new domelement(biblioteca) $raiz = $biblioteca-gtappendChild($raiz) $tema = new domelement(tema) $tema = $raiz-gtappendChild($tema) $tema-gtsetAttribute(idinformaacutetica) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloManual Imprescindible de PHP 5 bull $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autor Luis Miguel Cabezas Granado) $autor = $libro-gtappendChild($autor) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloDelphi 7 ) $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autorMarco Cantu) $autor = $libro-gtappendChild($autor) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloDelphi 6 y Kylix) $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autor Francisco Charte Ojeda) $autor = $libro-gtappendChild($autor) $biblioteca-gtsave(bibliotecaxml) gt

Lectura y escritura de archivos XML 259

El conjunto de liacuteneas de coacutedigo anterior crea un archivo completo XML Quizaacute sea mejor dividir el texto en funciones recursivas que permitan teshyclear menos a la hora de crear los documentos pero eso ya es trabajo para el lector El meacutetodo s e t A t t r i b u t e () antildeade un atributo al objeto que hace la llamada el primer argumento seraacute el nombre del atributo y el segundo su valor La llamada a domelement () puede tener uno o dos valores Si lleva un atributo significaraacute que el nombre de la etiqueta seraacute ese paraacutemeshytro Si se llama con dos paraacutemetros el primero seraacute el nombre de la etiqueta y el segundo un objeto de texto que se antildeadiraacute como texto hijo del nodo

Modificar archivos XML

La verdadera potencia de D O M reside en el poder de gestionar los archishyvos para antildeadir modificar o eliminar nodos La mayoriacutea de los algoritmos que realizan alguna de estas operaciones se basan en la buacutesqueda de los nodos para posteriormente antildeadir hijos nuevos o eliminar los encontrashydos Para antildeadir nuevos elementos se hace como cuando creamos el ficheshyro b i b l i o t e c a xml con el meacutetodo a p p e n d C h i I d ( ) Antes de antildeadir nuevos nodos tiene que localizar el lugar exacto donde quiere antildeadir las etiquetas El ejemplo siguiente muestra coacutemo antildeadir un nuevo nodo tema

ltphp $biblioteca = new domdocument(10) $biblioteca-gtload(bibliotecaxml) $raiz = $biblioteca-gtdocumentElement $tema_nuevo = new domelement(tema) $tema_nuevo = $raiz-gtappendChild($tema_nuevo) $tema_nuevo-gtsetAttribute (id ficcioacuten ) $biblioteca-gtsave(biblioteca2xml) gt

Los pasos son los que ya ha aprendido Cargue el documento y cree un objeto llamado $ r a i z que se convierta en la etiqueta raiacutez mediante el meacutetodo documentElement Cree un nuevo elemento del tipo tema y antildeaacuteshydalo para despueacutes insertar el atributo que se necesita Por uacuteltimo guarde el archivo en el fichero b i b l i o t e c a 2 xml

SimpleXML

Probablemente el punto maacutes fuerte de PHP 4 fue la incorporacioacuten de heshyrramientas para el soporte de XML PHP 5 le da una vuelta maacutes a la tuerca

260 Capiacutetulo 14

implementando nuevas herramientas de lectura elaboracioacuten y modificashycioacuten de archivos XML basado en la libreriacutea l i b x m l 2 y una nueva API llamada SimpleXML

Si XML es un lenguaje bien construido y legible por personas y ordenadoshyres los programas para manipular estos archivos deberiacutean ser tambieacuten sencillos de utilizar SimpleXML nace con esta premisa permitiendo leer un fichero completo con una sola instruccioacuten e inmediatamente despueacutes poder leer los datos como conjunto de variables PHP

El conjunto de funciones que pertenece a la API SimpleXML es nuevo en PHP 5 Mantiene una absoluta flexibilidad a favor de la simplicidad y bajo nivel de memoria usado SimpleXML utiliza el menor nuacutemero de liacuteneas de coacutedigo para leer o escribir datos en un fichero XML El e jemplo s iguiente muestra coacutemo p o d e m o s parsear el a rch ivo b i b l i o t e c a xml

ltphp $biblioteca = simplexTnl_load_fiie(bibliotecaxml) foreach ($biblioteca-gttema as $tema)

echo Tema es $tema[id] ltbrgt foreach ($tema-libro as $libro)

echo ltbgt $libro-gttitulo ltbgt -

echo $libro-gtautor ltbrgt

gt

Lo primero que llama la atencioacuten es que en apenas 10 liacuteneas de coacutedigo se ha conseguido extraer todos los datos necesarios a diferencia de SAX o DOM

La funcioacuten s implexml__load_f i le () crea un objeto con el archivo XML que pase como argumento

A partir de aquiacute puede acceder a todos los datos asiacute como acceder a las variables de los objetos

echo $biblioteca-gttema-gtlibro [0] -gttitulo echo $biblioteca-gttema-gtlibro[1]-gttitulo

Para extraer el contenido que necesita lo maacutes sencillo es crear una estrucshytura de bucles f o r e a c h para ir sacando los datos ordenados

El nombre SimpleXML es totalmente descriptivo aunque no hay que conshyfundir la palabra simple con baacutesico La prueba de su potencia estaacute en que los desarrolladores de PEAR van a utilizar SimpleXML para desarrollar su libreriacutea de SOAP

Lectura y escritura de archivos XML 261

Resumen

XML se ha convertido en un estaacutendar para el intercambio de informacioacuten en Internet Numerosas aplicaciones estaacuten construidas con alguacuten tipo de tecnologiacutea que implementa XML como XML-RPC RSS o SOAP

En este capiacutetulo ha aprendido a leer y escribir documentos de tres formas posibles La maacutes completa sin duda es DOM que permite ademaacutes de leer archivos escribir y modificarlos a nuestro antojo El problema es que pueshyde resultar algo complicado de entender al principio y quizaacute no merezca la pena en aplicaciones sencillas

En el capiacutetulo siguiente conoceraacute la verdadera aplicacioacuten praacutectica Basaacutenshydonos en SimpleXML y en DOM crearemos algunas clases para leer archishyvos de noticias o ejecutar funciones definidas en un ordenador remoto

264 Capiacutetulo 15

Introduccioacuten

Existen en el mercado muchas publicaciones que hablan sobre XML y sus tecnologiacuteas derivadas En estos libros que suelen ser de unas 1000 paacuteginas se hace un recorrido por todos los rincones de XML DTD XLST etceacutetera Si lee alguna publicacioacuten de este tipo puede quedar desencanshytado porque entre tantos conceptos no se ve una aplicacioacuten real de la tecnologiacutea

Como este libro es eminentemente praacutectico me gustariacutea que el lector aprenshydiera dos metodologiacuteas que se utilizan actualmente en la Web RSS y XML-RPC La primera describe una forma de exportar informacioacuten noticias o datos al exterior para que desde cualquier paacutegina Web puedan leerse La segunda es una forma de trabajar que permite ejecutar funciones que esshytaacuten almacenadas en un ordenador remoto

Compartir informacioacuten con RSS

RSS es un mecanismo para publicar informacioacuten sobre el contenido de un sitio Web y es muy comuacuten utilizarlo para dar las uacuteltimas noticias Esto permite introducir en su sitio Web un documento XML con noticias de otras paacuteginas

La versioacuten original de RSS la 090 fue creada por Netscape con el objetishyvo de crear portales servidores de noticias de distinta categoriacutea pero reshysultoacute algo complejo de utilizar La versioacuten 091 mucho maacutes simple la desarrolloacute la empresa UserLand Software quien lo comercializoacute como parte de sus productos basados en paacutegina Web como los Weblogs

Un tercer grupo de desabolladores independientes basaacutendose en los coshymienzos de RSS la versioacuten 090 escribioacute una nueva revisioacuten basada en RDF esta versioacuten recibe el nombre de RSS 10 Desde la aparicioacuten de la versioacuten 01 UserLand Software ha seguido desarrollando las versiones 092 093 094 y la 20

Distintos formatos

Existen 7 formatos distintos y como programador deberiacutea ser lo suficienshyte habilidoso como para manejar cualquiera de ellos Pero como el conteacute-

Aplicaciones praacutecticas de XML 265

nido lo produce la Web que desea exportar su informacioacuten tendraacute que tener en cuenta las caracteriacutesticas de cada formato

Tabla 151 versiones de RSS

Versioacuten Desarrollo Descripcioacuten Status Recomendacioacuten

090 Netscape Obsoleta No usar por la apashyricioacuten de 10

091 UserLand Simple Muy popular Sencilla y faacutecil de pero obsoleta migrar a la versioacuten por la aparicioacuten 20 de 20

092 UserLand Permite texto Obsoleto por Mejor usar la 20 093 enriquecido y la 20 094 metadatos

10 Grupo de Basado en Muy estable Usar si necesitamos desarrollo RDF y exten- especificaciones RSS-DEV sible con avanzadas

moacutedulos

20 UserLand Exter=Aacuteble corraquo EsteWe y ef Uso de caraacutecter moacutedulos Faacutecil continuo general con meta-de migrar desarrollo datos y texto enri-desde cualquier quecido versioacuten 09

Como ejemplo vamos a leer el RSS 10 de la Web del autor wwwluisy fernandanet que contiene esta informacioacuten

ltxml version=10 encoding=iso-8859-1 gt ltrdfRDF xmlnsrdf=httpwwww3org19990222 -rdf-syntax-ns xmlns=httpmynetscapecomrdfsimple09gt

ltchannelgt lttitlegtwwwluiacutesyfernandanetlttitlegt ltlinkgthttpwwwluisyfernandanetiacutendexphp

blogId=2ltlinkgt ltdescriptionxdescriptiongt

ltchannelgt ltitemgt

lttitlegtPHP 5 en la liacutenea de salidalttitlegt ltdescriptiorvgtiacuteuumladi Gutwampias dice que en 24 horas estaraacute lista la nueva versioacuten de PHP5 bull que nervios ampltbr

266 Capiacutetulo 15

ampgtPara el que no pueda esperar la Releacutease Candidate 4 estaacute en amplta href =ampquothttp snapsphpnet~andiampquotampgthttpsnapsphpnet ~andiampltaampgtampltbrampgt ampltbrampgtampltbrampgtlt descriptiongt

ltlinkgthttpwwwluisyfernandanetiacutendexphpop=View ArticleampamparticleId=41ampampblogId=2ltlinkgt ltitemgt

lt itemgt lttitlegtGalopiacuten 10lttitlegt ltdescriptiongt amplt a

href=ampquothttpwwwluisyfernandanetresserverphp blogId=2amp amp resource=DSCN0840 JPG ampquot ampgt amplt img align=ampquot rightampquot style=ampquotmargin 5pxampquot border=ampquotOampquot alt=ampquotRueda de prensaampquot src=ampquothttpwwwluisyfernandanetresserver phpblogId=2ampampresource=DSCN0 840JPGampampmode=previewampquot ampgtampltaampgt

Hoy se ha presentado en la AAVV de La Antigua en Meacuterida la versioacuten 10 de Galopiacuten una herramienta escrita en PHP por dos desarrolladores extrementildeos Tras los forcejeos con la prensa y las salidas con quite de los implicados nos quedamos con la miel en los labios deseando probar la aplicacioacuten y porqueacute no destriparla para ver como funciona el chismeampltbr ampgtEl que quiera descargarla puede hacerlo desde la Web de sinuh en amplta href=ampquothttp galopinsinuhorgampquotampgtgalopinsinuhorgampltaampgtampltbr

ampgtScltbxSiacutegpound ampltbr ampgtltdescriptiongt ltlinkgthttpwwwluisyfernandanet

indexphpop=ViewArticleampamparticleld=4 0ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtEL TIEMPO DE MERIDAlttIacutetlegt ltdescriptiongt Hace unos diacuteas empeceacute escribir alguna cosilla para averiguar

la temperatura que hay en Meacuterida Los datos los recojo de la Web del Instituto Nacional de Meteorologiacutea y los plasmo en una tabla Si quieres puedes utilizar los datos llamando a la Web amplt a href = ampquothttpwwwluisyfernandanet clase_tiempophpLOCALIDAD=MERIDAampquotampgthttp wwwluisyfernandanetclase_tiempophpLOCALIDAD=MERIDAamplt aampgtampltbr ampgtDonde pone LOCALIDAD se puede poner alguna poblacioacuten distinta como CORIA CACERES BADAJOZUNIVERSIDAD etcampltbr ampgtEl moacutedulo estaacute en fase alfa y el dibujito que aparece puede que no corresponda con la realidad pero es un avance )ampltbr ampgtEn unas semanas implementareacute el servicio en SOAP como lo hace weathercomampltbr ampgtSaludosampltbr ampgtampltbr ampgtampltbr ampgtampltbrampgt

Aplicaciones praacutecticas de XML 267

ampltbr ampgtltdescriptiongt ltlinkgthttpwwwluisyfernandanet

indexphpop=ViacuteewArticleampamparticleld=3 6ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtPHP 5 a punto de caramelolttitlegt ltdescriptiongtHace un par de diacuteas en la lista interna de

desarrolladores de PHP Andi Gutmans ha escrito que PHP5 ya estaacute horneado y le falta un poquito de chocolate para salir al mercado Estaacuten teniendo alguacuten problemilla con libreriacuteas que controlan el acceso a memoria pero se preveacute que la primera versioacuten estable salga esta semana ampltbr ampgtamplta href=ampquothttpwwwzendcomlistsphp-dev2004 07 msg00059htmlampquot ampgtNotica de Zend ampltaampgtampltbr ampgtampltbr ampgtltdescriptiongt

ltlinkgthttpwwwluisyfernandanet indexphpop=ViewArticleampamparticleld=3 3ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtOpenOffice2htm en Sourceforgelttitlegt ltdescriptiongt Acaban de aceptar el Proyecto OpenOffice2htm

en sourceforge ellos sabraacuten lo que hacen Lo que pasa es que tengo un pequentildeo problema entre tanto menuacute de administracioacuten de ficheros documentos etc me pierdo y por ahora no he podido subir ninguacuten fichero de la clase Espero aclararme estos diacuteas y tener listo la primera Releacutease en amplta href=ampquothttpwwwluisyfernandanet wwwsourceforgecomampquotampgtwwwsourceforgecomamplt aampgtampltbr ampgtampltbrampgtampltbr ampgtltdescriptiongt

ltlinkgthttpwwwluisyfernandanet indexphpop=ViewArticleampamparticleld=17ampampblogId=2ltlinkgt ltitemgt ltrdfRDFgt

El archivo anterior muestra las uacuteltimas noticias de la Web www lu i sy fernadanet sobre PHP y proyectos en los que el autor estaacute involucrado

Si se fija no es maacutes que un archivo XML con un formato determinado

Puede verlo en la figura 151

Tiene dos partes diferenciadas

bull Una parte de descripcioacuten del documento entre las etiquetas ltchan-n e l gt En esta zona puede encontrar el tiacutetulo de Web donde estaacuten las noticias la URL del archivo RSS y una descripcioacuten de la temaacutetica que aborda

bull Otra zona entre los nodos lt i t emgt que contiene todas las noticias que quiere exportar

Leer un archivo RSS

En el capiacutetulo anterior vimos coacutemo parsear un archivo XML creado por nosotros mismos Esta vez tenemos que extraer el contenido que nos inshyteresa de un archivo con un formato determinado Vamos a crear un peshyquentildeo objeto que sea capaz de insertar en nuestra Web las noticias de la paacutegina wwwluisyfernandanet Por supuesto vamos a utilizar SimpleXML por ser una de las herramientas estrella de PHP 5

ltphp class SimpleRSS

priacutevate $RSS function construct($fichero)

$this-gtRSS = simplexml_load_file($fichero)

public function parsea_item() foreach ($this-gtRSS-gtitem as $item)

$this-gtparsea_titulo($item) $this-gtparsea_descripcion($item) $this-gtparsea_enlace($item)

private function parsea_titulo($item)

Aplicaciones praacutecticas de XML 269

echo $item-gttitle bull ltbrgt echo lthrgt

priacutevate function parsea_descripcion ($item)

echo $item-gtdescription ltbrgt

priacutevate function prsea_enlace($item)

echo $item-gtlink bull ltbrgt

public function paiacutesea_cabecera()

ampc^o Titilo- laquo St^va-^SSS-gtet^trade^l-gttltLe -JaxV- echo Web $this-gtRSS-gtchannel-gtlink ltbrgt echo lthrgt

$RSS = new SimpleRSS(httpwwwluisyfernandanet rssphpcategoryId = 3ampblogId=2 ) $RSS-gtparsea_cabecera () $RSS-gtparsea_item() gt

Si ejecuta el programa tendraacute como resultado las uacuteltimas noticias sobre PHP del portal wwwluisyfernandanet separadas por liacuteneas horizontashyles El meacutetodo puacuteblico p a r s e a _ i t e m () es el encargado de extraer notishycia a noticia y mandarlas al navegador Este meacutetodo hace 3 llamadas a 3 meacutetodos distintos que se encargan de recuperar el tiacutetulo el enlace a la noticia y la descripcioacuten Hemos separado los meacutetodos para que cada lector personalice la forma de visualizar los distintos datos Mi forma particular puede verla en la fishygura 152 Por ejemplo el tiacutetulo podriacutea mostrarlo en azul y el texto en gris todo metido en una tabla-

Escribir archivos RSS

Los archivos XML y en particular los archivos RSS pueden generarse de la misma forma que creamos un fichero de texto antildeadiendo etiquetas con cierto criterio a un archivo de texto pero la opcioacuten maacutes correcta es utilizar DOM para generar nuestros propios documentos de noticias Como ya sabe la extensioacuten DOM permite antildeadir borrar y modificar eleshymentos a lo largo de un documento en cualquier orden

Para este cometido tenemos la siguiente clase que nos va a generar docushymentos RSS a partir de cualquier fuente de datos

ltphp class GeneraRSS

priacutevate documento private $raiz priacutevate $channel private $titulo private $enlace private descripcioacuten private $item function construct() $this-gtdocumento = new domdocument(1bull0 ) $this-gtinicio ( )

private function inicio() $this-gtraiz = $this-gtdocumento-gtcreateElement(rdfRDF ) $this-gtraiz-gtsetAttribute(xmlnsrdfhttpwwww3org1999 0222-rdf-syntax-ns) $this-gtraiz-gtsetAttribute(xmlnshttppurlorgrss10) $this-gtraiz = $this-gtdocumento-gtappendChild($this-gtraiz)

Aplicaciones praacutecticas de XML 271

pub l i c funct ion c a n a l ( $ t i t u l o $ e n l a c e $ d e s c r i p c i o n $ s o b r e )

$this-gtchannel = $this-gtdocumento-gtcreateacuteElement(channel) $this-gtchannel = $ th i s -gtra iz -gtappendChi ld ($ th i s -gtchanne l ) $ th i s -gt t i tu lo=$th i s -gtdocumento-gtcrea teElement ( t i t l e ) $ th i s -gt tex to t i t u lo=$ th i s -gtdocumen to -gtc rea t eTex tNode($ t i tu lo ) $ t h i s - gt t i t u l o - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o t i t u l o ) $ t h i s - gt c h a n n e l - gt a p p e n d C h i l d ( $ t h i s - gt t i t u l o ) $ t h i s - gt e n l a c e = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l s m e n t ( l i n k ) $ th i s -gt tex toen lace=$th i s -gtdocumento-gtcrea teTextNode($en lace) $ t h i s - gt e n l a c e - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o e n l a c e ) $ th i s -gtchanne l -gtappendChi ld ($ th i s -gten lace ) $ t h i s - gt d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( d e s c r i p t i o n ) $ t h i s - gt t e x t o d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e T e x t N o d e ( $ d e s c r i p c i o n ) $ t h i s - gt d e s c r i p c i o n - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o d e s c r i p c i o n $ th i s -gtchanne l -gtappendCh i ld ($ th i s -gtdesc r ipc ion )

pub l i c funct ion i t em_nuevo($ t i tu lo $en lace $descr ipcion)

$this-gti tem = $this-gtdocumento-gtcreateElltment( i tem) $ this-gti tem = $ th i s -gtra iz -gtappendChi ld ($ th i s -gt i t em) $ t h i s - gt t i t u l o = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( t i t l e ) $ th i s -gt t ex to t i t u lo=$ th i s -gtdocumen to -gtc rea t eTex tNode ($ t i t u lo ) $ t h i s - gt t i t u l o - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o t i t u l o )

$ t h i s - gt i t e m - gt a p p e n d C h i l d ( $ t h i s - gt t i t u l o ) $ t h i s - gt e n l a c e = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( l i n k ) $ th i s -gt tex toen lace=$th i s -gtdocumento-gtcrea teTextNode($en lace) $ t h i s - gt e n l a c e - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o e n l a c e ) $ t h i s - gt i t e m - gt a p p e n d c h i l d ( $ t h i s - gt e n l a c e ) $ t h i s - gt d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( d e s c r i p t i o n ) $ t h i s - gt t e x t o d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e T e x t N o d e ( $ d e s c r i p c i o n ) $ t h i s - gt d e s c r i p c i o n - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o d e s c r i p c i o n ) $ t h i s - gt i t e m - gt a p p e n d C h i l d ( $ t h i s - gt d e s c r i p c i oacute n ) $ th i s -gt i t ems [ ]=$ th i s -gt i t em

public function grabar($fichero) $this-gtdocumento-gtsave($fichero)

^documento = new GeneraRSS () ^documento-gtcanal (wwwluisyfernandanet httpwwwluisy fernandanet La Web del auto) $docimeito-gtitev1_YYievo VMaiwial Imprescindible de PHP 5 http- v iwwluisyfernandanet Ya a la v e n t a )

272 Capiacutetulo 15

$documento-gtitem_nuevo(Nueva releacutease de PHP 5http wwwiuisyfernandanetLa nueva releacutease corrige algunos fallos) Sdocumento-gtgrabar(miRSSxml) gt

La clase anterior se puede guardar en un archivo independiente y utilizar cuando sea necesario en el transcurso de un proyecto

Aunque no implementa todas las especificaciones de RSS 10 puede utilishyzarse para generar noticias de nuestra base de datos

Nota

Si desea modificar ia ciase para que contemple todas las opciones de Ja especificacioacuten RSS 10 puede visitar ia Web httpllpurtorgl rss10

En el capiacutetulo anterior vimos coacutemo se puede generar un archivo XML con una sucesioacuten de llamadas a meacutetodos Esta vez hemos encapsulado todas las llamadas en varios meacutetodos que se encargan de generar la parte de descripcioacuten del RSS y por otro lado las noticias

El meacutetodo c r e a t e E l e m e n t () se encarga de crear nuevos nodos para desshypueacutes encadenarlos c o n a p p e n d C h i l d () a los nodos padre Para crear un nodo de texto sin embargo tenemos que utilizar el meacutetodo c r e a t e T e x t -Node () una vez creado el nodo de texto tenemos que asociarlo a un nodo-elemento (una etiqueta)

El uacuteltimo paso es hacer una llamada al meacutetodo s a v e () con el nombre del fichero como paraacutemetro para guardar el archivo RSS

Servicios Web XML-RPC

El trabajo como programador puede llevarle a desarrollar aplicaciones para distintos Sistemas Operativos y en distintos lenguajes de prograshymacioacuten

Si en alguacuten momento necesita comunicar dos programas que estaacuten funshycionando en maacutequinas distintas (un servidor Windows y otro gnuLinux) y escritos con lenguajes diferentes puede que XML-RPC sea la solucioacuten perfecta

El mecanismo permite que el ordenador cliente pueda acceder a los meacutetoshydos del ordenador servidor y ejecutar rutinas almacenadas remotamente

Aplicaciones praacutecticas de XML 273

Este apartado muestra alguacuten ejemplo de coacutemo implementar y explotar un servicio Web con la libreriacutea de clase IXR creada por Simoacuten Willison bajo el auspicio de Open Source

Una llamada XML-RPC consiste en dos partes una pregunta y una resshypuesta

Cada una de las partes es un archivo XML que contiene los paraacutemetros solicitados al servidor o los datos devueltos

Una pregunta al servidor puede ser como la que sigue

ltmethodCalIgt ltmethodNamegtconteritgetNotiacuteciasltmethodNamegt ltparamsgt

ltparamgt ltvaluexintgt23ltiacutent gtltvaluegt

ltparamgt ltparams gt

ltmethodCallgt

Como puede ver es un archivo XML con una definicioacuten determinada La etiqueta ltmethodNamegt contiene el nombre del meacutetodo que debe llamarse en el servidor y ltparamgt contiene un paraacutemetro que se le pasaraacute al meacutetoshydo de la llamada

El documento anterior seraacute transmitido viacutea HTTP mediante POST al sershyvidor de XML-RPC que parsearaacute el documento ejecutaraacute la funcioacuten y devolveraacute un documento similar con los datos de la respuesta

Clase IXR

IXR es un conjunto de clases que implementa un servidor y un cliente de XML-RPC

Nota

Puede encontrar la libreriacutea en la Web httpscriptsiricutiocom xmlrpc o en la paacutegina del libro en httpunuzunnaiamulti-mediacom

Lo mejor de la programacioacuten orientada a objetos es que no necesita saber coacutemo funcionan las clases que utilice soacutelo conocer el uso correcto de los meacutetodos Asiacute puede utilizar la clase IXR de la manera que vamos a ver sin conocer siquiera el formato de los archivos XML-RPC

274 Capiacutetulo 15

Cliente XML-RPC

Los servicios XML-RPC tienen una direccioacuten Web con una paacutegina Web escrita en PHP Si escribe la direccioacuten completa en el navegador se proshyduciraacute un error porque la Web esperaraacute que mande mediante POST un archivo XML Para utilizar sus servicios Web o los servicios Web de alshyguna empresa como UserLand tiene que utilizar un cliente XML-RPC escrito en este caso en PHP 5 En este caso vamos a utilizar la clase IXR__Client de la libreriacutea IXR El ejemplo muestra coacutemo utilizar el cliente en varios pasos

bull Crear un objeto cliente con la URL pasada como paraacutemetro

bull Usar el meacutetodo q u e r y () para hacer la consulta al servicio Web

bull Extrae el resultado con el meacutetodo g e t R e s p o n s e ()

Lo primero que vamos a hacer es implementar un pequentildeo objeto para recuperar la fecha de un servidor remoto

ltphp require_once(IXR_Libraryincphp) class XMLRPCFechacliente

private $cliente function construct($url$debug=false) $this-gtcliente= new IXR__Client ($url) $this-gtcliacuteente-gtdebug=$debug

function getFecha($argumentol) if ($this-gtcliente-gtquery(fechagetFecha$argumentol)) trigger_error($this-gtcliente-gtgetErrorCode () $this-gtcliente-gtgetErrorMessage()) return false

return $this-gtcliente-gtgetResponse ()

gt

La clase X M L R P C F e c h a c l i e n t e implementa dos meacutetodos El construcshytor crea un objeto cliente IXR que recibe el servidor de servicios Web El meacutetodo g e t F e c h a () tramita la peticioacuten de la fecha con el servidor y obshytiene una respuesta que devuelve a la paacutegina Web Si todo va bien el sershyvidor enviaraacute la fecha del lugar donde esteacute

La llamada a q u e r y () tiene como paraacutemetro primero el nombre del meacuteshytodo que debe ejecutar el servidor y como segundo paraacutemetro un argu-

Aplicaciones praacutecticas de XML 275

mentoacute que puede pasarse La Web que quiera mostrar esta informacioacuten debe crear el objeto anterior maacutes o menos como se muestra en el siguiente ejemplo

ltphp require_once(XMLRPCFechaclientephp) $servidor=httpwwwluisyfernandanetFechaphp $fechaRemota= new XMLRPCFechacliente($servidor) echo $fechaRemota-gtgetFecha(Hoy) gt

Si evaluacutea el coacutedigo en tan soacutelo 4 liacuteneas puede recibir cualquier tipo de informacioacuten que el servidor tenga Para ello debe crear una variable que contenga el nombre del servidor y la paacutegina PHP que contiene el prograshyma de respuesta La instanciacioacuten del objeto X M L R P C F e c h a c l i e n t e y la llamada al meacutetodo g e t F e c h a () es suficiente para desencadenar la coshynexioacuten con el servidor

Servidor XML-RPC

En el apartado anterior ha visto que puede utilizar servicios Web ofrecishydos por otras empresas para averiguar la hora de un Paiacutes remoto el camshybio de moneda el tiempo o incluso el cataacutelogo de libros de una conocida tienda on-line Pero lo realmente interesante es poder crear sus propios servicios Web

La clase IXR_Server hace la mayoriacutea del trabajo por usted que puede emplear el tiempo en inventar nuevos servicios Web

Hemos creado una clase que implementa el servicio g e t F e c h a ( ) que el objeto cliente utiliza

ltphp require_once(IXR_Libraryincphp) class XMLRPCFechaservidor extends IXR_Server

function construct()

$this-gtIXR_Server(array(fechagetFecha =gt thisgetFecha)) function getFecha($argumentol)

if ($argumentol==Hoy) $fecha = La fecha remota es date(d-m-Y)

else

$fecha = Especifique un dia

2 7 6 Capiacutetulo 15

re turn $fecha

gt

La clave para entender el funcionamiento del servidor estaacute en el construcshytor Aquiacute se crea un array con el nombre de los meacutetodos que se pueden utilizar desde fuera

El primer valor f e c h a g e t F e c h a es el nombre que el cliente debe emshyplear para recuperar la Fecha del Servidor y el segundo valor t h i s g e t Fecha es el meacutetodo perteneciente al servidor que se ejecutaraacute cuando reciba una pregunta a esa funcioacuten

La figura 153 muestra el dato que obtiene el cliente

La definicioacuten del meacutetodo que enviacutea la fecha se hace como ya estamos acosshytumbrados

Lo que hemos visto es soacutelo la definicioacuten de la clase pero necesitamos una paacutegina Web de apoyo que instancie el objeto y lo ejecute Puede ser tan sencillo como

ltphp require_once(XMLRPCFechaservidorphp) $servidor= new XMLRPCFechaservidor() gt

Aplicaciones praacutecticas de XML 277

Usos de XML-RPC

Los ejemplos que hemos visto no son especialmente excitantes pero dan una idea de lo sencillo que es exportar cualquier tipo de informacioacuten La verdadera potencia de los servicios Web es que permiten disfrutar de nueshyvas funcionalidades de las que no disponemos Podriacuteamos crear un servishycio Web que permitiera a usuarios de PHP 4 utilizar nuestro objeto de SimpleXML pero esto lo dejo en manos del lector

Resumen

XML se ha convertido en los uacuteltimos antildeos en un estaacutendar libre para el inshytercambio de informacioacuten Incluso Microsoft poco amiga de los archivos abiertos estaacute implementando servicios en XML con su plataforma NET

Despueacutes de leer este capiacutetulo podraacute crear elegantes paacuteginas que contenshygan noticias relevantes sobre cualquier tema y exportarlas a otras paacuteginas amigas gracias a la tecnologiacutea RSS

En cuanto a la creacioacuten de servicios Web existe una controversia entre dos desarrollos principales XML-RPC y SOAP de Microsoft SOAP (Simshyple Object Access Protocol) es una implementacioacuten muy extensa de Microshysoft para la creacioacuten de servicios Web Pese a que su definicioacuten aboga por la simpleza (Protocolo Simple) la paradoja es que es mucho maacutes complishycada de utilizar que XML-RPC y por eso se escapa de los objetivos de este libro

Una de las nuevas caracteriacutesticas de PHP 5 es la inclusioacuten de una extenshysioacuten para la generacioacuten de servidores y clientes SOAP pero todaviacutea estaacute en fase experimental

El futuro cercano puede estar en SOAP asiacute que recomiendo al lector visishytar algunas paacuteginas Web sobre el tema para comenzar a entender su funshycionamiento

280 Capiacutetulo 16

Introduccioacuten

La construccioacuten de un sitio Web no soacutelo debe contar con textos bases de datos y funciones escritas en PHP para manejar los datos Existe un gran abanico de posibilidades que pueden dotar a la paacutegina de contenido multishymedia (imaacutegenes v sonidos) y que ademaacutes pueden ser procesados de alshyguna forma por PHP

Entre las funciones maacutes baacutesicas de interactuacioacuten con las imaacutegenes PHP puede realizar graacuteficos de barras para mostrar resultados estadiacutesticos antildeadir una marca de agua a todas nuestras fotografiacuteas o mostrar una reacuteshyplica de las imaacutegenes en un formato maacutes reducido para poder seleccionar entre un conjunto de ellas

La mayoriacutea de los ejemplos utilizan la libreriacutea graacutefica GD para PHP que puede instalarse faacutecilmente en los tres Sistemas Operativos maacutes comunes (gnuLinux MacOSX y Windows)

Graacuteficos HTML

Antes de entrar de lleno en las maravillas que ofrece la libreriacutea graacutefica GD vamos a realizar un pequentildeo ejemplo para aprovechar las posibilidades del lenguaje HTML para la creacioacuten de estadiacutesticas graacuteficas Esta posibilishydad nos permite realizar estudios graacuteficos baacutesicos sin tener que instalar ninguacuten paquete adicional a PHP

Puede decantarse por este meacutetodo o por utilizar la libreriacutea dependiendo de la complejidad de su proyecto

Vamos a crear como ejemplo un sistema de votacioacuten electroacutenico que cuente los votos de cada participante y los almacene en una base de datos Vashymos a utilizar el gestor SQLite visto en el capiacutetulo 11 Para tal fin hemos creado una clase de conexioacuten a SQLite muy parecida a la clase de conexioacuten de MySQL

ltphp

class Servidor_Base_Datos

priacutevate $base_datos priacutevate $descriacuteptor priacutevate ^resultado function construct($base_datos)

Generacioacuten de graacuteficos con PHP 5 281

$this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtpass = $pass $this-gtbase_datos = $base_datos $this-gtconectar_base_datos()

priacutevate function conectar_base_datos( )

$thiacutes-gtdescriptor = sqlite_open($this-gtbase_datos)

i public function consulta($consulta)

$this-gtresultado = sqlite_query($consulta $this-

gtdescriptor) public function extraer__registro ()

if ($fila = sqlite_fetch_array($this-

gtresultadoSQLITE_ASSOC)) return $fila

else return false

gt

Los meacutetodos son praacutecticamente iguales y la forma de utilizar el objeto es exactamente igual que en los ejemplos del capiacutetulo 12

Los datos que vamos a manejar en la encuesta son parte de una pequentildea tabla que almacenaraacute el nombre del Lenguaje de Programacioacuten que prefeshyrimos y el nuacutemero de votos que le hemos dado Podemos inicializar la base de datos con el siguiente script

ltphp requirejonee(clase_SQLitephp) $base_datos = new Servidor_Base_Datos(votacionesdb) $base_datos-gtconsulta(creacuteate table lenguaje (id_lenguaje INT PRIMARY KEY lenguaje CHAR(255) votos INT))

$base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees ( PHP 0) ) $base_datos-gtcoacutensulta(insert into lenguaj e (lenguaj evotos) valuacutees (JSPeuro)) $base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees (ASP 0) )

282 Capiacutetulo 16

$base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees (COLD FUSIOacuteN0)) $base_datos-gtconsulta(select from lenguaje)

while ($fila = $base_datos-gtextraer_registro ()) echo $fila [lenguaje] $fila[votos] ltbrgt

gt

Todo deberiacutea serle familiar Lo que hacemos es crear una tabla nueva en la base de datos e insertar los lenguajes objetivo de la encuesta Por uacuteltishymo hacemos una comprobacioacuten para ver si los datos estaacuten almacenados en la base de datos Lo siguiente que vamos a ver es una Web con un formulario para elegir el lenguaje que maacutes nos agrada En la zona inferior de la paacutegina tenemos un contador que nos indica el nuacutemero de votos

ltphp

Primero comprobamos si tenemos un voto

$base_datos = new Servidor_Base_Datos(votaciones2db)

Si hemos votado sumamos el valor al nuacutemero de votos almacenado

if (isset($_POST[voto] ) )

$voto = $_POST[voto] $base_datos-gtconsulta(select votos from lenguaje where id_lenguaj e=$voto) $numero_votos = $base_datos-gtextraer_registro() $numero_votos = $numero_votos[votos] $numero_votos + + $base_datos-gtconsulta(update lenguaje set votos= $numero_votos where id_lenguaje = $voto)

gt lthtmlgt ltbodygt iquestQueacute lenguaje de programacioacuten prefieres

Formulario que permite votar

ltform action=votophp method=post gt ltselect name=votogt ltphp $base_datos-gtconsulta (select from lenguaje) while ($fila = $base_datos-gtextraer_registro () )

$id_lenguaje = $fila[id_lenguaje] $lenguaje = $fila [lenguaje]

Generacioacuten de graacuteficos con PHP 5 283

echo ltoption value=$id_lenguajegt$lenguajeltoptiongt

gt ltselectgt ltinput type=submit name=Enviar value=Enviar gt ltformgt lttablegt ltphp $base_datos-gtconsulta(select from lenguaje) while ($fila = $base_datos-gtextraer_registro () )

$lenguaje = $fila [lenguaje] $votos = $fila [ votos] echo lt t rx tdgt$ lengua j e lt t d x t d gt $votos vo toslt tdgtlt

t r gt

gt lt t ab l egt ltbodygt lthtmlgt

Como puede ver es un mecanismo muy sencillo de entender La parte principal es el formulario que permite elegir entre los 4 lenguajes de script Si enviamos un voto la misma paacutegina recibiraacute el dato y actualizaraacute la base de datos mostrando posteriormente los votos que tienen los lenguajes En la figura 161 puede ver el resultado

284 Capitulo 16

Graacuteficos de barras

Despueacutes de todo este coacutedigo estaraacute preguntaacutendose por las imaacutegenes geshyneradas automaacuteticamente Todaviacutea no hemos hecho nada de eso pero en el coacutedigo siguiente tiene la clave de este apartado Baacutesicamente jugamos con 4 imaacutegenes r o j o png v e r d e p n g a z u l png y a m a r i l l o png Cada imagen tiene un tamantildeo de 1 piacutexel de ancho y alto El truco estaacute en hacer un caacutelculo porcentuado de los valores de votos con respecto al que mayor votos tiene

De ahiacute sacamos el ancho de la imagen Una vez encontrado este ancho se le pasa a la propiedad w i d t h de la etiqueta lt imggt y obtenemos un graacutefishyco con imaacutegenes de distintos anchos es decir obtenemos un graacutefico de barras estadiacutestico

El coacutedigo puede ser como el siguiente

ltphp $imagenes = array(rojopngazulpngverdepngamarillopng) $base_datos-gtconsulta(select from lenguaje) while ($fila = $base_datos-gtextraer_registro() )

$id_lenguaje = $fila [ id_lenguaje ] $lenguaje = $fila [lenguaje] $votos = $fila[votos] $ancho = dame_ancho($votos$id_lenguaje) $imagen = $ imagenes[$ id_ lengua je -1] echo lt t r x t d gt $ l e n g u a j e - $votos v o t o s lt t d x t d x i m g src=$imagen width=$ancho h e i g h t = 2 0 gt lt t d x t r gt

function dame_ancho($votos)

$base_datos2 = new Servidor_Base_Datos(votaciones2db) $base_datos2-gtconsulta(select max(votos) as maacuteximo from lenguaje) $numero_votos = $base_datos2-gtextraer_registro() $maximo_votos = $numero_votos[maacuteximo] return (intval($votos)300)intval($maximo_votos)

gt lttablegt

Antes generaacutebamos una tabla con los lenguajes y el nuacutemero de votos Ahora generamos los lenguajes y calculamos con la funcioacuten dame_an-cho () el porcentaje con respecto al mayor valor de cada uno de los votos de los lenguajes La figura 162 muestra los graacuteficos de barras de la votacioacuten electroacutenica

Libreriacutea GD

La libreriacutea graacutefica GD estaacute escrita en lenguaje C y permite crear y manipushylar graacuteficos faacutecilmente Permite importar y exportar graacuteficos de distinto tipo (GIF JPG y PNG) La filosofiacutea de los archivos GIF y PNG es casi la misma Estos dos archivos guardan en memoria el conjunto completo de piacutexeles con su color concreto y comprimen el resultado para que el archishyvo final no sea muy pesado Los archivos JPG tambieacuten estaacuten comprimishydos pero se basan en algoritmos complejos que permiten un mayor rendimiento y la hacen muy propicia para usarse con fotografiacuteas

Tipos MIME

El estaacutendar MIME se concibioacute originariamente para identificar los difeshyrentes contenidos que podemos enviar por correo electroacutenico Actualmente se utiliza para describir el tipo de archivo que enviamos a traveacutes de Intershynet Es importante conocer los tipos MIME para trabajar con las libreriacuteas GD

En general antes de recibir la respuesta del servidor eacuteste debe enviarnos una cabecera anunciando el tipo de contenido que vamos a recibir usando una cabecera especial C o n t e n t - T y p e PHP por defecto enviacutea el tipo

286 Capiacutetulo 16

MIME t e x t h t m l (documento HTML) Cuando utilice la libreriacutea GD necesitaraacute enviar una cabecera con el tipo de la imagen

ltphp header(Content-Type imagepng) gt

Tabla 161 Tipos MIME

Formato de imagen MIMEacute

JPG iexclmagejpeg

PNG imagepng

GIF imagegif

BMP imagebmp

SVG imagexml+svg

Mostrar una imagen en pantalla

Normalmente utilizamos la etiqueta ltimggt de HTML para mostrar una imagen en un lugar determinado de nuestra paacutegina Web La propiedad s r c debe indicar una imagen determinada con formato coshynocido La liacutenea siguiente mostraraacute en pantalla el logotipo de php

ltimg src=phppnggt

La libreriacutea graacutefica GD tambieacuten permite enviar imaacutegenes con el uso de unas funciones determinadas Como ejemplo vamos a ver coacutemo mostrar el misshymo logotipo esta vez utilizando GD

ltphp $imagen = imagecreatefrompng(phppng) header(Content-Type imagepng) imagepng($imagen) gt

Advertencia

La etiquete ltimggt de nuestra paacutegina Web debe apuntar ahora al

archivo PHP que genera la imagen ltimg s r c = imagen php gt

La funcioacuten i m a g e c r e a t e f rompng () recupera una imagen de un archishyvo y crea un descriptor en la variable $ imagen Para mostrar la imagen

Generacioacuten de graacuteficos con PHP 5 287

tiene que enviar la cabecera del tipo de archivo graacutefico que quiere mosshytrar y despueacutes enviar la imagen con imagepng ()

A simple vista parece demasiado esfuerzo para algo que resuelve perfecshytamente la etiqueta ltimggt pero examine el siguiente coacutedigo

ltphp

$imagenes = array(phppngzendpngparispng) Semilla aleatoria srand( (double)microtime 01000000) $aleatorio = rand(02) $fichero = $imagenes[$aleatorio] $imagen = imagecreatef rompng ($f ichero) header(Content-Type imagepng) imagepng($imagen) gt

El array $ i m aacute g e n e s contiene varios archivos graacuteficos en PNG Generashymos un nuacutemero aleatorio y recuperamos la imagen que ocupa la posicioacuten del nuacutemero

Los siguientes pasos son exactamente iguales a los vistos anteriormente El script muestra una imagen distinta cada vez que lo ejecutamos y puede servir para crear una Web con distintos banners aleatorios Puede ver el resultado en la figura 163

288 Capiacutetulo 16

Crear imaacutegenes en miniatura

Si su paacutegina Web permite enviar fotografiacuteas quizaacute necesite mostrar un gran nuacutemero de ellas en una sola paacutegina HTML permite poner un ancho determinado a la imagen aunque el tamantildeo permaneceraacute invariable Lo ideal es crear dos versiones de cada fotografiacutea Una en miniatura con poco peso en bites y otra la original que puede ser mostrada cuando se haga clic en la imagen pequentildea

Gracias a la libreriacutea GD podraacute modificar el tamantildeo de las fotografiacuteas que quiera Vamos a crear una clase para generar fotografiacuteas con la mitad de tamantildeo

ltphp class imagen

priacutevate $archivo priacutevate $ imagen priacutevate $dimensiones function construct($archivo)

$this-gtarchivo = $archivo $this-gtimagen = imagecreatefromjpeg($archivo) $this-gtdimensiones = getimagesize ($archivo)

i

public function imagen_original()

header(Content-Type imagejpeg) imagejpeg$this-gtimagen)

public function imagen_miniacuteatura()

$dimensionx = $thiacutes-gtdimensiones[0] 2 $dimensiony = $this-gtdimensiones[1] 2 $this-gtminiatura = imagecreatetruecolor($dimensionx $dimensiony) imagecopyresampled($this-gtminiatura $this-gtimagen 0 0 0 0 $dimensionx $dimensiony $this-gtdimensiones[0] $this-gtdimensiones[1])header (Content-Type imagejpeg) imagejpeg($tnis-gtminiatura)

$fotografia = new imagen($_GET[fotografiacutea])

if ($_GET[modo]==original)

$fotografia-gtimagen_original()

Generacioacuten de graacuteficos con PHP 5 289

else $fotografia-gtimagen_miniatura()

gt

La clase estaacute especializada en construir imaacutegenes con la mitad de tamantildeo Para que funcione tiene que hacer una l lamada a la url c l a s e _ imagen php pasando como paraacutemetros GET el nombre de la fotografiacutea y el modo (tamantildeo original o miniatura)

El constructor de la clase rescata el archivo graacutefico y averigua las dimenshysiones X e Y con la funcioacuten g e t i m a g e s i z e ()

El meacutetodo i m a g e n _ o r i g i n a l () funciona exactamente igual que el ejemshyplo anterior El meacutetodo i m a g e n _ m i n u a t u r a () divide entre 2 las dimenshysiones capturadas de la imagen y crea un entorno de trabajo con esas dimensiones con la funcioacuten i m a g e c r e a t e t r u e c o l o r ( ) En este momenshyto la variable $ m i n i a t u r a del objeto tiene un espacio de memoria asigshynado para almacenar un graacutefico pero estaacute vaciacuteo Lo que hacen las liacuteneas siguientes es redimensionar y copiar la imagen original a nuestro entorno de trabajo La funcioacuten i m a g e c o p y r e s a m p l e d () copia la imagen guarshydada en el segundo paraacutemetro en el espacio de trabajo del primer paraacuteshymetro

Los argumentos 3 y 4 son las coordenadas X e Y donde empezaraacute a pegarshyse la imagen copiada y el 5 y 6 las coordenadas desde las que se empezaraacute a copiar la imagen original Los siguientes paraacutemetros son el ancho y alto de las imaacutegenes destino y origen

Una vez copiada la imagen al espacio de trabajo ya podemos mostrarla enviando la cabecera y la imagen con la funcioacuten image j pg ( )

Vamos a crear una Web que haga uso de esta clase

lthtmlgt ltbodygt ltform action=imagenphp method=POST enctype=multipart form-datagt Elige un archivo de imagen jpg ltinput type=file name=ficherogt ltinput type=submit name=Enviar value=Enviargt ltformgt ltphp if (isset($_FILES[fichero] ) )

echo Imagen Originalltbrgt $fotografia = $_FILES[fichero][tmp_name] copy($fotografia$_FILES[fichero] [ntildeame]) $foto_copia = $_FILES[fichero] [ntildeame] ampmodo= original

290 Capiacutetulo 16

$url = clase_imagenphpfotografia=$foto_copia echo ltimg src=$urlgt echo Imagen Miniaturaltbrgt $foto_copia = $_FILES[fichero ] [ntildeame] ampmodo= miniatura $url = clase_imagenphpfotografia=$foto_copia echo ltimg src=$urlgt

gt ltbodygt lthtmlgt

La paacutegina Web muestra un formulario que nos da la posibilidad de enviar al servidor una fotografiacutea de nuestro ordenador

Si le damos a enviar la paacutegina nos mostraraacute la fotografiacutea en su versioacuten original y en su versioacuten reducida como puede comprobar en la figura 164

Generar una marca de agua

Otro problema comuacuten sencillo de resolver es la creacioacuten de marcas de agua sobre las fotografiacuteas que ofrecemos en nuestra Web La marca de agua puede ser un graacutefico o un texto que insertamos encima de la fotografiacutea original

Generacioacuten de graacuteficos con PHP 5 291

Una forma sencilla de implementar marcas de agua es antildeadiendo un meacuteshytodo nuevo a la clase

priacutevate function marca_agua()

$this-gtmarca_agua = imagecreatefrompngphppng) $dimensiones = getimagesize(phppng) $posicionx = $this-gtdimensiones [0] - $dimensiones [0] $posiciony = $this-gtdimensiones [1] - $dimensiones [1] imagecopy($this-gtimagen $this-gtmarca_agua $posicionx $posiciony 0 0 $dimensiones [0] $dimensiones[1] )

Podemos llamar al meacutetodo desde el constructor para que la imagen guarshyde la informacioacuten de la fotografiacutea grabada e inserte la marca en alguna parte de la misma Tambieacuten podemos generar un texto como marca de agua

Vamos a antildeadir un nuevo meacutetodo a la clase para poder marcar las fotoshygrafiacuteas

priacutevate function marca_texto()

$color = imagecolorallocate($this-gtiraagen 25500) iacutemagestriacuteng($thiacutes-gtimagen 4 0 0 Hecho con PHP5

$color)

La figura 165 muestra la inclusioacuten de una marca de agua graacutefica y otra marca de agua de texto

292 Capiacutetulo 16

La funcioacuten i m a g e a l l oacute c a t e () crea un color con los componentes RGB como paraacutemetros La funcioacuten devuelve un nuacutemero que identifica al color creado en la imagen La funcioacuten i m a g e s t r i n g () imprime un texto de color determinado en la imagen El segundo paraacutemetro es el tipo de fuenshyte que queremos introducir

Graacuteficos estadiacutesticos profesionales con JpGraph

JpGraph es una libreriacutea escrita en PHP que permite crear todo tipo de graacuteshyficos estadiacutesticos en dos y tres dimensiones Hace uso de la libreriacutea graacutefica GD en su versioacuten 2 Se puede descargar de la paacutegina wwwjpgraphorg

JpGraph tiene dos licencias de uso Una gratuita para proyectos no coshymerciales y con caraacutecter educativo y otra de caraacutecter comercial de pago Le recomiendo leer ambas licencias para comprobar que puede utilizarshylas

Para instalar la libreriacutea tiene que copiar el directorio con las clases en la ruta donde guarde su aplicacioacuten o en la ruta de buacutesqueda de PHP 5

Graacuteficos de barras

El ejemplo maacutes sencillo es la creacioacuten de un graacutefico con varios valores en el que podemos ver todos los valores interconectados entre siacute por unas liacuteneas

ltphp require_once (jpgraphjpgraphphp) require_once (jpgraph jpgraph_linephp) $datosy = array(11O81251913157) Creamos el graacutefico $grafico = new Graph(350250) $grafico-gtSetScale (textlin) Creamos una nueva linea de puntos $puntos =new LinePlot($datosy) $puntos-gtSetColor(blue) Antildeadimos los puntos al graacutefico $grafico-gtAdd($puntos) Se muestra el graacutefico $grafico-gtStroke ()

bull gt

Suponiendo que la libreriacutea esteacute guardada en la carpeta j p g r a p h haceshymos u n r e q u i r e _ o n c e () de la clase principal j p g r a p h php y de la clase que utilizaremos para graacuteficos de liacutenea j p g r a p h _ l i n e php La variable $ d a t o s y guarda diez valores que pueden identificar el nuacutemero de visishytas a nuestra Web o el nuacutemero de ventas por meses de un artiacuteculo Para crear un graacutefico tiene que crear el objeto Graph con el ancho y alto que quiere que tenga en la Web Lo siguiente es configurar la escala en la que apareceraacute el graacutefico Lo mejor es echar un vistazo al manual para eleshygir el que maacutes le convenga en cada momento

Seguidamente cree un conjunto de puntos con el meacutetodo L i n e p l o t () con los valores del array $ d a t o s y Puede elegir tambieacuten el color de la liacuteshynea resultado con el meacutetodo S e t C o l o r ()

Para finalizar antildeada los valores al graacutefico y mueacutestrelo con S t r o k e ()

Con estas liacuteneas hemos conseguido crear el graacutefico de la figura 166

Puede antildeadir algunas caracteriacutesticas maacutes a sus graacuteficos como tiacutetulos en

los ejes colores o varias liacuteneas de valores para comparar datos

Para antildeadir tiacutetulos a los graacuteficos le pueden servir las liacuteneas siguientes

$graf ico-gttitle-gtset (Graacutefico JpGraph) -

294 Capiacutetulo 16

$grafico-gtxaxis-gttitle-gtset(dia) $grafico-gtyaxis-gttitle-gtset(visitas)

El meacutetodo t i t l e genera un tiacutetulo asociado al objeto inmediatamente anshyterior Si el objeto es $ g r a f i c o el tiacutetulo seraacute el de la imagen completa Si el objeto anterior es el eje x o el eje y ( x a x i s o y a x i s ) el tiacutetulo corresshyponderaacute con cada uno de los ejes Puede ver el resultado en la figura 167

Ademaacutes puede antildeadir tantos datos como quiera para hacer un estudio comparativo de varios datos Para hacer esto debe repetir algunos pasos pero con distintos valores

$datosy2 = array(12378543127) $puntos2 = new LinePlot($datosy2) $puntos2-gtSetColor(red) $grafico-gtAdd($puntos2) $puntos-gtSetLegend(Europa) Spuntos2-gtSetLegend(America) $grafico-gtlegend-gtPos(00505rightcenter)

Como vimos en el ejemplo anterior podemos antildeadir otro array lleno de valores crear una nueva liacutenea de puntos con un color determinado y asoshyciarlo finalmente con el graacutefico que estamos creando como puede ver en

Graacuteficos en 3D

JpGraph realiza casi cualquier tipo de graacutefico estadiacutestico Uno de los maacutes utilizados es el graacutefico de quesito donde podemos evaluar por porcioshynes el dato de mayor amplitud soacutelo con un vistazo El ejemplo siguiente muestra coacutemo hacer un graacutefico de este tipo

ltphp include (jpgraph jpgraphphp) include (jpgraph jpgraph_piephp) include (jpgraph jpgraph_pie3dphp)

$datos = array(4 0So21 33)

$grafico = new PieGraph(300200) $grafico-gtSetShadow()bull

$grafico-gttitle-gtSet(Graacutefico de quesito) $pl = new PiePlot30($datos) $pl-gtSetAngle(20)

Generacioacuten de graacuteficos con PHP 5 295

la figura 168 Las uacuteltimas 3 liacuteneas antildeaden una leyenda en la parte derecha del graacutefico es decir un pequentildeo graacutefico explicativo de las liacuteneas de datos

296 Capiacutetulo 16

$pl-gtSetSize (05) $pl-gtSetCenter (045) $pl-gtSetLegends($gDateLocale-gtGetShortMonth())

$grafic0-gtAdd($pl) $grafic0-gtStroke ()

Para crearlo primero tiene que incluir los archivos j p g r a p h _ p i e php y j p g r a p h ^ p i e 3 d php que permitiraacuten instanciar el tipo de graacutefico P i e P l o t 3 D El meacutetodo SetShadowC) crea una sombra en eiacute contorno exterior del graacutefico La instanciacioacuten del graacutefico circular se hace sobre la variable $pi que empieza a tomar forma con las propiedades S e t A n -g l e () y S e t C e n t e r () que permiten definir el aacutengulo del graacutefico con respecto a la vista frontal y el centrado del graacutefico con respecto a la caja que lo contiene La fase final es antildeadir el quesito al graacutefico creado y mostrarlo en pantalla Una mejora del graacutefico anterior puede ser resaltar la porcioacuten del graacutefico que tiene mayor valor y separarlo notablemente Esto puede hacerse antildeadiendo la liacutenea siguiente

$ p l - gt E x p l o d e S l i c e ( 1 )

El graacutefico de quesito se muestra en la figura 169

Generacioacuten de graacuteficos con PHP 5 297

Resumen

El tratamiento de imaacutegenes desde PHP 5 nos da la posibilidad de crear proyectos muy profesionales Tanto la posibilidad de crear graacuteficos mas pequentildeos marcas de agua o texto sobreimpresos como la de generar esshytadiacutesticas en tiempo real crean un potencial que no todas las paacuteginas Web saben aprovechar

Existen algunos proyectos como K++ que permiten crear imaacutegenes del tipo Flash y que merece la pena indagar en la buacutesqueda de contenido orishyginales para nuestro portal

300 Capitulo 17

Introduccioacuten

Si estaacute familiarizado con otros lenguajes de programacioacuten como C o Java ya conoceraacute algunos mecanismos que permiten manejar errores y excepshyciones Una de las nuevas caracteriacutesticas que PHP 5 incluye es un objeto de manejo de excepciones con una sintaxis muy similar a Java El manejo de excepciones es una herramienta muy potente que podraacute apreciar una vez que comprenda el concepto y haga buen uso del objeto en su coacutedigo Estas funciones permiten depuiacutear condiciones de error reshycuperar situaciones inesperadas y presentar interfaces limpias de errores

Errores y Excepciones

Lo primero que tenemos que hacer es no pensar en una excepcioacuten como si fuera un error Una excepcioacuten es una condicioacuten que se experimenta en un programa inesperadamente y no puede ser manejada por el coacutedigo que hemos escrito Generalmente no causan la parada del programa pero siacute es posible detectarla para que continuacutee normalmente Las excepciones si son tratadas correctamente pueden dar maacutes fiabilidad a su aplicacioacuten y librarle de muchos dolores de cabeza Aunque si no son correctamente utilizadas pueden crear maacutes problemas que resolverlos Debe tomar un tiempo para determinar si necesita crear sus propios meacuteshytodos de manejo de errores y si es asiacute veraacute que a la larga resulta maacutes grashytificante Como ejemplo vamos a ver una pieza de coacutedigo que simula la recepcioacuten de un identificador de usuario y su posible comprobacioacuten en una base de datos Tal y como puede ver se comprueba que los tres prishymeros caracteres sean usr que el tamantildeo en caracteres sea al menos de 9 y que exista en una base de datos

ltphp extraemos el usuario por GET $usuario_id = $_GET[usuario_id ] Si existe el usuario escribimos el mensaje CORRECTO if (usuario_valido($usuario_id))

echo ERROR El usuario $usuario_id no existe else

echo CORRECTO El usuario $usuario_id existe

function usuario_valido($usuario_id)

Gestioacuten de errores en PHP 5 301

$cadena = usr Comprobaciones de usuario if ( (strstr ($usuario_id$cadena) == false) [[

(strpos($usuario_id$cadena) = 0)) return false

if (strlen ($usuario__id) lt 9) return false

if (existe__base_datos ($usuario_id) )

return true else

return false

gt

Como puede ver cualquier condicioacuten que estaacute dentro de la funcioacuten que valida los usuarios puede dar un resultado negativo y soacutelo uno de ellos daraacute un resultado positivo si el usuario existe en la base de datos

Las excepciones permiten distinguir entre distintos tipos de errores y manejarlos dependiendo de su naturaleza

La clase Exception

La clase Except ion se ha creado en PHP 5 para manejar las anomaliacuteas producidas En vez de utilizar comprobaciones que evaluacutean si es falso o verdadero una determinada condicioacuten se utiliza una instancia de la clase Except ion que captura los errores y permite mostrar un mensaje de error personalizado

ltphp extraemos el usuario por GET $usuario__id = $_GET [ usuario_id] Si existe el usuario escribimos el mensaje CORRECTO try

if ( lusuario_valido($usuario_id)) echo ERROR El usuario $usuario_id no existe

else echo CORRECTO El usuario $usuario_id existe

catch(Exception $ex)

Devuelve el mensaje de error $mensaje = ($ex-gtqetMessage() ) echo $mensaje

302 Capiacutetulo 17

function usuario_valido($usuario_id) $cadena = usr Comprobaciones de usuario if ( (strstr ($usuario_id$cadena) == false) |

(strpos($usuario_id $cadena) = 0)) throw new Exception ($usuario_id no contiene el

prefijo)

if (strlen($usuario_id) lt 9)

throw new Exception (El tamantildeo de $usuario_id es menor de 9 caracteres)

if (existe_base_datos($usuario_id) )

return false else

return false

Gestioacuten de errores en PHP 5 303

Como puede ver las excepciones se crean de una manera algo diferente En el momento en el que se escribe th row new E x c e p t i o n los errores que no se controlen con el flujo normal del programa son utilizados como excepciones separadas del resto de la aplicacioacuten

Bloque Try Catch

Las excepciones son controladas por el bloque t r y c a t c h Todo el coacutedishygo que escriba y que pueda generar un error se incluiraacute dentro de una estructura t r y Si dentro del bloque t r y se encuentra un error la ejecushycioacuten del coacutedigo se para y se pasa el control al bloque c a t c h Este bloque se consuita para encontrar la excepcioacuten que ha producido el error de acuershydo con el coacutedigo que hemos escrito

Una de las cosas maacutes convenientes de utilizar excepciones es que puede mostrar tanta informacioacuten o tan poca como quiera El objeto E x c e p t i o n tiene varios meacutetodos para manejar sus propios errores El coacutedigo siguiente muestra coacutemo utilizar t h row e inmediatamente capshyturar la excepcioacuten Podemos capturar tambieacuten algunos paraacutemetros uacutetiles

ltphp try

throw new Exception(Error de sintaxis) catch (Exception $ex)

Mensaje de error $mensaje = ($ex-gtgetMessage ()) Coacutedigo de error configurable $codigo = ($ex-igetCode()) Fichero del error $fichero = ($ex-gtgetFile ( ) ) Linea donde se ha producido el error $linea = ($ex-gtgetLine())

echo Error nuacutemero $codigo $mensaje en el fichero $fichero en la linea $linea

gt

El mensaje de error que se muestra es muy tiacutepico en PHP Como es totalshymente configurable puede generar su propio formato de Mensaje de Error que puede ver en la figura 172

Aunque en este ejemplo el coacutedigo que captura la excepcioacuten soacutelo tiene una liacutenea podraacute incluir dentro del bloque varias liacuteneas o funciones dentro que actuaraacuten de la misma forma

Heredar de (a clase Exception

PHP 5 permite definir sus propias clases qulta heredan de la clase E x c e p shyt i o n Puede hacerlo de la siguiente forma

ltphp class Excepcioacuten extends Exception

function construct($mensaje)

parent Exception($mensaj e)

gt

El siguiente ejemplo muestra coacutemo crear clases propias que manejan erroshyres a partir de la clase E x c e p t i o n

ltphp $usuario_id = $_GET[usuario_id] try

if f J usuario_valido ($usuario__id) ) [ echo ERROR El usuario $usuario id no existe

Gestioacuten de errores en PHP 5 305

else echo CORRECTO El usuario $usuario_id existe

catch(MiExcepcion $ex)

$cadena = usr if ((strpos($usuario_id$cadena) == false) |]

(strpos($usuario_id$cadena) = 0)) $mensaje = $ex-gtgetMessage()

catch(OtraExcepcion $ex)

if (strlen($usuario_id) lt 9) $mensaje = $ex-gtgetMessage()

Definicioacuten de las clases que heredan de Exception class MiExcepcion extends Excepcioacuten

function construct($mensaje)

parentException($mensaje)

class OtraExcepcion extends Excepcioacuten

function construct($mensaje)

parent Exception($mensaj e)

echo $mensaje function usuario_valido($usuario_id)

$cadena = usr if ((strpos($usuario_id$cadena) == false) ||

(strpos($usuario_id$cadena) = 0)) throw new MiExcepcion(Usuario $usuario_id no

contiene el prefijo )

if (strlen($usuario_id) lt 9) throw new OtraExcepcion(Usuario tiene menos de 9

caracteres)

gt

Limitaciones de PHP 5

El objeto de excepciones es totalmente nuevo en PHP 5 Debido a esto algunas funcionalidades creadas en otros lenguajes de programacioacuten como

306 Capiacutetulo 17

Java no han sido todaviacutea implementadas por ejemplo el uso de los meacutetoshydos f i n a l ly () y t h r o w s () Los errores comunes de PHP que se muesshytran en el navegador no son mapeados a excepciones automaacuteticamente Esta funcionalidad seraacute implementada en versiones posteriores de PHP Los errores que no pueden ser controlados por E x c e p t i o n pueden mashynejarse con otras teacutecnicas de programacioacuten

Control de errores sin excepciones

Si ya conoce algunas versiones de PHP sabraacute que hay multitud de funcioshynes capaces de controlar errores incluidos los errores nativos de PHP controladores personalizados de error y los errores de usuario

Errores nativos de PHP

PHP genera 3 tipos de error dependiendo de su seriedad

bull Notice No son errores severos y no crean problemas complejos Por defecto no se muestran en pantalla cuando suceden a menos que dishygamos lo contrario en el archivo de configuracioacuten php i n i

bull Warning Alguna parte del coacutedigo ha causado un error pero la ejecushycioacuten continuacutea

bull Fatal error Un problema serio que hace abortar la ejecucioacuten del proshygrama

Cada tipo de error es representado por una constante diferente E_USER_NOTICE E_USER_WARNING y E_USER_ERROR Puede elegir el nivel de error que quiere mostrar en pantalla con la funcioacuten e r r o r _ r e p o r t i n g ( )

ltphp Mostrar errores fatales error_reporting(E_USER_ERROR) Mostrar advertencias y notificaciones error_reporting(E_USER_WARNING | E_USER_NOTICE) Mostrar todos los errores error_reporting (E__USER__ALL) gt

El manejo de errores queda limitado la mayoriacutea de veces a los del tipo warn ing Los errores fatales se consideran tan criacuteticos que no pueden conshytrolarse y la ejecucioacuten del programa queda suspendida

Gestioacuten de errores en PHP 5 307

Controladores de error

Cuando suceda un error que no tenga contemplado en su aplicacioacuten pueshyden aparecer mensajes en la pantalla que no interesa mostrar La solucioacuten es crear su propia funcioacuten para controlar y mostrar errores

ltphp function errores($errormensaje$fichero$linea)

echo ltbgt ERROR ltbxbrgt echo Sentimos comunicarle que se ha producido un error echo Tipo de error $error $mensaje en $fichero en la linea $linea

gt

Con estas liacuteneas hemos creado una funcioacuten que muestra el error producishydo pero con un disentildeo acorde a nuestra paacutegina Web Puede mostrar tanta informacioacuten como quiera El siguiente paso es llamar a la funcioacuten s e t _ e r r o r _ h a n d l e r () para que PHP sepa que nuestra funcioacuten e r r o shyr e s () se va a encargar a partir de ahora de gestionar los posibles fallos en el flujo del programa

ltphp set_error_handler(errores) gt

308 Capiacutetulo 17

Con el coacutedigo anterior todos los errores producidos del nivel que tenga permitido ( f a t a l e r r o r w a r n i n g o n o t i c e ) seraacuten enviados a la funshycioacuten e r r o r e s () para mostrar su mensaje particular

Errores de usuario con trigger_error()

Desde PHP 4 puede usarse una funcioacuten para identificar los errores proshyducidos por los usuarios muy parecida a la funcioacuten de PHP 5 th row () La funcioacuten t r i g g e r _ e r r o r () genera un error del tipo que quiera ( f a shyt a l e r r o r warn ing o n o t i c e ) y seraacute gestionado por PHP o por su propio gestor de errores

ltphp error_reporting(E_ALL) function errores($error$mensaje$fichero$linea)

echo ltbgt ERROR ltbxbrgt

echo Sentimos comunicarle que se ha producido un error echo Tipo de error $error $mensaje en $fichero en la liacutenea $ linea

set_error_handler(errores)

if (1 = 0 ) trigger_error( Esto es falso E_USER_NOTICE)

gt

Es mejor u t i l izar s iempre la funcioacuten t r i gg e r _ e r r o r ( ) con s e t _ e r r o r _ h a n d l e r () El error que creemos puede ser de cualquiera de los 3 tipos existentes en PHP En este caso generamos un error no t i -ce para indicar que la condicioacuten es falsa

Depuracioacuten de errores

El manejo de errores puede ahorrar esfuerzos a la hora de depurar el funshycionamiento oacuteptimo de su coacutedigo pero tambieacuten puede crear algunos doshylores de cabeza si empieza a suprimir algunos fallos

La f u n c i oacute n e r r o r _ l o g () crea un archivo donde se iraacuten almacenando las ocurrencias de su coacutedigo Con el siguiente ejemplo podraacute capturar todos los errores producidos en el programa para despueacutes hacer un estudio de lo que ha pasado

ltphp

Gestioacuten de errores en PHP 5 309

try if ($usuario = Luis)

throw new Exception(El usuario no existe)

catch (Exception $ex)

$mensaje = ($ex-gtgetMessage() ) $codigo = ($ex-gtgetCode() ) $fichero = ($ex-gtgetFile()) $linea = ($ex-gtgetLine()) $log_mensaje =date(Hi d-m-Y) Error $codigo en

$fichero en la liacutenea $linea Error $mensaje error_log($log_mensaj e3 UsersluisSiteserrorlog) echo $log_mensaje

gt

Nota

Los ficheros l o g son muy utilizados en los Sistemas Operativos para mantener un registro de incidencias Los ficheros l o g guarshydan desde el nuacutemero de veces que ha entrado un usuario hasta los errores que se han producido en el inicio del sistema

La funcioacuten e r r o r _ l o g () puede pasar como segundo paraacutemetro un nuacuteshymero entero que identifica el tipo de error y queacute hacer con eacutel

bull 0 Se utiliza el mecanismo del sistema operativo bull 1 Enviacutea el error a una direccioacuten de correo especificada como cuarto

paraacutemetro (Debe formar parte de una cabecera) bull 2 Enviacutea el error a traveacutes de una sesioacuten de depuracioacuten de PHP (Debe

estar habilitado el modo depuracioacuten)

bull 3 Enviacutea el error a un fichero

Resumen

Como puede darse cuenta la mayoriacutea de los programas incluidos en el libro no tienen ninguacuten tipo de control de errores He preferido evitarlos para ganar en claridad y no tener que empezar explicando los bloques Try Catch desde el principio A partir de ahora sieacutentase libre para modifishycar todos los scripts a su antojo para que sean maacutes fiables y seguros

310 Capiacutetulo 17

El desarrollo de las posteriores versiones de PHP permitiraacute manejar los errores maacutes faacutecilmente El futuro de las excepciones no ha hecho maacutes que empezar con la versioacuten 5 de PHP y se esperan mejoras suculentas con respecto a las anteriores Pese a esto muchas libreriacuteas ya incluyen sus proshypios controles de error como la de MySQL o PEAR

312 Capiacutetulo 18

Introduccioacuten

Transferir ficheros de un ordenador a otro es una tarea que sucede milloshynes de veces a lo largo del diacutea en Internet Ya no es un problema comparshytir un fichero entre dos ordenadores ubicados entre distintos puntos del mundo Los dos meacutetodos maacutes utilizados son el protocolo FTP y el correo electroacutenico

Los ficheros pueden ser transferidos simplemente dejaacutendolos en alguacuten lugar puacuteblico de nuestro servidor Web o utilizando alguacuten programa para enviarlos El protocolo FTP y el correo electroacutenico son programas indeshypendientes que deben estar instalados en el servidor para poder usarse Son dos programas del tipo cliente servidor Para poder utilizar cualshyquiera de los dos servicios anteriores debe conectarse a un servidor en un ordenador remoto y enviar los datos

FTP

Para utilizar el protocolo FTP tiene que tener habilitada la opcioacuten cuando instale PHP Puede utilizar FTP para enviar ficheros en un script escrito en PHP desde alguna paacutegina Web Para conectar a un servidor tendraacute que utilizar la siguiente funcioacuten

$conexioacuten = f tp__connect ( www l u i s y f ernanda net)

Tambieacuten puede utilizar una direccioacuten IP para la conexioacuten $conexioacuten = f tp_connect (12 7 0 0 1)

Nota

La direccioacuten IP identifica un uacutenico ordenador dentro de Internet

La IP 127001 apunta a nuestro propio ordenador

El servidor FTP contiene un listado de usuarios a los que les permite la conexioacuten Dependiendo del usuario que se conecte el servidor le permitishyraacute descargar unos archivos u otros

El siguiente paso es autentificarse como usuario del servidor de FTP con la funcioacuten

ftp_login($conexioacuten $usuario $clave)

Conexiones desde PHP 5 313

Como paraacutemetros tiene que pasar la conexioacuten establecida anteriormente el usuario y la contrasentildea

Advertencia

El protocolo FTP no es seguro El usuario y la contrasentildea se enshyviacutean en formato de texto y podriacutean ser capturados por alguacuten proshygrama sniffer que se encuentre entre su ordenador y el servidor de destino

Como de costumbre puede encapsular todas las funciones para hacer una clase que permita conectar a un servidor

ltphp class ftp

priacutevate $serviacutedor priacutevate $usuario priacutevate $clave priacutevate $conexion priacutevate $login function construct($servidor$usuario $clave)

set_time_limit(0) $this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtclave = $clave $thiacutes-gtconectar($this-gtservidor)

priacutevate function conectar($servidor)

$this-gtconexion = ftp_connect($servidor21 30) priacutevate function loginFtp($usuario$clave)

$this-gtlogin = ftp_login($this-gtconexion usuario $clave)

$ftp = new ftp(127001luissecreto) gt

Como puede ver el meacutetodo constructor utiliza la funcioacuten set__t ime_ l i m i t () Normalmente los script de PHP tienen un tiempo de vida deshyterminado en el fichero de configuracioacuten php i n i Este tiempo suele ser de 30 segundos y es una proteccioacuten para que si un programa se queda

314 Capiacutetulo 18

bloqueado y su ejecucioacuten lleva maacutes de ese tiempo automaacuteticamente queshyde cancelada su ejecucioacuten

La funcioacuten s e t _ t i m e _ l i m i t () le da la posibilidad de ampliar el tiemshypo de ejecucioacuten al nuacutemero de segundos que indique como paraacutemetro Si el argumento es un 0 el tiempo de ejecucioacuten seraacute infinito

La funcioacuten f t p _ c o n n e c t () tambieacuten puede llevar como paraacutemetros el puerto de conexioacuten (por defecto es el 21) y el nuacutemero de segundos que tardaraacute PHP en volver a intentar la conexioacuten si el intento anterior ha sido fallido

Mostrar los archivos remotos

Despueacutes de conectar con el servidor de FTP lo maacutes usual es recuperar un listado de ficheros que estaacuten en el servidor La funcioacuten f t p _ n l i s t () extrae el nombre de los archivos del directorio que pasemos como paraacuteshymetro

El resultado es un array

public function ver($directoriacuteo = )

$this-gtarchivos = ftp_nlist($this-gtconexion$directorio) foreach ($this-gtarchiacutevos as $archivo)

echo $archivoltbrgt

Puede antildeadir el meacutetodo anterior a la clase f t p La funcioacuten f t p _ n l iacute s t () utiliza la conexioacuten almacenada en el constructor de la clase y recibe un listado de ficheros que guarda como array en la variable $this-gtarchivos

Maacutes adelante utilizando un bucle f o r e a c h podraacute extraer todos los nombres e imprimirlos en pantalla como puede comprobar en la figushyra 181

Si no es la primera vez que utiliza el protocolo FTP sabraacute que al conecshytar con un servidor lo maacutes comuacuten es que conecte en el sistema raiacutez donshyde encontraraacute los archivos y directorios que puede utilizar La funcioacuten f t p _ c h d i r () permite cambiar de directorio dentro del sistema de fishycheros

Si en alguacuten momento no sabe en queacute directorio se encuentra puede hashycer uso de la funcioacuten f tp_pwd ( ) que le daraacute la ruta completa de su situacioacuten

Descargar y Enviar ficheros

Puede descargar ficheros con la funcioacuten f tp_ge t () El siguiente ejemshyplo descarga un fichero despueacutes de hacer la conexioacuten

ftp_get($conexioacuten nuevoFicherotxtFicherotxtFTP_ASCII)

El nombre nuevoFichero t x t se corresponde con el nombre del ficheshyro que tendraacute el archivo despueacutes de ser descargado y F iche ro t x t es el archivo remoto que queremos descargar El uacuteltimo paraacutemetro FTP_ASCI I le dice al FTP el tipo de archivo que va a ser descargado Los modos que puede elegir son FTP_ASCI I o FTP_BINARY Los ficheros binarios son archivos escritos en el lenguaje maacutequina como los archivos graacuteficos Ademaacutes puede enviar archivos al servidor con la funcioacuten f tp_put () El siguiente ejemplo muestra coacutemo subir un archivo al servidor

ftp_put($conexion nuevoFicherotxtFicherotxtFTP_ASCII)

Como en el ejemplo anterior n u e v o F i c h e r o t x t seraacute el nombre del archivo en el servidor remoto y F i c h e r o t x t el archivo que vamos a enviar El ejemplo siguiente descarga todos los archivos con extensioacuten PHP en nuestro ordenador local

public function descargaPHP($directorio = )

316 Capiacutetulo 18

$this-gtarchivos = ftp_nlist($this-gtconexion$directorio) foreach ($this-gtarchivos as $archivo)

if (ereg(php$archivo)) if ( f ile__exists ($archivo) )

ftp_get($this-gtconexion$archivo$directorio $archivoFTP_ASCII)

else

echo Fichero $archivo ya existeltbrgt

else

echo El archivo $archivo no es de PHPltbrgt

Otras funciones de FTP

Ademaacutes de las funciones descritas en este capiacutetulo existen otras muchas para el manejo del protocolo FTP

Tabla 181 Funciones comunes al manejo de FTP

Funciones Descripcioacuten

ftp_cdup($conexion) Cambia al directorio inmediatamente

superior al directorio actual ftp_chdir($conexioacuten Cambia al directorio que pasemos como

nombre directorio) paraacutemetro

ftp_close($conexion) Cierra una conexioacuten FTP

ftpconnect(servidor) Establece una conexioacuten con el servidor

ftp_delete($conexioacuten ruta) Borra un fichero del servidor

ftp_exec($conexioacuten comando) Ejecuta un comando del sistema remoto

ftp_fget($conexioacuten $descriptor Descarga un fichero y vuelca los datos Ficherotxt FTP_ASCII) en un fichero abierto en el ordenador

local

ftp_fput($conexioacuten $descriptor Enviacutea un archivo a un fichero abierto Ficherotxt FTP_ASCII)

ftp_get($conexioacuten nuevoFicherotxt Recupera un fichero de un servidor Ficherotxt FTP_ASCII)

ftp_put($conexioacuten nuevoFicherotxt Enviacutea un fichero al servidor

Ficherotxt FTP_ASCII)

Conexiones desde PHP 5 317

Funciones Descripcioacuten

ftp_login($conexiexcloacuten $usuario $clave) Autentifica al usuario en el servidor ftp_mdtm($conexioacutenFicherotxt) Recupera la fecha de la uacuteltima actualishy

zacioacuten del fichero ftp_mkdir($conexioacuten directorio) Crea un directorio

ftp_nlist($conexioacuten directorio) Recupera la lista de archivos de un directorio

ftp_pwd($conexion) Obtiene el nombre del directorio actual ftp_rename($conexioacuten Cambia de nombre un archivo remoto ArchivoAntiguoArchivoNuevo) ftp_size($conexionFicherotxt) Devuelve el tamantildeo de un fichero ftp_systype($conexion) Permite obtener el tipo de sistema

Correo electroacutenico

La aplicacioacuten maacutes utilizada sin duda en Internet es el correo electroacutenico La explosioacuten de Internet y la expansioacuten de servidores gratuitos que ceden cuentas de correo a todos los usuarios ha permitido que el crecimiento de los e-tnail se dispare en estos uacuteltimos antildeos

Para lograr la comunicacioacuten a traveacutes del correo electroacutenico han de intershyvenir numerosas piezas de un puzzle

La mayor parte del modelo utiliza

bull Servidor TCP IP Se encarga de mantener activos para la conexioacuten diversos servicios como FTP SMTP o POP

bull MTA (Mail Transfer Agent) Acepta correo de otros servidores SMTP y busca una ruta para que los correos lleguen a su destino

bull Cola de correo Recipiente donde se almacenan todos los correos enshytrantes dirigidos a una persona

bull MUA (Mail User Agent) Programa muy liviano para leer el correo elecshytroacutenico normalmente desde el servidor

bull Servidor POP IMAP Recibe peticiones de lecturas de correo El sershyvidor chequea si hay correos nuevos y los enviacutea al cliente

bull MLM (Mailing List Manager) Este software ayuda a enviar grandes cantidades de correo

318 Capiacutetulo 18

Enviar correo desde PHP

Soacutelo existe una funcioacuten para enviar correo electroacutenico desde PHP 5 La funcioacuten mail () devolveraacute un valor true si los datos son enviados correcshytamente La forma maacutes sencilla de utilizar esta funcioacuten la puede ver en el ejemplo siguiente

ltphp $resultado = mail ( luisaacutenccextremadura org Ejemplo de Asunto Cuerpo del mensaje) if ($resultado)

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt

El primer paraacutemetro recibe el correo de la persona a la que quiere enviar el mensaje El segundo es un resumen del contenido de su carta electroacutenishyca y por uacuteltimo el tercer paraacutemetro es el mensaje que quiere transmitir Puede dividir la funcioacuten en variables para que sea maacutes sencillo de utishylizar

ltphp $correo = luisnccextremaduraorg $asunto = Ejemplo de Asunto $cuerpo = Cuerpo del mensaje $resultado = mail($correo $asunto $cuerpo) if ($resultado)

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt

Hay veces que necesitaraacute algo maacutes de control sobre lo que quiera enviar o necesite enviar un correo a varias personas a la vez Esto es posible antildeashydiendo cabeceras adicionales a la funcioacuten mail

ltphp $correo = luisnccextremaduraorg $asunto = Ejemplo de Asunto $cuerpo = Cuerpo del mensaje $cabecera = From fernandarnbccpedronccextremaduraorgrnContent-type textplainrnX-mailer PHP phpversion () $resultado = mail($correo $asunto $cuerpo $cabecera) if ($resultado)

Conexiones desde PHP 5 319

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

La cabecera muestra coacutemo enviar junto al correo la direccioacuten de la persoshyna que lo enviacutea y una copia del mismo mensaje al correo pedroncc extremaduraorg Es necesario antildeadir los separadores r y n para indishycar un salto de liacutenea entre los paraacutemetros de la cabecera

Las cabeceras adicionales pueden antildeadir muchos tipos de informacioacuten entre los que se encuentran

bull El nombre del emisor

bull Correo del emisor

bull Correo de respuesta

bull X-mailer y nuacutemero de versioacuten

bull versioacuten MIME

bull Content-type

bull Codificacioacuten

bull Campo de copia y copia oculta

La funcioacuten m a i l () estaacute preparada para emitir mensajes sencillos pero hay muchas caracteriacutesticas que debe implementar con cabeceras Por eso han nacido una serie de libreriacuteas escritas en PHP que facilitan el enviacuteo de correos

La libreriacutea PHPMailer antildeade a la funcioacuten m a i l () muchas funcionalidashydes como ficheros adjuntos o correos HTML

PHPMailer

PHPMailer estaacute basado en programacioacuten orientada a objetos Contiene varios ficheros que deben guardarse en el directorio de PHP dedicado a libreriacuteas o en nuestro espacio de trabajo

La construccioacuten maacutes baacutesica es la siguiente

ltphp require_once(phpmailerclassphpmailerphp) $correo = new phpmailer() Datos personales del emisor $mail-gtFrom = luisnccextremaduraorg

320 Capitulo 18

$mail-gtFromName = Luis Miguel Cabezas

$mail-gtSubject = Mensaje de prueba

$mail-gtBody = Cuerpo del mensaje Direccioacuten de destino $mail-gtAddAddress(zeevSphpzendcomZeev Suraski)

if ( l$mail-gtSend()) echo Correo enviado correctamente

else echo El correo no ha podido enviarse

gt

Como puede ver las propiedades de la clase p h p m a i l e r son auto explishycativas El ejemplo va asociando cada propiedad a un dato necesario para el enviacuteo El meacutetodo A d d A d d r e s s () antildeade una direccioacuten de correo a la que enviar el mensaje y Send () lo enviacutea a traveacutes de Internet

Antildeadir un fichero adjunto

Existen tres meacutetodos para antildeadir un fichero adjunto a un mensaje dos para archivos y otro maacutes especiacutefico para imaacutegenes

bull AddAttachment(ruta nombre) Antildeade un fichero localizado en el servidor Este archivo se puede subir antes al servidor mediante un formulario

bull AddStringAttachment(caracteres fichero) Se puede utilizar para enviar ficheros almacenados en variables

bull AddEmbeddedImage(ruta cid nombre) Antildeade una imagen y pershymite antildeadirla al cuerpo de un correo HTML

Las liacuteneas siguientes se pueden antildeadir al ejemplo anterior para enviar un fotografiacutea almacenada en el servidor

if ($mail-gtAddAttachment(abuelojpgabuelojpg))

echo Falloacute al antildeadir un fichero adjunto

Para demostrar la teoriacutea anterior vamos a crear un pequentildeo formulario que permita enviar correo Es un coacutedigo muy sencillo pero permite enshyviar mensajes escritos en HTML e incluir imaacutegenes

ltphp if (isset($_POST[nombre]))

require_once(phpmailerclassphpmailerphp)

Conexiones desde PHP 5 321

$correo = new phpmailer() Datos personales del emisor $mail-gtFrom = luisnccextremaduraorg $mail-gtFxowpoundawgte = Luis Miguel Cabezas $mail-gtSubject = $_POST [ asunte ] $mail-gtBody = $_POST[mensaje] Direccioacuten de destino $mail-gtAddAddress($_POST[nombre]$_POST[correo]) if ($mail-gtAddEmbeddedImage($_FILES[imagen] [tmp_name 12 34 5 imagen))

echo Falloacute al antildeadir un fichero adjunto

if ( $mail-gtSend() )

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt lthtmlgt ltbodygt ltform action=mailphp method=post enctype=multipartform-data name=formlgt lttable width=50 border=0 cellspacing=0

cellpadding=Ogt lttrgt

lttd width=28gtNombrelttdgt lttd width=72xinput name=nombre type=text

id=nombregtlttdgt lttrgt lttrgt lttdgtCorreolttdgt lttdxinput name=correo type=text id=correogtlttdgt

lttrgt lttrgt lttdgtAsuntolttdgt lttdxinput name=asunto type=text id= asuntogtlttdgt

lttrgt lttrgt lttdgtMensajelttdgt lttdxtextarea name= mensa j e rowS=5 id= mensa j e gtlt textareaxtdgt

lttrgt lttrgt lttdgtSelecciona imagen lttdgt lttdxinput name=imagen type=file id= imagen xtdgt

lttrgt lttablegt ltpgt

322 Capiacutetulo 18

ltinput type=submit name=Submit value=Enviargt ltPgt

lt formgt ltbodygt lthtmlgt

La figura 182 muestra un formulario capaz de enviar contenido HTML e imaacutegenes adjuntas

Resumen

PHP se ha promovido tanto debido a las numerosas extensiones que pershymiten hacer casi cualquier cosa En concreto las dos formas vistas para conectarse con un servidor le seraacuten muy uacutetiles para ofrecer servicios inshynovadores a sus usiiarios

La mayoriacutea de los portales Web que necesitan el registro de sus usuarios enviacutean por correo electroacutenico las contrasentildeas y los datos de inscripcioacuten La funcioacuten mail () le puede servir para hacer sus pequentildeos controles de usuarios

Conexiones desde PHP 5 323

Si se siente maacutes ambicioso tambieacuten puede utilizar PHPMailer para consshytruir una paacutegina Web que permita enviar o recibir correo electroacutenico La recomendacioacuten es que continuacutee investigando en la clase PHPMailer y en todo lo que ofrece que no hemos podido ver en este capiacutetulo

326 Capiacutetulo 19

Introduccioacuten

Como probablemente ya sabe el HTML no es el uacutenico formato para mosshytrar contenido en Internet Ademaacutes de los distintos tipos de imaacutegenes teshynemos varios formatos capaces de contener textos como Adobe PDF Macromedia Flash o algunos documentos alternativos escritos en XML como los archivos graacuteficos SVG (Graacuteficos Vectoriales Escalables) WML (Lenguaje de Marcas Inalaacutembrico) o XUL (Lenguaje de interfaz de Usuashyrio en XML con Mozilla) Cada uno de estos tipos de documentos tiene su propio terreno y de nosotros depende elegir cuaacutel o cuaacuteles utilizar para dotar a nuestra Web de mayores posibilidades

Los archivos Adobe PDF se han establecido como un estaacutendar en los doshycumentos de texto para la Web

Existen dos extensiones escritas para PHP PDFLib y C l ibPDF capaces de generar archivos PDF Desgraciadamente estas libreriacuteas son de uso coshymercial y requieren el pago de alguacuten tipo de licencia Ademaacutes de las extensiones anteriores tenemos una serie de aplicaciones escritas completamente en PHP que permiten llegar al mismo resultado como RampOS PDF o FPDF No son tan raacutepidas como las extensiones pero cumplen perfectamente nuestras expectativas

Libreriacutea FPDF

La libreriacutea FPDF creada en septiembre de 2001 no necesita licencia de uso ni tampoco alguna configuracioacuten especial de PHP Lo uacutenico que neshycesita es la libreriacutea que la puede descargar del sitio Web h t t p wwwfpdforg

La libreriacutea principal contiene la definicioacuten de una clase que debe instan-ciar para poder generar sus documentos Nuestro coacutedigo inicial deberiacutea ser algo parecido a

ltphp require__once ( f pdf fpdf php) $pdf = new FPDF() gt

El constructor se utiliza de esta forma con los valores por defecto que son paacutegina A4 con orientacioacuten vertical y el tamantildeo medido en miliacutemetros El primer paraacutemetro del constructor permite elegir entre orientacioacuten verti-

Creacioacuten de archivos PDF 327

cal (L) u horizontal (P) El segundo paraacutemetro sirve para que las medidas de referencia se hagan en base a puntos (pt) miliacutemetros (mm) centiacutemetro (cm) o pulgadas (in) El uacuteltimo paraacutemetro nos ofrece la oportunidad de elegir entre los diferentes formatos de paacutegina que existen A3 A4 A5 Let-ter y Legal

Nota

Hay que recordar que un punto es 172 pulgadas

$pdf = new FPDF( P cm A 4 )

Nuestro primer documento

El siguiente ejemplo muestra la creacioacuten baacutesica de un documento PDF de forma lineal

ltphp define(FPDF_FONTPATHfpdffont) require_once ( fpdffpdfphp) $pdf = new FPDF() $pdpound-gtAddPageU bull $pdf-gtSetFont(Arial 15) $pdf-gtWrite(155 Mi primer documento) $pdf-gtOutput() gt

La primera liacutenea define una constante que contiene la ruta donde estaacuten almacenadas las fuentes Despueacutes de las funciones que incluyen la clase y la instancia del objeto tenemos una serie de llamadas a meacutetodos que nos permiten manipular el documento a nuestro antojo

Advertencia

FPDF mantiene la posicioacuten de un cursor Las funciones que geneshyran texto imprimiraacuten los datos de acuerdo con la posicioacuten del curshysor en ese momento Es posible de todas formas cambiar de sitio el cursor con algunas funciones que veremos en este capiacutetulo

El meacutetodo AddPage () antildeade una paacutegina al documento con la orientashycioacuten que Le pida En este caso hemos antildeadido una con orientacioacuten vertical que es la elegida por defecto S e t F o n t () selecciona una fuente tomando

Funciones de texto

Meacutetodo Write()

Imprime el texto pasado como paraacutemetro en la posicioacuten que indica el curshysor La construccioacuten es

W r i t e ( a l t u r a t e x t o e n l a c e )

Los paraacutemetros son los siguientes

bull altura Altura de la celda bull texto Texto a imprimir bull enlace Podemos considerar el texto como un enlace a una paacutegina o a

una Web

Como ejemplo puede ver el primer coacutedigo que hemos realizado

328 Capiacutetulo 19

como paraacutemetro el tipo la propiedad (negrita cursiva) y el tamantildeo Por uacuteltimo tenemos una llamada a los meacutetodos Write () y Output () que escriben el texto en una posicioacuten determinada del documento y lo muesshytran en pantalla respectivamente como puede ver en la figura 191

Creacioacuten de archivos PDF 329

Meacutetodo Cell()

El meacutetodo c e l l () puede tomar hasta 8 paraacutemetros y es el encargado de imprimir en el documento PDF un cuadro de texto en la posicioacuten indicashyda El cuadro de texto puede tener un borde alrededor o en alguno de los lados

La construccioacuten es como sigue

cell(ancho altura texto borde liacutenea alineacioacuten relleno enlace)

Los dos primeros paraacutemetros son obligatorios los demaacutes opcionales A continuacioacuten vemos para queacute sirve cada paraacutemetro

bull ancho Ancho de la celda Si es 0 se considera el ancho total del folio

bull altura Altura de la celda

bull texto Texto a imprimir

bull borde Un 1 significa que llevaraacute borde Tambieacuten se pueden incluir algunos caracteres para indicar en cuaacutel de las partes de la celda debe llevar borde L R T y B significan Izquierda Derecha Arriba y Abajo respectivamente

bull liacutenea Cuando termine la llamada a la creacioacuten de la celda indica al generador de PDF doacutende debe colocar el cursor para continuar Un 0 indica a la derecha de la tabla un 1 en la siguiente liacutenea y un 2 seguido

bull alineacioacuten Acepta 3 caracteres L para alinear a la izquierda R a la derecha y C para texto centrado

bull relleno Indica con un 1 si la celda debe tener un relleno para diferenshyciarla del resto del folio

bull enlace Enlace devuelto por la funcioacuten A d d l i n k ()

Como ejemplo puede ver la forma de introducir un tiacutetulo en una paacutegina

lt php define(FPDF_FONTPATHfpdffont) require__once ( fpdffpdf php i $pdf = new FPDF()

$pdf-gtAddPage() $pdf-gtSetFont(Courier 1 0 ) $pdf-gtCell(80) $pdf-gtCell (2010 Titulo 11C) $pdf-gtOutput() gt

Una celda soacutelo puede contener el nuacutemero de caracteres que quepa en una liacutenea Si necesita mostrar maacutes liacuteneas de texto puede utilizar el meacutetodo

330 Capiacutetulo 19

Muiacute ti Ce 11 () que toma los mismo paraacutemetros que Ce 11 ( ) pero cuanshydo el texto llegue al final de la liacutenea se antildeade automaacuteticamente un salto a la liacutenea siguiente

Truco

Puede utilizar Ce 11 () para desplazar el cursor hacia la derecha antildeadiendo como paraacutemetro un ancho de 8 centiacutemetros (80 miliacuteshymetros) Despueacutes para imprimir el texto antildeada otra celda que inshycluya el literal Tiacutetulo centrado dentro de una celda con borde

Desplazamiento de los cursores

Existen varias funciones para colocar el cursor en distintas partes del doshycumento Se tX () y S e t Y () colocan el texto en el punto indicado en la medida seleccionada (centiacutemetros miliacutemetros etc)

Se tX () desplaza el cursor de izquierda a derecha tantas unidades como indique el paraacutemetro y S e t Y () de arriba hacia abajo Si se les pasa un nuacutemero negativo el origen se tomaraacute desde la derecha o desde abajo resshypectivamente

SetXY () toma dos valores y permite realizar las dos operaciones con una sola instruccioacuten

$pdf-gtSetXY(100100) $pdf-gtwrite(2Este texto se mostraraacute a 10 cm del margen)

Salto de paacutegina automaacutetico

El meacutetodo S e t A u t o P a g e B r e a k () activa o desactiva el salto de paacutegina automaacutetico

Esto quiere decir que si estaacute activado cuando el texto llegue al final de la paacutegina se crearaacute una paacutegina nueva para poder contener el resto El primer paraacutemetro debe ser true ofalse para activa o desactivar la proshypiedad

El segundo paraacutemetro indica la distancia desde la parte inferior que desshyencadena la llamada a una nueva paacutegina

Se tAutoPageBreak( t rue 20 )

El coacutedigo anterior activa el salto de paacutegina automaacutetico cuando el texto lleshygue a 2 centiacutemetros del margen inferior

Creacioacuten de archivos PDF 331

Sobrescribir los meacutetodos

La clase FPDF contiene algunos meacutetodos vaciacuteos que debe escribir usted si quiere que sus documentos queden profesionales Puede crear un objeto propio que herede del objeto FPDF e implementar algunas caracteriacutesticas avanzadas

Cabecera

La cabecera de un documento es un conjunto de texto escrito en la parte superior del folio y que debe aparecer en todas las paacuteginas La clase FPDF implementa el meacutetodo header () que se llama cada vez que existe un salto de paacutegina

Puesto que el meacutetodo estaacute vaciacuteo en FPDF tendraacute que crear un objeto nueshyvo que herede todos sus meacutetodos e implemente la cabecera

ltphp define ( FPDF_FONTPATH fpdffont ) requireonce(fpdffpdfphp) class PDF extends FPDF

function Header()

$this-gtSetFont(ArialB15) $this-gtSetX(70) $this-gtCell(100 10 Manual Imprescindible de PHP 510C) $this-gtLn(20)

$pdf = new PDF () for($i=l$ilt=200$i++) $pdf-gtCell(010Imprimiendo liacutenea nuacutemero $i0l)

$pdf-gtOutput () gt

El meacutetodo header () configura un tipo de letra determinado en negrita avanza el cursor 8 centiacutemetros hacia la derecha e imprime una celda con el tiacutetulo El meacutetodo Ln (2 0 ) inserta un salto de liacutenea cuya altura es determinada por el argumento

Para probar el objeto hemos hecho un bucle que imprime 100 liacuteneas y asiacute comprobar que la cabecera aparece invariable El resultado se puede obshyservar en la figura 192

Imagen de cabecera

Tambieacuten es posible antildeadir una imagen a la cabecera con el meacutetodo Ima-ge ( ) La construccioacuten es la siguiente

Image(fichero x y ancho alto tipo enlace)

Los paraacutemetros necesarios son fichero x e y La descripcioacuten de todos los argumentos es

bull fichero Indica la ruta hacia el fichero que va a insertar

bull x Posicioacuten en el eje x de la imagen

bull y Posicioacuten en el eje y de la imagen

bull ancho Ancho de la imagen

bull alto Alto de la imagen Si no se indica y el paraacutemetro ancho estaacute defishynido el alto se escala en funcioacuten del ancho

bull tipo El tipo de imagen Por ahora soacutelo se aceptan imaacutegenes JPG JPEG y PNG

bull enlace La imagen puede ser un enlace

Ahora que sabe coacutemo insertar imaacutegenes puede incluir en la cabecera el logotipo de su empresa o asociacioacuten

funct ion Header()

Creacioacuten de archivos PDF 333

$this-gtSetFontArialB15) $this-gtSetX(70) $this-gtCell(10010Manual Imprescindible de PHP 510C) $this-gtSetX(-20) $this-gtImage(phppng1705) $this-gtLn (20)

La figura 193 muestra una cabecera con una imagen insertada

Pie de paacutegina

De la misma forma puede sobrescribir el meacutetodo que imprime el pie de paacutegina de la clase FPDF

Este meacutetodo recibe el nombre de F o o t e r () y tiene el mismo tratamiento que la cabecera cada vez que existe un salto de paacutegina se hace una llamashyda al mismo Nuestro pie de paacutegina puede quedar de la siguiente forma

funct ion Footer()

$this-gtSetY (-15) $this-gtSetFont(Arial I 10) $this-gtCell (010 Paacutegina $this-gtPageNo() 00 C )

334 Capiacutetulo 19

S e t Y () nos coloca el cursor a 15 miliacutemetros del borde derecho Seguidashymente escoja el tipo de fuente Aria e imprima el nuacutemero de la paacutegina acshytual con el meacutetodo PageNo ()

Muchos documentos informan ademaacutes del nuacutemero de paacuteginas que tiene el texto Esto es complicado a primera vista porque a priori no podraacute saber cuaacutentas paacuteginas ocuparaacute su texto Existe un meacutetodo que se ejecuta cuando el documento es cerrado y sustituye una marca por el nuacutemero de folios con los que cuenta nuestro proyecto

function FooterO

$this-gtSetY(-15) $this-gtSetFont ( Anal I 10) $this-gtAliasNbPages() $this-gtCell(0 10 Paacutegina $this-gtPageNo()

nb 00 C)

El meacutetodo A l i a s N b P a g e s () cuenta el nuacutemero de paacuteginas cuando el doshycumento estaacute cerrado y sustituye la marca nb por este nuacutemero

Tablas

Una tabla no es maacutes que un conjunto de celdas colocadas en un orden determinado Podemos diferenciar entre la cabecera de la tabla que conshytendraacute las propiedades y los datos Si realiza una clase para escribir tashyblas puede hacer tambieacuten esa diferenciacioacuten cambiando el tipo de letra el tamantildeo o el color El coacutedigo siguiente muestra coacutemo se puede instaurar una clase para la creacioacuten de tablas faacutecilmente

ltphp define(FPDF_FONTPATHfpdffont) require_once(fpdffpdfphp) class PDF extends FPDF function tabla($cabecera$datos)

$this-gtcabecera ($cabecera) $this-gtdatos($datos)

function cabecera($cabecera) Cabecera

$this-gtSetFont(ArialB15)

Creacioacuten de archivos PDF 335

foreach($cabecera as $columna) $this-gtCell(407$columna1 0 C )

$this-gtLn()

function datos($datos) Datos

$this-gtSetFont(Arial12) foreach ($datos as $dato)

foreach ($dato as $columna) $this-gtCell(407$columna10 C )

$this-gtLn ()

$pdf = new PDF () $pdf-gtAddPage ()

$cabecera = array(UsuariosVisitasLocalidadTeleacutefono) $datos = array(array(Luis Miguel 12Badajoz555345678)

array(Mariacutea Fernanda 45 Meacuterida 234234654) array(Pedro Casas3Caacuteceres342123 890))

$pdf-gttabla($cabecera$datos) $pdf-gtOutput () gt

En este caso los datos se sacan de un array de dos dimensiones pero pueshyde utilizar la libreriacutea de bases de datos o la de XML creadas en los capiacutetushylos anteriores para extraerlos

Los datos los recibe el meacutetodo T a b l a ( ) que los enviacutea a sus corresponshydientes meacutetodos para ser tratados El funcionamiento baacutesico consiste en la creacioacuten repetitiva de celdas cuyo nuacutemero coincidiraacute con el nuacutemero de datos existentes en el array Todas las celdas se muestran seguidas dando sensacioacuten de ser una tabla como puede ver en la figura 194 Ahora que es casi un experto en la creacioacuten de tablas para facturas o alba-ranes en PDF puede dar un toque de color al relleno texto o liacuteneas de las celdas

Puede comprobar que con tan soacutelo tres liacuteneas de coacutedigo maacutes el aspecto visual del documento mejora considerablemente

function cabecera($cabecera)

Cabecera $this-gtSetFillColor (25500)

336 Capiacutetulo 19

$this-gtSetTextColor(255) $this-gtSetDrawColor(12 800) $this-gtSetFont(ArialB15) foreach($cabecera as $columna)

$this-gtCell(407$columna10C1)

$this-gtLn()

function datos($datos)

D a t o s $this-gtSetTextColor (1) $thiacutes-gtSetDrawColor (12 800) $this-gtSetFont ( Arial 12) foreach ($datos as $dato)

foreach ($dato as $columna) $this-gtCell(407$columna10C)

$this-gtLn ()

El resultado es mucho maacutes llamativo gracias a los meacutetodos que antildeaden color El meacutetodo S e t F i l l C o l o r () define el color de fondo de las celdas

Creacioacuten de archivos PDF 337

y los rectaacutengulos que no sean transparentes Puede ser expresado con un componente RGB o en escala de grises El valor se mantiene durante todo el documento hasta que se vuelva a invocar el meacutetodo

S e t T e x t C o l o r () y S e t D r a w C o l o r () funcionan de la misma forma actuando esta vez sobre el color del texto o el color de las liacuteneas y bordes de celda La figura 194 muestra los colores (tonos de grises en este caso) distintos que pueden tomar un archivo PDF

Enlaces

Una de las ventajas del formato PDF es que permite hacer enlaces intershynos es decir que si tiene un documento de 500 folios podraacute acceder a cada uno de los capiacutetulos haciendo clic en el iacutendice tal y como funcionan los enlaces en las paacuteginas Web

Un enlace externo es muy faacutecil de crear

$pdf-gtWrite(5wwwluisyfernandanethttpwwwluisyfernandanet)

Los meacutetodos dedicados a texto tienen un argumento para antildeadir un enlashyce que si es externo debe llevar la direccioacuten URL completa

338 Capiacutetulo 19

Crear un enlace interno es algo maacutes complicado Tiene que hacer uso del meacutetodo A d d l i n k ( ) que genera una referencia que debe ponerse en el lugar hacia donde quiere que se produzca el salto En ese lugar utilice el meacutetodo S e t L i n k () para cerrar el enlace

El coacutedigo de ejemplo puede aclarar el concepto

ltphp define(FPDF_FONTPATHfpdffont) require_once(fpdffpdfphp) $pdf = new FPDF() $pdf-gtAddPage () $pdf-gtSetFont(Arial 15) $enLace = $pdf-gtAddLink() $pdf-gtWrite(5Este texto contiene un enlace$enlace) $pdf-gtAddPage) $pdf-gtSetLink($enlace) $pdf-gtWrite (5 Enlace Interno) $pdf-gtOutput () gt

Lo uacutenico a destacar es la creacioacuten del enlace con AddLink ( ) La variable $ e n l a c e recoge el valor de referencia y se antildeade al texto de la liacutenea sishyguiente En este momento el texto contiene un enlace pero no sabemos hacia doacutende La solucioacuten estaacute en llamar al meacutetodo S e t L i n k () en la paacutegishyna de destino con la referencia de paraacutemetro

Resumen

Los archivos PDF se consideran desde hace unos antildeos ideales para la geshyneracioacuten de contenidos on-line As iacute revistas digitales como w w w phparchcom o wwwphpmagnet utilizan este sistema para vender su publicacioacuten

Ademaacutes de revistas digitales podemos encontrar empresas que hacen lleshygar las instrucciones de sus productos en PDF o realizan las facturas de los clientes on-line como el programa de facturacioacuten extrementildeo Galopiacuten (httpgalopinsinuhorg)

La generacioacuten de sus propios archivos ya no es un misterio y puede im-plementar clases muchos maacutes potentes que las mostradas en el libro para sus propios proyectos La inclusioacuten de colores imaacutegenes y tablas de disshytintos tipos haraacuten del lector un profesional de la edicioacuten Web

En este capiacutetulo aprenderaacute a

bull Conocer queacute es un sistema de plantillas con Smarty

bull Independizar el coacutedigo HTML de PHP bull Crear plantillas con variables y bucles bull Crear plugins propios y modificar los ya existentes bull Crear filtros para mejorar el proceso

340 Capiacutetulo 20

Introduccioacuten

Cuando PHP nacioacute fue considerado como un sencillo lenguaje para geneshyrar dinaacutemicamente etiquetas de HTML Tras la versioacuten 3 de PHP se antildeashydioacute un compendio de funciones complejas para el manejo de cadenas arrays y bases de datos lo suficientemente completas como para crear sishytios Web muy extensos

Despueacutes de la creacioacuten de entornos completos en PHP los desarrollado-res comenzaron a pensar que no era muy uacutetil mezclar coacutedigo PHP con coacutedigo HTML e inventaron una forma de independizar los dos lenguajes mediante el uso de plantillas El primer entorno de plantillas que apareshycioacute fue FastTemplate escrito originariamente en Perl

En un periacuteodo corto de tiempo aparecieron muchos programas que facilishytaban el uso de plantillas como vTemplate Xtemplate TemplatePower o SmartTemplate Todos permiten sustitucioacuten de variables bloques repetishytivos inclusioacuten de muacuteltiples plantillas y bloques opcionales con estructushyras del tipo i f La diferencia estaacute en que muchos de estos sistemas utilizan expresiones regulares y hace muy complicado su uso Ademaacutes la velocishydad con la que se generan las plantillas es una propiedad a tener en cuenshyta en un entorno de trabajo en produccioacuten

SmartTemplate aparecioacute en 1999 y es el predecesor de lo que hoy conoceshymos como Smarty Es un entorno muy similar a otros pero incluye caracshyteriacutesticas muy avanzadas que lo hacen uacutenico la compilacioacuten de plantillas Esto significa que Smarty lee la plantilla y crea un script escrito en PHP Una vez creado este script se ejecuta y muestra el resultado en pantalla Lo bueno es que la compilacioacuten soacutelo se hace la primera vez las veces sishyguientes Smarty comprueba si hay nuevos datos que mostrar y si no los hay se utiliza la plantilla escrita en PHP por lo que la ejecucioacuten se hace muy raacutepida Algunas de las caracteriacutesticas generales de Smarty son

bull Extremadamente raacutepido

bull Muy eficiente porque el parse de PHP hace todo el trabajo

bull Soacutelo se compilan las plantillas que cambien los datos

bull Podemos realizar funciones propias y modificadores de variables Esto hace que Smarty sea extensible por el usuario

bull Se pueden utilizar varios delimitadores como j ltmdashmdashgt

bull Las estructuras de control son manejadas directamente por el parse de PHP por lo tanto pueden ser tan complejas como quiera

Plantillas con Smarty 341

bull Se puede incluir coacutedigo PHP dentro de nuestras plantillas

bull Funciones configurables para el manejo de la cacheacute

bull Arquitectura de plugins ampliable

Instalacioacuten de Smarty

La instalacioacuten del entorno de Smarty es muy sencillo y pasa por descargar de la Web httpsmartyphpnet la uacuteltima actualizacioacuten del sistema El archivo comprimido consta de varias carpetas que deberiacutean estar dentro del directorio de libreriacuteas de PHP Tambieacuten es posible guardar la carpeta de Smarty junto con nuestros programas pero no es recomendable

Las libreriacuteas del sistema de plantillas incluidas dentro del directorio l i b s son

Smartyclassphp Smarty_Compilerclassphp Config_Fileclassphp debugtpl

Ademaacutes de estos archivos existen las carpetas c o r e y p l u g i n s que se encargan de controlar el flujo de los objetos de Smarty

Las plantillas que creemos las vamos a guardar en un directorio llamado t e m p l a t e s y las plantillas compiladas deberaacuten estar en t e m p l a t e s _ c

Advertencia

La carpeta t e m p l a t e s _ c debe permitir la escritura porque aquiacute se iraacuten guardando las plantillas compiladas

Utilizacioacuten baacutesica de Smarty

Durante el desarrollo del libro hemos visto algunas teacutecnicas para escribir limpiamente nuestro coacutedigo PHP mezclado con HTML Vamos a ver una clase implementada por nosotros que genera una Web desde PHP y desshypueacutes vamos a ver coacutemo hacer lo mismo desde Smarty

ltphp c l a s s PaginaWeb

342 Capiacutetulo 20

priacutevate $titulo function construct($titulo)

$this-gttitulo = $titulo

priacutevate function cabecera($titulo)

echo lthtmlgt echo ltheadgt -echo lttitlegt$tituloltheadgt echo ltheadgt echo ltbodygt

priacutevate function cuerpo()

echo Este es el cuerpo de nuestra Webltbrgt priacutevate function pie()

echo Pie creado con PaginaWeb class echo ltbodygt echo lthtmlgt

public function creaWeb()

$this-gtcabecera($this-gttitulo) $this-gtcuerpo () $this-gtpie ()

$pagina = new PaginaWeb(Pagina Web generada con PHP) $pagina-gtcreaWeb () gt

Lo que hace cada meacutetodo es generar las etiquetas necesarias para crear una paacutegina Web Imagine ahora un gran sitio Web con cientos de paacuteginas Web con distinto tipo de informacioacuten Cambiar el aspecto visual de esa Web seriacutea un trabajo muy laborioso de varios meses primero buscando doacutende se encuentran las etiquetas junto al coacutedigo PHP y segundo modishyficando todo el coacutedigo HTML para que cambie el aspecto visual Las planshytillas solucionan este problema en muy poco tiempo separando el coacutedigo de la presentacioacuten

El resultado se puede ver en la figura 201

La paacutegina Web siguiente p l a n t i l l a r t p l es la misma que genera la clase anterior pero esta vez creada como plantilla

plantillaltpl

Plantillas con Smarty 343

lthtmlgt ltheadgt lttitlegt$titulolttitlegt ltheadgt ltbodygt $cuerpo $pie ltbodygt lthtmlgt

Todas las etiquetas conservan el estilo de HTML antildeadiendo siacutembolos de llave donde debe aparecer contenido dinaacutemico $ t i t u l o $cuerpo y $pie son variables que reciben su valor desde el programa escrito en PHP

Nota

Todo lo que estaacute entre se considera un comentario

344 Capiacutetulo 20

Para poder asignar valores a la plantilla tiene que hacer una instancia de la clase Smar ty

Puede modificar el objeto anterior para que haga uso de plantillas

ltphp class PaginaWeb

priacutevate $titulo priacutevate $Web function construct($titulo)

$this-gttitulo = $titulo requiacutere_once(Smarty1 ibsSmartyclassphp) $this-gtWeb = new Smarty

priacutevate function cabecera($titulo)

$this-gtWeb-gtassign(titulo$this-gttitulo) priacutevate function cuerpo()

$this-gtWeb-gtassign(cuerpoEste es el cuerpo de nuestra Web)

priacutevate function pie ( )

$this-gtWeb-gtassiacutegn(pie Pie creado con PaginaWeb) public function creaWeb()

$this~gtcabecera($this-gttitulo) $this-gtcuerpo () $this-gtpie()

$this-gtWeb-gtdisplay(plantilla1tpl)

$pagina = new PaginaWeb(Pagina Web generada con PHP) $pagina-gtcreaWeb() gt

La clase es exactamente igual (con los mismos meacutetodos) pero ahora se encuentra libre de etiquetas HTML En su lugar aparecen asignaciones a variables de Smarty El constructor instancia un objeto desde la clase Smarshyty y lo guarda en $ t h i s - gtWeb Las asignaciones de variables se hacen con el meacutetodo a s s i g n () que tiene que recibir como primer paraacutemetro el nombre de la variable escrita en la plantilla y como segundo argumento el texto que debe aparecer en lugar de la variable

Plantillas con Smarty 345

Despueacutes de asignar todos los valores tendremos que llamar al meacutetodo d i s -p l a y () con la plantilla como argumento para que la Web aparezca en el navegador

Si se fija ahora en el directorio de las plantillas compiladas t e m p l a t e s _ c veraacute que ha aparecido un archivo que contiene el siguiente coacutedigo

ltphp Smarty versioacuten 263 created on 2004-08-15 130335

compiled from plantillaltpl gt lthtmlgt ltheadgt lttitlexphp echo $this-gt_tpl_vars [ titulo ] bull gt lttitlegt ltheadgt ltbodygt ltphp echo $this-gt_tpl_vars[cuerpo] gt

ltbrxbrgt ltphp echo $this-gt_tpl_vars[pie] gt

ltbodygt lthtmlgt

Como puede apreciar la compilacioacuten de una plantilla de Smarty consiste en cambiar los valores entre llaves por coacutedigo PHP que hace llamadas a las variables Esto lo convierte en un meacutetodo muy raacutepido porque es el mismo PHP el que se encarga de mostrar la plantilla ya compilada

Cuidado con los estilos CSS

Es muy uacutetil utilizar estilos CSS para definir los colores tipos de letra y demaacutes objetos de presentacioacuten que vamos a utilizar en nuestras paacuteginas Web

El problema surge porque su construccioacuten es de la siguiente forma

lts ty l e t y p e = t e x t c s s gt lt - -P colorgreen - - gt ltstylegt

Este estilo sirve para que los paacuterrafos sean por defecto de color verde El problema es que Smarty parsea todo lo que estaacute entre siacutembolos de llave como c o l o r g r e e n En este caso se produciriacutea un error porque el parse no identificariacutea ninguna funcioacuten estructura o variable de plantilla Para solucionar esto se pueden antildeadir las etiquetas l i t e r a l y l i t e -

346 Capiacutetulo 20

r a l que al ser parseadas su contenido se identifica como un comentashyrio y se salta hasta el siguiente juego de llaves

literal ltstyle type=textcssgt lt --P colorgreen mdash gt ltstylegt literal

Llamada a varias plantillas

Casi todas las paacuteginas Web pueden dividirse en varias partes bien difeshyrenciadas cabecera menuacute cuerpo pie

Con Smarty podraacute crear una Web simple que incluya todas las partes de la Web como un uacutenico archivo HTML o crear 4 plantillas distintas y 1 que las unifique por lo que seriacutea maacutes sencillo cambiar el aspecto de cada una de las partes

La funcioacuten i n c l u d e f i l e de Smarty permite antildeadir plantillas a un fishychero La plantilla principal puede ser de la siguiente forma

lthtmlgt ltheadgt lttitlegt$titulolttitlegt ltheadgt ltbodygt include file=cabeceratpl include file=cuerpotpl include file=$pie ltbodygt lthtmlgt

De esta forma podemos modificar alguna de las plantillas y automaacuteticashymente todas las Web que hagan referencia a la misma cambiaraacuten su asshypecto

Como puede ver la plantilla que genera el pie de paacutegina es una variashyble por lo tanto podemos pasar desde PHP el nombre de cualquier planshytilla en funcioacuten de alguacuten caacutelculo interno o de alguacuten dato de MySQL etceacutetera

Variables

Smarty acepta muchos tipos de variables diferentes

Plantillas con Smarty 347

Pueden ser utilizadas para mostrarse directamente o como paraacutemetro de alguna funcioacuten o modificador dentro de alguna estructura de control etshyceacutetera

$nombre $contactonombre $contacto [0] $persona-gtnombre config_load_file=configuracioacutenconf lttitlegttitulolttitlegt

El coacutedigo anterior contiene diferentes tipos de variables y la forma de imshyprimir el dato que nos interesa Para una variable del tipo array puede utilizar la forma asociativa $ c o n t a c t o nombre o la forma indicativa $ c o n t a c t o [0] Tambieacuten es posible mostrar las propiedades de un objeshyto haciendo referencia asiacute $ p e r s o n a - gtnombre

Por uacuteltimo Smarty posee una funcioacuten que permite cargar una configurashycioacuten de un fichero Con la instruccioacuten c o n f iacute g _ l o a d _ f iacute l e cargaraacute en memoria la configuracioacuten del fichero que deacute como argumento El fichero debe estar escrito de esta forma

titulo = Pagina Web con PHP nombre = Luis Miguel color = FFFFFF

Modificadores

Los modificadores se pueden aplicar a las variables funciones o cadenas de caracteres Eacutestos permiten embellecer el texto recortarlo o adecuarlo a un formato determinado Para utilizar un modificador tiene que especifishycar la variable seguido de un siacutembolo de tuberiacutea ( I ) y el nombre del modificador

lthtmlgt ltheadgt cambia el texto a mayuacutesculas lttitlegt$titulo|upperlttitlegt ltheadgt ltbodygt Recorta el texto a 10 caracteres y le suma tren puntos suspensivos $cuerpoiexcltruacutencate10 ltbrxbrgt $pie ltbodygt lthtmlgt

348 Capiacutetulo 20

La plantilla anterior contiene el modificador upper que convierte todos los caracteres que recibe en mayuacutesculas El modificador t r uacute n c a t e recorshyta el texto dejaacutendolo en 10 caracteres y le antildeade puntos suspensivos como puede apreciar en la figura 202 La tabla 201 contiene un conjunto de modificadores que pueden utilizarse en las plantillas

Tabla 201 Modificadores de Smarty

Modificador Descripcioacuten Paraacutemetros

capitalize Convierte la primera letra Ninguno de cada palabra a mayuacutescula

count_characters Se usa para contar los Ninguno caracteres de una variable

cat Concatena el paraacutemetro 1 El texto a concatenar pasado a la variable

count_paragraphs Cuenta el nuacutemero de paacuterrafos Ninguno que contiene una variable

count_words Cuenta el nuacutemero de palabras Ninguno

Plantillas con Smarty 349

Modificador Descripcioacuten Paraacutemetros

date_format Imprime en un formato 1 Formato de salida 2 Si determinado la fecha y hora la entrada estaacute vaciacutea acep-del sistema este paraacutemetro por defecto

default Valor por defecto de la 1 El valor por defecto variable Si no se asigna ninguacuten valor la variable tendraacute el valor por defecto

escape Antildeade caracteres de escape 1 html htmlall url quo-a la variable tes hex hexentity javas-

cript

indent Antildeade varios caracteres a 1 Nuacutemero de caracteres a la izquierda de la variable indentar 2 Caraacutecter elegishy

do para indentar

lower Convierte a minuacutescula todos Ninguno los caracteres

nl2br Convierte los saltos de liacutenea a ltbrgt

regexreplace Busca y reemplaza una 1 Expresioacuten regular 2 Ca-expresioacuten regular dena de texto a reemplazar

replace Reemplaza una cadena de 1 Cadena a reemplazar caracteres por otra 2 Cadena de texto que susshy

tituiraacute al paraacutemetro 1

spacify Inserta un caraacutecter determinado 1 Caraacutecter entre los caracteres de la variable Por defecto un espacio en blanco

string_format Formatea un texto 1 Formato del texto como lo usa s p r i n t f

strip Reemplaza todos los espacios Ninguno saltos de liacuteneas y fabuladores por un espacio en blanco

strip_tags Elimina todas las etiquetas Ninguno

truacutencate Recorta una variable el nuacutemero 1 Nuacutemero de caracteres a de caracteres que indiquen los recortar 2 Texto que debe paraacutemetros aparecer si se recorta 3

True permite recortar en mitad de una palabra

upper Convierte a mayuacutesculas todos los caracteres de una variable

350 Capiacutetulo 20

Es bueno saber que podraacute aplicar varios modificadores a una misma vashyriable Tiene que antildeadirlos en el orden en el que quiera que se ejecuten de izquierda a derecha

$cuerpo[upper|spacify j truacutencate20

Nota

Si la variable es un array se aplicaraacute el modificador a todos ss valores

Funciones

El gestor Smarty tiene varias funciones que se pueden utilizar dentro del aacutembito de las plantillas Ademaacutes puede crear sus propias funciones o modificar las que ya estaacuten construidas

foreach

El bucle foreach se utiliza para mostrar un array simple La sintaxis es algo distinta al bucle de PHP

lttablegt foreach from=$art is tas i tem=valor lt t r x t d gt $ v a l o r lt t d x t r gt foreach lt t ab legt

Lo puede utilizar para antildeadir los valores de un array a una tabla como en el coacutedigo anterior La construccioacuten maacutes baacutesica de fo reach recibe en el atributo f rom el array que contiene los valores El atributo item crea una variable de Smarty que recoge los valores del array y se puede utilizar para mostrar el valor unas liacuteneas maacutes abajo

Otra construccioacuten un poco maacutes compleja es lttablegt foreach name=buclel from=$artistas key=indice item=valor lttrxtdgt $indice $valor lttdxtrgt foreach lttablegt

Funciona exactamente igual que el anterior El atributo key recoge el vashylor del iacutendice del array y ntildeame da un nombre al bucle para poder acceder a eacutel desde las variables propias de Smarty

Plantillas con Smarty 351

Truco

Se puede acceder al bucle mediante la variable global de Smarty Esta variable es $ smar ty Para acceder al bucle puede hacerlo de la siguiente forma $ s m a r t y f o r e a c h b u c l e 1

El resultado de la ejecucioacuten de la plantilla es

0 Paquito DRivera 1 Michel Camilo 2 Jerry Gonzaacutelez

if elseif else

La construccioacuten i f es tan flexible como la sentencia de PHP Cada i f debe tener una pareja del tipo i f

if $artistas[0] = Michel Camilo El primer artista toca el saxofoacuten alto

else El primer a r t i s t a toca e l piano

i f

Ademaacutes de los operadores baacutesicos de PHP tambieacuten puede utilizar mushychos otros como eq ne neq g t l t l t e l e g t e g e i s even i s odd i s n o t odd no t mod d i v by e v e n by o odd by El coacutedigo siguiente es similar al anterior

if $artistas[0] ne Michel Camilo El primer artista toca el saxofoacuten alto

else

El primer artista toca el piano

if

php incluido en plantillas

Puede antildeadir a una plantilla coacutedigo PHP encerrado entre las etiquetas de Smarty php y phpiexcl Si recuerda la filosofiacutea de las plantillas separar el coacutedigo de la presentacioacuten no se me ocurre ninguna excusa para utilizar esta habilidad en alguacuten proyecto por si acaso alguien le encuentra alguacuten sentido su uso es muy sencillo

php Incluir aquiacute alguacuten coacutedigo escrito en PHP include_once(logotiposphp) Php

352 Capiacutetulo 20

assign

Crea una variable y le asigna un valor determinado

assign var=variable value=Michel Camilo El valor de $variable es $variable

Se utiliza en tiempo de ejecucioacuten de la plantilla

counter

Se utiliza para imprimir un contador en pantalla

counter start=0 skip=3 print=falseltbrgt counterltbrgt counterltbrgt counterltbrgt

El atributo s t a r t indica el nuacutemero desde el que va a empezar el contashydor y s k i p el nuacutemero que debe sumarse al contador cada vez que exista una ocurrencia Cada vez que el parse encuentre c o u n t e r se incremenshytaraacute el contador y el navegador mostraraacute el resultado Para el ejemplo anterior podemos obtener

3

6

9

cycle

Una funcioacuten interesante que permite alternar entre varios valores pasashydos Cada vez que se ejecuta se recupera un valor distinto hasta el final de los valores Cuando se llega al final de la lista se vuelve a empezar Es muy uacutetil cuando queremos mostrar valores en una tabla y que cada liacutenea de detalle muestre un color diferente

lttablegt foreach name=buclel from=$artistas key=indice item=valor lttr bgcolor=cycle valueacutes=EEEEEEd0d0d0gtlttdgt$indice $valorlttdxtrgt foreach lttablegt

En este caso el bucle genera nombres de artistas del Jazz Latino y los inshytroduce en una tabla Gracias a la funcioacuten c y c l e se pueden diferenciar unos de otros por tener los colores de fondo de cada liacutenea distintos

Plantillas con Smarty 353

Opciones avanzadas de Smarty

Existen muchos tutoriales en Internet sobre el sistema de plantillas Toshydos abarcan la forma de utilizar las funciones y variables del entorno pero pocos se ocupan de las caracteriacutesticas que lo hacen uacutenico

La arquitectura de Smarty estaacute escrita en PHP Los ficheros que contienen las funciones baacutesicas para que el parse pueda realizar su trabajo estaacuten dentro de c o r e Pero la mayoriacutea de las funciones de presentacioacuten estaacuten incluidas dentro de la carpeta de p l u g i n s

Plugins

Un plugin dentro de la estructura de Smarty es un pequentildeo programa que realiza una tarea determinada Por ejemplo todos los modificadores son plugins y cada uno se encarga de hacer algo con el texto Veamos la estructura del plugin c a p i t a l i z e que recordemos modifica la primera letra de cada palabra y la convierte a mayuacutescula

ltphp function smarty_modifiacuteer_capitalize($string)

return ucwords($string)

gt

El funcionamiento del plugin es obvio Tan soacutelo hace uso de una funcioacuten existente en PHP para mostrar el resultado Puesto que es tan sencillo vamos a crear un plugin que serviraacute para enfatizar nuestro texto en detershyminadas ocasiones

ltphp function smarty_modifier_enfatizar($string)

re turn ltbgt $ s t r ing ltbgt

gt

Para crear un plugin modi f icador cree un fichero con el nombre modif i e r nombre php y guaacuterdelo en el directorio d e p l u g i n s En este caso tendraacute que crear un archivo con el nombre modi f i e r e n f a t i z a r php El nombre de la funcioacuten tambieacuten debe llevar un nombre estructurado Nuestro modificador se llamaraacute s m a r t y _ m o d i f i e r _ e n f a t i z a r y reci-

354 Capiacutetulo 20

biraacute como paraacutemetro la cadena de caracteres que lo utilice Dentro de la funcioacuten puede antildeadir el coacutedigo que sea necesario para cumplir su propoacuteshysito y despueacutes devolver el valor con la funcioacuten re turn

En nuestro caso devolvemos la misma cadena pero antildeadiendo la etiqueta de HTML para mostrar el texto en negrita por lo que quedaraacute enfatizado Tambieacuten podemos antildeadir alguacuten paraacutemetro para elegir entre distintos tishypos de eacutenfasis

ltphp funetion smarty_modifier_enfatizar($string $parametrol)

switch ($parametrol)

case 1 return ltbgt $striacuteng ltbgt break-

case 2 return ltemgt $string ltemgt break

case 3 return i i iexcl $string break

default return ltbgt $string ltbgt

gt

Ahora tenemos tres formas distintas de mostrar un texto que llame la atenshycioacuten Para invocar desde la plantilla cualquiera de los tipos de eacutenfasis hashybraacute que separar el modificador con un siacutembolo de dos puntos ( )

$valor|enfatizar3

Filtros

Los filtros son funciones que realizan una tarea determinada en nuestra plantilla justo antes o despueacutes de que sea compilada Se pueden consideshyrar los pre-filtros y los post-filtros respectivamente Existe un tercer tipo de filtro que se ejecuta en el momento de la llamada al meacutetododisplay ()

Crear un filtro para Smarty es tan sencillo como crear un plugin Hay que seguir estrictamente la nomenclatura del archivo y del nombre de la funshycioacuten para que funcione correctamente

ltphp function smarty_jostfilter_HechoCon($compiled amp$smarty)

Plantillas con Smarty 355

return $compiled ltbgtHecho con Smartyltbgt

gt

El filtro HechoCon () es una funcioacuten que recibe como paraacutemetros la fuente de la paacutegina Web ya compilada y el objeto Smarty que estamos utilizanshydo Nuestro filtro HechoCon devuelve la Web y antildeade un pequentildeo texto que indica que ha sido creado con Smarty

Para poder utilizar el filtro tenemos que cargarlo antes de utilizar el meacuteshytodo d i s p l a y ( ) en nuestro coacutedigo Esto se hace con la funcioacuten l o a d _ f i l t e r ( )

$this-gtWeb- gtload__f ilter (pre trim) $this-gtWeb-gtload_filter(postHechoCon) $this-gtWeb-gtload_filter(outputcompress)

El primer paraacutemetro del meacutetodo l o a d _ f i l t e r () indica el tipo de filtro que vamos a cargar y el segundo el nombre que recibe

Resumen

Alguacuten lector se preguntaraacute despueacutes de entender correctamente lo bueno que es separar el coacutedigo de la presentacioacuten por queacute he esperado tanto tiempo en contar el secreto de Smarty La verdad es que es mejor aprenshyder PHP paso a paso haciendo pequentildeos programas con HTML embebishydo para despueacutes ir concibiendo la mejor forma de atajar los diferentes proyectos que nos propongan

Con Smarty tiene una viacutea libre de exploracioacuten maacutes porque muchas de sus caracteriacutesticas no han podido ser tratadas en este capiacutetulo Le queda aveshyriguar coacutemo utilizar la cacheacute los recursos (habilidad para leer de una base de datos una plantilla) y las numerosas funciones que hemos dejado en el tintero Una vez que conozca la potencia de Smarty no querraacute mezclar nunca maacutes su coacutedigo con HTML

358 Apeacutendice A

Antes de comenzar

El primer paso para desarrollar programas en PHP 5 es encontrar un sershyvidor donde hacer las pruebas del programa y posteriormente dejarlo almacenado para que los usuarios puedan utilizarlo Este servidor debeshyriacutea estar disponible las 24 horas del diacutea con una conexioacuten fija a Internet

Como esto puede ser algo complicado al principio vamos a ver los pasos necesarios para instalar un servidor de pruebas donde escribir nuestros primeros scripts

PHP 5 se distribuye como coacutedigo fuente listo para compilar en el sistema operativo que quiera El problema es que es algo complicado si nunca ha compilado un programa Por eso he elegido paquetes ya compilados que soacutelo necesitan ser instalados para comenzar a funcionar

Vamos a instalar los siguientes programas

bull Servidor Web Apache

bull PHP 5

bull MySQL 4

Instalacioacuten en MacOSX

Uno de los maacutes excitantes desarrollos Open Source ha sido la apertura parshycial del coacutedigo de la plataforma Macintosh Gracias a esto muchos usuashyrios estaacuten contribuyendo con la creacioacuten de paquetes de instalacioacuten como el de PHP 5

Apache

El servidor Web Apache es necesario para enviar las peticiones HTTP de los clientes

Afortunadamente Apache viene ya instalado en MacOSX Para ponerlo en funcionamiento tendraacute que seguir los siguientes pasos

bull Abra una Terminal

bull Entre como suacuteper usuario con el comando su

bull Introduzca la passzvord de suacuteper usuario

bull Escriba a p a c h e c t l s t a r t

La figura A l muestra los pasos realizados en el terminal para iniciar el servidor Web A partir de ahora puede probar si funciona Apache escribiendo en el nashyvegador la direccioacuten l o c a l h o s t como muestra la figura A2

360 Apeacutendice A

PHP5

Existe una Web dedicada al mundo de MacOSX que se actualiza todos los diacuteas

Su administrador L i y a n a g e es el encargado de crear paquetes con toshydas las versiones de PHP 5 que ven la luz que en el momento de redactar el libro es la 501

Para instalar PHP 5 tendraacute que descargar el paquete de

ht tp www2entropychdownloadEntropy-PHP-5-01-1dmg

Una vez copiado el archivo en su sistema soacutelo tiene que hacer doble clic en eacutel y seguir los pasos de instalacioacuten del sistema operativo como puede ver en la figura A3

MySQL 4

Los pasos son exactamente igual que en la instalacioacuten de PHP 5

El primer paso es descargar el paquete para MacOSXmysql - s t a n d a r d -4 0 2 0 - a p p l e - d a r w i n 7 3 0 -powerpc dmg que se encuentra en la seccioacuten de descargas de la Web wwwmysql com

El paquete se instala como cualquier paquete de MacOSX simplemente haciendo doble clic

Instalacioacuten de PHP 5 y MySQL 361

Comprobacioacuten final

Para comprobar que todo funciona correctamente tendraacute que seguir los pasos siguientes

bull Abra una Terminal

bull Entre como suacuteper usuario con el comando su

bull Introduzca la password de suacuteper usuario

bull Reinicie la ejecucioacuten de Apache para que acepte la nueva configurashycioacuten de PHP 5 con el comando a p a c h e c t l r e s t a r t

bull Inicie MySQL con el comando u s r l o c a l m y s q l - s t a n d a r d -4 0 2 0 - a p p l e - d a r w i n 7 3 O - p o w e r p c b i n m y s q l d - u r o o t

bull Cree una Web de prueba y guaacuterdela en la ruta del usuario para paacutegishynas Web Normalmente es U s e r s u s u a r i o S i t e s

bull Abra el navegador y escriba la direccioacuten del servidor junto con el nomshybre de la Web La direccioacuten seraacute parecida a esta l o c a l h o s t - u s u a shyr i o i n f o r m a c i oacute n php

El programa que hemos escrito para comprobar que todo funciona correcshytamente y muestra el contenido de la figura A4 es

ltphp

362 Apeacutendice A

p h p i n f o ( ) gt

En la figura A4 puede ver el funcionamiento de todo el sistema instalado

Instalacioacuten en Windows

Instalar un sistema completamente funcional en un sistema operativo Windows puede ser tan sencillo o tan complicado como quiera Existe un paquete de aplicaciones llamado XAMPP que contiene todo lo necesario para funcionar con Apache PHP 5 y MySQL

En la Web wwwapachefriendsorg puede encontrar un archivo de instashylacioacuten de Windows

Despueacutes de descargar el archivo tiene que hacer doble clic y seguir las instrucciones impresas en pantalla como muestra la figura A5

Una vez instalado en la ruta lniciogtProgramasgtapachefriendsgtxampp veraacute tres apartados importantes

bull xampp basic start Se encarga de iniciar Apache PHP 5 y MySQL

bull xampp basic stop Para la ejecucioacuten de los servidores

bull xampp httpdoc folder Carpeta donde tiene que guardar todos sus programas escritos en PHP 5

Para probar que todo funciona puede ejecutar el programa xampp bashys i c s t a r t abrir un navegador y escribir como direccioacuten l o c a l h o s t Si

Instalacioacuten en gnuuumlnux

Existen en el mercado varias versiones de gnuLinux como gnuLinEx 2004 SuSe RedHat Gentoo Cada una de ellas posee un sistema de paquetes distinto Puesto que no tenemos espacio para describir 3 formas diferenshytes de instalar PHP 5 nos conformaremos con describir un tema general que sirve para todos los sistemas gnuLinux

Como ya puede imaginar nos vamos a apoyar en X A M P P para gnushyLinux

Una vez descargada la versioacuten para gnuLinux en el disco duro tendraacute que descomprimirla en un directorio El archivo comprimido deberiacutea llamarse x a m p p - l i n u x - 1 4 7 t a r g z Para instalarlo debe seguir los pasos sishyguientes

bull Descomprima con el comando g z i p -d x a m p p - l i n u x - 1 4 7 t a r g z

bull Vuelva a descomprimir el archivo esta vez con t a r x v f x a m p p - l i -n u x - 1 4 7 t a r

Instalacioacuten de PHP 5 y MySQL 363

todo se instaloacute correctamente podraacute ver una Web parecida a la de la figushyra A6

364 Apeacutendice A

bull Se crearaacute una carpeta llamada lampp

bull Copie la carpeta al directorio op t con el comando cp -r lampp opt

bull Ya lo tiene instalado Para ejecutarlo debe ser suacuteper usuario e invocar el comando opt lampp lampp s t a r t

La figura A7 muestra un terminal con el comando de inicio

En la figura A8 puede ver la paacutegina de inicio de XAMPP tras poner en el navegador l o c a l h o s t como direccioacuten Web Todas las paacuteginas Web que genere tendraacute que guardarlas en el directorio op t l ampp h tdocs para poder verlas a traveacutes del navegador

Recomendacioacuten final

La forma maacutes raacutepida y sencilla de hacer funcionar PHP 5 en su sistema es la que hemos visto pero no es la mejor La forma maacutes recomendable que se escapa del enfoque de este libro es compilar su PHP 5 De esta manera tendraacute la posibilidad de antildeadir los

Instalacioacuten de PHP 5 y MySQL 365

moacutedulos y extensiones que realmente vaya a utilizar La recomendacioacuten es que navegue por la Web wwwphpnet e investigue la forma de compishylar su sistema

368 Apeacutendice B

Introduccioacuten

El archivophp i n i contiene informacioacuten de configuracioacuten que puede moshydificar a su antojo Es un fichero de texto que se lee cada vez que se inicia el servidor Web Apache Para averiguar la ruta del disco duro donde se almacena el archivo php i n i soacutelo tiene que fijarse en el apartado Conf i g u r a t i o n F i l e (php i n i ) Path de la Web que recibioacute al ejecutar phpinf o () La configuracioacuten contiene parejas de variables valores separadas por puntos y comas Los valores que tenemos que asignar suelen ser rutas del disco duro 10 Yes No On Off o True False Cada vez que cambie alguna parte de la configuracioacuten tendraacute que reini-ciar Apache para que los cambios surtan efecto

short_open_tag

Permite la forma corta de antildeadir scripts de PHP de la forma lt gt Si quiere utilizar funciones XML es mejor dejarlo a Off

disable_functions

Desactiva funciones que nos resulten peligrosas como el enviacuteo de correos funciones de red etceacutetera

max_execution_time

Tiempo maacuteximo de ejecucioacuten de un script PHP en el servidor

error_reporting

Muestra el nivel de error que configure cuando un script falla Los tipos de errores los puede ver en el capiacutetulo 17

register_globals

Esta configuracioacuten ya no se utiliza a partir de la versioacuten PHP 42 y estaacute destinada a desaparecer

Configuracioacuten de phpini 369

Si la activa todas las variables seraacuten pasadas como globales y no dentro de las variables suacuteper globales

magic_quotes_runtime

Antildeade el siacutembolo de escape cuando se pasan variables con los siacutembolos de comillas simples o dobles

include_path

Antildeade rutas donde puede almacenar libreriacuteas que pueda utilizar sus proshygramas

Resumen

Hemos visto las principales opciones de configuracioacuten del archivo php i n i La configuracioacuten es mucho maacutes extensa pero no merece la pena indagar en otras opciones a menos que vaya a dedicarse a la administrashycioacuten del Sistema

372 Apeacutendice C

Bibliografiacutea

El desarrollo del libro ha sido posible gracias a la consulta de numerosas publicaciones escritas paacuteginas Web y revistas profesionales que han dado una visioacuten actual de la programacioacuten en PHP 5 La bibliografiacutea presente en este libro muestra un compendio de libros revistas y paacuteginas Web que pueden ser uacutetiles al lector si decide ampliar sus conocimientos una vez terminado este libro

Libros de PHP 5

bull PHP5 and MySQL Bible Tim Converse y Joyce Park Completo libro que abarca numerosos temas Especializado en generar bases de datos con MySQL y PHP 5

bull The PHP Anthology Harry Fuecks El mejor libro sobre PHP esshycrito nunca Abarca casi todos los temas importantes a la hora de crear un sitio Web profesional Todos los scripts estaacuten cuidadosashymente pensados y orientados a objetos El autor es uno de los proshypulsores de los patrones de disentildeo

bull Learning PHP5 David Sklar Contenido muy sencillo pero direcshyto Para aprender PHP 5 desde 0

bull PHP5 for Dummies Janet Valade Un buen libro para aprender y profundizar en varias aacutereas Desde luego el teacutermino Dummies no le hace justicia porque a veces se hace algo complicado de seguir

bull Proyectos Profesionales PHP Ashish Wilfred Meeta Gupta Kartik Bhatnagar Proyectos orientados a PHP 4 pero muy bien construidos

bull PHP 4 Esteban Trigos Libro muy sencillo para iniciarse en PHP 4 bull PHP 5 Power Programming Andi Gutmans De uno de los creashy

dores de PHP Muy bien enfocado y con muacuteltiples temas bull Beginning PHP 5 Equipo Wrox Libro extenso sobre PHP 5 Cubre

todo lo que se puede conocer sobre PHP 5 En Octubre saldraacute la seshygunda parte llamada Proffesional PHP 5

Revistas profesionales

bull PHP Solutions Revista polaca traducida al espantildeol Contiene muy buenos artiacuteculos sobre desarrollo actual con PHP

Bibliografiacutea 373

bull PHP Magazine Revista alemana de gran alcance bull PHP Architect Revista canadiense donde habitualmente escriben

desabolladores como Harry Fuecks Marco Tabini o Andi Gutmans La misma editora de esta revista ha sacado el libro de estudio para preshysentarse al examen de Certificacioacuten de PHP

Paacuteginas Web

bull wwwphpsolmagorg Web de la revista PHP Solutions bull wwwphpmagnet Web de la revista PHP Magazine bull wwwphparchcom Web de la revista PHP Architect bull wwwsinuhorg Comunidad GnuLinux de Extremadura

bull wwwphpbuildercom Comunidad de usuarios con mucho coacutedishygo libre

bull wwwluisyfernandanet Web del autor bull wwwphppatternscom La Web de Harry Fuecks bull wwwphpnet Web oficial de PHP

bull wwwzendcom La empresa que hay detraacutes de PHP Ofrece curshysos y seminarios on-line

bull wwwcodewalkerscom Web con mucho coacutedigo libre

Page 3: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo

Todos los nombres propios de programas sistemas operativos equipos hardware etc que aparecen en este libro son marcas registradas de sus respectivas compantildeiacuteas u organizaciones

Reservados todos los derechos El contenido de esta obra estaacute protegido por la ley que estashyblece penas de prisioacuten y o multas ademaacutes de las correspondientes indemnizaciones por dantildeos y perjuicios para quienes reprodujeren plagiaren distribuyeren o comunicasen puacuteblishycamente en todo o en parte una obra literaria artiacutestica o cientiacutefica o su transformacioacuten interpretacioacuten o ejecucioacuten artiacutestica fijada en cualquier tipo de soporte o comunicada a traveacutes de cualquier medio sin la preceptiva autorizacioacuten

copy EDICIONES ANA YA MULTIMEDIA (GRUPO ANAYA SA) 2004 Juan Ignacio Luca de Tena 15 28027 Madrid Depoacutesito legal M-44920-2004 ISBN 84-415-1785-1 Printed in Spain Imprime Artes Graacuteficas Guemo SL Febrero 32 Madrid 28022

A mi mujer Mariacutea Fernanda por creer en nuestro Proyecto de vida

Agradecimientos

Finalizar este libro ha sido una odisea donde han intervenido muchas personas y factores mudanza incluida Para empezar me gustariacutea agradecer a Marta Camarero y a Eugenio Tuya su fe en miacute como escritor Me dieron aacutenimos desde el principio y un poquito de prisa A Zeev Suraski y Andi Gutmans creadores de PHP 5 por crear el lenguashyje y tratarme como a uno de los suyos en los iquestseminar de wwwzendcom Ademaacutes tengo que agradecerles la rapidez con la que escribieron el proacuteshylogo del libro A Marco Tabini director de la revista canadiense PHParchitect por enshyviarme el manual de Certificacioacuten PHP en papel y no en PDF A Tim Converse y Joyce Park por escribir PHP5 and MySQL Bible cuyos conocimientos me bebiacute en apenas 3 diacuteas A Harry Fuecks por escribir el mejor libro de PHP de todos los tiempos The PHP Anthology que me hizo reorientar todos los esfuerzos a la innoshyvacioacuten

A la Asociacioacuten Regional de Universidades Populares de Extremadura (AUPEX) por probar todos mis programas escritos en PHP (libros de visita foros nccproject newton etceacutetera) Espero dar alguacuten diacutea con la tecla A mis compantildeeros de trabajo Pako Palomo Javi y Pedro por las largas horas de discusioacuten en torno a Delphi Java C y por supuesto PHP A Justo Cabezas porque todo lo que me regaloacute fueron libros de informaacuteshytica y encima escritos por eacutel Sigo tus pasos A los grupos de usuario de gnuLinux de Extremadura wwwsinuhorg y wwwgulexorg por ser una fuente inagotable de conocimientos Por uacuteltimo A mi padre Ramoacuten que ya no estaacute a mi madre Felisa y a mi hermano Felipe porque nunca entendieron nada de informaacutetica pero me animashyron a seguir adelante con todo lo que me propuse Al resto de la familia porque cada uno de ellos ha tenido algo que ver en miacute vida y forman parte de lo que soy

iacutendice

Coacutemo usar este libro 19 Destinatarios de este libro 20 Organizacioacuten del libro 20 Convenios que emplea este libro 25 Los ejemplos en la Web de Anaya 26

Proacutelogo 27

Introduccioacuten 29 Historia de PHP 30 Nuevas Caracteriacutesticas de PHP 5 31

Faacutecil de usar 31 Embebido en HTML 32 Multiplataforma 33 Licencia Open Source 34 Multitud de Extensiones 34 Velocidad e incorporacioacuten de objetos 34 Popularidad 35 Gran Comunidad de apoyo 35

Objetivos del libro 36

1 Introduccioacuten a PHP 5 39 Introduccioacuten 40

8 iacutendice

HTML estaacutetico 40 Tecnologiacuteas del lado del cliente 42 Tecnologiacuteas del lado del servidor 43 Etiquetas de PHP 45 Nuestro primer programa en PHP 5 46 Repaso de HTML 47

Cabecera y cuerpo de una paacutegina Web 47 Cabecera 48 Cuerpo del documento 48 Paacuterrafos y saltos de liacuteneas 49 Estilo de texto 49 Enlaces de texto 51 Listas 51 Imaacutegenes 52 Tablas 53

Resumen 54

2 Variables constantes y tipos de datos 55 Variables en PHP 5 56

Tipos de Variables 56 Asignacioacuten de variables 57

Tipos simples 57 Enteros (integer) 58 Nuacutemeros de coma flotante (double) 59 Cadena de caracteres (string) 59 Boolean 61 NULL 62

Variables de variables 62 Constantes 63

defined() 63 Constantes predefinidas 64

Funciones relacionadas con variables 65 isset() 65 unsetQ 66 gettype() 66 settype() 67 empty() 67 is_integer() is_double() is_string() 67 intvalQ doublevalQ strvalQ 68

Resumen 68

iacutendice 9

3 Operadores 69

Introduccioacuten 70 Operador de asignacioacuten 70 Operador Unario 71 Operadores Aritmeacuteticos 71 Operadores de comparacioacuten 71 Operadores Loacutegicos 73 Operador Ternario 74 Operadores bit a bit 74 Operadores de asignacioacuten combinados 75 Operador de ejecucioacuten 76 Operador de supresioacuten de errores 77 Precedencia de Operadores 78 Resumen 80

4 Estructuras de control 81

Introduccioacuten 82 Estructuras de eleccioacuten 82

if-else 82 elseif 83 switch 84

Bucles 86 while 86 do-while 89 for 89

break y continueacute 92 Finalizar la ejecucioacuten de un programa 93 Sintaxis alternativa 93 Resumen 94

5 Funciones 95 Introduccioacuten 96 Valores de las funciones 96 Funcioacuten de ejemplo Obtencioacuten de la fecha actual 97 Documentacioacuten sobre funciones 98 Funciones de usuario 99

Definicioacuten de funciones 99 Paraacutemetros insuficientes 101 Paraacutemetros en exceso 102

10 iacutendice

Aacutembito de las variables 102 Variables estaacuteticas 104

Include() y require() 105 Recursividad 105 Funciones con nuacutemero de argumentos variables 106

Argumentos por defecto 106 Argumentos mediante un array 107 Muacuteltiples argumentos con func_num_args() 109

Llamadas por valor 110 Llamadas por referencia 111

Referencia a variables 112 Funciones variables 113 Resumen 114

6 Cadenas de caracteres y expresiones regulares 115 Introduccioacuten 116 Propiedades de las cadenas 116

iacutendices de string 116 Operadores 118 Sintaxis para muacuteltiples liacuteneas 118

Funciones de string 119 Tamantildeo de la cadena 120 Posicioacuten de los caracteres 120 Comparacioacuten 121 Buacutesqueda de caracteres 122 Seleccioacuten de subcadenas 122 Funciones de limpieza de cadenas 124 Sustitucioacuten de cadenas 126 Funciones de mayuacutescula y minuacutescula 126

Expresiones regulares 127 Comprobar expresiones regulares 129 Reemplazar patrones 131

Resumen 131

7 Conjuntos de datos del tipo array 133

Introduccioacuten 134 Creacioacuten de arrays 134

Asignacioacuten directa 134 array() 135 Funciones que devuelven arrays 136

iacutendice 11

Arrays multidimensionales 136 Propiedades de arrays 137

count() 1 3 7

in_array() 137 Borrar ocurrencias 138 Interactuar con arrays 138

Funciones para avanzar en un array 140 Funciones para retroceder en un array 142 Intercambio de valores 143 Inversioacuten del contenido 144 Mezcla de los valores 145

Pilas 145 Ordenacioacuten de los valores 146 Resumen 148

amp Paso de informacioacuten entre formularios 149

Introduccioacuten 150 Argumentos GET 150

Formularios con GET 151 Paso de informacioacuten con GET 155

Argumentos POST 157 Variables suacuteper-globales 158 Resumen 159

9 Programacioacuten orientada a objetos bull bull 1 6 1

Introduccioacuten 162 Definicioacuten de clases 163

Instancia de clase 164 Funcioacuten constructor 165

Herencia 165 Meacutetodos o funciones de objeto 166 Herencia encadenada 168 Valores y alcance de variables 168

Miembros puacuteblicos privados y protegidos 170 Meacutetodos privados 170 Meacutetodos protegidos 171 Meacutetodos puacuteblicos 171

Interfaces 172 Clases abstractas 172 Clases con meacutetodos estaacuteticos 173

12 iacutendice

Llamadas a funciones padre 174 Sobrecarga de meacutetodos 176 Sentildealizacioacuten 176 Funciones de manejo de clases 177 Resumen 179

10 Ficheros y almacenamiento de datos 181 Introduccioacuten 182 Funciones de lectura y escritura de ficheros 182

Abrir el fichero 182 Lectura de ficheros 183 Escritura de ficheros 185

Sistema de ficheros y directorios 188 Copiar borrar y renombrar 188 Funciones de comprobacioacuten 189 Directorios 190

Ficheros de configuracioacuten 191 Manejo de ficheros en el servidor 193

Subida de ficheros 193 Descarga de ficheros 195

Resumen 197

11 Bases de datos con SQL y SQLite 199 Introduccioacuten 200 SQL 200

SELECT 202 Uniones 203

INSERT 205 UPDATE 206 DELETE 207

Definicioacuten de tablas 207 SQLite 208

Creacioacuten de bases de datos 209 Uacuteltimos cambios en una tabla 211 Seleccioacuten de datos 212

SQLite orientado a objetos 213 Seleccioacuten de registros 214 Funciones de Array para recuperar datos 215 Nuacutemero de filas 216 Moverse entre registros 216

Resumen 218

iacutendice 13

12 PHP 5 y MySQL 219 Introduccioacuten 220 Administracioacuten de usuarios 220 Conexioacuten a MySQL 220

Seleccionar datos 222 Manipulacioacuten de datos 224

Insertar una fila 224 Actualizar una fila 225 Borrar una fila 225

Errores con las comillas 226 Contando filas 228

Contar filas con PHP 228 Contar filas con MySQL 229

Contar filas afectadas 230 Uacuteltimo nuacutemero insertado 230 Buacutesquedas dentro de una tabla 231 Definicioacuten de bases de datos 231

Creacioacuten de bases de datos 231 Creacioacuten de tablas 231

Resumen 233

13 Sesiones y Cookies 235 Introduccioacuten 236 Sesiones en PHP 5 237

Instanciando sesiones 237 Variables de sesioacuten 239 Problemas con los navegadores 240 Funciones para el manejo de sesiones 241

Cookies 243 setcookie() 243 Borrar una cookie 244

Cabeceras HTTP laquo 245 Resumen 246

14 Lectura y escritura de archivos XML 247 Introduccioacuten 248 SAXDOMySimpleXML 250 SAX 250 DOM 254

14 iacutendice

Usar DOM para leer archivos 255 Todo es un objeto 255 Atributos 256 Buacutesquedas muacuteltiples 257

Escribir archivos XML con DOM 257 Modificar archivos XML 259

SimpleXML 259 Resumen 261

15 Aplicaciones praacutecticas de XML 263 Introduccioacuten 264 Compartir informacioacuten con RSS 264

Distintos formatos 264 Leer un archivo RSS 268 Escribir archivos RSS 269

Servicios Web XML-RPC 272 Clase IXR 273 Cliente XML-RPC 274 Servidor XML-RPC 275 Usos de XML-RPC 277

Resumen 277

16 Generacioacuten de graacuteficos con PHP 5 279 Introduccioacuten 280 Graacuteficos HTML 280

Graacuteficos de barras 284 Libreriacutea GD 285

Tipos MIME 285 Mostrar una imagen en pantalla 286 Crear imaacutegenes en miniatura 288 Generar una marca de agua 290

Graacuteficos estadiacutesticos profesionales con JpGraph 292 Graacuteficos de barras 292 Graacuteficos en 3D 295

Resumen 297

17 Gestioacuten de errores en PHP 5 299 Introduccioacuten 300 Errores y Excepciones 300

iacutendice 15

La clase Exception 301 Bloque Try Catch 303 Heredar de la clase Exception 304 Limitaciones de PHP 5 305

Control de errores sin excepciones 306 Errores nativos de PHP 306 Controladores de error 307 Errores de usuario con trigger_error() 308

Depuracioacuten de errores 308 Resumen 309

18 Conexiones desde PHP 5 311

Introduccioacuten 312 FTP 312

Mostrar los archivos remotos 314 Descargar y Enviar ficheros 315 Otras funciones de FTP 316

Correo electroacutenico 317 Enviar correo desde PHP 318

PHPMailer 319 Antildeadir un fichero adjunto 320

Resumen 322

19 Creacioacuten de archivos PDF 325

Introduccioacuten 326 Libreriacutea FPDF 326

Nuestro primer documento 327 Funciones de texto 328

Meacutetodo Write() 328 Meacutetodo Cell() 329

Desplazamiento de los cursores 330 Salto de paacutegina automaacutetico 330

Sobrescribir los meacutetodos 331 Cabecera 331 Imagen de cabecera 332 Pie de paacutegina 333

Tablas 334 Enlaces 337 Resumen 338

16 iacutendice

20 Plantillas con Smarty 339

Introduccioacuten 340 Instalacioacuten de Smarty 341 Utilizacioacuten baacutesica de Smarty 341

Cuidado con los estilos CSS 345 Llamada a varias plantillas 346 Variables 346 Modificadores 347

Funciones 350 foreach 350 if elseif else 351 php incluido en plantillas 351 assign 352 counter 352 cycle 352

Opciones avanzadas de Smarty 353 Plugins 353 Filtros 354

Resumen 355

Apeacutendice A Instalacioacuten de PHP 5 y MySQL 357

Antes de comenzar 358 Instalacioacuten en MacOSX 358

Apache 358 PHP 5 360 MySQL 4 360 Comprobacioacuten final 361

Instalacioacuten en Windows 362 Instalacioacuten en gnuLinux 363 Recomendacioacuten final 364

Apeacutendice B Configuracioacuten de phpini 367 Introduccioacuten 368

short_open_tag 368 disable_functions 368 max_execution_time 368 error_reporting 368 register_globals 368 magic_quotes_runtime 369

iacutendice 17

include_path 369

Resumen 369

Apeacutendice C Bibliografiacutea 371 Bibliografiacutea 372

Libros de PHP 5 372 Revistas profesionales 372 Paacuteginas Web 373

Glosario 375

iacutendice alfabeacutetico 381

Coacutemo usar este libro

20 Coacutemo usar este libro

Destinatarios de este libro

Este libro estaacute dirigido a usuarios noveles que no sepan programar en ninshyguacuten lenguaje de desarrollo y a usuarios que ya conocen PHP pero desean tener una base soacutelida sobre la nueva versioacuten

PHP 5 estaacute ligado a Internet por lo tanto todas las aplicaciones praacutecticas del lenguaje estaacuten orientadas a realizar contenidos dinaacutemicos para paacutegishynas Por eso el lector debe conocer los aspectos baacutesicos de disentildeo en HTML

El libro puede dividirse en dos partes Una primera en la que se detallan los conceptos principales del lenguaje como las variables estructuras de control manejo de cadenas de caracteres creacioacuten de objetos y conectivi-dad con bases de datos que daraacute al lector novel una visioacuten general de PHP 5 y le permitiraacute comenzar a desarrollar sus primeras aplicaciones La segundaparte algo maacutes compleja haraacute las delicias del usuario novel y del medio Esta cuenta con teacutecnicas avanzadas para la lectura escritura de archivos XML creacioacuten de imaacutegenes en tiempo de ejecucioacuten conexioshynes de FTP y correo electroacutenico o disentildeo de plantillas con Smarty

El Software Libre estaacute presente en el aacutembito de la programacioacuten Por eso podemos utilizar algunos programas libres como base para construir aplishycaciones maacutes complejas El disentildeo de plantillas o la creacioacuten de llamadas a procedimientos remotos no seriacutea posible sin las libreriacuteas Smarty o IXR para XML-RPC desarrolladas por la comunidad de PHP para su uso libre

Por tanto el libro va dirigido a usuarios noveles que no saben nada de PHP Pero tambieacuten a usuarios medios o avanzados que desean conocer las nuevas caracteriacutesticas de PHP 5 y manejar teacutecnicas avanzadas de coshymunicacioacuten y disentildeo

Organizacioacuten del libro

Este libro estaacute dividido en 20 capiacutetulos con los siguientes contenidos

bull Capiacutetulo 1 Introduccioacuten a PHP 5 La introduccioacuten a PHP hace un reshycorrido por las nociones baacutesicas de HTML Ademaacutes aprenderaacute coacutemo crear su primera paacutegina en PHP y coacutemo mezclar el coacutedigo HTML con PHP

bull Capiacutetulo 2 Variables constantes y tipos de datos Los valores que manejamos en los programas deben ser almacenados en zonas de me-

PHP 5 21

moria reservadas por PHP Estas zonas reciben el nombre de variables y pueden ser tratadas de diferentes forma dependiendo de los valores que guarden (nuacutemeros enteros cadenas de caracteres valores boolea-nos) Este capiacutetulo contiene todo lo necesario para comprender coacutemo maneja PHP 5 las variables y las constantes estableciendo una diferenshycia con otros lenguajes fuertemente tipados como Java o C

bull Capiacutetulo 3 Operadores Otro aspecto de los lenguajes de programashycioacuten tiene que ver con los siacutembolos que se utilizan para realizar operashyciones aritmeacuteticas loacutegicas o de asignacioacuten Cada uno de los siacutembolos recibe el nombre de operador Este capiacutetulo muestra por grupos todos los operadores con los que se puede encontrar en PHP 5 Asiacute podraacute ver operadores especializados en sumas restas multiplicaciones o dishyvisiones (aritmeacuteticos) operadores de igualdad desigualdad o asignashycioacuten (de comparacioacuten) incluso operadores de manejo a nivel de bits (binarios)

bull Capiacutetulo 4 Estructuras de control El flujo de los programas viene deshyterminado siempre por las estructuras de control Estas indican en cada momento el rumbo que debe llevar el coacutedigo y lo que debe mostrar nuesshytra paacutegina basaacutendose en el valor contenido en las variables Las estrucshyturas de control y los operadores estaacuten iacutentimamente relacionados y su unioacuten permite desviar a evolucioacuten del programa en uno u otro sentido Las estructuras de control que veraacute en este capiacutetulo le daraacuten la potencia suficiente para crear sus primeros programas funcionales

bull Capiacutetulo 5 Funciones Si su coacutedigo se hace muy extenso a medida que avanza en la comprensioacuten del libro en este capiacutetulo aprenderaacute a remeshydiarlo Las funciones permitiraacuten al lector agrupar fragmentos de coacutedishygo repetitivo y aislarlo en ficheros independientes Este capiacutetulo no soacutelo cubre los aspectos teoacutericos para la creacioacuten de funciones sino que adeshymaacutes es un compendio de buenas praacutecticas a tener en cuenta para que sus proyectos se desarrollen ordenadamente Los aspectos baacutesicos a trashytar son la creacioacuten de funciones propias y el paso de paraacutemetros entre funciones de varias formas diferentes

bull Capiacutetulo 6 Cadenas de caracteres y expresiones regulares La mayor parte de la informacioacuten que puede encontrar en las paacuteginas es texto Conocer todas las teacutecnicas para concatenar medir cortar y buscar texshytos es baacutesico para crear un proyecto basado en contenido dinaacutemico Un perioacutedico digital un Log o incluso su propio CMS ya no tendraacuten seshycretos despueacutes de leer este capiacutetulo Ademaacutes la gran potencia de buacutesshyqueda de patrones viene de la mano de las expresiones regulares Eacutestas

22 Coacutemo usar este libro

permiten encontrar palabras frases y patrones dentro de un texto deshyterminado para manipularlo a nuestro antojo

bull Capiacutetulo 7 Conjuntos de datos del tipo array Este capiacutetulo trata a fonshydo las colecciones de datos PHP 5 maneja los conjuntos de datos como arrays asociativos Es posible acceder a los valores de un array de forma simple utilizando un iacutendice como en C y de forma asociativa asocianshydo una palabra a un valor determinado dentro del array Los arrays tieshynen un incalculable valor en los posteriores capiacutetulos usaacutendose como valor de retorno de muchas funciones de conectividad de bases de dashytos lectura de archivos XML o creacioacuten de plantillas

bull Capiacutetulo 8 Paso de informacioacuten entre formularios Si en el capiacutetulo 1 pudo ver los conceptos baacutesicos de la creacioacuten de paacuteginas en este podraacute conocer las teacutecnicas para enviar informacioacuten a traveacutes de formularios La mayoriacutea de las paacuteginas utilizan formularios para interactuar con los usuashyrios Aprenderaacute a pasar variables y arrays entre dos paacuteginas y coacutemo recoshyger desde PHP 5 los valores que se enviacutean Ademaacutes podraacute saber la diferencia entre los meacutetodos GET y POST y las variables suacuteper-globales

bull Capiacutetulo 9 Programacioacuten orientada a objetos El gran avance queacute ha sufrido PHP 5 desde su versioacuten anterior ha sido la total incorporacioacuten de la sintaxis y teacutecnica orientada a objetos Esto permite desarrollar proshygramas reutilizables en varios proyectos Una de las ventajas de la proshygramacioacuten orientada a objetos es que nos permite utilizar software de otras personas simplemente conociendo los meacutetodos que implementa no es necesario conocer coacutemo funciona el objeto para utilizarlo En este capiacutetulo el usuario novel y medio aprenderaacute las nuevas caracteriacutesticas de la programacioacuten orientada a objetos de PHP 5 A partir del capiacutetulo 9 casi todos los ejemplos estaraacuten basados en esta metodologiacutea de trabajo

bull Capiacutetulo 10 Ficheros y almacenamiento de datos La forma maacutes natushyral de almacenar datos persistentes es guardarlos en un fichero de dashytos Es una tarea muy sencilla y no dependemos de la instalacioacuten de alguacuten programa externo como una base de datos El capiacutetulo 10 mueacutes- tra coacutemo almacenar variables y textos dentro de un archivo para desshypueacutes recuperarlo en nuestra paacutegina Ademaacutes aprenderaacute una serie de teacutecnicas para recuperar ficheros enviados a traveacutes de un formulario y para poner en descarga archivos del servidor

bull Capiacutetulo 11 Bases de datos con SQL y SQLite Sin duda la mejor forma de almacenar datos masivos es utilizar una base de datos PHP 5 incorshypora una API de gestioacuten de bases de datos SQLite que permite almaceshynar millones de registros de diferentes tipos en un archivo binario Lo

PHP 5 23

mejor de utilizar SQLite es que no necesita instalacioacuten de una base de datos ni su administracioacuten todo estaacute contenido dentro de la API Aunshyque este libro no estaacute dedicado a la programacioacuten con bases de datos se da una referencia de los usos maacutes comunes del lenguaje de consultas estructurado (SQL) para que se pueda iniciar en este complejo mundo

bull Capiacutetulo 12 PHP 5 y MySQL MySQL ha sido siempre la panacea del desarrollo en el aacutembito profesional Es una base de datos robusta que permite administracioacuten de usuarios y seguridad a nivel de tablas y celshydas Es algo compleja de administrar pero muy sencilla de manejar desde PHP 5 Su utilizacioacuten ha sido tal que en el mundo de desarrollo se habla de las paacuteginas LAMP (Linux + Apache + MySQL + PHP) En este capiacutetulo aprenderaacute a manejar las funciones maacutes caracteriacutesticas de MySQL y a utilizarlas por medio de objetos en sus aplicaciones La proacutexima aparicioacuten de MySQL 5 hace prever que la combinacioacuten con PHP seraacute perfecta (MySQL 5 + PHP 5 = 10)

bull Capiacutetulo 13 Sesiones y Cookies En este capiacutetulo se detallan las teacutecnishycas necesarias para grabar informacioacuten en el equipo de los usuarios Estas pequentildeas variables (Cookies) permiten crear un pequentildeo control de asistencia de sus usuarios o guardar configuraciones especiales En cuanto a las sesiones son muy necesarias a la hora de crear espacios de venta de productos Las sesiones identifican a un usuario en concreto dentro de una paacutegina y permiten asociar variables concretas a ese usuashyrio aunque la paacutegina esteacute siendo visitada por muchas personas a la vez

bull Capiacutetulo 14 Lectura y escritura de archivos XML Frente a una inmenshysa cantidad de tipos de archivos propietarios como los documentos DOC o XLS nos encontramos a una serie de archivos basados en el lenguaje XML Este tipo de archivos como SXW (Openoffice) o SVG (graacuteficos vectoriales) estaacuten creados para ser entendidos por las personas y por los ordenadores Por lo tanto crear programas que interpreten estos archivos no es nada complejo El capiacutetulo 14 muestra tres caminos disshytintos para leer archivos XML Dos de ellos que vienen funcionando desde versiones anteriores SAX y DOM Y uno nuevo implementado en PHP 5 para facilitar esta tarea al programados Ademaacutes se incluyen las pautas necesarias para que cree sus propios archivos XML con la metodologiacutea DOM

bull Capiacutetulo 15 Aplicaciones praacutecticas de XML Si en el capiacutetulo anterior sentaacutebamos las bases para la lectura de informacioacuten desde archivos XML en este capiacutetulo crearemos objetos que implementen aplicacioshynes reales y actuales para compartir informacioacuten Es muy habitual hoy

24 Coacutemo usar este libro

en diacutea que las paacuteginas lleven asociados un panel de noticias que se generan en portales diferentes Esta informacioacuten se puede mostrar grashycias a teacutecnicas como RSS

Ademaacutes de crear sus propios objetos de generacioacuten de contenido RSS y su lectura haremos hincapieacute en lo que actualmente se llaman servicios Los servicios son pequentildeos programas almacenados en alguacuten servidor que informan acerca de algo concreto Aquiacute aprenderaacute a crear sus sershyvicios con las teacutecnicas ya adquiridas en el capiacutetulo 14

bull Capiacutetulo 16 Generacioacuten de graacuteficos con PHP 5 La generacioacuten de graacuteshyficos desde PHP 5 es posible gracias a la utilizacioacuten de libreriacuteas extershynas como GD Esto le permite manipular archivos graacuteficos que sus usuarios puedan subir a traveacutes de un formulario Con esta libreriacutea pueshyde generar graacuteficos en miniatura para despueacutes de hacer clic en eacutel antildeashydir una marca de agua a todas las imaacutegenes antildeadiendo el logo de su empresa o asociacioacuten

Otra gran libreriacutea es JpGraph que permite crear todo tipo de graacuteficos estadiacutesticos Esto le serviraacute para conocer el nuacutemero de visitas por diacutea mes o antildeo comparativas anuales de ventas de productos y todo un abanico de posibilidades

bull Capiacutetulo 17 Gestioacuten de errores en PHP 5 Una vez terminada la aplishycacioacuten tendraacute que tener en cuenta las partes del coacutedigo donde puede tener problemas Algunos usuarios pueden introducir caracteres no permitidos o nuacutemeros donde se esperaban letras La gestioacuten de errores permite mostrar al desarrollador y al usuario doacutende aparece el error y el tipo de fallo que se ha producido Una buena gestioacuten de errores haraacute que su programa sea maacutes fiable

bull Capiacutetulo 18 Conexiones desde PHP 5 La conectividad de PHP con otras aplicaciones o servicios ha sido siempre una preocupacioacuten de sus desarrolladores Asiacute desde anteriores versiones puede encontrar coshynectividad con servicios LDAP POP3 SMTP o FTP

Este capiacutetulo trata de abarcar dos servicios muy utilizados por la coshymunidad de usuarios El FTP en primer lugar para enviar y recuperar informacioacuten de otros servidores desde un programa escrito en PHP Y en segundo lugar el manejo de las funciones necesarias para enviar informacioacuten por correo electroacutenico

bull Capiacutetulo 19 Creacioacuten de archivos PDF El formato de texto maacutes difundishydo en Internet es el PDF Tanto se ha extendido este formato que la mayoshyriacutea de las paacuteginas profesionales contienen archivos PDF con diferentes contenidos Desde paacuteginas de contenido tecnoloacutegico hasta las de cocina

PHP 5 25

exportan sus contenidos en PDF para que sus usuarios puedan disfrutar desde su ordenador del manual del video o la receta de la semana

En este capiacutetulo veraacute paso a paso coacutemo generar un archivo PDF comshypleto desde la cabecera hasta el pie de paacutegina pasando por todo tipo de textos e imaacutegenes

bull Capiacutetulo 20 Plantillas con Smarty La uacuteltima aportacioacuten de este libro tiene que ver con la tendencia de separar el coacutedigo PHP de la presentashycioacuten en HTML Smarty provee unos sencillos mecanismos desde PHP que permiten realizar sencillamente esta separacioacuten Ademaacutes de las caracteriacutesticas baacutesicas de las plantillas la potencia de Smarty reside en la compilacioacuten del disentildeo cada vez que cambian los datos hecho que otorga a Smarty el puesto nuacutemero 1 en velocidad en el ranking de sisteshymas de plantillas En este capiacutetulo aprenderaacute a crear plantillas con Smarty que permitiraacuten cambiar el aspecto graacutefico de su aplicacioacuten sin tocar el coacutedigo escrito en PHP 5

bull Apeacutendice A Instalacioacuten de Apache y PHP 5 en distintos Sistemas Opeshyrativos La instalacioacuten de PHP 5 es muy sencilla en gnuLinux MacOSX y Windows El Apeacutendice muestra los pasos necesarios para instalar un servidor Apache con el parse de PHP 5 listo para ser utilizado con los ejemplos En cada caso la instalacioacuten se hace de una forma distinta Hemos buscado para cada Sistema Operativo la opcioacuten maacutes sencilla que es utilizando alguacuten paquete compacto que se instale y deje listo el sistema Puesto que es un libro para principiantes hemos huido de crear PHP 5 desde el coacutedigo fuente compilando el programa

bull Apeacutendice B Configuracioacuten baacutesica de phpini El archivo de configurashycioacuten php i n i contiene aspectos de funcionamiento de PHP 5 que pueshyden cambiarse sin necesidad de compilar el programa Este Apeacutendice contiene algunos paraacutemetros de configuracioacuten que pueden ser uacutetiles

bull Apeacutendice C Bibliografiacutea Este libro estaacute basado en el conocimiento adquirido tras la lectura de numerosos libros sobre la temaacutetica paacutegishynas Web y revistas profesionales del sector Este Apeacutendice cubre todas las posibilidades dando al lector un camino a seguir despueacutes de termishynar el presente libro

Convenios que emplea este libro

El nombre de los comandos funciones meacutetodos u objetos aparecen resalshytados en el libro de la siguiente forma ob j e t o

26 Coacutemo usar este libro

Algunas palabras teacutecnicas que no tienen una traduccioacuten faacutecil al castellano o simplemente estaacute fuertemente asentada en el idioma teacutecnico aparecen de la siguiente forma array true ofalse

En el libro aparecen resaltados una serie de temas circunstancias o aconshytecimientos extraordinarios de la siguiente forma array true ofalse

Nota

Anotaciones sobre el texto

Advertencia

Informacioacuten importante a tener en cuenta a la hora de desarrollar un programa Explican de alguna manera posibles equivocacioshynes o ayudas para no caer en errores frecuentes

Truco

Consejo o informacioacuten importante que puede facilitar el trabajo

Los ejemplos en la Web de Anaya

La mayoriacutea de los ejemplos del libro se pueden obtener en la Web de Anashyya Multimedia en la direccioacuten siguiente

httpwwwanayamultimediaes Seleccionando los menuacutes Atencioacuten a clientegtComplementosgtManuales lmprescindiblesgtManual Imprescindible de PHP 5 Ademaacutes de los ejemplos puede encontrar las aplicaciones externas o enshylaces a las mismas que utilizamos para desarrollar algunos ejemplos como Smarty FPDF JpGraph o la libreriacutea IXR

Todos los ejemplos han sido probados en el servidor Apache para MacOSX con el paquete de PHP 501 y en un servidor Apache sobre gnuLinEx Todas las capturas de pantalla se han realizado con el navegador Grulla (Mozilla Firefox) de gnuLinEx 2004

Proacutelogo

28 Proacutelogo

Una de las preguntas maacutes interesantes que nos hacen es queacute hace que PHP tenga tanto eacutexito Distintas personas nos han dado respuesta a esta preshygunta Algunos sostienen que es su excelente conexioacuten con bases de dashytos otros que se debe al coacutedigo abierto por el contrario otros mantienen que es su funcionamiento Sin embargo nuestra opinioacuten difiere PHP pershymite que cualquier usuario obtenga raacutepidamente resultados de forma senshycilla incluso aquellos que no posean experiencia en programacioacuten Al mismo tiempo a diferencia de las herramientas RAD PHP permite el deshysarrollo de proyectos tan complejos como se desee En nuestra opinioacuten esta combinacioacuten ausente en la mayoriacutea de las plataformas Web actuales es lo que hace que PHP sea especial

Lograr el equilibrio entre estas dos liacuteneas (la potencia y la sencillez) no ha sido faacutecil pero siacute imprescindible para el eacutexito de PHP como tambieacuten lo son las nuevas caracteriacutesticas que permiten al desarrollador aprovechar la uacuteltima tecnologiacutea

PHP 5 es el producto de este importante equilibrio Aunque dotado de muchas funciones nuevas esta versioacuten es tan accesible como lo fueron PHP 3 y PHP 4 con lo que permite un raacutepido aprendizaje para aquellos que se inicien De hecho algunas de las novedades basadas en la interfaz de Zend Engine II como SimpleXML SQLite y SOAP hacen maacutes sencillo el uso de PHP al tiempo que incrementa el potencial de aquellos usuarios noveles pues les permite trabajar con XML SQL y Web Services sin esfuerzo

La nueva generacioacuten PHP tambieacuten supone una buena noticia para desashybolladores experimentados En primer lugar por simplificar todas aqueshyllas funciones que ya se han indicado (al contrario de lo que normalmente se piensa ni siquiera a los desabolladores avanzados les gusta trabajar a menos que sea imprescindible) y en segundo lugar por poner a su disposhysicioacuten funciones mejoradas Las nuevas opciones orientadas a objetos de Zend Engine II son un regalo para el desarrollo de aplicaciones de media y gran escala como la nueva extensioacuten mysqli y el nuevo moacutedulo de inteshygracioacuten NET que permite la creacioacuten de aplicaciones hiacutebridas de PHP que emplean la estructura NET

Este libro es una gran introduccioacuten a PHP en general y de PHP 5 en partishycular Si no tiene experiencia previa con PHP e incluso si no tiene ningushyna experiencia en programacioacuten en breve podraacute trabajar con eacutel

Zeev Suraski Tel A v i v

Andi Gutmans Cupertino

Introduccioacuten

30 Introduccioacuten

Historia de PHP

Rasmus Lerdorf miembro del equipo de desarrollo de Apache creoacute PHP (Personal Home Page) en 1994 Su uacutenica intencioacuten fue la de crear un pequeshyntildeo sistema de control para verificar el nuacutemero de personas que leiacutean su curriculum vitae en la Web

En los meses siguientes a su creacioacuten PHP se desarrolloacute en torno a un grushypo de programadores que comprobaban el coacutedigo y sus revisiones Para dar maacutes potencia al sistema Rasmus creoacute funciones en lenguaje C para permitir conexioacuten a bases de datos Este fue el comienzo de la potencia real del leguaje

En 1995 aparecioacute un conjunto de herramientas sobre PHP Esta biblioteca se llamoacute Herramientas para paacuteginas personales y conteniacutean un analizashydor de coacutedigo muy sencillo un libro de visitas un contador y algunas macros que facilitaban el trabajo de los disentildeadores

A mediados de 1995 aparecioacute una revisioacuten puacuteblica llamada PHPFI 20 Esta nueva versioacuten contaba con un analizador sintaacutectico reescrito desde 0 ademaacutes de unas herramientas escritas para el tratamiento de datos desshyde un formulario (de ahiacute el nombre aacuteeFI Form iacutenterpreter) y conectividad con mSQL (Gestor de bases de datos)

Hacia 1997 PHPFI se estaba usando en maacutes de 50000 paacuteginas en todo el mundo En este periacuteodo de tiempo Zeev Suraski y Andi Gutmans decishydieron crear una nueva versioacuten de PHPFI para solventar unos probleshymas con una aplicacioacuten de comercio electroacutenico que estaban desarrollando PHP 30 nacioacute con suculentas innovaciones como la conectividad con vashyrios gestores de bases de datos protocolos y una API ampliada La vershysioacuten oficial de PHP 30 vio la luz en junio de 1998 donde se contemplaba ya la programacioacuten orientada a objetos

En 1999 se realizoacute la primera revisioacuten del motor Zend (Zend Engine) que aportaba modularidad claridad y herramientas de optimizacioacuten para paacuteshyginas de gran escala Zend viene de la unioacuten de Zeev y Andi

PHP 40 vio la luz en mayo de 2000 dividida en 3 partes El motor Zend la API de servidor y los moacutedulos de funcionas El motor Zend es el responshysable de analizar el coacutedigo PHP definir la sintaxis y del lenguaje de proshygramacioacuten La API permite la comunicacioacuten con el servidor Con esta API es posible utilizar PHP desde varios servidores Los moacutedulos contienen funciones para el manejo de cadenas archivos XML o tratamiento de imaacuteshygenes

PHP 5 31

La orientacioacuten a objetos no estaacute muy lograda en PHP 40 Los objetos tieshynen un tratamiento muy pobre e iloacutegico La definicioacuten de las variables miembro (propiedades) y los meacutetodos son siempre puacuteblicos por lo que la encapsulacioacuten es nula Todos los objetos se pasan por valor por defecto cuando deberiacutean pasarse por referencia

Todas estas propuestas realizadas por el equipo de desarrollo de PHP han desembocado en la creacioacuten del motor Zend 20 y su consecuencia PHP 5

PHP 5 incorpora una verdadera orientacioacuten a objetos Antildeadiendo las pashylabras reservadas public protected y priacutevate a la definicioacuten de las propiedashydes y meacutetodos de los objetos se permite una verdadera encapsulacioacuten Ademaacutes del considerable avance con respecto a los objetos PHP 5 incorshypora un control de errores muy mejorado al estilo de los lenguajes de proshygramacioacuten maacutes avanzados

Nota

Despueacutes de una encuesta entre desarrolladores y usuarios de PHP se decidioacute cambiar el significado de PHP a PHP Hypertext Pre-processor Este cambio sigue los pasos de Richard Stallman al nombrar a su sistema operativo GNU (GNU is not Unix) doshytando a la palabra PHP de recursividad Es un juego de palabras muy utilizado en el ambiente hacker

Nuevas Caracteriacutesticas de PHP 5

Existen muchas razones para elegir PHP 5

Faacutecil de usar

PHP 5 es un lenguaje muy faacutecil de aprender con respecto a otros lenguashyjes utilizados para el mismo propoacutesito como JAVA o ASP Debido a esto no es necesario hacer un estudio muy concienzudo de sus funciones para realizar programas sencillos que nos resuelvan la mayoriacutea de los probleshymas diarios

La mayoriacutea de las funciones maacutes usuales estaacuten disponibles por defecto como la conexioacuten a bases de datos o la utilizacioacuten de servidores IMAP Existe una gran cantidad de paacuteginas con documentacioacuten y programas heshychos por desarrolladores que se pueden leer y modificar libremente

32 Introduccioacuten

Embebido en HTML

Las paacuteginas escritas en PHP son simples paacuteginas en HTML que contieshynen ademaacutes de las etiquetas normales el programa que queremos ejecushytar Por ejemplo

ltHTMLgt ltBODYgt ltHEADgt ltTITLEgtEjemplo de PHP5 embebidoltTITLEgt ltHEADgt ltBODY ltPgtEsto es HTML del buenoltPgt ltphp Aquiacute comienza el coacutedigo PHP Lo siguiente es una simple asignacioacuten de variables y su salida por pantalla $nombre=Luis Miguel $apellidos=Cabezas Granado $fecha_hoy=date(d-ra-Y1) gt ltPgtEste paacuterrafo contiene HTML y PHP El autor del script es ltphp echo ($nombre $apellidosgt gtlt Pgt ltPgtLa fecha de ejecucioacuten del script es ltphp echo($fecha_hoy)gtltPgt ltBODYgt ltHTMLgt

Cuando un cliente solicita esta paacutegina el servidor preprocesa los datos y ejecuta las instrucciones de PHP En este caso las variables (las palabras que tienen el signo $ delante) se llenan con los valores que hay a la dereshycha del signo igual Una vez resuelto todo el proceso el servidor le enviacutea al cliente una paacutegina soacutelo con etiquetas de HTML La figura 11 muestra este proceso

Si inspeccionamos ahora el coacutedigo que tenemos en el navegador nos dareshymos cuenta de que las etiquetas de PHP han desaparecido

ltHEAD ltTITLEgtEjemplo de PHP5 embebido-TITLEgt ltHEADgt ltBODYgt ltPgtEsto es HTML del buenoltPgt ltPgtEste paacuterrafo contiene HTML y PHP El autor del script es Luis Miguel Cabezas GranadoltPgt ltPgtLa fecha de ejecucioacuten del script es 05-07-2004ltPgt ltBODYgt ltHTMLgt

higura ii Kesuitaao ae ejecutar un scnpi sencillo

La consecuencia maacutes inmediata es que no es necesario compilar el prograshyma en coacutedigo binario antes de poder testar si funciona o no PHP es un lenshyguaje interpretado como otros muchos en el mercado (ASP Python o JSP)

Multiplataforma

PHP 5 se ejecuta en multitud de plataformas Sistemas Operativos y Sershyvidores existentes Es compatible con los tres servidores liacutederes del mershycado Apache Microsoft Internet Information Server y Netscape Enterprise Server

Tabla 11 Sistemas Operativos y Servidores para PHP 5

Basados en UNIX Windows

Sistema Operativo AIX AUX BSDI Digital UNIXTru64 FreeBSD HP-UX IacuteRIX MacOS X gnuLinux gnuLinEx NetBSD OpenBSD SCO UnixWare Solaris SunOS Ultrix Xenix y muchos maacutes Windows 98Me Windows NT 2000XP2003

Servidores Apache fhttpd Netscape US PWS Netscape Apashyche Omni

Puesto que PHP se ejecuta en todos los Sistemas Operativos indicados en la tabla 11 y en la mayoriacutea de las plataformas hardware existentes (Intel

PHP 5 33

34 Introduccioacuten

A M D PowerPc SPARC etceacutetera) nos seraacute muy sencillo conseguir un lashyboratorio de pruebas para nuestros script

Licencia Open Source

La licencia de Coacutedigo Abierto implica que el coacutedigo fuente de PHP 5 es libre de ser descargado e inspeccionado por nosotros La consecuencia principal es que el coste del producto en la mayoriacutea de los casos es de 0 Euros Tener el coacutedigo fuente de PHP 5 sirve entre otras cosas para poshyder hacer nuestro servidor a medida es decir podemos compilar el proshygrama con las opciones que realmente utilicemos (base de datos LDAP)

Si acompantildeamos Apache el servidor maacutes popular a la instalacioacuten de PHP 5 y antildeadimos alguna base de datos Open Source como PostgreSQL tendreshymos un sistema completo de script de servidor cuyo coste es nulo frente a otras opciones en las que es necesario el uso de licencias

Multitud de Extensiones

PHP 5 se desarrolla para dar la mayor versatilidad y flexibilidad a los usuashyrios que lo utilizan Es por esto por lo que existen muchas extensiones del lenguaje que permiten utilizar nuevas bases de datos protocolos enlaces a libreriacuteas etceacutetera

El acceso a bases de datos tiene una gran potencia implementando soporshyte nativo para 15 Sistemas Gestores de Bases de Datos muy populares En cuanto a los protocolos podemos contar con extensiones que controlan el acceso a LDAP IMAP o POP3 Tambieacuten se ha cuidado el soporte para crear imaacutegenes en tiempo de ejecucioacuten gracias a la libreriacutea GD

Dada la importancia del desarrollo del lenguaje XML en los uacuteltimos antildeos PHP 5 incorpora tres meacutetodos de acceso a este tipo de archivos SAX D O M y simpleXML Ademaacutes se incorpora a PHP 5 la gestioacuten de errores mediante el manejo de excepciones

En esta versioacuten se han antildeadido facilidades para utilizar los repositorios de coacutedigo de PEAR

Velocidad e incorporacioacuten de objetos

El nuevo motor Zend 20 acelera los procesos de ejecucioacuten del coacutedigo Ademaacutes incorpora un nuevo modelo de objetos que permite crear ciacutea-

Figura 12 Uso de PHP desde el antildeo 2000

Gran Comunidad de apoyo

PHP 5 se ha escrito bajo el auspicio del Coacutedigo Abierto Por lo tanto exisshyte una comunidad que apoya su desarrollo en colaboracioacuten La ventaja principal es que existen multitud de paacuteginas listas de correo y foros de debate cuyo tema de conversacioacuten es el manejo de este lenguaje de proshygramacioacuten

Esta comunidad sirve de apoyo para todos los que necesitamos conocer desde los aspectos maacutes baacutesicos hasta las implementaciones maacutes complishycadas Tan pronto como hagamos uso de esta ayuda nos sentiremos oblishygados a prestar la nuestra a usuarios principiantes y asiacute la Comunidad se

PHP 5 35

ses y meacutetodos privados protegidos y puacuteblicos clases abstractas e inter-faces

Popularidad

El uso de PHP se ha disparado desde el antildeo 1999 como puede verse en la figura 12

36 Introduccioacuten

iraacute ampliando Si nuestros conocimientos llegan a superar alguacuten diacutea los objetivos de este libro podemos pensar en contribuir enviando fallos en el lenguaje respondiendo a mensajes de las listas de correo participando en foros de debate o escribiendo extensiones en lenguaje C

Objetivos del libro

A la hora de seleccionar este libro o cualquier otro sobre PHP 5 creo que es esencial que conozca los objetivos que marcan sus capiacutetulos Este libro en concreto estaacute pensado para

bull Tener una visioacuten general de los lenguajes de script para desarrollo

bull Conocer las ventajas de PHP 5 frente a otros lenguajes similares Tener una visioacuten general de las nuevas caracteriacutesticas que ofrece PHP 5

bull Aprender los conceptos baacutesicos para empezar a desarrollar aplicacioshynes sencillas que muestren contenido dinaacutemico

bull Identificar claramente todas las caracteriacutesticas de la orientacioacuten a objeshytos y aprender a desarrollar aplicaciones divididas en partes con moacuteshydulos reutilizables en distintos proyectos

bull Sacar partido de la API SQLite y del gestor de bases de datos MySQL para crear aplicaciones maacutes profesionales que nutran de contenido las paacuteginas

bull Crear formularios que enviacuteen informacioacuten y ficheros entre varias paacuteshyginas de distinta forma

bull Aprender a generar archivos para Internet de distintos formatos Los archivos XML o PDF se han vuelto indispensables en esta era y muy uacutetiles para exportar informacioacuten a los usuarios

bull Conocer las funciones baacutesicas para la creacioacuten de paacuteginas que controshylen y manipulen imaacutegenes Ademaacutes conoceraacute herramientas para geshynerar en el momento graacuteficos estadiacutesticos de diferentes formas

bull Controlar todos los errores que puedan producir los programas evishytando mostrar en el navegador mensajes de error geneacutericos para mosshytrar errores controlados por nosotros

bull Generar plantillas con libreriacuteas para separar el coacutedigo escrito en PHP de la presentacioacuten creada con HTML o alguacuten programa de disentildeo

El libro crea una base muy fuerte para comenzar a realizar aplicaciones profesionales Es evidente que la creacioacuten de archivos XML PDF genera-

PHP 5 37

cioacuten de graacuteficos o plantillas Smarty necesitan un libro entero para cubrir todas las caracteriacutesticas que ofrecen Este libro da una visioacuten general a los lectores y permite conocer las herramientas que actualmente se utilizan para que cada uno pueda investigar por su cuenta las que maacutes le interese

Capiacutetulo 1

Introduccioacuten aPHP5

En este capiacutetulo aprenderaacute a

bull Diferenciar entre scripts de cliente y servidor bull Utilizar diferentes tipos de etiquetas de inicio de PHP bull Escribir su primer programa en PHP bull Conocer las etiquetas HTML

40 Capiacutetulo 1

Introduccioacuten

El mundo de los desarrolladores de paacuteginas ha cambiado de forma vertishyginosa en los uacuteltimos antildeos En poco tiempo han surgido tecnologiacuteas y reshyvisiones de esas tecnologiacuteas que hacen que los programadores tengamos que reciclarnos continuamente

Hace unos antildeos el desarrollo de grandes paacuteginas era complicado de manshytener El lenguaje existente era uacutenicamente HTML y solo permitiacutea crear las paacuteginas y subirlas a un servidor El problema de esto es que modificar alguacuten dato de una de las paacuteginas implicaba un trabajo extra que incluiacutea descargarla modificarla maquetarla de nuevo y subirla al servidor

Actualmente existe un conjunto de lenguajes que permiten desarrollar paacutegishynas Web dinaacutemicas es decir que el contenido puede variar muy raacutepidamente sin ninguacuten esfuerzo por parte de los desarrolladores Eacutestos se denominan lenguajes de script de servidor porque la ejecucioacuten del programa se realiza en el servidor Web donde se encuentra alojada la paacutegina Existe un largo compendio de lenguajes que se pueden utilizar para la creacioacuten de paacuteginas Web dinaacutemicas ASP de Microsoft Java y JSP de Sun Perl Python PHP

HTML estaacutetico

El tipo maacutes baacutesico de paacutegina Web es completamente estaacutetico basado en texto plano y completamente escrito en HTML La paacutegina siguiente es un ejemplo de Web estaacutetica

ltHTMLgt ltHEADgt

ltTITLEbLibros sobre PHP 5 y gnuLinuxltTITLEgt ltHEADgt ltBODYgt ltTABLE BORDER-lgt ltTRgt

ltTDgtTiacutetulo de libros americanos sobre PHP 5ltTDgt ltTRgt ltTABLEgt ltulgt ltlixbgt Advanced PHP Programmingltbxbrxligt ltlixbgtPHP5 and MySQL bibleltbxbrxligt ltlixbgtLearning PHP 5ltbgtltbrxligt ltlixbgtUpgrading to PHP 5ltbxbrxligt ltlixbgtBeginning PHP 5 and MySQLltbxbrxligt

Introduccioacuten a PHP 5 41

ltlixbgtPHP 5 Power Programmingltfcgtgtltbrgtltligt lt u lgt ltTABLE border=lgt ltTRgt ltTDgtTiacutetulo de libros americanos sobre gnuLinuxltTDgt ltTRgt ltTABLEgt ltulgt ltlixbgtRunning Linuxltbxbrxligt ltlixbgtLinux in a Nutshellltbxbrxligt ltlixbgtHow Linux Worksltbxbrxligt ltlixbgtLinux for Non-Geeksltbxbrxligt ltulgt ltBODYgt ltHTHLgt

Figura 11 Ejemplo de paacutegina Web estaacutetica

La figura 11 muestra el ejemplo de una Web estaacutetica El funcionamiento de Internet es algo complejo para explicarlo en este capiacutetulo pero vamos a dar vinas nociones baacutesicas sobre lo que pasa tras la peticioacuten de una paacutegina Web por un cliente Los pasos que sigue nuestro navegador de Internet son

bull Nuestro ordenador solicita al servidor una paacutegina Web a traveacutes de Inshyternet

bull El servidor enviacutea los datos solicitados en formato de texto

42 Capiacutetulo 1

bull El navegador recibe estos datos interpreta la paacutegina Web enviada y la muestra en la pantalla de acuerdo con la resolucioacuten del monitor las preferencias del usuario y alguacuten otro factor

En la figura 12 podemos ver todo el proceso

Figura 12 Esquema de peticioacuten de una Web estaacutetica

Las paacuteginas Web estaacuteticas no permiten apenas una interactividad con el usuario final Por eso han aparecido numerosas tecnologiacuteas que hacen maacutes usable las paacuteginas y eliminan algunas restricciones o limitaciones Los lenshyguajes Javascript Vbscript CSS o los ap-plet de Java ofrecen una mayor interactividad pero son dependientes del navegador que utilicemos o de programas externos

Tecnologiacuteas del lado del cliente

Muchas de las mejoras antildeadidas al lenguaje HTML pertenecen a tecnoloshygiacuteas del lado del cliente es decir que se descargan junto con la paacutegina Web solicitada al servidor y se ejecutan en nuestro ordenador local La tabla 11 todas las tecnologiacuteas aparecidas hasta ahora del lado del cliente Estas tecnologiacuteas aunque son maacutes llamativas y permiten desarrollar la imashyginacioacuten en pro del disentildeo dependen totalmente de las caracteriacutesticas del navegador Por ejemplo si tiene un ordenador ibook de Apple con un Sisshytema Operativo gnuLinux Debiacutean (como el autor) le seraacute complicado obshytener una maacutequina virtual de Java y un inteacuterprete de Flash Las tecnologiacuteas de cliente no pueden rescatar datos de servidores porque su ejecucioacuten es uacutenicamente en local Eacutesto los imposibilita para recuperar informacioacuten de bases de datos o servicios

introduccioacuten a PHP 5 43

Tabla 11 Tecnologiacuteas del lado del cliente

[Tecnologiacutea Descripcioacuten Efecto de ejemplo

CSS HTML Sirve para dar formato a las Enlaces con movi-Dinaacutemico paacuteginas color tamantildeo capas efectos miento Javascript Manejo de eventos del navegador Imaacutegenes que Vbscript cambian cuando

se aproxima el ratoacuten Applets Aplicaciones pequentildeas Puzzles conectivi-de Java dad con bases de

datos Animaciones Animaciones graacuteficas Peliacuteculas iexclnteracti-Flash vas

Tecnologiacuteas del lado del servidor

Los lenguajes del lado del servidor son invisibles para los clientes Las paacuteginas que utilicen scripts de este tipo contienen el coacutedigo entre etique-fas parecidas a las de HTML pero eacutestas desaparecen cuando el cliente reshycibe la paacutegina

Los pasos que debe seguir nuestro navegador de Internet son

bull Nuestro ordenador solicita al servidor una paacutegina Web a traveacutes de Inshyternet

bull El servidor comprueba si la paacutegina solicitada contiene scrvpt del lado del servidor (PHP ASP JSP etceacutetera)

bull Ejecuta los posibles scripiacutes y antildeade el resultado final a la paacutegina Web resultante

bull El navegador recibe estos datos interpreta la paacutegina Web enviada y la muestra en la pantalla de acuerdo con la resolucioacuten del monitor las preferencias del usuario y alguacuten otro factor

La figura 13 muestra el proceso Los lenguajes del lado del servidor necesitan un motor (un programa) que interprete el coacutedigo Este programa puede formar parte o no del servidor Web En nuestro caso utilizaremos el motor Zend Engine 20 para parsear (interpretar) los proshygramas escritos en PHP 5

Figura 14 Zend Studio 351 para MacOSX

Suponiendo que ya tiene un servidor para probar los programas o ha leiacuteshydo el Apeacutendice A para instalar su propio servidor Web con PHP 5 vamos a crear nuestro primer programa del lado del servidor Para escribir los programas puede utilizar cualquier editor de texto plano

44 Capiacutetulo 1

Introduccioacuten a PHP 5 45

En gnuLinux tiene algunos editores libres que funcionan muy bien Sus nombres son Bluefish o Anjuta En entornos propietarios como Windows o MacO^X existen editores proshyfesionales que ademaacutes de disentildear paacuteginas Web permiten antildeadir todo tipo de coacutedigo PHP eso siacute los programas no son gratuitos y hay que pagar una elevada licencia por su uso Para los tres sistemas operativos tenemos una impresionante herramienta de edicioacuten y depuracioacuten creada por los programa^ores de PHP 5 La herramienta Zend Studio tiene dos versiones una de pago bajo licenshycia con muacuteltiples opciones de depuracioacuten y otra gratuita con opciones de desarrollo tan interesantes como el auto completado de funciones y variables

Etiquetas de PHP

Lo primero que debe saber es que todo prograrr1^ escrito en PHP debe empezar por unas etiquetas determinadas

ltphp gt

Ademaacutes aacutee esta iacuteoxma oacutee iacutemciax xm programa pu^dt ^urf^cam -iquesti -hiti iquesti-vo php i n i para que sus programas puedan empezar entre

lt gt

Nota

El archivo php i n i contiene la configuracioacuten de PHP en ese moshymento Cambiando algunos paraacutemetros podraacute cambiar la forma de funcionar del parser

El paraacutemetro s h o r t - o p e n - t a g puede igualarse a off o a on Si contiene el valor on PHP permitiraacute el uso de la etiqueta cofta Otra forma posible de empezar un programa escrito en PHP es utilizando las etiquetas de ASP Mucha gente que desarrolla con programas de Microsoft como Fron-tPage para generar paacuteginas Web utiliza esta forma de empezar el coacuteshydigo

lt gt

46 Capiacutetulo 1

Nuestro primer programa en PHP 5

Despueacutes de estas pequentildeas nociones ya estaacute preparado para crear su prishymer programa Eacuteste le va a permitir tener una visioacuten de la configuracioacuten global de PHP 5

Puede escribir el programa siguiente en cualquier editor de texto como vimos anteriormente

ltHTMLgt

ltHEADgt ltTITLEgtMi primer programa en PHP 5ltTITLEgt ltHEADgt ltBODYgt ltphp echo Este es el tiacutepico Hola Mundo ltbrxbrgt phpinfo() gt ltBODYgt ltHTMLgt

Como puede ver el programa contiene la estructura normal de una paacutegishyna Web La etiqueta ltHTMLgt define el comienzo y el final de la paacutegina Esta puede dividirse en dos partes La primera estaacute separada por la etishyqueta ltHEADgt y contiene informacioacuten sobre el autor tiacutetulo y meta datos que pueden servir para antildeadir coacutedigo Javascript o CSS La segunda parte es el cuerpo de la paacutegina Web es decir contiene todos los datos que veraacute el usuario en el navegador Estaacute separada entre etiquetas ltBODYgt

Dentro del BODY puede ver que empleamos las etiquetas de inicio y fin de programa PHP Dentro de estas etiquetas hay dos funciones que hacen cosas distintas Las funciones son programas ya creados y funcionales que pueden utilizarse en el transcurso de nuestro programa Existen en PHP 5 una infinidad de funciones uacutetiles para el manejo de cadenas de caracteshyres funciones aritmeacuteticas o funciones para mostrar texto en pantalla La funcioacuten echo ) se encarga de mostrar los datos en pantalla en este caso se encargaraacute de mostrar la frase Este es el tiacutepico Hola Mundo Ademaacutes imprime dos etiquetas ltbr gt que no se muestran porque tienen sentido dentro de HTML La etiqueta ltbrgt antildeade un salto de liacutenea a la paacutegina Web

La funcioacuten phpinf o () enviacutea al navegador la configuracioacuten de PHP que estamos utilizando en el servidor Aquiacute aparece la configuracioacuten que se ha utilizado para compilar el parser las libreriacuteas auxiliares que contiene el sistema que se estaacute utilizando etceacutetera

Introduccioacuten a PHP 5 47

Nota r Durante el proceso de aprendizaje del libro conoceraacute muchas funshyciones y sus aplicaciones inmediatas En el capiacutetulo 5 del libro aprenderaacute a crear sus propias funciones

El resultado de la ejecucioacuten del programa lo muestra la figura 15

Figura 15 Resultado de nuestro primer script

Repaso de HTML

El lenguaje de marcas de hipertexto se ha convertido en el principal refeshyrente de la Web Para seguir adecuadamente los contenidos del libro neshycesitaraacute conocer el funcionamiento de HTML para insertar sus programas escritos en PHP 5

Cabecera y cuerpo de una paacutegina Web

Todo documento escrito en HTML estaacute contenido entre las etiquetas ltHTMLgt y ltHTMLgt Se pueden estructurar en

bull Cabecera Entre las etiquetas ltHEADgt y ltHEADgt Contiene informashycioacuten relativa al documento

48 Capiacutetulo 1

bull Cuerpo Entre las etiquetas ltBODYgt y ltBODYgt Debe contener la inshyformacioacuten que el usuario veraacute en el navegador

Cabecera

El tiacutetulo del documento debe ir entre las etiquetas ltTITLEgt y ltTITLEgt Este tiacutetulo se mostraraacute en la parte superior del navegador Ademaacutes se utiliza como descripcioacuten si guarda la paacutegina en el apartado de Favoritos

Para antildeadir informacioacuten sobre el autor fecha de expiracioacuten o el programa con el que hemos disentildeado la Web puede utilizar la etiqueta ltMETAgt

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODYgt ltBODYgt

ltHTMLgt

Algunas etiquetas permiten la inclusioacuten de atributos La etiqueta ltMETAgt contiene el atributo NtildeAME y CONTENT para sentildealar en el documento el autor de la paacutegina Los buscadores haraacuten buen uso del contenido de estas etishyquetas para enlazarlas en sus motores de buacutesqueda

Cuerpo del documento

La etiqueta ltBODYgt tambieacuten puede contener atributos que modifiquen el aspecto exterior de la paacutegina

Los principales atributos son

bull BGCOLOR Indica el color de fondo de la Web

bull TEXT Color general del texto

bull LINK Color del texto de los enlaces

bull VLINK Color de los enlaces que ya han sido utilizados

bull ALINK Color de activacioacuten del texto

bull BACKGROUND Imagen de fondo de un documento

En el siguiente ejemplo puede ver la utilizacioacuten de los atributos de la etishyqueta del cuerpo

ltHTMLgt ltHEADgt

introduccioacuten a PHP 5 49

ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODY BGCOLOR=FF0 0 00 LINK=000000 VLINK=FF00FFgt ltBODYgt ltHTMLgt

Nota

El color se escribe en formato RGB Esto quiere decir que un color puede dividirse en tres componentes (rojo verde y azul) y elishygiendo la intensidad de cada componente se forma el color deseashydo Cada componente tiene 2 cifras en hexadecimal Asiacute el color FF0000 tiene al nuacutemero FF hexadecimal (255 en decimal) en su componente rojo y los demaacutes a 0 por lo tanto el color resulshytante seraacute Rojo intenso

Paacuterrafos y saltos de liacuteneas

Los textos pueden escribirse dentro de la etiqueta ltBODYgt en el orden que quiera los navegadores no interpretan los saltos de liacuteneas o liacuteneas en blanshyco eliminando todos los espacios vaciacuteos Para crear un salto de liacutenea tiene que utilizar ltBRgt escrito despueacutes del texto Para crear paacuterrafos tendraacute que escribir el texto entre las etiquetas ltPgt ltpgt

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltHEADgt ltB0DYgt ltPgt Esto es paacuterrafo y tambieacuten un salto de liacuteneasbrgt ltPgt ltBODYgt ltHTMLgt

Estilo de texto

Podemos resaltar partes del texto con algunas etiquetas

bull ltBgt Bloque de texto en negrita bull ltIgt Texto en cursiva

Figura 16 Diferentes estilos de textos

Ademaacutes puede elegir el formato de las fuentes de cada bloque de texto

50 Capiacutetulo 1

bull ltUgt Bloque de texto subrayado bull ltBIGgt Texto con su mayor tamantildeo bull ltSMALLgt Texto con m tamantildeo pequentildeo bull ltCENTERgt Texto centrado

bull ltSUPgtSuperiacutendice bull ltSUBgt Subiacutendice

El ejemplo siguiente que tambieacuten se muestra en la figura 16 muestra la utilizacioacuten de alguna de las etiquetas anteriores

ltHTMLgt

ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODYgt ltCENTERgtTexto centrado-CENTERxBRgt ltUxIxBIGgtTexto subrayado y cursivaltBIGxIgtltUxBRgt ltBgtTexto en negritaltBxBRgt ltSUPgtTexto superiacutendiceltSUPxBRgt Este cont iene un ltSUBgtsubiacutendiceltSUBgt ltBRgt ltBODYgt ltHTMLgt

Introduccioacuten a PHP 5 51

La etiqueta ltFONTgt permite seleccionar entre varios atributos para utilishyzar distintas fuentes colores o tamantildeos Entre los atributos que podemos utilizar

bull COLOR Color de la fuente

bull SIZE Tamantildeo de la fuente

bull FACE Tipo de fuente ltFONT SIZE=1 FACE=ComicgtTexto con tamantildeo y fuente determinadosltFONTgt

Enlaces de texto

Un enlace es un mecanismo que permite dirigirse a una paacutegina determishynada despueacutes de hacer clic en el texto Si entre las etiquetas ltAgt y ltAgt aparece alguacuten contenido (texto o imagen) al hacer clic en la situacioacuten denshytro de navegador la paacutegina seraacute dirigida a la nueva direccioacuten

El atributo HREF contiene la direccioacuten del enlace

ltA HREF=pagina2htmgtenlaceltAgt

Listas

Las listas son capaces de presentar ordenadamente una serie de concepshytos Los tipos de lista son

bull ltULgt Lista desordenada

bull ltOLgt Lista ordenada

bull ltDLgt Lista de definicioacuten

La diferencia entre los tipos de lista radica en el caraacutecter que aparece en la zona izquierda de cada liacutenea de la lista Las listas desordenadas tendraacuten un graacutefico formal (una forma geomeacutetrica) las ordenadas tendraacuten un nuacuteshymero de orden y las listas de definicioacuten una letra

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltHEADgt ltBODYgt ltBgtLiacutesta desordenada-BxBRgt ltULgt

ltLIgtLiacutenea 1 laquoLis-Liacutenea 2 ltLIgtLiacutenea 3

Figura 17 Listas ordenadas y desordenadas

52 Capiacutetulo 1

ltUI-igt

ltLIgtLiacutenea 31 ltLIgtLiacutenea 32

ltULgt ltLIacutegtLiacutenea 4

ltULgt ltBgtLiacutesta ordenadaltBgtltBRgt ltOLgt

ltLIacutegtLiacutenea 1 ltLJgtLiacutenea 2 ltLlgtLiacutenea 3 ltotgt

ltLIgtLiacutenea 31 ltLIgtLiacutenea 32

ltOLgt ltLIacutegtLiacutenea 4

ltOLgt ltBODYgt ltHTMLgt

Cada liacuteitea de una lista debe estar precedida de la etiqueta ltLIgt El coacutedishygo anterior genera la Web de la figura 17

Imaacutegenes

La etiqueta lt IMGgt utiliza el atributo SRC para insertar la imagen seleccioshynada en el documento

Introduccioacuten a PHP 5 53

Ademaacutes puede utilizar ALT para antildeadir una descripcioacuten a la imagen Entre las imaacutegenes que se pueden incluir en la Web estaacuten los tipos de archishyvos GIF PNG y JPG

ltIMG SRC=fo to l jpg ALIGN=centergt

La alineacioacuten de la imagen con respecto a la pantalla se puede controlar con el atributo ALIGN

Tablas

El elemento estrella en una paacutegina Web es la tabla Actualmente las tashyblas se utilizan para colocar en lugares determinados de la pantalla texshytos imaacutegenes o el menuacute de seleccioacuten Para definir u n a tabla tiene que insertar todos los datos entre las etiquetas ltTABLEi y ltTABLEgt

A continuacioacuten antildeada las filas y las columnas de nuestras tablas Para antildeadir una fila tendraacute que utilizar la etiqueta ltT^gt y para incluir una nueva columna la etiqueta ltTDgt

Para disentildear una tabla de 3 filas y 4 columnas siga los pasos que muestra el ejemplo

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author COMTENT=Luis Miguel Cabltbzas Granadogt ltHEADgt ltBODYgt ltTABLE B0RDER=1gt ltTRgt ltTDgtColumna 11ltTDgt ltTDgtColumna 12ltTDgt ltTDgtColumna 13ltTDgt ltTDgtColumna 14ltTDgt ltTRgt ltTRgt ltTDgtColumna 2 1ltTDgt ltTDgtColumna 2 2ltTDgt ltTDgtColumna 2 3ltTDgt ltTDgtColumna 24ltTDgt ltTRgt ltTRgt ltTDgtColumna 31ltTDgt ltTDgtColumna 3 2ltTDgt ltTDgtColumna 33ltTDgt ltTDgtColumna 34ltTDgt ltTRgt

Figura 18 Tabla de 3 filas y 4 columnas

54 Capiacutetulo 1

ltTABLEgt ltBODYgt ltHTMLgt

Como muestra el coacutedigo la etiqueta ltTABLEgt puede contener atributos como BORDER que antildeade un borde a todas las celdas de la tabla Esta forshyma de actuar la vemos en la figura 18

Resumen

Es muy importante para la lectura de los capiacutetulos del libro que conozca el lenguaje HTML en profundidad PHP 5 se encarga de generar datos dinaacutemicamente desde una base de datos archivos o haciendo caacutelculos complejos pero al final seraacute una etiqueta HTML la que muestre esos dashytos en pantalla Puesto que el objetivo de este libro no es conocer los asshypectos de HTML invito al lector a indagar en otras publicaciones o en Internet para suplir las posibles carencias que pueda tener

Los ejemplos del libro se han escrito directamente en un editor de textos pero esta no es la uacutenica posibilidad Tambieacuten puede utilizar para realizarshylos alguacuten programa de disentildeo Web con la ventaja de que las etiquetas HTML seraacuten antildeadidas a golpe de clic

Capiacutetulo 2

Variables constantes y tipos

de datos

En este capiacutetulo aprenderaacute a

bull Almacenar informacioacuten en variables bull Manejar variables constantes y constantes predefinidas por PHP 5

bull Utilizar funciones de manejo de datos

56 Capiacutetulo 2

Variables en PHP 5

Como en todos los lenguajes de programacioacuten PHP 5 permite almacenar datos de distintos tipos en memoria Estas zonas de memoria se llaman variables Las variables comienzan por el siacutembolo de doacutelar ($) y no necesishytan ser declaradas antes de comenzar el programa como en otros lenguashyjes

Tipos de Variables

Existen varios tipos de variables

bull Entero (integer) Almacena nuacutemeros sin decimales Se puede utilizar la notacioacuten decimal (83) octal (0123) o hexadecimal (0x12)

bull Coma Flotante (double) Nuacutemeros con decimales bull Caraacutecter (string) Texto o informacioacuten numeacuterica escrita entre comillas

dobles () o simples () bull Bootean Soacutelo tiene dos posibles valores Verdadero o Falso bull Nulo NULL) Es un tipo especial que solo contiene un valor NULL bull Vectores (array) Colecciones de datos

bull Objetos (object) Conjunto de datos y funciones independientes

Los 5 primeros tipos son simples y los 2 siguientes (array y object) son comshypuestos Trataremos los tipos compuestos en capiacutetulos sucesivos

ltphp Asignacioacuten de nuacutemeros enteros de coma flotante y cadenas de caracteres $numero_entero = 12343 $numero_flotante = 12343123 $cadena_caracter = 12 34 3 Asignacioacuten de los tipos especiales boolean y NULL $verdadero = TRUE $vacio = NULL gt

Hay que tener en cuenta que el nombre de las variables no puede empeshyzar por un nuacutemero pero siacute puede contenerlos Tambieacuten pueden empezar por un guioacuten bajo (__) Puesto que PHP 5 es sensible a las mayuacutesculas y minuacutesculas las variables $numero y $NUMERO seraacuten distintas

ltphp $4numero = 23 Esta liacutenea da error

Variables constantes y tipos de datos 57

$_numero = 45 Las liacuteneas siguientes muestran que PHP 5 es sensible a mayuacutesculas $numero = 23 $NUMERO = 24 $Numero = 25 echo (numero es $numeroltbrgt) echo (NUMERO es $NUMEROltbrgt ) echo (Numero es $Numeroltbrgt) gt

Nota

Es una buena praacutectica de programacioacuten llamar a las variables de una forma descriptiva Si tenemos un formulario que intenta pashysar datos sobre el nombre y apellido de una persona lo maacutes coshyrrecto es llamar a las variables $nombre y $ ape l l i do en vez de $n y $a Hay que buscar siempre la similitud entre el dato que pasamos y el nombre de la variable para que el programa resulte legible

Asignacioacuten de variables

La asignacioacuten es simplemente dar un valor a la variable Esto se hace poshyniendo un siacutembolo = entre la variable y el dato que queremos asignar

ltphp $numero_pi = 314159 Aproximadamente gt

Si se fija en el ejemplo acabamos de asignar un nuacutemero de coma flotante a la variable $numero_pi En este momento podemos cambiar el valor de la variable asignando un nuevo valor que puede ser de un tipo difeshyrente

ltphp $numerojiacute = 314159 El tipo se convierte a cadena de caracteres gt

Tipos simples

Los tipos de variables simples (enteros coma flotante cadenas de caracteshyres boolean y NULL) deberiacutean ser familiares si conocemos alguacuten lenguaje

58 Capiacutetulo 2

de programacioacuten como C Puesto que la base de la programacioacuten consiste en almacenar datos correctamente vamos a ver las peculiaridades de los diferentes tipos

Enteros (integer)

Corresponde a un nuacutemero entero sin decimales pudiendo ser negativo o el nuacutemero cero Pueden ser almacenados en diferentes formatos corresshypondiendo con las bases decimal (base 10) octal (base 8) y hexadecimal (base 16) Por defecto se utiliza la numeracioacuten decimal Para utilizar base 8 debe ponerse un 0 delante del nuacutemero asignado y un Ox si queremos utilizar base 16 Para antildeadir un nuacutemero negativo basta con poner el signo menos (-) delante del nuacutemero

ltphp $entero_baselO = 1234 $entero_base8 = 01234 $entero_basel6 = 0x1234 $entero_negativo = -1234 echo (Decimal $entero_baselOltbrgt) echo (Octal $entero_base8ltbrgt) echo (Hexadecimal $entero_basel6ltbrgt) echo (Negativo $entero_negativoltbrgt) gt

La salida del navegador es

Figura 21 Asignacioacuten de enteros en decimal octal y hexadecimal

Variables constantes y tipos de datos 59

La salida de los nuacutemeros se hace en decimal aunque la asignacioacuten se haya hecho en hexadecimal o en octal Esto es asiacute porque PHP trabaja internashymente en binario y hace la conversioacuten a decimal de todos los nuacutemeros enteros y de coma flotante

Nuacutemeros de coma flotante (double)

Este tipo de dato contiene nuacutemeros enteros con decimales Se almacenan de forma diferente a los nuacutemeros enteros por lo que las sumas de cantishydades de coma flotante con cantidades enteras daraacuten como resultado un nuacutemero de coma flotante

ltphp Nuacutemeros de coma flotante $numero__double = 1234123 $numero_double2 = 01213 $numero_double3 = -12 3 40 echo (Salida de la funcioacuten echo() $numero_double3ltbrgt) gt

La salida en el navegador seriacutea S a l i d a de echo -1234

Como puede comprobar parece que el nuacutemero que se muestra en pantashylla es del tipo entero Esto es porque la funcioacuten echo 0 no muestra el forshymato del dato Para que esto ocurra debemos utilizar otro tipo de funcioacuten

ltphp $numero_double3 = -12340 echo (Salida de printft) ) printf(f$numero_double3) gt

El coacutedigo anterior muestra ahora una salida por pantalla maacutes coherente Salida de printf() es -1234000000

Cadena de caracteres (string)

Es un conjunto de caracteres encerrados entre comillas dobles () o sim-pies ( )bull

ltphp Definicioacuten de variables de tipo string $cadenal = Esto es una cadena de caracteres $cadena2 = Esto es una cadena entre comillas simples $cadena3 = Cadena con 0 caracteres gt

60 Capiacutetulo 2

La diferencia entre las comillas simples y las comillas dobles radica en

bull Comillas simples Permiten imprimir el contenido iacutentegro de caracteshyres que esteacute entre las dos comillas

bull Comillas dobles Permiten incluir variables para imprimirlas junto al texto ltphp $dato = IMPRIMIBLE $texto_simple = No puede imprimir la variable $dato $texto_doble = Imprime la variable dato como $dato echo ($texto_simpleltbrgt) echo ($texto_doble) gt

Existen algunos caracteres especiales que no pueden ser antildeadidos a una variable de tipo string a menos que avisemos antes a PHP para que tenga cuidado a la hora de manejar el dato Este aviso se conoce como secuenshycia de escape y no es maacutes que la inclusioacuten delante del caraacutecter especial de un siacutembolo Asiacute si quiere insertar unas comillas dobles entre un texto tendraacute que escribir para que no se produzca un error

ltphp Secuencias de escape $cadenal = Aquiacute se pueden antildeadir comillas doblesltbrgt $cadena2 = Aquiacute se pueden antildeadir comillas simplesltbrgt $cadena3 = Esta cadena da errores por las comillas doblesltbrgt $cadena4 = Esta cadena no da errores por las comillas doblesltbrgt echo $cadenal echo $cadena2 echo $cadena3 echo $cadena4 gt

El resultado muestra la impresioacuten de las cadenas excepto la cadena3 que da un error por no incluir la secuencia de escape para las comillas

Tabla 21 Secuencias de escape comunes

Secuencia Valor

$ Signo de doacutelar $

Comillas dobles

V Comillas simples

Bar ra invert ida

Variables constantes y tipos de datos 61

Secuencia Valor

n Nueva liacutenea

r Retorno de carro

t Tabulador

Boolean

Una variable de tipo boolean soacutelo puede contener dos valores Verdadero o Falso Se suelen utilizar para comprobar si se cumple una condicioacuten en el programa

ltphp $variable_booleana = TRUE if ($variable_booleana) echo (El resultado es VERDADERO)

gt

El resultado se muestra en la figura 22

Aunque todaviacutea no hemos visto las estructuras de control podemos adshyvertir que la salida del programa anterior da como resultado la impresioacuten en pantalla del texto que contiene la funcioacuten echo () Ademaacutes de las vashyriables boolean podemos tomar otros tipos de datos como Verdaderos o Falsos para hacer nuestras comprobaciones

62 Capiacutetulo 2

bull Los nuacutemeros enteros o decimales positivos o negativos son todos Verdashyderos El 0 se considera Falso En cualquier caso se recomienda no utilishyzar variables de coma flotante para comprobar si son Verdaderos o Falsos

bull Las cadenas de caracteres son Verdaderas excepto cuando no contieshynen ninguacuten dato o contienen uacutenicamente el caraacutecter 0

bull Las variables del tipo NULL son siempre Falsas

NULL

Es un tipo especial de datos que soacutelo contiene el valor NULL Aunque se suele utilizar por norma en mayuacutescula PHP 5 lo acepta escrito de divershysas formas NULL nuil NuLl

ltphp $variable_nula = NuLl if ($variable_nula) echo (La comprobacioacuten es VERDADERA)

else echo (La comprobacioacuten es FALSA) gt

Variables de variables

Las variables son en definitiva nombres descriptivos que asocian un esshypacio en memoria del servidor con una palabra entendible por nosotros En ese espacio de memoria podemos almacenar diferentes tipos de datos Podemos definir una variable de la siguiente forma

ltphp $variablel = hola gt

En este momento tenemos un espacio de memoria llamado $ v a r i a b l e l donde se aloja el dato hola iquestQueacute pasa si queremos tratar la palabra hola como una variable Podemos hacerlo antildeadiendo un signo de $ delante de $ v a r i a b l e l por lo que se reservaraacute otro espacio en memoria para aloshyjar el nuevo contenido esta vez con el nombre $hola

ltphp $variablel = hola $$variablel = mundo

Variables constantes y tipos de datos 63

Las dos liacuteneas siguientes producen la misma salida echo ($variablel $$variablelltbrgt) echo ($variablel $holaltbrgt) gt

La salida por pantalla nos da el siguiente resultado hola mundo hola mundo

Constantes

Las constantes son tipos de datos que no variacutean en el desarrollo de un programa En la vida real existen muchos tipos de constantes el nuacutemero pi la temperatura de congelacioacuten del agua el nombre de la Empresa etshyceacutetera Para crear una constante tiene que usar la funcioacuten de f ine () de la siguiente forma

ltphp define(EMPRESAZendSA) define(AutorLuis Miguel Cabezas Granado) gt

Para mostrar el valor de las constantes uacutenicamente hay que invocar su nombre esta vez sin utilizar el siacutembolo de $

ltphp Definimos primero la constante define (COLOR_ROJO FF0000) Y ahora escribimos en pantalla su resultado echo COLOR_ROJO Hay que destacar que el signo de $ no hace falta ponerlo Existe otra funcioacuten que nos permite averiguar el valor de la constante echo constant ( C0L0R_R0JO) gt

defined()

Puede utilizar def ined () para averiguar si una constante ya se ha creado

ltphp define(EditorialAnaya) if (defined(Editorial) ) echo La Editorial es Editorial

gt

64 Capiacutetulo 2

Constantes predefinidas

PHP 5 define varias constantes cada vez que se ejecuta un script y que son accesibles por nosotros

Tabla 22 Algunas constantes definidas por PHP 5

Nombre Descripcioacuten

PHP_VERSION Versioacuten del parse de PHP que estamos utilizando

PHP_OS Sistema operativo del servidor de PHP

PEAR_EXTENSION_DIR Ruta donde estaacute instalada la extensioacuten PEAR

PHP_LIBDIR Ruta donde estaacuten almacenadas las libreriacuteas de PHP 5

Finalmente tenemos 5 constantes maacutegicas tal y como las definen en el sishytio Web wwwphpnet que cambian de valor dependiendo del lugar donshyde se usen Por ejemplo el valor de la constante LINE depende de la liacutenea donde la estemos usando en nuestro programa

Tabla 23 Constantes maacutegicas

Nombre Descripcioacuten

LINE Indica el nuacutemero de liacutenea desde la que imprimimos el

valor

FILE Ruta completa al fichero

FUNCTION Nombre de la funcioacuten que la contiene

CLASS Nombre de la clase

_ M E T H O D _ Nombre del meacutetodo

Advertencia

Hay que tener cuidado con el nombre de las constantes maacutegicas Los siacutembolos que hay a la izquierda y ala derecha del nombre son dos guiones bajos seguidos (_)

ltphp echo LINE - VERSIOacuteN de PHP 5PHP_VERSION echo ltbrgt

Variables constantes y tipos de datos 65

echo LINE - SISTEMA Operativo Servidor PHP_OS echo ltbrgt echo LINE - Ruta de las extensiones PHP_EXTENSION_DIR echo ltbrgt echo LINE - API de Servidor PHPJ3API gt

Funciones relacionadas con variables

PHP 5 brinda al programador una serie de funciones para el manejo de variables

isset()

Con esta funcioacuten podemos averiguar si una funcioacuten existe dentro de nuesshytro programa Si existe devuelve true y si no existe false

ltphp $DNI = 8868543-Z if (isset($DNI)) echo (La variable DNI existe)

66 Capiacutetulo 2

gt

unset()

Libera la memoria ocupada por una variable destruyendo su nombre y su contenido Despueacutes de usar unset () la variable destruida apareceraacute comoase al utilizar la funcioacuten i s s e t ()

ltphp $Nombre = Mariacutea Fernanda if (isset($Nombre)) echo (El nombre existe)

Podemos comprobar queacute pasa si liberamos la variable $Nombre unset($Nombre)iexcl if (isset($Nombre)) echo (El nombre existe) else echo (El nombre ya no existe) gt

El resultado es el siguiente El nombre e x i s t e El nombre ya no e x i s t e

gettype()

Con esta funcioacuten podemos averiguar el tipo de dato almacenado en la variable Nos puede devolver uno de los siguientes valores

bull integer

bull double

bull string

bull array

bull object

bull class

bull unknown type ltphp $correo = luisnccextremaduraorg echo la variable correo es del tipo

Variables constantes y tipos de datos 67

echo g e t t y p e ( $ c o r r e o ) gt

settype()

Convierte el tipo de la variable al especificado en la funcioacuten El tipo debe especificarse eligiendo uno de los siguientes array double integer object o string Si la funcioacuten no es capaz de convertir el tipo de la variable devuelshyve el valor false

ltphp $correo = luisnccextremaduraorg if (settype($correointeger))

echo (Variable correo convertida a Enteroltbrgt)

else

echo (Imposible convertir al tipo Enteroltbrgt)

echo (Valor actual de correo es $correo) gt

Al tratar de convertir un tipo string (una cadena de caracteres) a un enteshyro PHP 5 comprueba si existe alguacuten nuacutemero Si no existe cambia el valor a O y la funcioacuten s e t t y p e () la evaluacutea como correcta

empty()

Comprueba si una variable estaacute vaciacutea no existe o su valor es 0 ltphp $correo = luisnccextremaduraorg if (empty($nombre))

echo (La variable nombre no existe)

$numero_entero = O if (empty($numero_entero))

echo (La variable numero_entero no existe o tiene el valor O) gt

isjntegerf) is_double() is_string()

Estas funciones devuelven true si la variable pasada coincide con el tipo que indica la funcioacuten

68 Capiacutetulo 2

Si la variable $numero_en te ro se evaluacutea con la funcioacuten i s _ i n t e g e r ( ) devolveraacute true

ltphp $numero_entero = 0 if (is_integer()($numero_entero))

echo (numero_entero es del tipo integer)

gt

intval() doublevalQ strval()

Convierte el valor de una variable al tipo indicado en la funcioacuten Esta funshycioacuten no permite la conversioacuten a tipos object o array

ltphp Conversioacuten de un tipo string a un integer $cadena = 232 echo El tipo de la variable cadena es gettype($cadena)ltbrgt $numero = intval($cadena) echo (el numero es $numero) gt

Resumen

La base de la programacioacuten reside en la creacioacuten de datos y su procesashymiento En este capiacutetulo hemos visto coacutemo declarar variables de diferenshytes tipos y coacutemo utilizar funciones para averiguar las propiedades de cada una de ellas Ademaacutes de las variables las constantes juegan un papel muy importante sobre todo las predefinidas por PHP 5 que nos dan informashycioacuten muy uacutetil con la que poder trabajar

En este capiacutetulo aprenderaacute a

bull Utilizar los diferentes tipos de operadores existentes bull Distinguir entre operadores unarios binarios y ternarios

bull Comprender la preferencia de ejecucioacuten entre operadores

70 Capiacutetulo 3

Introduccioacuten

En el capiacutetulo anterior hemos visto ejemplos de coacutedigo escrito en PHP que utilizan siacutembolos muy comunes en el ambiente matemaacutetico e inforshymaacutetico Estos siacutembolos que aparecen entre variables o dentro de funciones son conocidos como operadores Existen varios tipos de operadores

bull De asignacioacuten bull Unario bull Aritmeacuteticos bull De comparacioacuten bull Loacutegicos bull Ternario bull Bit a bit bull Asignacioacuten combinados bull De ejecucioacuten bull Supresioacuten de errores

Operador de asignacioacuten

El maacutes baacutesico es el siacutembolo de asignacioacuten (=) utilizado para dar valores a las variables que usamos en nuestro coacutedigo

ltphp $variable = 34 $variable2 = Asignacioacuten de valores gt

Las variables que estaacuten a la izquierda del operador toman el valor que se encuentra en la expresioacuten de la derecha

Advertencia

No hay que confundir el operador de asignacioacuten (=) con el operashydor de comparacioacuten (==) sobre todo en bucles de control donde seriacutea difiacutecil encontrar alguacuten fallo

Operadores 71

Operador Unario

El signo menos (-) se utiliza delante de un nuacutemero o variable numeacuterica Este operador tiene la propiedad de hacer a los nuacutemeros negativos o poshysitivos dependiendo del signo actual

ltphp $entero = 23 $entero_negativo = -$entero El valor es ahora -23 entero2 = -$entero__negativo El valor cambia ahora a 23 gt

Operadores Aritmeacuteticos

Este tipo de operadores forman parte de la aritmeacutetica baacutesica Nos resultashyraacute familiar porque son siacutembolos muy utilizados en el aprendizaje de las matemaacuteticas

Tabla 31 Operadores aritmeacuteticos

Ejemplo Nombre Resultado

$a + $b suma Suma las dos variables $a - $b resta Hace la diferencia de las dos variables Sa $b multiplicacioacuten Producto de las variables $a $b divisioacuten Cociente entre las dos variables $a $b Moacutedulo Resto de la divisioacuten de $a entre $b

Nota

-rr PHP 5 ignora los espacios en blanco entre las variables y los opeshyradores Aunque $a + $b es equivalente a $a + $b es preferible utilizar la primera forma de escribir porque se hace maacutes legible

Operadores de comparacioacuten

En algunos ejemplos del capiacutetulo anterior puede ver que se utiliza la esshytructura de control if el se Como veremos maacutes adelante esta estructu-

72 Capiacutetulo 3

ra compara dos valores y elige el camino a seguir El valor de la comparashycioacuten siempre es true ofalse

Tabla 32 Operadores de comparacioacuten

Ejemplo Nombre Resultado

$a == $b Igualdad Devuelve true si $a y $b son iguales $a === $b Identidad Verdadero si son iguales y del mismo tipo $a = $b Distinto True si son distintos $a ltgt $b Distinto True si son distintos $a lt $b Menor que Cierto si $a es menor que $b $a gt $b Mayor que Cierto si $a es mayor que $b $a lt= $b Menor o igual Correcto si $a es menor o igual que $b $a gt= $b Mayor o igual Correcto si $a es mayor o igual que $b

ltphp $a = 23 Asignacioacuten de los valores $b = 75 if ($a gt= $b) La condicioacuten no se cumple El resultado es false

echo Esta parte no se ejecuta else

echo La comparacioacuten es false porque $a es menor que $b

gt

Operadores 73

Operadores Loacutegicos

Durante el desarrollo de su proyecto puede encontrarse con situaciones en las que necesite hacer varias comparaciones seguidas para que se cumshypla una determinada condicioacuten PHP 5 permite unir todas las comparashyciones en una mediante el uso de los operadores loacutegicos

Tabla 33 Operadores loacutegicos

Ejemplo Nombre Resultado

expresionl and expresion2 Y Si las dos expresiones son vershydaderas el valor es true

expresionl or expresion2 O Si una de las expresiones es vershydadera el valor es true

expresionl xor expresion2 O exclusivo True si una expresioacuten es verdashydera y la otra falsa

expresionl Negacioacuten Verdadero si la expresioacuten no es cierta

expresionl ampamp expresion2 Y Si las dos expresiones son vershydaderas el valor es true

expresionl || expresion2 O Si una de las expresiones es vershydadera el valor es true

El listado siguiente muestra dos condiciones anidadas lt php $a = 2 3 Sb = 75 $c = true if ($a lt $b)

if ($c) echo (Se cumplen las dos condiciones)

gt gt

Egtta expresioacuten se puede hacer maacutes legible utilizando alguacuten operador loacuteshygico

ltphp $a = 23 3b = 75 $c = t rue

74 Capiacutetulo 3

i f ($a lt $b and $c) echo Se cumplen l a s dos cond ic iones

gt

Operador Ternario

Los operadores que hemos visto hasta ahora son capaces de manejar un operando (Unarios) o dos operandos (binarios) El operador ternario o de comparacioacuten evaluacutea un operando y dependiendo de si es falso o vershydadero evaluacutea el segundo operando o el tercero La expresioacuten que se quiere evaluar se escribe delante de un siacutembolo () despueacutes la expresioacuten que tiene que ejecutarse si la evaluacioacuten anterior es true seguida del siacutembolo () con la expresioacuten que debe ejecutarse si es false

ltphp $valor = false $valor == true $resultado = OK $resultado = FALLO Si $value es true $resultado seraacute OK Si es false $re sultado seraacute FALLO echo $resultado gt

Operadores bit a bit

Estos operadores son complicados de entender si no conoce la loacutegica bishynaria Afortunadamente se utilizan en muy pocas ocasiones Los operashydores de bit utilizan las variables a nivel bajo tal y como se almacenan en memoria fiacutesica y comparan bit a bit los valores Lo mejor es verlo con un ejemplo

ltphp bull$a = 4 Valor binario 100 $b = 5 Valor binario 101 $c = $a amp $b echo $c El valor de c es 100 gt

El operador binario Y (siacutembolo amp) compara bit a bit las variables $a y $b Si los bits de una misma posicioacuten son true (tienen el valor 1) el bit resultashydo es 1 En este caso soacutelo existe una pareja de bits que es igual a true (sus

Operadores 75

dos valores son 1) por lo tanto el valor de la variable $c es 4 (en binario 100)

Tabla 34 Operadores bit a bit

Ejemplo Nombre Resultado

$a amp $b Y Si las parejas de bits son verdaderas el resultado es

verdadero

$a | $b O Si alguacuten bit de la pareja es verdadero el resultado es

verdadero

$a A $b O Si un bit de la pareja es true y el otro false el resultado exclusiva es verdadero

~$a No Los bits 1 se vuelven 0 y viceversa Tambieacuten cambia el bit que se refiere al signo positivo o negativo

$a ltlt $b Desplaza- Desplaza a la izquierda los bits de la variable $a tantos miento a bits como indique la variable $b la izquierda de bits

$a gtgt $b Desplaza- Desplaza a la derecha los bits de la variable $a tantos miento a bits como indique la variable $b la derecha

Nota

Puesto que la notacioacuten binaria se escapa del enfoque de este libro le recomiendo algunas lecturas posteriores referidas a la loacutegica de bit si es que tiene curiosidad Probablemente no utilizaraacute estos operadores nunca pero eso depende de la magnitud de los proyecshytos a los que se enfrente

Operadores de asignacioacuten combinados

En numerosas ocasiones se nos presentan situaciones en las que una va-riable debe incrementar o disminuir su valor en 1

ltphp

$a =23

$a = $a +1 Incrementamos en 1 el valor de la variable gt

HP 5 provee operadores combinados que permiten asignar raacutepidamente crementos de valor concatenaciones de caracteres etceacutetera

76 Capiacutetulo 3

Tabla 35 Operadores de asignacioacuten combinados

Ejemplo Nombre Equivalencia

$a++ Incremento $a = $a +1

$a~ Decremento $a = $a -1

++$a Incremento $a = $a +1

~$a Decremento $a = $a -1

$a += $b Suma $a = $a + $b

$a -= $b Resta $a = $a - $b

$a = $b Multiplicacioacuten $a = $a $b

$a = $b Divisioacuten $a = $a $b

$a = $b Moacutedulo $a = $a $b

$a amp= $b Y $a = $a amp $b

$a |= $b O $a = $a | $b

$a A= $b O exclusiva $a = $a A $b

$a = $b Concatenacioacuten $a = $a $b

$a gtgt= $b Desplazamiento a la derecha $a = $a gtgt $b

$a ltlt= $b Desplazamiento a la izquierda $a = $a ltlt $b

Advertencia

Como vemos en la tabla 35 iexclos operadores de incremento y deshycremento pueden aparecer a la derecha o a la izquierda de un vashyriable La posicioacuten del operador influye en el orden en el que la variable se asigna o se incrementa Mejor verlo en un ejemplo ltphp $a = 23 $b = $a++ $b es igual a 23 porque $a se incrementa despueacutes de la asignacioacuten

$a = 2 3 $c = + + $a $c es igual a 24 porque $a se incrementa antes de la asignacioacuten

echo la variable b es $b y c es $c gt

Operador de ejecucioacuten

Si tiene experiencia con la programacioacuten en shell de Unix o gnuLinux sabraacute que el apostrofe invertido sirve para ejecutar comandos del sis-

Operadores 77

tema PHP 5 ha adoptado esta nomenclatura y funciona exactamente igual

ltphp $listado_archivos = Is -la~ Hacemos un listado de los ficheros del directorio actual echo $listado_archivos y lo sacamos por pantalla gt

Nota

El comando ls del ejemplo anterior es propio de sistemas Unix y gnuLinux Siacute hace pruebas sobre un sistema basado en el Sistema Operativo Windows el ejemplo anterior no funcionariacutea tendriacutea que cambiar el comando por dir

Operador de supresioacuten de errores

La mayoriacutea de las funciones que se utilizan en PHP 5 muestran errores en el navegador cuando algo falla

Si intenta abrir un fichero que no existe PHP mostraraacute un mensaje de error v continuaraacute la ejecucioacuten del programa

78 Capiacutetulo 3

El operador () colocado delante de una funcioacuten evitaraacute que se muestre el error

ltphp $fichero = fopen(pruebatxt r) Muestra un error en el navegador echo (El programa sigue ejecutaacutendose) gt

El coacutedigo siguiente oculta la salida de error por pantalla

ltphp $fichero = fopen(pruebatxtr) echo (El programa sigue ejecutaacutendose) gt

Precedencia de Operadores

Vamos a echar un vistazo al coacutedigo siguiente

ltphp $resultado = 20 + 10 10 echo $resultado gt

Aparentemente es un coacutedigo muy simple pero encierra un problema mashytemaacutetico

Existen dos resultados posibles en funcioacuten del operador que debe ejecushytarse antes

Si la suma se ejecuta antes la variable $ r e s u l t a d o tendraacute el valor 300 y si la multiplicacioacuten se ejecuta antes tendremos q u e $ r e s u l t a d o equivashyle a 120

Si comprobamos el coacutedigo el resultado que nos muestra es 120 por lo tanto el operador de multiplicacioacuten () es preferente con respecto al operador de suma (+)

Si los operadores que aparecen son ideacutenticos existe un orden de ejecushycioacuten que puede ser desde la izquierda a la derecha o derecha a izquierda

ltphp $resultado = 2 0 1 0 2 echo $resultado gt

El valor de $ r e s u l t a d o es ahora 1 porque primero se calcula 20 10 y despueacutes ese mismo resultado se divide entre 2 es decir la asociacioacuten enshytre operadores de divisioacuten es desde la izquierda

Operadores 79

Tabla 36 Orden de preferencia de los operadores

Operador Operacioacuten Asociacioacuten

() Pareacutentesis de preferencia NA

new Instancia de objeto NA

[] array Derecha

NO loacutegico Derecha

Signo menos Derecha

++ -- Incremento decremento Derecha

Supresioacuten de errores Derecha

Multiplicacioacuten divisioacuten y moacutedulo Izquierda

+ - Suma resta concatenacioacuten Izquierda

ltlt gtgt Desplazamiento izquierda y derecha Izquierda

lt lt = gt gt = Menor que menor o igual NA

mayor que mayor o igual

== = Igual no igual NA

amp Y izquierda A O exclusivo Izquierda

| O Izquierda

ampamp Y loacutegico Izquierda

|| O loacutegico Izquierda

condicional Derecha = += = = = Asignacioacuten Derecha = = amp= = -= ltlt= gtgt=

and Y loacutegico Izquierda

xor O exclusivo loacutegico Izquierda

or O loacutegico Izquierda

El operador pareacutentesis tiene la propiedad de dar preferencia en la evaluashyron a todos los operadores que contiene El siguiente ejemplo muestra oacutemo podemos utilizar correctamente el operador pareacutentesis

ltphp $resultado = 2 0 1 0 + 2 echo $resultado El resultado es 4 $resultado = 20 (10 + 2) echo $resultado El resultado es 166666667 gt

Resumen

Los operadores son responsables de todas las operaciones que realizamos en nuestros programas Por eso es importante conocer las propiedades v los casos de uso de cada uno de ellos para poder sacarles el maacuteximo partishydo Sin embargo si ya conoce alguacuten lenguaje de programacioacuten la intuishycioacuten le haraacute utilizarlos adecuadamente sin pararse a pensar en el tipo de operador

Por uacuteltimo debe prestar un especial intereacutes a la preferencia de uso ya que una mala utilizacioacuten redundaraacute en un error muy difiacutecil de controlar

En este capiacutetulo aprenderaacute a

bull Utilizar las estructuras de control de eleccioacuten simple y muacuteltiple bull Crear bucles de diferentes tipos bull Crear sus primeros programas bull Conocer las sentencias para interrumpir un bucle

82 Capiacutetulo 4

Introduccioacuten

Es difiacutecil imaginar un programa sin estructuras de control Eacutestas nos permishyten elegir diferentes caminos en funcioacuten de los datos que evaluamos en cada momento En este capiacutetulo trataremos dos tipos de estructuras de control

bull Estructuras de eleccioacuten

bull Estructuras de bucle

Las estructuras de eleccioacuten permiten evaluar una condicioacuten o varias y eleshygir el camino correcto Las de bucle repiten un nuacutemero determinado de veces un conjunto de instrucciones

Estructuras de eleccioacuten

Existen dos tipos

bull Eleccioacuten simple bull Eleccioacuten muacuteltiple

if-else

La sintaxis de esta estructura es if (condicioacuten) instruccioacuten

Si se cumple la condicioacuten se ejecuta la instruccioacuten que le sigue Si quiere que se ejecuten varias instrucciones debe utilizar el siacutembolo llave ( insshytrucciones iexcl )

if (condicioacuten) instruccionl instruccion2iexcl

instruccion3

La estructura if puede ampliarse para que se pueda elegir entre condishycioacuten verdadera y falsa

if (condicioacuten) instruccionl instruccioacuten2 instruccion3

else

Estructuras de control 83

instruccionl -instruccioacuten2 instruccion3

Si la condicioacuten es verdadera se ejecutan las instrucciones inmediatamente despueacutes del if y si la condicioacuten es falsa se ejecutan las instrucciones disshypuestas despueacutes de la palabra e l s e Puede ver un ejemplo completo

ltphp $valor = 23 $valor2 = 27 if ($valor lt $valor2)

echo La variable valor es menor que valor2 else

echo La variable valor es mayor que valor2

gt

elseif

Es muy comuacuten hacer comparaciones en cascada para comprobar varios valores

ltphp $ d i a = 4 if ($d ia == 1)

84 Capiacutetulo 4

echo El diacutea es Lunes else

if ($dia == 2) echo El diacutea es Martes

else if ($dia == 3)

echo El diacutea es Mieacutercoles else

if ($dia == 4) echo El diacutea es Jueves

gt

El patroacuten anterior es tan comuacuten que existe una estructura especial para manejarlo

Puede escribir el ejemplo anterior con la palabra reservada e l s e i f de la siguiente forma

ltphp $dia=4

if ($dia == 1) echo El diacutea es Lunes

elseif ($dia == 2) echo El diacutea es Martes

elseif ($dia == 3) echo El diacutea es Mieacutercoles

elseif ($dia == 4) echo El diacutea es Jueves

gt

El ejemplo anterior evaluacutea la variable $dia hasta que encuentra el valor correcto y ejecuta las instrucciones

switch

La construccioacuten swi t ch comprueba el valor de una expresioacuten y permite elegir entre un conjunto de instrucciones El formato es el siguiente switch (expresioacuten)

case valorl instruccionl instruccion2 instruccion3 break

Estructuras de control 85

case valor2 instruccionl instruccion2 instruccion3 break

case valor3 instruccionl instruccion2 instruccion3 break

default instruccionl instruccion2

instruccion3

La expresioacuten puede ser de cualquier tipo siempre que devuelva un valor de tipo entero de coma flotante o de cadena de caracteres Una vez evashyluada la expresioacuten se busca el valor en la instruccioacuten case y si coincide se ejecutan todas las instrucciones hasta la palabra reservada break Si no coincide ninguacuten valor se ejecutan las instrucciones por defecto Veamos un ejemplo completo

ltphp $dia = 4 switch ($dia)

case 1

echo El diacutea es Lunes break

case 2 echo El diacutea es Martes break

case 3 echo El diacutea es Mieacutercoles break

case 4 echo El diacutea es Jueves break

case 5 echo El diacutea es Viernes break

case 6 echo El diacutea es Saacutebado break

case 7 echo El diacutea es Domingo break

default

Bucles

Los bucles son estructuras de control que permiten repetir varias veces las mismas instrucciones

while

El bucle while es el maacutes baacutesico de todos La construccioacuten baacutesica es la sishyguiente

while (condicioacuten) instruccioacutenlbull instruccioacuten2 instruccioacuten3

La condicioacuten se evaluacutea al principio

Si es verdadera se ejecutan las instrucciones que estaacuten dentro del bucle y se vuelve a evaluar la condicioacuten

86 Capiacutetulo 4

echo El diacutea de la semana es incorrecto

gt

Estructuras de control 87

Si la condicioacuten es falsa no se ejecutan las instrucciones y se continuacutea con el desarrollo del programa

Puesto que la condicioacuten se evaluacutea antes de ejecutar las instrucciones es posible que algunos bucles no se ejecuten ninguna vez

El siguiente ejemplo muestra una instruccioacuten while que no se ejecuta nunshyca porque la condicioacuten es falsa

ltphp $variable = false while ($variable)

echo Esta linea no se ejecuta nunca

gt

Existe la posibilidad de que un bucle se ejecute infinitas veces si dentro de las instrucciones no existe nada que cambie la condicioacuten que se evaluacutea al principio

ltphp $variable = true while ($variable)

echo CUIDADO Esta liacutenea se ejecuta siempre

gt

88 Capiacutetulo 4

El bucle while se puede utilizar para ejecutar un nuacutemero determinado de veces las instrucciones que implica

Veacutease el ejemplo de la serie de Fibonacci

ltphp $numero_anterior = 1 $numero_posterior = 1 $serie = 1 $fin = 10000 echo Serie de Fibonacci while ($serie lt $fin) echo $serie $serie = $numero_anterior + $numero_posterior $numero_anterior = $numero_posterior $numero_posterior = $serie

gt

Cada nuacutemero de la serie de Fibonacci se forma sumando los dos nuacutemer -anteriores

En el ejemplo la condicioacuten es que el nuacutemero de la serie sea menor que t

nuacutemero que marca la variable $f i n es decir si el nuacutemero que indica iquest serie es mayor que 10000 el bucle finaliza

La variable $f in sirve de valor maacuteximo y puede cambiarlo en funcioacuten la cantidad de nuacutemeros que quiera tener en pantalla

Estructuras de control 89

do-while

Este bucle es igual que el anterior pero la condicioacuten se evaluacutea al final de las instrucciones Por lo tanto el coacutedigo que estaacute entre las llaves se ejecuta al menos una vez El formato baacutesico es el siguiente

do instruccioacutenl instruccioacuten2 instruccioacuten3

while (condicioacuten)

Puede comprobar que la diferencia es miacutenima cuando utiliza esta estrucshytura de control para la serie de Fibonacci

ltphp $numero_anterior = 1 $numero_posterior = 1 $serie = 1 $fin = 6765 echo Serie de Fibonacci do

echo $serie $serie = $numero_anterior + $numero_posterior $numero_anterior = $numero_posterior $numero_posterior = $serie

whi le ($ser ie lt $ f i n ) gt

for

La construccioacuten de bucle maacutes complicada es la del for Tiene la siguiente sintaxis

for (expresioacuten inicial condicioacuten de fin expresioacuten de fin) instruccioacutenl instruccioacuten2

instruccioacuten3

El funcionamiento es muy sencillo La expresioacuten inicial se ejecuta una sola vez al principio del bucle La condicioacuten de fin se evaluacutea cada vez que se ejecuta el bucle Si es verdashydera se continuacutea la ejecucioacuten y si es falsa se sale del bucle Al final de cada interaccioacuten se ejecuta la expresioacuten de fin

90 Capiacutetulo 4

Puede simular la instruccioacuten f or con una instruccioacuten w h i l e de esta forma

expresioacuten inicial

while (condicioacuten de fin)

instruccioacutenl

instruccioacuten2

instruccioacuten3

expresioacuten de fin

Otra forma poco corriente es eliminar alguna o todas las expresiones de bucle Si quita todas las expresiones se crea un bucle infinito

fOr ( )

instruccioacutenl

instruccioacuten2

instruccioacuten3

equivale a

while (true)

instruccioacutenl

instruccioacuten2

instruccioacuten3

El caso contrario es antildeadir maacutes de una condicioacuten en cada clase de expreshysioacuten separadas por comas En este caso la condicioacuten de fin se evaluara falso si alguna de las claacuteusulas es falsa En realidad funciona como un C loacutegico

ltphp

for ($x = 1 $y = 1 $z = 1 $y lt 10 $z lt 10 $x++ $y = $y -

2 $z = $z + 3)

echo ($x $y $zltbrgt)

gt

Un ejemplo claacutesico es la tabla de multiplicar lthtmlgt ltbodygt ltbgtTABLA DE MULTIPLICARltbgt lttable border=lgt ltphp echo (lttrgt) echo (ltthxthgt ) for ($cabecera = 1 $cabecera lt= 10 $cabecera++)

echo (ltthgt) echo $cabecera

Estructuras de control 91

echo (ltthgt)

echo (lttrgt) for ($x = l$x lt= 10 $x++ )

echo (lttrgt) echo (ltthgt) echo $x echo (ltthgt) for ($y = l$y lt= 10 $y++ )

$multiplicacion = $x $y echo (lttdgt) echo ($multiacutepliacutecaciacuteon) echo (lttdgt)

echo (lttrgt) gt gt lttablegt ltbodygt lthtmlgt

[ ejemplo se sirve de un bucle for que crea una cabecera de tabla con la queta especial ltthgt donde inserta los nuacutemeros del uno al diez Estos umeros escritos en horizontal se podraacuten cruzar con los verticales para atener asiacute el resultado de una multiplicacioacuten

92 Capiacutetulo 4

El siguiente paso es un conjunto de dos bucles anidados El primer bucle almacena en la variable $x los valores numeacutericos que apareceraacuten como cabecera de la columna uno El segundo bucle seraacute el encargado de multishyplicar el valor actual de $x por los valores del 1 al 10

Cada vez que se ejecuta el segundo f o r se obtiene una celda nueva con un valor determinado por la multiplicacioacuten y cada vez que se ejecuta el primer bucle aparece una nueva fila cuya cabecera es un nuacutemero del 1 al 10

break y continueacute

El camino ordinario para salir de un bucle es que la condicioacuten se evaluacutee a false Existe una forma especial de salir de un bucle utilizando las palashybras reservadas b r e a k y c o n t i n u eacute Su forma de actuar es la siguiente

bull break Sale del bucle actual y continuacutea el programa

bull continueacute Salta hasta el final de la interaccioacuten y continuacutea la ejecucioacuten desde el principio del bucle

El coacutedigo siguiente muestra la forma de utilizar b r e a k

ltphp for ($x = 1 $x lt 20 $x++)

if ($x == 10) break

else echo $xltbrgt

La salida por pantalla es una sucesioacuten de nuacutemeros del 1 al 9 Al llegar la variable $x al nuacutemero 10 la condicioacuten del if se cumple y se ejecuta la instruccioacuten b r e a k saliendo del bucle Veamos ahora el mismo ejemplo pero utilizando c o n t i n u eacute

ltphp for ($x = 1 $x lt 20 $x++)

if ($x == 10) continueacute

else echo $xltbrgt

gt

Estructuras de control 93

En este caso cuando $x alcanza el valor 101o que hace la instruccioacuten conshyt i n u eacute es ir hacia el final de bucle y volver al principio comprobando la condicioacuten

El resultado por pantalla es una sucesioacuten de nuacutemeros desde el 1 hasta el 19 sin incluir el nuacutemero 10

Finalizar la ejecucioacuten de un programa

Hay veces que necesitamos parar la ejecucioacuten de un programa por divershysas causas ha ocurrido un error un fallo en la entrada del nombre y la conshytrasentildea La funcioacuten para la ejecucioacuten es e x i t () o d i e () Estas dos funciones aceptan un paraacutemetro que se imprime en pantalla Por ejemplo considere el siguiente coacutedigo que asume la conexioacuten a una base de datos

ltphp $conexion = conectar_base_datos(libros) if ( $conexion)

die (Se ha producido alguacuten error en la conexioacuten)

gt

Se puede apreciar que si la variable $ c o n e x i oacute n se evaluacutea false (no se ha conseguido la conexioacuten) se detiene la ejecucioacuten del programa Una vershysioacuten maacutes compacta se consigue utilizando el operador or

ltphp $conexion = conectar_base_datos(libros) or die (Se ha producido alguacuten error en la conexioacuten) gt

Nota

e x i t () y d i e () eran iexclas uacutenicas alternativas para el control de errores criacuteticos en versiones anteriores de PHP En PHP 5 aforshytunadamente se ha incluido un potente manejo de excepciones que hace la ejecucioacuten maacutes flexible

Sintaxis alternativa

Algunas estructuras de control pueden escribirse de una forma distinta Las estructuras i f w h i l e f or y s w i t c h pueden escribirse sustituyen-

94 Capiacutetulo 4

do la llave de inicio por un siacutembolo de dos puntos () y la llave de cierre por e n d i f e n d w h i l e endf or y e n d s w i t c h respectivamente

Como ejemplo podemos ver la estructura i f

ltphp $variable = 10 if ($variable == 10)

echo Nueva estructura de control gt

El coacutedigo siguiente es equivalente al anterior

ltphp $variable = 10 if ($variable == 10)

echo Nueva estructura de control end i f

gt

Resumen

Si ha llegado hasta aquiacute ya conoceraacute los secretos baacutesicos de la programashycioacuten en PHP 5 Como puede darse cuenta lo uacutenico necesario para hacer un programa es tener claro la forma de utilizar las variables los operadoshyres y las estructuras de control Una vez dominado esto lo demaacutes es aprenshyder funciones de PHP y teacutecnicas de recuperacioacuten e insercioacuten de datos

Los capiacutetulos siguientes hacen un estudio maacutes concienzudo de las variashybles y las funciones que facilitan el proceso de interaccioacuten entre ellas

En este capiacutetulo aprenderaacute a

bull Crear sus propias funciones bull Utilizar paraacutemetros fijos y variables

bull Realizar funciones recursivas bull Separar el coacutedigo fuente en varios ficheros

96 Capiacutetulo 5

Introduccioacuten

Las funciones son grupos de instrucciones independientes que tienen un propoacutesito determinado

Asiacute tenemos funciones que calculan la raiacutez cuadrada de un nuacutemero nos dan un nuacutemero aleatorio o permiten contar los caracteres de una palabra La sintaxis baacutesica de una funcioacuten es la siguiente

nombre_funcioacuten (paraacutemetrol paraacutemetro2 paraacutemetro3paraacutemetro_n)

Las funciones pueden ser llamadas con varios paraacutemetros o con ninguno dependiendo de su definicioacuten

Cuando PHP encuentra en el coacutedigo la llamada a una funcioacuten primero evaluacutea cada argumento y los utiliza como paraacutemetro de entrada Despueacutes ejecuta la funcioacuten y devuelve el valor solicitado o realiza alguna accioacuten sin enviar ninguacuten valor de salida

El siguiente ejemplo contiene un conjunto de llamadas a funciones con 01 oacute 2 paraacutemetros de entrada

ltphp echo sqrt(9) Raiacutez cuadrada de 9 es 3 echo rand(1020) Nuacutemero aleatorio entre 10 y 20 echo pi() Nuacutemero pi gt

Valores de las funciones

Cada funcioacuten en PHP se considera como una expresioacuten Se pueden utilishyzar las funciones para lo mismo que se utilizan las expresiones como alshymacenar su resultado en una variable o formar parte de una expresioacuten maacutes compleja

ltphp $numero_aleatorio = rand (1100) Se almacena en una variable $numero_aleatorio = rand (1100) + rand (1100) sqrt(9) Expresioacuten compleja gt

No todas las funciones devuelven un valor numeacuterico Tambieacuten pueden devolver caracteres array o truefalse si la funcioacuten ha tenido eacutexito o no Este tipo de funciones se utiliza para conectar a bases de datos escribir a ficheros de texto manipular imaacutegenes etceacutetera

Funciones 97

Funcioacuten de ejemplo Obtencioacuten de la fecha actual

Existen un conjunto de funciones que permiten averiguar la fecha actual del sistema Una de estas funciones es d a t e ( ) que permite recuperar el antildeo diacutea mes etceacutetera del momento en el que se hace la consulta Para averiguar el diacutea de hoy podemos utilizar la construccioacuten

lt d a t e (d) gt

El paraacutemetro que pasamos entre pareacutentesis indica a la funcioacuten el formato de fecha que queremos obtener En este caso la d indica que queremos obtener el diacutea en formato numeacuterico La siguiente tabla relaciona los caracshyteres dentro de la funcioacuten d a t e () con su aplicacioacuten praacutectica

Tabla 51 Formato de fecha con date()

Caraacutecter Valor

a Imprime am o pm

A AM o PM

h La hora en formato (01-12)

H Hora en formato 24 (00-23)

g Hora de 1 a 12 sin un cero delante

G Hora de 1 a 23 sin cero delante

i Minutos de 00 a 59

s Segundos de 00 a 59

d Diacutea del mes (01 a 31)

j Diacutea del mes sin cero (1 a 31)

w Diacutea de la semana (0 a 6) El 0 es el domingo

m Mes actual (01 al 12)

n Mes actual sin ceros (1 a 12)

Y Antildeo con 4 diacutegitos (2004)

y Antildeo con 2 diacutegitos (04)

z Diacutea del antildeo (0 a 365)

t Nuacutemero de diacuteas que tiene el mes actual

98 Capiacutetulo 5

Se pueden utilizar varios caracteres dentro de la funcioacuten indicando el forshymato de fecha que nos interesa

ltphp $meses = array (Enero Febrero Marzo Abril Mayo

Junio Julio Agosto Septiembre Octubre Noviembre Diciembre)

echo Fecha actual date(d-m-Y) ltbrgt echo Diacutea del antildeo date(z) ltbrgt echo Estamos en el mes $meses[date(n) ] ltbrgt gt

El resultado en pantalla es el siguiente

Documentacioacuten sobre funciones

Desde sus inicios PHP se disentildeoacute para que fuera sencillo de utilizar y de extender por la comunidad de desarrolladores La potencia reside en la gran cantidad de funciones escritas de todo tipo Este libro cubre las funciones maacutes utilizadas en el desarrollo de un proshyyecto profesional pero seriacutea imposible cubrir todas las funciones existenshytes con detalle Por esta razoacuten es imprescindible tener como referencia la

Funciones 99

guiacutea on-line de PHP en wwwphpnet donde podemos encontrar clasifishycadas por temaacutetica todas las funciones existentes hasta ahora

Ademaacutes contamos con un buscador de apoyo que nos permite buscar la definicioacuten de una funcioacuten y ejemplos de uso escritas por usuarios de PHP

Para los usuarios que no conocen la forma de trabajar con el lenguaje C se hace necesario explicar coacutemo aparecen las funciones descritas en el mashynual de wwwphpnet El formato es el siguiente

tipo_devuelto nombre_funcioacuten (tipol argl tipo2 arg2) -

El t i p o - d e v u e l t o es el tipo de valor que la funcioacuten daraacute como salida Puede ser un integer double array etceacutetera El nombre de la f u n c i oacute n es la forma correcta de ejecutar el coacutedigo Los p a r aacute m e t r o s de e n t r a d a (arshygumentos) deben pertenecer al tipo que define la funcioacuten Un ejemplo de definicioacuten es

string substr (string string int start[ int length] )

Puede ver que la funcioacuten s u b s t r () devolveraacute como resultado una cadeshyna de caracteres y que tiene 2 argumentos de entrada como miacutenimo El paraacutemetro que se encuentra entre dos corchetes es opcional y puede decishydir usarlo o no

Funciones de usuario

Para realizar programas complejos en PHP 5 no es necesario escribir funshyciones Se pueden escribir programas utilizando todo lo aprendido hasta ahora

A medida que el proyecto se haga maacutes complejo el coacutedigo se haraacute maacutes extenso y menos legible En este punto deberiacutea comenzar a pensar en crear funciones que realicen determinadas tareas

Definicioacuten de funciones

El formato es el siguiente

function nombre_funcioacuten($argumentol $argumento2 )

instruccioacutenl instruccioacuten2 instruccioacuten3

100 Capiacutetulo 5

Como puede ver se comienza con la palabra reservada f u n c t i o n seguishyda del nombre de la f u n c i oacute n y el nuacutemero de p a r aacute m e t r o s n e c e s a shyr i o El bloque de coacutedigo que pertenece a nuestra funcioacuten debe introducirse entre dos siacutembolos de llave ( ) Un ejemplo claacutesico consiste en calcular el factorial de varios nuacutemeros El factorial del nuacutemero x se obtiene multishyplicando el nuacutemero x por el factorial de (x-1) teniendo en cuenta que el factorial de 1 es 1 Por ejemplo el factorial de 3 seriacutea 3 por el factorial de 2 es decir 3 2 1 El coacutedigo sin utilizar funciones es

ltphp $resultado = 1 $factorial = 3 Queremos calcular el factorial de 3 for ($x = $factorial $x gt 0 $x--)

^resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt bull

$resultado = 1 $factorial = 4 Queremos calcular el factorial de 4 for ($x = $factorial $x gt 0 $x--)

$resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt

$resultado = 1 $factorial = 5 Queremos calcular el factorial de 5 for ($x = $factorial $x gt 0 $x--)

$resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt

gt

Si se fija en el coacutedigo anterior podraacute comprobar que sigue un patroacuten muy evidente El caacutelculo del factorial se realiza en un bucle que va disminushyyendo el valor de una variable y multiplicando todos los valores entre siacute Aprovechando este patroacuten puede crear una funcioacuten que realice el factoshyrial del nuacutemero x ahorrando liacuteneas de coacutedigo

ltphp function factorial($numero)

$resultado = 1 for ($x = $numero $x gt 0 $x--)

$resultado = $resultado $x return $resultado

echo El factorial de 3 es factorial(3)ltbrgt

Funciones 101

echo El factorial de 4 es factorial(4)ltbrgt echo El factorial de 5 es factorial(5) ltbrgt gt

Si comparamos los dos ejemplos podemos llegar a la conclusioacuten de que el segundo es mucho maacutes legible y maacutes sencillo de realizar Como puede ver la funcioacuten f a c t o r i a l () hace uso de la palabra reservada r e t u r n que es la encargada de devolver el valor que estamos solicitando cuando se invoca la funcioacuten

Nota

Aunque en el ejemplo la funcioacuten f a c t o r i a l () recibe como pashyraacutemetro el nuacutemero 3 4 oacute 5 tambieacuten es posible llamarla con una variable del tipo integer o double

Paraacutemetros insuficientes

Si llama a una funcioacuten con menos paraacutemetros de los que debe utilizar por definicioacuten apareceraacute el siguiente error por defecto

Warning Missing argument 1 for factorial()

Este tipo de error no es criacutetico y puede controlarse con excepciones como veremos en capiacutetulos sucesivos Ademaacutes de las excepciones podemos utilishyzar el operador de supresioacuten de error delante de la funcioacuten de esta forshyma f a c t o r i a l ( )

No se recomienda eliminar los mensajes de error en este caso ya que hace complicado la correccioacuten de los posibles fallos

Paraacutemetros en exceso

Si al contrario que en el apartado anterior le pasa a una funcioacuten maacutes paraacuteshymetros que los definidos eacutestos seraacuten omitidos y la ejecucioacuten continuaraacute normalmente sin ninguacuten mensaje de error Esta propiedad de PHP 5 pershymite utilizar variables con un nuacutemero de paraacutemetros variable

Aacutembito de las variables

Las variables definidas en un archivo de PHP permanecen declaradas en todo el fichero menos en las funciones Las funciones crean un entorno de ejecucioacuten donde soacutelo pueden ver las variables que estaacuten dentro de las mismas Aunque no parece muy loacutegico esto nos permite tener variables

Funciones 103

con el mismo nombre en diferentes funciones haciendo el coacutedigo reutili-zable

Si nos fijamos en el ejemplo

ltphp $pi = 3 1 4 funct ion v a l o r _ p i ( )

if ( uuml s s e t ($pi) ) $pi = p i ()

re turn $pi

echo v a l o r _ p i ( ) gt

Se puede observar que definimos al comienzo del coacutedigo la variable $pi como un valor aproximado del nuacutemero pi (314) La funcioacuten v a l o r _ p i () comprueba si la variable $pi estaacute definida y si no lo estaacute recupera ese valor con una funcioacuten de PHP 5 Para entender el alcance de las variables vamos a ir paso a paso viendo queacute es lo que ocurre

bull Se define $pi a nivel global en el programa

bull Se define la funcioacuten v a l o r _ p i () que por ahora no se utiliza

bull Se lanza la ejecucioacuten de la funcioacuten

bull La funcioacuten evaluacutea si existe la variable $pi y da como resultado false Esto es asiacute porque la variable estaacute definida fuera de la funcioacuten y no dentro de ella por lo tanto se considera que la variable $p i dentro de la funcioacuten es distinta (entorno local) a la variable $pi definida fuera de la funcioacuten (entorno global)

bull El resultado por pantalla es 31415926535898

Esta forma de programar se considera la correcta en la comunidad de de-sarrolladores de PHP Auacuten asiacute existen mecanismos que permiten que una variable definida fuera de una funcioacuten pueda ser utilizada dentro de la misma simplemente anteponiendo la palabra reservada g l o b a l a la vashyriable definida dentro de la funcioacuten

Utilizando el ejemplo anterior tenemos

ltphp $pi = 3 1 4 funct ion v a l o r _ p i ( )

g l o b a l $pi if ( Uuml s s e t ($pi) )

$pi = pi ()

104 Capiacutetulo 5

re turn $pi

echo v a l o r _ p i ( )

gt

Si vemos paso a paso el ejemplo

bull Se define $pi a nivel global en el programa bull Se define la funcioacuten v a l o r _ p i () que por ahora no se utiliza bull Se lanza la ejecucioacuten de la funcioacuten

bull Dentro de la funcioacuten la variable $pi se define como global es decir se utiliza la variable creada al principio del coacutedigo

bull La funcioacuten evaluacutea si existe la variable $p i y da como resultado true

bull El resultado por pantalla es 314

Variables estaacuteticas

Por defecto las funciones que creamos en PHP 5 no retienen en memoria el valor de las variables que se utilizan Cada llamada a una funcioacuten imshyplica la nueva creacioacuten de las variables locales con su valor inicial La deshyclaracioacuten static antildeadida a una variable causa que la funcioacuten retenga en memoria el valor de esa variable en cada llamada Como puede ver en el ejemplo las 100 llamadas a la funcioacuten c o n t a d o r () dan siempre el misshymo resultado porque la variable $ c o n t a d o r se crea con cada llamada

ltphp function contador()

$contador = 0 $contador = $contador +1 return $contador

for ($x = 1 $X lt= 100 $x++)

echo contador() gt

Sin embargo podemos hacer que la funcioacuten recuerde los valores antildeadienshydo la palabra s t a t i c a la definicioacuten de la variable

ltphp function contador()

static $contador = 0 $contador = $contador + 1 return $contador

for ($x = 1 $x lt= 100 $x++)

Funciones 105

echo contador()

gt

iacutenclude() y require()

A medida que su proyecto se hace maacutes complejo comenzaraacute a crear funshyciones muy uacutetiles para conectar a bases de datos crear imaacutegenes al vuelo conectar por FTP etceacutetera y seguramente quiera emplear estas funcioshynes en otros proyectos distintos para ahorrar tiempo El camino para hashycer esto es muy sencillo Soacutelo tiene que guardar las funciones necesarias en un fichero con extensioacuten php htm c s s i n c etceacutetera y utilizar las directivas i n c l u d e () o r e q u i r e f ) desde la Web que vaya a utilizarlas

En PHP 5 no existen apenas diferencia entre ambas funciones salvo que la funcioacuten i n c l u d e () es maacutes tolerante a fallos que r e q u i r e () y permishyte continuar la ejecucioacuten del programa aunque se haya encontrado un fashyllo

La conclusioacuten es que debe utilizarse r e q u i r e () para aplicaciones que necesiten obligatoriamente alguacuten archivo criacutetico y no pueda continuarse la ejecucioacuten sin eacutel

Si en el desarrollo de nuestro proyecto nos encontramos con que vamos a utilizar varios archivos que hacen llamadas unos a otros podriacutea pasar que hagamos varias inclusiones del mismo archivo en distintos puntos proshyvocando alguacuten fallo difiacutecil de detectar Las funciones r e q u i r e _ o n c e () e i n c l u d e _ o n c e () solucionan eacuteste problema ya que si se intenta incluir un fichero varias veces con dichas funciones PHP 5 simplemente ignorashyraacute las llamadas El formato es el siguiente

require base_datosphp include contador_vistasphp require_once test php-include_once visitasphp

Recursividad

El paradigma de la programacioacuten nos lleva a los desarrolladores a invenshytar foacutermulas que minimicen el esfuerzo en nuestros programas pecando

106 Capiacutetulo 5

algunas veces de complejidad Las funciones recursivas son aquellas cashypaces de llamarse a siacute mismas Como uacutenico requisito es que haya una forshyma de salir en la llamada recursiva Si volvemos al ejemplo del nuacutemero factorial nos encontramos en que se puede escribir de la siguiente forma

ltphp function factorial($numero)

if ($numero == 1) return $numero

else return $numero factorial($numero-l)

echo El factorial de 7 es factorial(7) ltbrgt gt

Lo primero que llama la atencioacuten es que carece de un bucle f or para ir disminuyendo los nuacutemeros implicados en el factorial Lo que hace la funshycioacuten es multiplicar el nuacutemero que se pasa por el factorial del nuacutemero-1 Si el nuacutemero que se pasa es igual a 1 la funcioacuten deja de hacer llamadas reshycursivas y comienza a devolver los valores hasta llegar al resultado final

Funciones con nuacutemero de argumentos variables

Es habitual que el nuacutemero de paraacutemetros que se le pase a una funcioacuten dependa de la situacioacuten en la cual es llamada Hay tres formas de hacer esto en PHP

bull Definiendo la funcioacuten con argumentos por defecto Este meacutetodo pershymite hacer llamadas con menos paraacutemetros sin que aparezca un error

bull Usando un array para pasar las variables

bull Usando las funciones de argumento variable f unc_num_args () f u n c _ g e t _ a r g () y f u n c _ g e t _ a r g s () ya utilizadas en PHP 4

Argumentos por defecto

Para definir paraacutemetros de este tipo se sustituyen las variables por exshypresiones de asignacioacuten El formato es el siguiente

function nombre_funcioacuten($argumentol=valorl $argumento2=valor2 )

Funciones 107

De esta forma al llamar a la funcioacuten podemos hacerlo con varios paraacutemeshytros Si alguno de los paraacutemetros es obviado la variable tendraacute como vashylor el valor por defecto de la definicioacuten

ltphp function capitales($Pais$Capital = Madrid$habitantes = muchos)

re turn (La c a p i t a l de $Pais es $Capi ta l y t i ene $habi tantes hab i tan tes ltbrgt)

echo capitales(Espantildea) echo capitales(PortugalLisboa) echo capitales(FranciaParismuchiacutesimos) gt

La salida por pantalla es la siguiente

La capital de Espantildea es Madrid y tiene muchos habitantes La capital de Portugal es Lisboa y tiene muchos habitantes La capital de Francia es Paris y tiene muchiacutesimos habitantes

La funcioacuten c a p i t a l e s () tiene un paraacutemetro fijo y dos paraacutemetros por defecto El paraacutemetro $ P a i s es obligatorio pero los demaacutes pueden queshydarse en blanco recibiendo el valor por defecto La limitacioacuten de este meacutetodo es que los argumentos tienen un orden y no podemos saltarnos ninguno es decir no podemos dar los valores $ C a p i t a l y $ h a b i t a n -t e s porque en medio hay otro paraacutemetro

Argumentos mediante un array

Si no encontroacute alguna utilidad a la anterior forma de pasar valores variashybles quizaacutes necesite utilizar un array para pasarlos El ejemplo siguiente usa esta estrategia y algunos trucos maacutes como el operador ternario y los array asociativos

ltphp function capitales($datos)

$Pais = isset ($datos[Pais ] ) $datos [Pais] Espantildea $Capital = isset ($datos[Capital] ) $datos [Capital] Madrid $habitantes = isset ($datos[habitantes] ) $datos [habitantes] muchos return (La capital de $Pais es $Capital y tiene $habitantes habitantesltbrgt)

Introducimos en el array los datos uno por uno para que sea maacutes faacutecil de entender $datos [Pais] = Espantildea echo capitales($datos) $datos [Pais] = Portugal

108 Capiacutetulo 5

$datos [Capital] = Lisboa echo capitales($datos) $datos [Pais] = Francia $datos [Capital] = Paris $datos [habitantes] = muchiacutesimos echo capitales($datos) gt

Como puede ver la funcioacuten tiene un uacutenico argumento que contiene toshydos los datos que nuestro programa necesita Esta vez los valores por defecto los introducimos mediante el operador ternario que chequea si existe el dato referido al P a i s C a p i t a l o h a b i t a n t e s y si no existe se antildeaden los datos E s p a ntilde a Madr id y muchos El ejemplo utiliza la funcioacuten con 0 2 y 3 paraacutemetros La ventaja de este meacutetodo es que podraacute utilizar los argumentos que quiera y en el orden que necesite sin encasishyllarse en una forma especial de pasar los datos

Nota

Jgt Aunque todaviacutea no hemos visto el capiacutetulo 7 que trata con detalle el manejo dearrays el lector puede hacerse una idea de coacutemo funshycionan en el aacutembito de los paraacutemetros defunciones Si queda alshyguna duda de coacutemo utilizarlos siempre puede echar un breve vistazo al capiacutetulo 7 para aclarar esas lagunas

Funciones 109

Muacuteltiples argumentos con func_num_args()

Desde la versioacuten 4 PHP ofrece algunas funciones que pueden ser utilizashydas para recuperar los argumentos

Son muy similares al lenguaje C

bull func_num_args() Devuelve el nuacutemero de argumentos que recibe la funcioacuten desde la que es llamada

bull func_get_arg() Devuelve uno a uno los argumentos pasados de la sishyguiente forma func_get_arg(0) func_get_arg(l) func_get_arg(5)

bull func_get_args() Devuelve un array con todos los argumentos pasashydos a la funcioacuten con los iacutendices del array empezando desde 0

Cualquiera de estas funciones daraacute un error si son llamadas fuera del enshytorno de una funcioacuten y f u n c _ g e t _ a r g () produciraacute un fallo si es llashymada con un nuacutemero maacutes alto que los argumentos que se reciben

Las funciones anteriores dan una ventaja a largo plazo ya que si durante el periacuteodo de vida de una funcioacuten necesita antildeadir alguacuten argumento maacutes puede capturar sin necesidad de cambiar el coacutedigo de las llamadas o el de definicioacuten de la funcioacuten

En el ejemplo siguiente puede comprobar coacutemo se utiliza este meacutetodo

ltphp function capitales()

$numero_argumentos = func_num_args() $Pais = $numero_argumentos gt 0 func_get_arg(0) Espantildea $Capital = $numero_argumentos gt 1 func_get_arg(1) Madrid $habitantes = $numero_argumentos gt 2 func_get_arg (2) muchos return (Nuacutemero de argumentos es $numero_arguraentos La capital de $Pais es $Capital y tiene $habitantes habitantesltbrgt)

echo capitales() echo capitales(Portugal Lisboa) echo capitales(Francia Paris muchiacutesimos) gt

Esta forma de utilizar los argumentos sigue teniendo una limitacioacuten Los argumentos deben ser pasados en un lugar determinado sino la funcioacuten no haraacute bien su trabajo Utilizar los paraacutemetros como array es el meacutetodo maacutes flexible y el maacutes utishylizado en los programas PHP Auacuten asiacute es muy uacutetil cuando no sepa cuaacutentos datos necesita manejar una funcioacuten Podemos utilizarlo para funciones que sumen todos los parame-

110 Capiacutetulo 5

tros que introduzca o concatenen todas las palabras como el ejemplo sishyguiente

ltphp function concatenar()

$resultado = $numero_argumentos = func_num_args() $array_parametros = func_get_args() for ($x = 0 $x lt= $numero_argumentos $x++)

$resultado = $resultado $array_parametros[$x]

return $resultadoltbrgt

echo concatenar(Hola Mundo) echo concatenar(Esto es una prueba dela potencia de este meacutetodo) gt

Llamadas por valor

Por defecto las llamadas a funciones se hacen por valor Esto quiere decir que las variables que se utilizan como paraacutemetros se copian al entorno de la funcioacuten

Todos los cambios de valor que sufra la variable en este entorno no afecshytaraacuten al programa fuera de la funcioacuten

ltphp function elevado($nuraero$ iacutendice)

$resultado = $numero for ($x = $indice $x gt 0 $x--)

$resultado = $resultado $nuraero

$numero = $resultado return $numero

$numero = 2 $indice = 5 echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt echo $numero elevado a $indice es igual a elevado ($numero$ indice) ltbrgt gt

El resultado por pantalla es

2 elevado a 5 es igual a 64 2 elevado a 5 es igual a 64

Funciones 111

El ejemplo anterior calcula el resultado de $numero elevado a $ Iacute n d i c e La funcioacuten e l e v a d o () crea un bucle para multiplicar $numero por las veces que indica el $ iacute n d i c e y lo va almacenando en la variable temporal $resultado

Cuando el bucle termina este resultado se vuelve a pasar a la variable $ numero que es devuelta como salida de la funcioacuten Cuando volvemos a ejecutar la funcioacuten con los mismos paraacutemetros vemos que la variable $nu-mero no ha cambiado en la ejecucioacuten anterior porque en realidad lo que se pasa es una copia del valor y todas las modificaciones se hacen sobre la copia y no sobre la variable original

Llamadas por referencia

PHP 5 ofrece actualmente dos caminos diferentes para cambiar sus argushymentos en la definicioacuten de la funcioacuten y en la llamada a la misma

Las variables pasadas por referencia pueden ser modificadas durante el proceso de una llamada porque lo que se pasa no es una copia sino la variable en siacute misma

Para pasar variables por referencia hay que utilizar el operador (amp) deshylante de la variable

Lo mejor es verlo en un ejemplo

ltphp function elevado(amp$numeroamp$indice)

$resultado = $numero for ($x = $iacutendiacutece $x gt 0 $x--)

$resultado = $resultado $numero

$numero = $resultado return $numero

$numero = 2 $ iacutendice = 5 echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt gt

El resultado por pantalla es ahora

2 elevado a 5 es igual a 64 64 elevado a 5 es igual a 68719476736

El funcionamiento es exactamente igual pero el resultado es distinto El operador (amp) hace que la variable $numero pueda ser modificada dentro de la funcioacuten y guarde este nuacutemero fuera de ella

Tambieacuten puede forzar a una funcioacuten a tomar argumentos por referencia aunque esta capacidad de PHP puede desaparecer en futuras versiones del lenguaje Las llamadas pueden hacerse de la siguiente forma

$numero = 2 $indice = 5 echo $numero elevado a $indice es igual a elevado(amp$numeroamp$indice)ltbrgt echo $numero elevado a $indice es igual a elevado(amp$numeroamp$indice)ltbrgt

El resultado es exactamente igual que al poner la referencia en la definishycioacuten de la funcioacuten

Referencia a variables

Las referencias pueden usarse tambieacuten fuera de las funciones en el aacutembishyto de las variables El ejemplo siguiente muestra coacutemo trabaja el operador (amp) con las variables

ltphp $nombre = Luis Miguel

Funciones 113

$apelliacutedos = Cabezas Granado $nombre auxiliar es simplemente una copia de $nombre $nombre_auxiliar = $nombre-$nombre_referencia es una referencia a la variable $nombre_referencia = amp$nombre echo $nombre $apellidosltbrgt $nombre_auxiliar = Alberto echo $nombre $apellidosltbrgt $nombre_referencia = Felipe echo $nombre $apellidosltbrgt gt

$nombre__aux i l i a r es una copia de la variable $nombre y por mucho que la cambiemos $nombre permaneceraacute con el mismo valor En cambio la variable $nombre_ref e r e n c i a es un alias de $nombre por lo tanto todos los cambios que se hagan en cualquiera de las dos variables les afecshytaraacute por igual

Funciones variables

Uno de los trucos que se pueden hacer con PHP es utilizar variables para almacenar el nombre de funciones Si una variable almacena el nombre de una funcioacuten simplemente tendraacute que antildeadir unos pareacutentesis al final de la variable para hacer la llamada correctamente

ltphp function saludo_maniana()

return (Buenos Diacuteas)

function saludo_tarde()

return (Buenas Tardes)

function saludo_noche()

return (Buenas Noches) $horario = tarde $funcion_variable = saludo_$horario echo $funcion_variable () gt

En el ejemplo anterior tenemos tres funciones que nos saludan depenshydiendo del horario en el que ejecutemos el programa Este valor se recoge en la variable $ h o r a r iacute o Sabemos que todas las funciones comienzan con la palabra saludo_ Si a la variable $f u n c i o n _ v a r iacute a b l e le concatenashymos el valor de $ h o r a r i o tenemos como resultado el nombre de la fun-

1 1 4 Capiacutetulo 5

cioacuten que nos daraacute el saludo Para que esto funcione antildeadimos dos siacutemboshylos de pareacutentesis al final de la expresioacuten

Resumen

Si el capiacutetulo anterior daba rienda suelta a su imaginacioacuten para comenzar con el desarrollo de pequentildeos scripts despueacutes de leer este capiacutetulo estaraacute en situacioacuten de realizar un gran proyecto Ahora que conoce el secreto para almacenar en distintos archivos funciones y partes de un programa escrishyto en PHP podraacute crear aplicaciones maacutes extensas y complejas

Ahora bien debe tener en cuenta que hay que tener cuidado con el alcanshyce de las variables y los pasos por valor y referencia aspecto muy relevanshyte en el capiacutetulo referido a los objetos

En este capiacutetulo aprenderaacute a

bull Diferenciar entre las comillas simples y las comillas dobles bull Trabajar con cadenas de muacuteltiples liacuteneas bull Concatenar varias cadenas bull Generar nuevas cadenas de caracteres a partir de una original bull Eliminar los espacios en blanco de las cadenas bull Convertir a mayuacutesculas o minuacutesculas bull Definir patrones de verificacioacuten de cadenas

116 Capiacutetulo 6

Introduccioacuten

Si pensamos en los tipos de datos que circulan por la red llegaremos a la conclusioacuten de que una gran porcioacuten la ocupan las imaacutegenes animaciones en Macromedia Flash videos o subprogramas escritos en Java La otra gran porcioacuten mayoritaria son los textos o las cadenas de caracteres

Las cadenas de caracteres o string son secuencias de caracteres que pueshyden ser tratadas como una unidad asignadas a variables pasadas como paraacutemetros a funciones o enviadas como salida al navegador Un string se diferencia de otro tipo de dato en PHP 5 porque va encerrado entre comishyllas dobles ( ) o simples ( )

Cadena entre comillas dobles Cadena entre comillas simples

PHP interpreta de distinta forma las cadenas que van entre comillas doshybles y las que van entre comillas simples Losstrings entre comillas dobles pueden sustituir ciertos siacutembolos por acciones como la inclusioacuten del vashylor de una variable Las comillas simples simplemente muestran todo el contenido sin atender a caracteres especiales Podemos ver un ejemplo donde sucede esto

ltphp $variable = Domingo $frase_l = Hoy es $variable el cielo estaacute gris $frase_2 = Hoy es $variable el cielo estaacute gris echo $frase_l echo $frase_2 gt

El resultado en el navegador es

Hoy es Domingo el cielo estaacute gris Hoy es $variable el cielo estaacute gris

Como se puede observar la cadena $f r a s e _ l es capaz de sustituir la vashyriable por su valor por el simple hecho de estar entre comillas dobles

Propiedades de las cadenas

iacutendices de string

Si pensamos en las cadenas como una sucesioacuten de caracteres en un orden determinado podemos llegar a desear acceder libremente a parte de los

Cadenas de caracteres y expresiones regulares 117

caracteres Esto es posible gracias a los siacutembolos de llave ( ) y un iacutendice numeacuterico que se corresponderaacute con la posicioacuten del caraacutecter que buscamos El ejemplo muestra coacutemo crear una funcioacuten que duplica las letras de una cadena aprovechando esta forma de acceder a los caracteres

ltphp function duplicar_caracteres($cadena)

$tamanio = strlen ($cadena) $cadena_auxiliar = for ($x = 0$x lt $tamanio $x++)

$cadena_auxiliar = $cadena_auxiliar $cadena$x $cadena$x

return $cadena_auxiliar

$cadena = Duplicar las letras echo duplicar_caracteres($cadena)iexcl gt

La salida por pantalla como puede adivinar es

118 Capiacutetulo 6

Operadores

En este punto aprovecharemos para hacer un breve repaso de los operashydores de string vistos en el capiacutetulo 3 En otros lenguajes como Java se utiliza el operador suma (+) para unir dos cadenas En PHP este mismo resultado se obtiene con el operador punto ( ) Asiacute podemos concatenar varias cadenas de la forma siguiente

ltphp $cadenal = Hola $cadena2 = Mundo $cadena3 = iexclQueacute tiacutepico $supercadena = $cadenal $cadena2 $cadena3 echo $supercadena gt

Es faacutecil intuir que el operador puede concatenar caracteres y variables de tipo string de forma conjunta Es posible que desee ahora antildeadir texto a una cadena ya existente esto se puede hacer de dos formas muy similashyres La primera es asignando a la variable su valor maacutes el valor a antildeadir de la siguiente forma

ltphp $cadenal = Hola $cadena2 = Mundo $cadenal = $cadenal $cadena2 echo $cadenal gt

O utilizando el operador de concatenacioacuten y asignacioacuten ( = ) como en el ejemplo

ltphp $cadenal = Hola $cadena2 = Mundo $cadenal = $cadena2 echo $cadenal gt

Sintaxis para muacuteltiples liacuteneas

Existe en PHP una forma maacutes de introducir cadenas aparte de las comishyllas muy recomendable para largos textos o un considerable conjunto de etiquetas HTML La sintaxis es muy sencilla y comienza con el operador (ltltlt) seguido de una etiqueta que indica el principio del texto Despueacutes de esto podemos escribir un conjunto de caracteres muy numerosos y para

Cadenas de caracteres y expresiones regulares 119

finalizar la etiqueta de fin El ejemplo muestra coacutemo almacenar un forshymulario en una variable

ltphp $formulario = ltltltINICIO ltformgt ltiacutenput type=text name=Nombre value=Luiacutes Miguel Cabezasgt ltbrgt ltinput type=submit name=submit value=Enviar gt ltformgt INICIO echo $formulario gt

Siempre debe comenzar por el operador (ltltlt) seguido de un identifica-dor por ejemplo INICIO Despueacutes se incluye el texto en este caso un forshymulario y para finalizar la misma etiqueta de inicio Esta forma de almacenar datos permite utilizar indistintamente comillas simples o doshybles dentro de una variable La imagen 62 muestra el resultado del script

Funciones de string

Si conoce el lenguaje C podraacute comprobar que las funciones de manejo de caracteres son muy parecidas en nombre y uso Los desarrolladores de PHP

120 Capiacutetulo 6

siempre han querido que exista esta similitud para facilitar el aprendizaje del lenguaje

La mayoriacutea de las funciones existentes en PHP 5 tienen una homologa en C

Tamantildeo de la cadena

La funcioacuten s t r l e n () devuelve como resultado el tamantildeo en caracteres de la cadena que pasemos de paraacutemetro Este valor puede asignarse a una variable como indica el ejemplo

ltphp $cadena = Esta cadena tiene muchas letras $numero_letras = strlen($cadena) echo cadena tiene $numero_letras caracteres gt

Simplemente imprime

cadena tiene 31 caracteres

Posicioacuten de los caracteres

Para crear buenos motores de buacutesqueda en nuestros sitios Web necesitashyremos potentes herramientas que sean capaces de buscar caracteres cashydenas o patrones coincidentes dentro de textos extensos La funcioacuten s t r p o s () encuentra en un string la posicioacuten de un caraacutecter determinado

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de a es strpos($cadena a) ltbrgt echo La primera ocurrencia de m es strpos($cadena m) ltbrgt gt La s a l i d a en el navegador no es o t ra que La primera ocur renc ia de a es 3 La primera ocur renc ia de m es 18

Si s t r p o s () se utiliza para averiguar la posicioacuten de la primera L mashyyuacutescula de $ cadena vemos que nos devuelve un 0 esto es asiacute porque el iacutendice de caracteres comienza en 0 como pasa en muchos lenguajes de programacioacuten Si no se encuentra ninguna ocurrencia del caraacutecter buscashydo el resultado seraacutease

Cadenas de caracteres y expresiones regulares 121

La funcioacuten s t r p o s () tambieacuten puede utilizarse para buscar varios caracshyteres seguidos en una misma cadena

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de tiene es strpos($cadenatiene) ltbrgt gt

Si lo que nos interesa es encontrar caracteres buscando desde el final de la cadena la funcioacuten que tenemos que utilizar es s t r r p o s () (la letra r que se antildeade viene del ingleacutes reverse) El ejemplo anterior nos sirve para comshyprobar el funcionamiento de la funcioacuten

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de a es strpos($cadena a ) ltbrgt echo La primera ocurrencia desde atraacutes de a es strrpos($cadena a) ltbrgt gt

siendo el resultado

La primera ocurrencia de a es 3 La primera ocurrencia desde atraacutes de a es 29

Comparacioacuten

El operador (==) nos puede servir para evaluar si dos cadenas de caracteshyres son iguales dentro de una estructura de control Ademaacutes tenemos la funcioacuten s t r c m p ( ) que compara bit a bit dos cadenas de caracteres Atenshydiendo al valor de salida de la funcioacuten podemos obtener los siguientes resultados

bull Si el valor que se obtiene es 0 las dos cadenas son exactamente igual

bull Si obtenemos un valor negativo el primer string es maacutes pequentildeo que el segundo

bull Si obtenemos un valor positivo el primer string es maacutes grande que el segundo ltphp $cadenal = Prueba $cadena2 = Prueba if (strcmp($cadenal$cadena2) == 0)

echo Las dos cadenas son iguales elseif (strcmp($cadenal$cadena2) lt 0)

echo La cadenal es menor que la cadena2

122 Capiacutetulo 6

else echo La cadenal es mayor que la cadena2

gt

La comparacioacuten anterior soacutelo da como resultado dos cadenas iguales si las dos cadenas son exactamente iguales haciendo distincioacuten entre mashyyuacutesculas y minuacutesculas

Para evitar este problema podemos utilizar la funcioacuten s t r c a s e c m p ( ) que no es sensible a mayuacutesculas Asiacute s t r c a s e c m p (HoLa hOlA) da como resultado 0 es decir las dos cadenas son iguales

Buacutesqueda de caracteres

Siguiendo con las buacutesquedas de texto la funcioacuten s t r s t r () recibe como paraacutemetros una cadena de caracteres donde buscar y otra con un conjunshyto de caracteres que queremos encontrar Si se encuentra el patroacuten de buacutesshyqueda el resultado seraacute una cadena de caracteres que comenzaraacute justo en el patroacuten hasta el final del string primero Si no se encuentra el patroacuten el resultado seraacutefalse

lt php $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de cadena es strstr ($cadenacadena) ltbrgt

gt

Como cabe esperar el resultado es La primera ocurrencia de cadena es cadena tiene muchas letras

Seleccioacuten de subcadenas

La funcioacuten s u b s t r () permite seleccionar un conjunto de caracteres de una cadena quedando intacto el string original Puede tomar varios paraacuteshymetros

bull s u b s t r ( c a d e n a iacute n d i c e ) Cadena es el conjunto de caracteres que queremos cortar e iacute n d i c e la posicioacuten a partir de la cual se cortaraacute la cadena hasta el final

bull s u b s t r ( cadena iacute n d i c e numero) Cadena es el conjunto de cashyracteres que queremos cortar e iacute n d i c e la posicioacuten a partir de la cual se cortaraacute la cadena tantas posiciones como indique el nuacutemero

Cadenas de caracteres y expresiones regulares 123

Por ejemplo

ltphp $cadena = Esta cadena tiene muchas letras Devuelve la cadena completa echo substr($cadena 0) echo ltbrgt Desde el caraacutecter 12 hasta el final echo substr($cadena 12) echo ltbrgt Devuelve 6 caracteres desde el caraacutecter 18 echo substr($cadena 186) echo ltbrgt Devuelve los 6 uacuteltimos caracteres echo substr($cadena -6) echo ltbrgt Desde la posicioacuten 26 contando desde atraacutes 6 caracteres echo substr($cadena -266) echo ltbrgt Empezando en el caraacutecter 4 y terminando en el 7 desde atraacutes echo substr($cadena 4-7) gt

El resultado lo podemos ver maacutes abajo Recuerde que la variable $ cade -na queda intacta

124 Capiacutetulo 6

Dependiendo de la posicioacuten del nuacutemero negativo s u b s t r () actuaraacute de una forma u otra

Tabla 61 Respuestas de la funcioacuten substr ()

Ejemplo Resultado

substr(Hola2) Devuelve la cadena completa empezando por el caraacutecter 2 substr(Hola-2) Devuelve la cadena completa empezando por el caraacutecter

2 esta vez empezando a contar desde atraacutes

substr(Hola13) El resultado son 3 caracteres empezando desde el caraacutecshyter 1

substr(Hola-32) Doscaracteres empezando desde el caraacutecter 3 contando desde la uacuteltima letra

substr(Hola2-1) Devuelve un conjunto de caracteres que estaacuten desde la posicioacuten 2 a la posicioacuten 1 comenzando desde atraacutes

substr(Hola-2-3) No tiene aplicacioacuten posible

Funciones de limpieza de cadenas

Sirven para limpiar espacios en blanco al principio de la cadena al final o en cualquier parte desde el principio al final y son respectivamente l t r i m ( ) chop () y t r i m () Su aplicacioacuten es tan sencilla que bastaraacute un ejemplo para entender su funcionamiento

ltphp $salto_linea = n $cadena = cadena con varios espacios en blanco echo $salto_linea $cadena tamantildeo strlen($cadena) echo ltbrgt echo $salto_linea ltrim($cadena) tamantildeo strlen(ltrim($cadena)) echo ltbrgt echo $salto_linea chop($cadena) tamantildeo strlen(chop($cadena)) echo ltbrgt echo $salto_linea trim($cadena) tamantildeo strlen(trim($cadena)) gt

Cada liacutenea realiza una de las operaciones vistas e imprime el resultado de la cadena en el navegador junto con el tamantildeo de la cadena

La figura 64 muestra el resultado por pantalla

126 Capiacutetulo 6

Sustitucioacuten de cadenas

La funcioacuten s t r _ r e p l a c e () toma como paraacutemetros un conjunto de cashyracteres a buscar un grupo que debe sustituirse por el anterior y una cashydena de caracteres sobre la que actuar

ltphp $cadena = Esta cadena tiene muchas letras $cadena = str_replace(EstaEste$cadena) echo str_replace(cadenaconjunto$cadena) gt

Si en la cadena existiera maacutes de una instancia del conjunto buscado todas las ocurrencias quedariacutean cambiadas

ltphp cadena = Esta cadena tiene muchas letras y cadenas $cadena = str_replaceacute(EstaEste$cadena) echo str^replace(cadenaconjunto$cadena) gt

El resultado es Este conjunto tiene muchas letras y conjuntos

Truco

Puede probar esta funcioacuten para cambiar todos iexclos caracteres de un tipo de una cadena de iexcla siguiente forma s t r _ r e p l a c e (h j hola h o l a )

Funciones de mayuacutescula y minuacutescula

Las funciones s t r t o l o w e r () y s t r toupper () devuelven la cadena que se pasa como argumento completamente en minuacutescula o mayuacutescula resshypectivamente

ltphp $cadena = Hay palabras en MAYUacuteSCULAS y en minuacutesculasltbrgt echo strtolower($cadena) echo strtoupper($cadena) gt

El resultado es hay palabras en mayuacutesculas y en minuacutesculas HAY PALABRAS EN MAYUacuteSCULAS Y EN MINUacuteSCULAS

Si lo que realmente nos interesa es que la primera letra de un texto apashyrezca como letra Capital o que letras iniciales de cada palabra en una fra-

Cadenas de caracteres y expresiones regulares 127

se aparezcan en mayuacutescula tenemos las funciones u c f i r s t ( ) y u c w o r d s ( )

ltphp $cadena = habiacutea una vezltbrgt echo ucfirst($cadena) $cadena2 = linux user group echo LUG significa ucwords($cadena2) gt

Expresiones regulares

Las funciones vistas anteriormente basan su potencia en la buacutesqueda o susshytitucioacuten de los caracteres de una cadena pero son poco uacutetiles cuando tratashymos de comprobar si un conjunto de caracteres cumple un formato determinado Si solicitamos mediante un formulario un correo electroacutenico necesitamos saber a priori si ese correo por lo menos estaacute bien construido

luisnccextremaduraorg luiszendcom

La idea es poder descartar de alguna forma los correos escritos de esta manera

l u i s (Snccextremaduraorg E s p a c i o en medio

128 Capiacutetulo 6

LUISzendcom En mayuacutesculas luisaupexorg Dos

Las expresiones regulares son patrones de buacutesqueda dentro de cadenas Estos patrones se construyen mediante caracteres especiales que cumplen unas reglas determinadas

Tabla 62 Reglas de expresiones regulares

Ejemplo Regla

aabb Los caracteres no especiales como un grupo de letras se escriben como de costumbre

A Indica que hay que buscar el patroacuten desde el principio de la cadena $ Este simbolo obliga al patroacuten a cumplirse hasta el final de la

cadena Simboliza cualquier caraacutecter

Indica que puede haber O o maacutes instancias de una expresioacuten + Indica que puede haber 1 o maacutes instancias de una expresioacuten [ab] Indica que se puede encontrar el caraacutecter a o el b y la expresioacuten

seriacutea correcta Lo podemos acompantildear de [ab] para evaluar si hay varias letras seguidas del tipo a o b

[a-z] Indica que se puede elegir entre un rango de caracteres que va desde la a hasta la z

Si queremos utilizar cualquiera de los anteriores caracteres como parte del patroacuten tendremos que utilizar eacuteste siacutembolo para indicarle a PHP que es un literal

Como ejemplo vamos a intentar hacer un patroacuten que verifique si un coshyrreo electroacutenico estaacute correctamente construido o no Seriacutea faacutecil pensar en una expresioacuten parecida a la siguiente

[ a - z ] + [ a - z ] + o r g

La primera parte [ a - z ] + nos dice que aceptaraacute una letra o conjunto de letras sin espacios y en minuacutesculas que pueden corresponderse con el nombre de usuario de la cuenta de correo Despueacutes aceptaraacute un siacutembolo seguido de otro conjunto de caracteres correspondientes al servidor de correo La uacuteltima parte de la expresioacuten la componen los siacutembolos que indican que tiene que aparecer un punto que separe la descripcioacuten del servidor del dominio y la cadena o r g que obliga a que todos los correos sean de dominio no gubernamental

Cadenas de caracteres y expresiones regulares 129

La expresioacuten anterior tiene algunas limitaciones que veremos como solshyventar La primera es que se puede aplicar a cualquier texto con indepenshydencia del tamantildeo Si en alguna parte de ese texto aparece un conjunto de caracteres que cumpla con la expresioacuten la validacioacuten seriacutea true Esto no es bueno cuando queremos chequear si un correo es introducido correctashymente La solucioacuten es aplicar las reglas de inicio y fin que obligan a que el comienzo de la cadena y el final sean parte de la expresioacuten

[ a - z ] + [ a - 2 ] + o r g $

Tambieacuten podemos encontrarnos con que existen correos introducidos coshyrrectamente pero el dominio es otro distinto a org Esta vez la solucioacuten es introducir el operador O loacutegico | que permite elegir entre varias opcioshynes

^ [ a - z ] + [ a - z ] + ( o r g | c o m | n e t ) $

Por uacuteltimo un problema menor aunque habitual en el aacutembito de los coshyrreos electroacutenicos es la utilizacioacuten de signos de puntuacioacuten para separar nombres y apellidos y servidores de servidores virtuales Por ejemplo el correo siguiente es correcto pero no seriacutea evaluado por la expresioacuten anteshyrior

l u iacute s c a b e z a s n c c a u p e x o r g

Una posible solucioacuten es

[ a - z | ] + [ a - z | ] + ( o r g | c o m ( n e t ) $

Comprobar expresiones regulares

La funcioacuten e reg () es capaz de comprobar si una cadena se corresponde con el patroacuten que se pasa como paraacutemetro Toma dos argumentos obligashytorios una expresioacuten regular y una cadena de caracteres donde buscar el patroacuten Seguidamente puede ver un ejemplo completo de utilizacioacuten de expresiones regulares y la funcioacuten

ltphp $correo = luiscabezasnccaupexorg $correol = LUISnccaupexorg $correo2 = luiscabezasnccaupexorg if (ereg ( [a-z|]+[a-z|]+ (org|com|net)$$correo))

echo El correo $correo se aceptaltbrgt else

echo El correo $correo no cumple el patroacutenltbrgt

iacutef (ereg(^ [a-z|]+ [a-z|]+ (org|comjnet)$$correol) )

echo El correo $correol se aceptaltbrgt

130 Capiacutetulo 6

else echo El correo $correol no cumple el patroacutenltbrgt

if (ereg(A [a-zj]+ [a-zj]+ (org|com|net)$$correo2))

echo El correo $correo2 se aceptaltbrgt else

echo El correo $correo2 no cumple el patroacutenltbrgt gt

El resultado por pantalla es

Puesto que hay muchos usuarios acostumbrados a escribir su correo elecshytroacutenico completamente en mayuacutesculas se hace necesario comprobar este contratiempo tambieacuten Lo maacutes raacutepido es utilizar la funcioacuten e r e g i () que funciona exactamente igual que e r e g ( ) pero no es sensible a mayuacutescula o minuacutescula El ejemplo anterior lo podemos arreglar de la siguiente forma

ltphp $correo = LUISnccaupexorg if (ereg([a-z|]+[a-z|]+(org|com|net)$$correo$pepe))

echo El correo $correo se aceptaltbrgt else

echo El correo $correo no cumple el patroacutenltbrgt

gt

Cadenas de caracteres y expresiones regulares 131

Nota

e reg () y e r e g i () tienen un tercer argumento opcional del tipo array Si iexcla expresioacuten regular la dividimos en pequentildeas parshytes entre pareacutentesis cada ocurrencia encontrada en la cadena se va almacenando como un elemento del array

Reemplazar patrones

e r e g _ r e p l a c e () y e r e g i _ r e p l a c e () tiene tres paraacutemetros El prishymero es una expresioacuten regular el segundo un string por el que se cambiashyraacuten todas las ocurrencias del patroacuten y por uacuteltimo una cadena donde buscar Como antes la diferencia entre las dos es uacutenicamente que la prishymera es sensible a mayuacutesculas El siguiente ejemplo muestra el funcionashymiento

ltphp $texto = El correo es de luisnccaupexorg echo ereg_replace([a-z|]+[a-z|]+(org|com|net)Luis Miguel$texto) gt

Asiacute da como resultado el cambio del correo electroacutenico por el nombre de la persona asociada

Resumen

Desde hace unos antildeos se ha puesto de moda una serie de productos donshyde prima el contenido frente al disentildeo Los CMS (Content Manager System) son programas la mayoriacutea escritos en PHP que permiten gestionar mushycho contenido escrito por diferentes personas El tratamiento de los textos se agudiza al maacuteximo en este caso siendo indispensable la utilizacioacuten de expresiones regulares para verificar los datos nuevos que puedan incor- porarse Ademaacutes suelen llevar un buscador capaz de encontrar patrones determishynados dentro de las noticias expuestas Este capiacutetulo le ha servido para conocer funciones para concatenar recorshytar o verificar cadenas Con esto bien aprendido ya puede comenzar a crear su propio CMS

En este capiacutetulo aprenderaacute a

bull Comprender queacute es un array y coacutemo se define bull Trabajar con funciones que definen listas de datos bull Diferenciar entre los distintos meacutetodos para recorrer los array

bull Ordenar los conjuntos de datos con diferentes meacutetodos bull Crear pilas y colas

134 Capiacutetulo 7

Introduccioacuten

Un array es una coleccioacuten de valores con un uacutenico nombre Para acceder a los distintos valores de la variable se utiliza un iacutendice numeacuterico o alfanu-meacuterico Nos vamos a servir de la definicioacuten de un array en el lenguaje C para ver la potencia de este tipo de datos en PHP La definicioacuten es la siguiente

int mi_array[100] Esto es C

Lo primero que debe llamarnos la atencioacuten es que la variable estaacute predefishynida como i n t (entero) En PHP los arrays no tienen que definirse de una forma concreta sino que pueden tomar distintos tipos de valores enteshyros caracteres objetos etceacutetera Lo siguiente es que en C se necesita sashyber de antemano el nuacutemero de valores maacuteximo que podraacute tomar el array Esto no es necesario en PHP ya que podraacute ir creando valores nuevos a medida que lo vaya necesitando Lo uacuteltimo es que en C el iacutendice para acshyceder a los 100 valores distintos debe ser numeacuterico en cambio en PHP el iacutendice puede ser numeacuterico o alfanumeacuterico

ltphp $mi_array[l] = 23 $mi_array[2] = Este valor es un string $mi_array[ejemplo] = Esto es un array asociativo gt

Creacioacuten de arrays

Vamos a ver tres formas distintas de crear un array dentro de un script de PHP

Asignacioacuten directa

El camino maacutes simple y por otro lado loacutegico es asignar valores cuando se necesiten La primera vez que asignemos un valor el array se crearaacute en el entorno

ltphp $mi_array[l] = 23 Asignacioacuten directa gt

De esta forma tenemos un valor asignado al iacutendice 1 del array Puede asigshynar cualquier iacutendice en la creacioacuten de este tipo de dato e incluso no asig-

Conjuntos de datos del tipo array 135

nar ninguno de forma que PHP se encarga de asociar un iacutendice distinto para cada valor

ltphp $mi_array[] = 23 Empieza en el iacutendice 0 $mi_array[] = 54 iacutendice 1 gt

array()

Esta funcioacuten crea un array con los valores que pase como datos de entrashyda Los iacutendices seraacuten antildeadidos automaacuteticamente empezando desde 0

Si no asigna paraacutemetros a a r r a y ( ) la funcioacuten le devolveraacute un array vaciacuteo

ltphp $mi_array = array(2345762365) gt

El meacutetodo es similar a

ltphp $mi_array[0] = 23 $mi_array[l] = 4 5 $mi_array[2] = 76 $mi_array[3] = 23 $mi_array[4] = 65 gt

La funcioacuten a r r a y () permite tambieacuten antildeadir iacutendices a los valores que se introducen

Para ello se utiliza el operador =gt de esta forma

ltphp $mi_array = array0 =gt 23 1 =gt 45 2 =gt 76) gt

Tambieacuten es posible antildeadir iacutendices que no sean correlativos o iacutendices alf-anumeacutericos incluso mezclar los dos tipos

ltphp $mi_array = a r r a y ( c e r o =gt 23 uno =gt 45 2 =gt 7 6 ) gt

Para recuperar cualquier valor se utiliza el iacutendice dentro de los corchetes

ltphp $mi_array = array(cero =gt 23 uno =gt 45 2 =gt 76) echo $mi_array [ uno] ltbrgt echo $mi_array[2] gt

136 Capiacutetulo 7

Funciones que devuelven arrays

La uacuteltima forma de obtener un array es utilizando alguna de las funcioshynes que devuelven este tipo de datos

Es muy frecuente que las funciones que manejan bases de datos devuelshyvan las ocurrencias dentro de un array

Por ejemplo la funcioacuten r a n g e () devuelve un array con valores numeacuterishycos que van desde un nuacutemero de inicio hasta un nuacutemero final tal y como se muestra en el ejemplo

ltphp $mi_array = range(120130) gt

Esta funcioacuten crea un array empezando desde el iacutendice 0 y el valor 120 hasta el iacutendice 10 y el valor 130

Arrays multidimensionales

Hasta aquiacute hemos visto ejemplos de arrays de una sola dimensioacuten PHP soporta el uso de arrays de varias dimensiones faacutecilmente aunque son complejos de entender y de usar El array siguiente es de 5 dimensiones

ltphp $ m i _ a r r a y [ l ] [ 1 ] [ 2 3 ] [ 4 3 ] [ 0 ] = A r r a y de 5 d i m e n s i o n e s gt

Cada iacutendice encerrado entre corchetes corresponde a una dimensioacuten disshytinta En realidad cada dimensioacuten es un array que se introduce como vashylor dentro de la dimensioacuten anterior

Asiacute podraacute crear un array multidimensional de la siguiente forma

ltphp $colores = array(fuertessuaves) $colores [fuertes] = array ( rojo =gt FF0000 verde =gt 00FF00 azul =gt 0000FF)

$ c o l o r e s [ s u a v e s ] = a r r a y ( r o s a =gt FE9ABC a m a r i l l o =gt FDF189 malva =gt 9 A 2 F 6 8 ) echo $colores[fuertes] [rojo] gt

Para recuperar los valores se utilizan un iacutendice del primer array (fuertes o suaves) y un iacutendice de alguno de los dos arrays secundarios

Conjuntos de datos del tipo array 137

Otra forma de definir el array anterior es

ltphp

$colores = array( fuertes =gt array ( rojo =gt FF0000 verde =gt 00FF00 azul =gt 0000FF)

suaves =gt array ( rosa =gt FE9ABC amarillo =gt FDF189 malva =gt 9A2F68))

echo $colores[fuertes] [rojo] gt

Propiedades de arrays

Existen numerosas funciones que son capaces de averiguar datos de los arrays tales como el tamantildeo si un valor forma parte del conjunto o si un determinado iacutendice estaacute registrado

count()

Cuenta el nuacutemero de elementos que contiene un array

ltphp echo elementos de 1 dimensioacuten count ($colores) ltbrgt echo elementos de 2 dimensiones count ($colores[fuertes]) gt

El ejemplo anterior se basa en la definicioacuten del array de colores inicializa-do antes Para contar el nuacutemero de elementos debe ponerse tambieacuten la dimensioacuten Si el array es de una sola dimensioacuten no hace falta La funcioacuten s i z e o f () actuacutea de la misma forma

in_array()

Busca dentro de un array un valor pasado como paraacutemetro y si lo encuenshytra devuelve el valor true si no devuelve false Toma dos argumentos el valor a buscar y el array doacutende buscar

ltphp $colores = array (rojoverdeamarilloazul) if (in_array(rojo$colores))

echo Se ha encontrado el valor rojo

138 Capiacutetulo 7

e l s e echo No se ha encontrado

gt

Borrar ocurrencias

Para borrar un elemento simplemente se utiliza la misma funcioacuten que borra las variables definidas unset ()

ltphp $colores = array (rojoverdeamarilloazulrosa) echo El nuacutemero de elementos de colores es count ($colores) ltbrgt unset ($colores[2]) echo El nuacutemero de elementos de colores es count ($colores) ltbrgt gt

Se puede observar que para borrar un elemento hay que conocer el iacutendishyce El resultado del ejemplo por pantalla es

El nuacutemero de elementos de colores es 5 El nuacutemero de elementos de colores es 0

Advertencia

Debe tener cuidado el lector con utilizar unset () con el nombre de un array sin iacutendice pues esto causaraacute el borrado del conjunto de datos en su totalidad Unset ($colores) borra el array comshypleto unset ($colores [2] borra soacutelo el iacutendice 2 del conjunto

Interactuar con arrays

Anteriormente tuvo la oportunidad de conocer las estructuras de control existentes en PHP La estructura f oreach quedoacute en el aire para tratarlo a fondo en el presente capiacutetulo El uso es asiacute

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) foreach ($colores as $valor)

echo (El valor es $valorltbrgt)

gt

Conjuntos de datos del tipo array 139

La construccioacuten anterior recorre el array desde el principio En el ejemplo se puede ver que f oreach toma el array a recorrer y sus valores los va almacenando en la variable $ v a l o r a medida que el bucle se ejecuta Existe una segunda construccioacuten que permite recuperar el iacutendice y el valor Veashymos un ejemplo de esto

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) foreach ($ciacuteudades as $iacutendiacutece =gt $valor)

echo (El iacutendice $indice tiene el valor $valorltbrgt)

gt

La salida en el navegador nos la muestra la figura 71

Es un meacutetodo muy bueno para imprimir los valores de un array que tiene iacutendices numeacutericos y alfanumeacutericos

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia] = Paris foreach ($ciudades as $indice =gt $valor)

echo (El Iacutendice $indice tiene el valor $valorltbrgt)

gt

140 Capiacutetulo 7

Funciones para avanzar en un array

Cada vez que creamos un array dentro de un programa PHP se crea un puntero que permite recorrer en su totalidad el conjunto de valores Este puntero se inicializa al valor inicial del array La funcioacuten c u r r e n t () deshyvuelve el valor al que apunta el puntero La funcioacuten n e x t () hace avanshyzar el puntero una posicioacuten en el conjunto de datos

Si el puntero se encuentra al final del conjunto n e x t () devuelve un vashylor false El ejemplo siguiente muestra coacutemo utilizar estas funciones para recorrer un array

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia] = Paris do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

while (next($ciudades) ) gt

Podemos crear una funcioacuten que realice este traacutemite

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) Sciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia ] = Paris

function recorre($ciudades) do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

Jwhile (next($ciudades))

recorre($ciudades) recorre($ciudades) gt

La funcioacuten r e c o r r e () utiliza un array como paraacutemetro y va utilizando las funciones de introspeccioacuten para sacar los resultados Puesto que los valores son pasados por valor la funcioacuten r e c o r r e () crea una copia de los datos que recibe y genera el resultado de la figura 72

De esta forma no hay manera de controlar el puntero porque siempre que pase la variable $ c i u d a d e s el puntero comenzaraacute desde el principio

Conjuntos de datos del tipo array 141

La forma de arreglar esto es hacer las llamadas por referencia r e c o r r e (Sc$ciudades) r e c o r r e (amp$ciudades)

142 Capiacutetulo 7

Ahora ya no es una copia de $ c iudades lo que se pasa como paraacutemetro sino una referencia al valor real Esto hace posible tener una memoria de la situacioacuten del puntero Una vez recorrido elarray el puntero queda fijado al final del conjunto de datos Para volver al principio se puede utilizar la funcioacuten r e s e t () que enviacutea al puntero al principio La funcioacuten puede quedar asiacute

function recorre($ciudades) if (current($ciudades))

reset($ciudades)

do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

Jwhile (next($ciudades))

Ahora lo que hacemos es comprobar si el puntero estaacute al final del array si esto es asiacute se llama a la funcioacutenreset 0 y el puntero se coloca al prinshycipio

Funciones para retroceder en un array

La funcioacuten prev () retrocede una posicioacuten el puntero y la funcioacuten end () se coloca al final de una lista de valores Esto puede ser uacutetil para mostrar el contenido en sentido inverso como puede ver en la nueva funcioacuten que hemos creado

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal ] = Lisboa $ciudades[Francia ] = Paris function recorre($ciudades)

if ( lcurrent($ciudades)) reset($ciudades)

do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

jwhile (next($ciudades))

function recorre_atras($ciudades)

end($ciudades) do

$valor = current($ciudades)

Conjuntos de datos del tipo array 143

echo (El valor es $valorltbrgt) while (prev($ciudades))

recorre(amp$ciudades) recorre_atras(amp$ciudades) gt

El navegador muestra El valor es Badajoz El valor es Meacuterida El valor es Caacuteceres El valor es Plasencia El valor es Madrid El valor es Lisboa El valor es Paris El valor es Paris El valor es Lisboa El valor es Madrid El valor es Plasencia El valor es Caacuteceres El valor es Meacuterida El valor es Badajoz

Por uacuteltimo para obtener el valor del iacutendice puede utilizar la funcioacuten key() La funcioacuten r e c o r r e () la puede actualizar de la siguiente forma

function recorre($ciudades) if ( current($ciudades) )

reset($ciudades)

do

$valor = current($ciudades) $indice = key($ciudades)

echo ($indice valor $valorltbrgt)

while (next($ciudades))

Intercambio de valores

La funcioacuten a r r a y _ f l i p () intercambia los valores de iacutendices y datos es decir los iacutendices seraacuten guardados como datos y los valores seraacuten sus nueshyvos iacutendices

ltphp function recorre ($numero)

foreach ($numero as $indice =gt $valor) echo $indice $valorltbrgt -

144 Capiacutetulo 7

$numero = array(uno =gt ldos =gt 2 tres =gt 3cuatro =gt 4) echo (Nuacutemerosltbrgt ) recorre($numero) echo (Nuacutemeros intercambiadosltbrgt) recorre(array_fliacutep$numero)) gt

El resultado es el esperado

Nuacutemeros uno 1 dos 2 tres 3 cuatro 4 Nuacutemeros intercambiados 1 uno 2 dos 3 tres 4 cuatro

Puede ver el resultado en la figura 74

Inversioacuten del contenido

Tambieacuten es posible ordenar a la inversa una lista de datos Esto se consishygue con la funcioacuten a r r a y _ r e v e r s e ()

Conjuntos de datos del tipo array 1 4 5

Si modifica el coacutedigo anterior tendraacute

echo (Nuacutemeros intercambiadosltbrgt ) recorre(array^reverse($numero))

Dando como resultado

Nuacutemeros uno 1 dos 2 tres 3 cuatro 4 Nuacutemeros intercambiados cuatro 4 tres 3 dos 2 uno 1

Mezcla de los valores

Si necesita alguna vez elegir un valor aleatorio de un array la funcioacuten shu-f f le () puede ser de gran ayuda ya que mezcla todos los valores cada vez que se ejecuta Parte del coacutedigo puede ser este

echo (Nuacutemeros mezcladosltbrgt ) shuffle($numero) recorre($numero)

Pilas

Las pilas son estructuras de datos que se utilizan mucho en el mundo de la informaacutetica La filosofiacutea baacutesica de las pilas es que todos los valores deshyben introducirse en un orden especiacutefico y soacutelo podemos recuperar esos valores en el orden inverso estricto al que fueron insertados Las pilas LIFO (Last ln First Out el uacuteltimo en entrar es el primero en salir) utilizan unas funciones especiacuteficas que permiten manejar todos los datos A r r a y _ p u s h () permite insertar en la pila un dato y a r r a y _ p o p () exshytrae un valor Es necesario antes que nada definir la variable como array pues ninguna de las funciones descritas lo hace

A r r a y _ p u s h () y a r r a y _ p o p () toman como argumento la variable array y los valores a introducir

lt php $pila = array() array_push($pilaunodostres)

146 Capiacutetulo 7

array_jpush($pilacuatrocinco) while ($valor = arrayjop($pila) )

echo valor extraiacutedo es $valorltbrgt

gt

El resultado por pantalla muestra que la extraccioacuten de los valores se hace en orden inverso del que fueron introducidos

valor extraiacutedo es cinco valor extraiacutedo es cuatro valor extraiacutedo es tres valor extraiacutedo es dos valor extraiacutedo es uno

Ordenacioacuten de los valores

Finalmente PHP ofrece una gran variedad de funciones para ordenar arrays Las funciones pueden verse en la tabla siguiente

Tabla 71 Funciones de ordenacioacuten

Funcioacuten Explicacioacuten

asort() Ordena de forma ascendente el array pasado como argumento Ordena las parejas iacutendicevalor atendiendo al dato Es un buen meacutetodo para los arrays asociativos

arsort() Igual que asort () pero ordena en sentido descendente ksort() Ordena de forma ascendente el array pasado como argumento

Ordena las parejas iacutendicevalor atendiendo esta vez al iacutendice

krsort() Igual que ksort () pero ordena en sentido descendente

sort() Ordena de forma ascendente el array pasado como argumento Se pierde el valor asociativo entre el iacutendice y el valor

rsort() Igual pero en orden descendente

Puede ver actuar todas las funciones de ordenacioacuten en el ejemplo sishyguiente

ltphp function recorre ($numero)

foreach ($numero as $indice =gt $valor) echo $indice $valorltbrgt

Conjuntos de datos del tipo array 147

$pi la = array(cinco = gt5uno = gtl cuatro = gt4dos = gt2 tres = gt3) echo Array sin ordenarltbrgt recorre($pila) echo Ordenacioacuten asort()ltbrgt asort($pila) recorre($pila) echo Ordenacioacuten arsort)ltbrgt arsort($pila) recorre($pila) echo Ordenacioacuten ksort()ltbrgt ksort($pila) recorre ($pila) echo Ordenacioacuten krsort()ltbrgt krsort ($pila) -recorre($pila) echo Ordenacioacuten sort()ltbrgt sort($pila) recorre($pila) echo Ordenacioacuten rsort()ltbrgt rsort($pila) recorre($pila) gt

La figura 75 muestra todos los tipos de ordenacioacuten que puede utilizar sobre un array

148 Capiacutetulo 7

Resumen

En este capiacutetulo ha conocido el tipo de variable estrella de PHP el array Controlar los meacutetodos y las funciones para extraer la informacioacuten le daraacute ventaja en los capiacutetulos posteriores Muchas funciones que tienen que ver con el manejo de datos como funciones de bases de datos XML o generashycioacuten de plantillas devuelven un array como respuesta El tipo array es el vehiacuteculo estaacutendar para la recuperacioacuten de datos estrucshyturados como veremos en los proacuteximos capiacutetulos

En este capiacutetulo aprenderaacute a

bull Crear formularios para pasar datos entre paacuteginas

bull Utilizar las variables suacuteper-globales para recibir la informacioacuten de un formulario

bull Diferenciar entre los meacutetodos de enviacuteo GET y POST

bull Encontrar posibles errores revisando las variables suacuteper-globales

150 Capiacutetulo 8

Introduccioacuten

Hasta ahora en los capiacutetulos anteriores hemos visto coacutemo construir dishyversos programas en PHP con un limitado radio de accioacuten La verdadera potencia del lenguaje reside en la aplicacioacuten de las teacutecnicas aprendidas a traveacutes de varias paacuteginas Web pasando informacioacuten de unas a otras Como veremos maacutes adelante las dos teacutecnicas principales son el uso de formulashyrios y la utilizacioacuten de la barra de direccioacuten para pasar los valores

Argumentos GET

Los argumentos GET pasan la informacioacuten como parte de la URL Cuando utilice esta forma de trabajar las parejas de variable valor podraacuten verse en la casilla de direccioacuten del navegador Para probar esto podemos escrishybir un pequentildeo script que guardaremos como paacutegina Web

lthtmlgt ltbodygt ltphp echo Variables pasadas mediante GETltbrgt foreach ($_GET as $indice =gt $valor)

echo $indice $valor

gt ltbodygt lthtmlgt

Si ejecuta el coacutedigo anterior veraacute que uacutenicamente se imprime en pantalla el texto que muestra la orden echo En realidad esto es correcto puesto que no hemos introducido ninguna variable tipo GET a la Web Para hashycerlo debemos escribir el nombre de la paacutegina Web seguido de un siacutembolo de interrogacioacuten () y el conjunto de parejas de variable valor separadas del siacutembolo (amp)

La direccioacuten queda algo asiacute f o r m u l a r i o php v a r i a b l e l = H o l a M u n d o amp v a r i a b l e 2 = 1234 Ahora el resultado es diferente El bucle f o shyr e a c h inspecciona el array $_GET e imprime en pantalla

Variables pasadas mediante GET variablel Hola Mundo variable2 1234

El array $_GET es considerado en PHP 5 una variable suacuteper-global Este en concreto almacena todas las variables pasadas entre paacuteginas mediante

Paso de informacioacuten entre formularios 151

el meacutetodo GET Para extraer el valor de una variable pasada por este meacuteshytodo soacutelo hay que escribir $_GET [ n o m b r e _ v a r i a b l e ] en la paacutegina que recibe los datos

Advertencia

En versiones anteriores de PHP para recuperar el valor de una variable simplemente habiacutea que escribir un siacutembolo $ delante del nombre como $ n o m b r e _ v a r i a b l e Esto es porque el paraacutemeshytro register_globals del fichero de configuracioacuten php i n i estaacute en PHP 5 a off

Formularios con GET

La forma maacutes utilizada para recabar informacioacuten acerca de los usuarios es emplear formularios HTML Los formularios pueden hacerse escribiendo en un editor de texto las etiquetas HTML o utilizando alguacuten editor Web profesional como Macromedia Dreamweaver Netscape Composer o Nvu La siguiente paacutegina Web llamada f o r m u l a r i o php muestra coacutemo reshycoger informacioacuten

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt

ltpgtIntroduzca sus datos personales ltpgt ltform name=formulario method=GET action=formulario2 php gt lttable width=50 border=0 cellspacing=0 cellpadding=0gt lttrgt lttd width=24gtNombrelttdgt lttd width=76xinput name=nombre type=text id=nombrextdgt

lttrgt lttrgt lttdgtApellidoslttdgt lttdxiacutenput name=apellidos type=text id=apellidos2gtlttdgt

lttrgt lttrgt lttdgtCorreolttdgt lttdxinput name=correo type=text id= correo xtdgt

lttrgt lttrgt lttdgtEstado civil lttdgt lttdxselect name= estado id= estado gt ltoption value=SolterogtSolteroltoptiongt ltoption value=CasadogtCasadoltoptiongt

152 Capiacutetulo 8

bullcoption value=DivorciadogtDivorciadoltoptiongt ltoption value=ViudogtViudoltoptiongt

ltselectgtlttdgt lttrgt lttrgt lttdgtNampuacutemero hijos lttdgt lttdgt 0 ltinput name=hijos type=radio value=0 checkedgt

1 ltinput name=hijos type=radio value=lgt 2 ltinput name=hijos type=radio value=2gt 3 ltinput name=hijos type=radio value=3gtlttdgt

lttrgt lttrgt lttdgtGustoslttdgt lttdgt Informampaacutetica ltinput type=checkbox name=gustos []

value=Informaacuteticagt Buceo ltinput type=checkbox name=gustos [] value=Buceogt Magia ltinput type=checkbox name=gustos [ ] value=Magiagt Jazz ltinput type=checkbox name=gustos [] value=Jazzgtlttdgt

lttrgt lttrgt lttdxinput type=submit name=Submit value=Enviargtlttdgt lttdgtampnbsplttdgt

lttrgt lttablegt

ltformgt ltpgtampnbsp ltpgt ltbodygt lthtmlgt

La figura 81 muestra el aspecto en el navegador Hay varios aspectos a tener en cuenta Lo primero es que el apartado a c t i o n de la etiqueta ltFORMgt contiene la paacutegina Web a la que se enviaraacuten los datos y el apartashydo method permite seleccionar el meacutetodo de enviacuteo por ahora utilizareshymos el meacutetodo GET La paacutegina f o r m u l a r i o 2 php recoge la informacioacuten del formulario y la imprime en pantalla utilizando un bucle f o r e a c h a la variable suacuteper-global $_GET

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidosltpgt ltphp foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

gt ltbodygt lthtmlgt

Para sacar los datos hemos utilizado un bucle que busca todos los valores dentro de $__GET Otra forma de hacerlo es imprimir los datos uno a uno

154 Capiacutetulo 8

si sabemos el nombre de las variables definidas en el formulario anterior de la siguiente forma $_GET [ n o m b r e ] $_GET [ a p e l l i d o s ] $_GET [ c o r r e o ]

Existen en el formulario visto varias teacutecnicas de recogida de informacioacuten Los cuadros de texto que permiten escribir valores alfanumeacutericos lista de seleccioacuten y botones de opcioacuten es donde podemos elegir una de las opciones existentes y casillas de verificacioacuten que permiten elegir 0 o maacutes opciones existentes Todas estas partes del formulario tienen una variable asociada que puede buscarse en $_GET

El uacutenico meacutetodo que puede plantear alguacuten problema es el que utiliza cashysillas de verificacioacuten Puesto que podemos elegir varias opciones eacutestas son enviadas como un array y deben recuperarse atendiendo a esta razoacuten

Advertencia

Para que los valores de las casillas de verificacioacuten sean enviados como array hay que declararlas en el formulario como tal escrishybiendo dos siacutembolos de corchetes en la propiedad ntildeame asociada a las casillas por ejemplo lt i n p u t t y p e = c h e c k b o x n a m e = g u s t o s [] v a l u e = I n f o r m aacute t i c a gt

La paacutegina f o r m u l a r i o 2 php queda de esta forma para que pueda recishybir los gustos de los usuarios

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidos ltpgt ltphp foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

echo ltbrgtGUSTOSltbrgt $gustos = $_GET[gustos] foreach ($gustos as $indice =gt $valor)

echo $indice $valorltbrgt gt ltbodygt lthtmlgt

La figura 83 muestra la mejora incluida en el programa Ahora es capaz de recuperar los gustos de los usuarios e imprimirlos en pantalla Para esto

Paso de informacioacuten entre formularios 155

hemos antildeadido un bucle nuevo que inspecciona los valores enviados al array $gustos

Paso de informacioacuten con GET

Si se fija en la barra de direccioacuten de los navegadores cuando visita paacutegishynas Web sobre noticias o carritos de la compra en la URL van aparecienshydo variables que tienen que ver con los distintos menuacutes que existen en la Web

El siguiente ejemplo muestra una pequentildea revista digital escrita en pocas liacuteneas y en una sola paacutegina Web que cambia sus noticias eligiendo las disshytintas opciones del menuacute

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitIacuteonalEN

httpwwww3orgTRhtml4loosedtdgt lthtmlgt ltbodygt ltphp $menu = array (1 =gt Editorial 2 =gt Opinioacuten 3 =gt Regional 4 =gt Nacional) echo (--Revista Digital --ltbrxbrgt) echo (--MENU--ltbrgt ) foreach ($menu as $indice =gt $valor)

echo (lta href = Iacutendexphpmenu=$indicegt$valorltaxbrgt)

156 Capiacutetulo 8

j

echo ( ltbrgt--NOTICIAS--ltbrgt) switch ($_GET[menuacute])

case 1 echo (Editorial) break

case 2 echo (Opinioacuten) break

case 3 echo (Regional) break

case 4 echo (Nacional) break

default echo (Noticias de Portada) break

gt ltbodygt lthtmlgt

El array $menu se carga de los distintos valores que podemos ir seleccioshynando

En la actualidad estos valores se suelen extraer de una base de datos

Para mostrar el menuacute se hace un bucle donde se extraen todos los valores e iacutendices del array y se ponen como valores en los enlaces

echo (lta href=Iacutendexphpmenu=$indicegt$valorltaxbrgt)

Los enlaces siempre se dirigen a la paacutegina principal pero con un valor distinto en la variable menuacute

La segunda parte de la Web es una eleccioacuten muacuteltiple mediante la estrucshytura s w i t c h donde en funcioacuten del valor de la variable menuacute pasada por GET se eligen unas noticias vi otras

Puede ver el resultado en la figura 84

echo (lta href=Iacutendexphpmenu=$indicegt$valorltaxbrgt)

Los enlaces siempre se dirigen a la paacutegina principal pero con un valor distinto en la variable menuacute

La segunda parte de la Web es una eleccioacuten muacuteltiple mediante la estrucshytura s w i t c h donde en funcioacuten del valor de la variable menuacute pasada por GET se eligen unas noticias u otras

Puede ver el resultado en la figura 84

Argumentos POST

La utilizacioacuten del meacutetodo GET es totalmente inseguro porque no hay forshyma de ocultar datos privados en la direccioacuten Web tales como la contraseshyntildea de entrada o el nuacutemero de cuenta bancaria

El meacutetodo POST arregla estos problemas siendo el preferido de los desa-rrolladores Este meacutetodo es tan sencillo como cambiar en el formulario el meacutetodo de enviacuteo de datos

ltpgtIntroduzca sus datos personalesltpgt ltform name=formulario method=POST action=formulario2 php gt

lttable width=50 border=0 cellspacing=0 cellpadding=0gt

En cuanto a la recuperacioacuten de los datos tambieacuten debe cambiar el nombre de la variable suacuteper-global $_GET por $_POST de esta manera

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidosltpgt ltphp foreach ($_POST as $indice =gt $valor)

echo $indice $valorltbrgt

e c h o ltbrgtGUSTOSltbrgt $ g u s t o s = $ _ P O S T [ g u s t o s ]

158 Capiacutetulo 8

foreach ($gustos as $indice =gt $valor) echo $indice $valorltbrgt

gt ltbodygt lthtmlgt

Variables suacuteper-globales

Desde PHP 4 se vienen utilizando los arrays suacuteper-globales para almaceshynar los valores que pasan de unas paacuteginas a otras se almacenan en el orshydenador del usuario o en el servidor En PHP 5 el uso de estas variables se hace obligatorio para recuperar todos los valores Las variables a utilizar son

bull $_GET Almacena las variables que se pasan desde un formulario meshydiante el meacutetodo GET

bull $_POST Almacena las variables pasadas por POST

bull $_COOKIE Guarda los valores que estaacuten almacenados en cookies Ya veremos en capiacutetulos sucesivos coacutemo utilizarlo

bull $_SESSlON bull Guarda las variables que se pasan entre sesiones

bull $_SERVER Contiene numerosos valores relativos al servidor

bull $_FILES Los archivos que enviemos a traveacutes de un formulario seshyraacuten recogidos en este array

Una equivocacioacuten en el nombre de una variable puede llevarle a dar vuelshytas sobre el coacutedigo hasta encontrar el error Por eso es necesario conocer el contenido de las variables suacuteper-globales asiacute podraacute averiguar si estaacute pasando los datos correctamente La funcioacuten siguiente se puede utilizar cada vez que le surja un error de este tipo La funcioacuten muestra todos los valores de los arrays suacuteper-globales

ltphp function depuracioacuten() echo --Variables GET--ltbrgt foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

echo --Variables POST--ltbrgt foreach ($_POST as $indice =gt $valor)

echo $indice $valorltbrgt

echo --Variables COOKIES--ltbrgt

Paso de informacioacuten entre formularios 159

foreach ($_COOKIE as $indice =gt $valor) echo $iacutendiacutece $valorltbrgt

echo --Variables SESSION--ltbrgt foreach ($_SESSION as $indice =gt $valor)

echo $iacutendiacutece $valorltbrgt

echo --Variables SERVER-~ltbrgt foreach ($_SERVER as $indice =gt $valor)

echo $indice $valorltbrgt

depuracioacuten () gt

La figura 85 muestra los valores de todas las variables suacuteper-globales

Resumen

Hasta ahora soacutelo habiacuteamos tenido la oportunidad de crear programas en PHP que realizaran tareas en una uacutenica paacutegina Web

Este capiacutetulo ha dado una visioacuten praacutectica de coacutemo utilizar los conceptos aprendidos para escribir programas distribuidos en varias paacuteginas

160 Capiacutetulo 8

Aunque no ha aprendido ninguna funcioacuten nueva ha descubierto el vershydadero secreto del disentildeo de una Web dinaacutemica el paso de variables

Si viene de otras versiones de PHP tendraacute que tener en cuenta que la forshyma de recuperar las variables es a partir de la versioacuten 43 a traveacutes de las variables suacuteper-globales

En este capiacutetulo aprenderaacute a

bull Diferenciar entre clase y objeto bull Crear clases que hereden de otras clases bull Utilizar los modificadores pr iacutevate protected ypubl ic

bull Crear meacutetodos estaacuteticos y finales bull Guardar el estado de un objeto mediante la sentildealizacioacuten bull Recuperar informacioacuten referente a las clases meacutetodos y propiedades

162 Capiacutetulo 9

Introduccioacuten

PHP comenzoacute su andadura como un simple lenguaje de scripts A medishyda que las versiones avanzaban se fueron incluyendo algunas caracteshyriacutesticas que permitiacutean programar con orientacioacuten a objetos Con la aparicioacuten de PHP 5 los desabolladores tenemos una verdadera platashyforma de programacioacuten orientada a objetos gracias a la potencia del nuevo engine Zend 20 que permite ejecutar maacutes raacutepido y eficientemenshyte este tipo de programas

La programacioacuten orientada a objetos utiliza los elementos c l a s e y o b shyj e t o con punto de inicio Actualmente en las carreras teacutecnicas es posishyble encontrar ensentildeanzas sobre lenguajes orientados a objetos como Java o C++

Nota

En realidad Java y C++ son considerados como seudo lenguajes orientados a objetos Un ejemplo de lenguaje puro es SmallTalk o su versioacuten graacutefica Squeak (httpsqueaklinexorg) con muchos antildeos de antiguumledad

La programacioacuten orientada a objetos en PHP 5 no necesita una sintaxis muy diferente sino que es una aproximacioacuten a la realidad en otro camino diferente al acostumbrado Por ejemplo si piensa en un programa que tenga que averiguar la letra del DNI de un cliente lo normal es que cree una funcioacuten con un paraacutemetro al que le pase el nuacutemero de DNI y le deshyvuelva la letra buscada

Un desarrollo orientado a objetos pensariacutea en cada problema como una idenshytidad uacutenica como un objeto Puesto que el DNI siempre va asociado a una persona puede crear un objeto que identifique a personas y dentro de ese objeto programar una funcioacuten (meacutetodo en este caso) que calcule la letra La aproximacioacuten procedural (crear una funcioacuten) no asocia esa funcioacuten a persoshynas directamente y le podriacutea pasar cualquier nuacutemero entero recibiendo una respuesta vaacutelida En cambio la aproximacioacuten de objetos crea la funcioacuten dentro del objeto c l i e n t e y soacutelo permite mediante teacutecnicas que veremos maacutes adelante recuperar la letra del DNI de una persona

La programacioacuten orientada a objetos desarrolla nuevos conceptos y termishynologiacuteas que deben aprenderse correctamente para generar buen coacutedigo

Programacioacuten orientada a objetos 163

Definicioacuten de clases

Una clase es un tipo de dato que contiene en una misma estructura vashyriables y funciones Una clase es una especie de plantilla desde la que los objetos son instanciados y toman su valor Desde una clase se pueden consshytruir varios objetos del mismo tipo La definicioacuten es la siguiente

class pagina_Web

var $titulo function getTitulo()

return $this-gttitulo

Mediante la palabra reservada c l a s s definimos una clase completa Utishylizando va r podemos definir las variables que utilizaremos en el desarroshyllo del programa La palabra reservada va r desapareceraacute en versiones siguientes de PHP a favor de las palabras publ ic p r iacute v a t e y p r o t e c -ted Las funciones se definen como en el capiacutetulo 5 siempre que esteacuten dentro de la construccioacuten de la clase En este capiacutetulo vamos a definir una clase completa cuya misioacuten seraacute mostrar una paacutegina Web Podemos seshyguir con el ejemplo ampliando las funciones

ltphp class pagina_Web

var $titulo function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

function getTitulo() return $this-gttitulo

function cabecera() echo (lthtmlxheadxtitlegt) echo $this-gttitulo echo ( lttitlexheadxbodygt) bull

function cuerpo() echo(Este es el cuerpo de la paacutegina Web)

164 Capiacutetulo 9

function pie ( )

echo (ltbodyxhtmlgt)

function mostrar_pagina()

echo $thiacutes-gtcabecera () echo $this-gtcuerpo()

echo $this-gtpie()

Como puede ver la clase se divide en varias funciones y en una sola vashyriable La variable $ ti t u l o guardaraacute el tiacutetulo deacute la paacutegina Web Las funshyciones c a b e c e r a ( ) c u e r p o () y p i e () son las encargadas de mostrar las distintas partes de una Web

Estas funciones se llaman desde la f u n c i oacute n m o s t r a r _ p a g i n a ( ) Es inteshyresante observar que en unas pocas liacuteneas de coacutedigo hemos definido un objeto que podriacutea utilizarse como base de muchas aplicaciones El operador $ t h i s es una variable que contiene el objeto actual desde el que la invocamos Para acceder dentro de un objeto a funciones o variashybles propias debe anteponerse al nombre de eacutestas la expresioacuten $ t h i s - gt Para acceder desde la funcioacuten m o s t r a r _ p a g i n a () a cualquiera de las funciones de la clase tendraacute que escribir

$this-gtcabecera () $this-gtcuerpo ( ) $this-gtpie ()

Instancia de clase

Para que el coacutedigo funcione necesita crear el objeto Esto se hace utilizanshydo el operador new seguido del nombre de la clase

$ p a g i n a = new p a g i n a _ W e b ( )

Con el coacutedigo anterior hemos creado un objeto que contiene todas las vashyriables y funciones de la clase pag ina_Web ( ) La variable que contiene ese objeto es $pag ina

Para acceder a las funciones desde el nuevo objeto creado tenemos que utilizar la variable que contiene al objeto en este caso $ p a g i n a seguido del operador - gt y el nombre de la funcioacuten Para mostrar la Web tenemos que seguir estos sencillos pasos

$ p a g i n a = new p a g i n a _ W e b ( )

Programacioacuten orientada a objetos 165

$pagina-gtsetTitulo(Paacutegina Web nueva) $pagina- gtmostrar__pagina ( )

Funcioacuten constructor

Existen algunas funciones especiales en la definicioacuten de una clase La maacutes importante es el constructor Esta se ejecuta cada vez que se crea un nueshyvo objeto y permite crear las variables iniciales que se necesitan como el tiacutetulo de la Web o el autor El nombre de la funcioacuten debe ser c o n s -t r u c t () Nuestro constructor se encargaraacute de crear el tiacutetulo de la paacutegina Web que estamos creando

funct ion c o n s t r u c t ( $ t i t u l o )

$this-gtsetTitulo($titulo)

Herencia

La programacioacuten orientada a objetos permite heredar de otras clases Con esta teacutecnica puede ahorrar mucho tiempo de trabajo La clase hija (clase que hereda de otra) adquiere estas propiedades

bull Automaacuteticamente obtiene todas las variables miembro de la clase padre

bull Tambieacuten obtiene todas las funciones miembro de la clase padre que funcionaraacuten exactamente de la misma forma

bull La clase hija puede a su vez definir nuevas variables y funciones

La sintaxis es la siguiente

class pagina_Web_formulario extends pagina_Web

function formulario_inicio() Escribir el coacutedigo necesario

La palabra reservada e x t e n d s indica que la nueva clase creada seraacute una extensioacuten (heredaraacute) de la clase que se escribe justo a la derecha de la deshyfinicioacuten Puede crear un objeto formulario a partir de la clase pagina_Web de la siguiente forma

class pagina_Web_formulario extends pagina_Web

166 Capiacutetulo 9

function formulariacuteo_inicio($accion)

echo (ltform action=$acciongt)

function formulario_fin() echo (ltformgt)

function formulario_caj a_texto($nombre) echo ($nombre ltinput type=text name=$nombregt)

function formulario_boton() echo (ltinput type=submit name=Submit

valuacutee = Enviargt )

function mostrar_pagina () $this-gtcabecera () $this- gtf ormulario__inicio ( Iacutendex php) $this- gtf ormulario__caj a_texto (Nombre) $this-gtformulario_boton() $this-gtformulario_fin()

$this- gtpie ()

Si ahora ejecuta el coacutedigo instanciando la clase que hemos creado puede ver que las funciones c a b e c e r a () p i e ( ) incluso el constructor pueshyden ser utilizadas auacuten no perteneciendo a la clase p a g i n a _ W e b _ f o r -m u l a r i o

$formulario = new pagina_Web_formularioPagina con f o r m u l a r i o ) $formular io-gtmostrar_pagina ( )

La figura 91 muestra la ejecucioacuten del objeto anterior

Meacutetodos o funciones de objeto

Cuando definimos una clase hija las funciones de la clase padre son autoshymaacuteticamente heredadas Se llama redefinicioacuten de meacutetodos a la creacioacuten de funciones en la clase hija con el mismo nombre que en la clase padre En el ejemplo anterior la funcioacuten m o s t r a r _ p a g i n a ( ) de la clase pag ina_Web_f o r m u l a r i o estaacute redefinida ya que existe una funcioacuten con

Programacioacuten orientada a objetos 167

el mismo nombre en la clase pag ina_Web Al instanciar el objeto y ejecushytar el meacutetodo m o s t r a r _ p a g i n a ( ) el meacutetodo que se ha definido es la clase hija

PHP 5 con su nuevo motor Zend Engine 2 introduce la palabra reservashyda f i n a l

Si en la clase padre ponemos delante de cualquier funcioacuten la palabra f i n a l eacutesta funcioacuten no podraacute ser sobrecargada en las clases que la heshyreden

Tambieacuten podemos declarar clases completas como f i n a l lo que signifishycaraacute que no podraacuten ser heredadas

final function mostrar_pagina()

echo $this-gtcabecera() echo $this-gtcuerpo()

echo $this-gtpie()

Si definimos la funcioacuten anterior como f i n a l en la clase pag ina_Web la clase p a g i n a _ W e b _ f o r m u l a r i o no podraacute tener una funcioacuten con este mismo nombre y mostraraacute un error en pantalla La figura 92 muestra el error que se produce al intentar sobrecargar un meacutetodo que estaacute marcado como f i n a l

Herencia encadenada

Algunos lenguajes de programacioacuten permiten heredar de varias clases a la vez esto es conocido como herencia muacuteltiple PHP 5 no permite herenshycia muacuteltiple pero siacute herencia encadenada es decir permite heredar de varias clases padres correlativamente Un ejemplo es

class A

class B extends A

class C extends B

class D extends C

Valores y alcance de variables

En versiones anteriores de PHP los objetos eran pasados por valor a otras funciones por lo tanto el estado de los objetos no se conservaba En PHP 5 los objetos son pasados por defecto por referencia gracias al Zend Engine 2

ltphp

Programacioacuten orientada a objetos 169

class Nombre

i var $nombre function setNombre($nombre)

$this-gtnombre = $nombre

function getNombre() return $this-gtnombre

function cambiaNombre($obj eto$nombre)

$objeto-gtsetNombre($nombre)

$luis = new Nombre $luis-gtsetNombre(Luis Miguel) echo El nombre del objeto es $luis-gtgetNombre() ltbrgt cambiaNombre($luisPedro) eche El nombre del objeto es $luis-gtgetNombre() ltbrgt gt

El coacutedigo muestra coacutemo cambiar las propiedades de un objeto desde una funcioacuten con PHP 5 El resultado en el navegador puede comprobarlo en la figura 93

170 Capiacutetulo 9

Dentro de los objetos debe tener tambieacuten cuidado con el alcance de las variables Las variables definidas fuera del entorno del objeto no son acshycesibles desde los meacutetodos de las clases a menos que anteponga la palashybra g l o b a l

Miembros puacuteblicos privados y protegidos

Mientras no se especifique otra cosa los meacutetodos y propiedades de una clase son siempre puacuteblicos es decir son accesibles desde fuera del objeto de la forma o b j e t o - gtf u n c i oacute n Pero existe un camino para que las vashyriables y los meacutetodos no puedan ser accedidos desde fuera del objeto Eche un vistazo ahora al objetopagina_Web Su variable $ t i t u l o es puacuteblico porque no lo hemos definido de alguna forma especial Para cambiar el valor de esta variable podriacutea utilizar la funcioacuten asociada o directamente haciendo $ o b j e t o - gt t i t u l o = nuevo v a l o r Esta forma de actuar rompe con la filosofiacutea de la programacioacuten orientada a objetos Como norshyma general las propiedades de los objetos deben estar ocultas al entorno exterior y tomar sus valores desde funciones definidas dentro del objeto

Meacutetodos privados

Si declaramos un meacutetodo o propiedad como privada soacutelo se podraacute acceshyder a eacutel desde la clase que lo define Las clases que hereden de una clase con meacutetodos privados no tendraacuten acceso a eacutestos meacutetodos y tampoco seraacute posible desde fuera del objeto hacer llamadas Para hacer un meacutetodo o propiedad privado soacutelo hay que anteponer la palabra p r iacute v a t e delante de la declaracioacuten

class pagina_Web

priacutevate $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

priacutevate function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

De esta manera la clase p a g i n a _ W e b _ f o r m u l a r i o que hereda de pagina_Web no puede acceder directamente a la funcioacuten s e t T i t u l o ()

Programacioacuten orientada a objetos 171

de la siguiente forma $ t h i s - gt s e t T i t u l o ( T i t u l o n u e v o ) porque obtenemos un error de acceso ilegal Despueacutes de esta modificacioacuten soacutelo es posible dar un tiacutetulo a la paacutegina Web a traveacutes del constructor que como siacute estaacute dentro de la clase tiene potestad para utilizarla

Meacutetodos protegidos

Los meacutetodos protegidos son menos restrictivos que los privados Cuando declaramos un meacutetodo como protegido su visibilidad es en la clase que lo declara y en todas las clases que lo heredan El ejemplo anterior puede modificarse de la siguiente forma

c l a s s pagina_Web

protected $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

protected function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

Meacutetodos puacuteblicos Por defecto todos los meacutetodos y propiedades que se declaren en un objeshyto son puacuteblicos a menos que lleven asociados la palabra p r o t e c t e d o p r iacute v a t e Como buena praacutectica de programacioacuten las variables deben deshyfinirse como privadas o protegidas para que no puedan modificarse desshyde fuera del objeto Ademaacutes deben llevar dos meacutetodos puacuteblicos asociados s e t V a r i a b l e () para dar un nuevo valor a la variable y g e t V a r i a b l e () para recibir el valor actual de la propiedad Veamos el ejemplo

class pagina_Web

private $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

public function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

172 Capiacutetulo 9

public function getTitulo()

return $this-gttitulo

Interfaces

En proyectos profesionales a veces es necesario que un equipo de varias personas trabajen juntas En este caso se hace imprescindible definir unas pautas generales de trabajo para que el resultado final sea el esperado Si el desarrollo consiste en programar varios objetos el analista de la aplicashycioacuten puede definir la estructura baacutesica en papel o crear una pequentildea planshytilla con meacutetodos que el objeto final deberiacutea tener obligatoriamente Esta plantilla es un i n t e r f a c e y permite definir una clase con funciones deshyfinidas pero sin desarrollar que obliga a todas las clases que lo imple-menten a declarar estos meacutetodos como miacutenimo

i n t e r f a c e Web

public function setTitulo($titulo = Titulo por defecto)

public function getTitulo()

La interface anterior define la estructura baacutesica que queremos para el obshyjeto declarando las funciones setTitulo y getTitulo Para que una clase haga uso de la i n t e r f a c e se declara de la siguiente forma

class pagina_Web implements Web

Clases abstractas

Un i n t e r f a c e no permite crear el cuerpo de ninguna funcioacuten dejando esta tarea a las clases que la implementen Las clases abstractas permiten definir funciones que deben implementarse obligatoriamente en los objetos que hereden y ademaacutes permiten definir funciones completas que pueden heredarse Las clases abstractas deben llevar la palabra rese rvadaabs t rac t en la declaracioacuten de la clase y en todos los meacutetodos que soacutelo definan su nombre

abstract class Web

protected $titulo

Programacioacuten orientada a objetos 173

public function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

a b s t r a c t pub l i c funct ion g e t T i t u l o ( )

En lugar de un i n t e r f a c e hemos optado por utilizar una clase abstracshyta porque tenemos claro que el meacutetodo s e t T i t u l o () tiene que funcioshynar asiacute Tambieacuten se define el meacutetodo abstracto g e t T i t u l o () que obligatoriamente debe ser declarado en la clase que herede de eacutesta En realidad un i n t e r f a c e es una clase que tiene todos sus meacutetodos absshytractos

Clases con meacutetodos estaacuteticos

En PHP 5 puede declarar funciones dentro de una clase que no utilicen propiedades o meacutetodos de la misma Estos meacutetodos pueden calcular valoshyres numeacutericos hacer una conexioacuten a una base de datos o comprobar que un correo electroacutenico esteacute bien definido Aunque no existe ninguna palashybra reservada para definirlo son conocidos como meacutetodos estaacuteticos y pueshyden ser utilizados sin necesidad de instanciar un objeto

ltphp class Nombre

protected $nombre public function getNombre(

return $this-gtnombre

public function setNombre($nombre)

$this-gtnombre = $nombre

public function NombreDefecto()

return Luis Miguelltbrgt

$luis = new Nombre echo $luis-gtNombreDefecto() Tambieacuten se puede acceder al nombre por defecto echo NombreNombreDefecto() gt

174 Capiacutetulo 9

Para acceder a un meacutetodo estaacutetico desde el cuerpo del programa se escrishybe el nombre de la clase que lo implementa seguido del operador ( ) y el nombre del meacutetodo En el ejemplo vemos que se puede acceder al meacutetoshydo NombreDef e c t o () creando un objeto o mediante la construccioacuten Nombre NombreDef e c t o Si intenta llamar a un meacutetodo que no es estaacutetico de esta forma se imprimiraacute un error en pantalla La figura 94 muestra el error que recibe si intenta llamar a un meacutetodo no estaacutetico desshyde fuera de un objeto

Llamadas a funciones padre

El operador ( ) se puede utilizar tambieacuten dentro de una clase para hacer llamadas a funciones de la clase padre que esteacuten sobrecargadas Si define un constructor para la clase padre y otro para la clase hijo cuando cree el objeto el constructor que se ejecuta es el de nivel infeshyrior el constructor hijo Para llamar al constructor padre debe utilizarshyse la nomenclatura N o m b r e _ c l a s e _ p a d r e c o n s t r u c t ()

ltphp class Nombre

protected $nombre

Programacioacuten orientada a objetos 175

f unet ion construct ( $nombre)

$this-gtnombre = $nombre

publie function getNombre() return $this-gtnombre

publie function setNombre($nombre) $this-gtnombre = $nombre

publie function NombreDefecto() return Luis Miguelltbrgt

class Apellido extends Nombre

protected $apellidos function construct($nombre$apellidos)

$this-gtapellidos = $apellidos Nombre construct(Snombre)

publie function getApellidos () return $this-gtapellidos

$luis = new Apellido(Luis MiguelCabezas Granado) echo $luis-gtgetNombre() ltbrgt echo $luis-gtgetApellidos() gt

Puede ver que el constructor de la clase Ape l l ido inicializa la variable $ape-11 idos y seguidamente llama al constructor de la clase padre Nombre Esta forma de actuar puede resultar complicada si no conoce el nombre de la clase padre La solucioacuten a este pequentildeo inconveniente la tenemos en la palabra parent que hace alusioacuten a la clase de la que heredamos El coacutedigo anterior puede quedar de esta forma

class Apellido extends Nombre

protected $apellidos function construct($nombre$apellidos)

$this-gtapellidos = $apellidos

176 Capiacutetulo 9

p a r e n t cons t ruc t ($nombre) public function getApellidos()

return $this-gtapellidos

Sobrecarga de meacutetodos

Algunos lenguajes de programacioacuten orientados a objetos permiten declashyrar maacutes de un meacutetodo con el mismo nombre La definicioacuten de estos meacutetoshydos variacutea en el nuacutemero de paraacutemetros o en los tipos de datos de los argumentos PHP 5 no permite sobrecarga de meacutetodos pero puede simushylar esta actuacioacuten empleando la teacutecnica de las funciones con un nuacutemero variable de paraacutemetros El constructor de la clase A p e l l i d o puede queshydar de la siguiente forma

class Apellido extends Nombre

protected $apellidos function construct($nombre)

if (func_num_args()= = 2 ) $apellidos = func_get_arg(1) $this-gtnombre = $nombre $this-gtapellidos = $apellidos parent construct($nombre)

else $this-gtnombre = $nombre $this-gtapellidos = $apellidos parent construct($nombre)

public function getApellidos()

return $this-gtapellidos

Sentildealizacioacuten

Los objetos son en realidad un conjunto de datos y funciones que guarshydan una serie de estados de ejecucioacuten Este conjunto de bits se pueden al-

Programacioacuten orientada a objetos 177

macenar en un momento dado y recuperar justo en el mismo estado en el que se encontraba cuando lo guardamos Esta teacutecnica se llama sentildealizashycioacuten y permite almacenar y recuperar el conjunto de bits que forman un objeto

PHP 5 ofrece dos funciones s e r i a l i ze () y u n s e r i a l i z e ( ) que toshyman como paraacutemetro un objeto y devuelven una cadena de caracteres Los objetos serializados los podemos almacenar en base de datos ficheros etshyceacutetera

$luis = new Apellido(Luis Miguel) echo $luis-gtgetNombre() ltbrgt echo $luis- gtgetApellidos () -$manuel = serialize($luis) $pedro = unserialize($manuel) echo $pedro-gtgetNombre ()

El coacutedigo anterior crea el objeto $ l u i s y utiliza los meacutetodos propios de la clase y los heredados Despueacutes utilizamos la funcioacuten s e r i a l i z e () para grabar el estado del objeto como un conjunto de caracteres en la variable $manuel La variable $pedro contiene el resultado de aplicar u n s e r i a shyl i z e () a $manuel

De esta forma conseguimos recuperar el objeto $ l u i s con los datos que ya habiacuteamos almacenado

Funciones de manejo de clases

Las funciones siguientes son uacutetiles para recuperar informacioacuten sobre la herencia de las clases sobre meacutetodos o variables miembro o llamadas a las funciones

Tabla 91 Funciones de clases

Funcioacuten Descricioacuten

ge t c l a s s () Devuelve el nombre de la clase que iexclmplementa el objeto pasado como paraacutemetro

g e t _ p a r e n t _ c l a s s 0 Devuelve el nombre de la clase padre

c l a s s _ e x iacute s t ( ) Si el paraacutemetro es el nombre de una clase devuelve un true

g e t _ d e c l a r e d _ c l a s s () Devuelve un array con el nombre de todas las clases definidas en el coacutedigo actual

178 Capiacutetulo 9

Funcioacuten Descricioacuten

i s _ s u b c l a s s _ o f () Toma dos paraacutemetros Si el primer paraacutemetro es una subclase del segundo paraacutemetro la funcioacuten devuelve un true

i s _ a ( ) g e t _ c l a s s _ v a r s ( ) Devuelve un array con parejas variable valor de una clase que tengan valores por

defecto

g e t _ o b j e c t _ v a r s () Devuelve un array con parejas variable valor de un objeto que tengan valores por defecto

method_ex is ts () Toma dos paraacutemetros Si el objeto pasado tiene un meacutetodo con el nombre del segundo paraacutemetro la funcioacuten devuelve true

ge t_c lass_method () Devuelve un array de meacutetodos definidos en una clase

Puede ver el funcionamiento de la funcioacuten g e t _ c l a s s () en el ejemplo siguiente y el resultado en la figura 95

$luis = new Nombre echo $luis-gtNombreDefecto() echo La variable $luis es un objeto del tipo get_class($luis)

Programacioacuten orientada a objetos 179

Resumen

Existe en el mundo de los desabolladores de PHP una antigua disputa sobre la mejor forma de afrontar un proyecto Web Unos opinan que la forma maacutes raacutepida de crear una Web es realizar funciones separadas en ficheros y desde las paacuteginas del proyecto hacer las llamadas necesarias

La otra vertiente opina que merece la pena dedicar un poco maacutes de tiemshypo al desarrollo de objetos porque despueacutes redundaraacute en un gran benefishycio en futuros programas En realidad depende del proyecto Si soacutelo necesita crear un formulario para recibir datos de un usuario quizaacute no merezca la pena crear un objeto y siacute algunas funciones de control Si su proyecto va a ser muy extenso la recomendacioacuten es que prepare un comshypendio de objetos que se interrelacionen para llevar a buen teacutermino el programa

Puesto que el libro versa sobre PHP 5 y sus mejoras con respecto a las vershysiones anteriores intentaremos en los capiacutetulos siguientes realizar la mashyyoriacutea de los ejemplos en metodologiacutea orientada a objetos

En este capiacutetulo aprenderaacute a

bull Abrir y cerrar ficheros de lectura y escritura

bull Utilizar funciones para leer el contenido de un fichero

bull Realizar programas para la escritura de informacioacuten en un fichero

bull Gestionar los ficheros y directorios de un sistema operativo

bull Crear ficheros de configuracioacuten

bull Generar cabeceras para la descarga de archivos

182 Capiacutetulo 10

Introduccioacuten

Antes de que la proliferacioacuten de los gestores de bases de datos se hiciera efectiva los lenguajes de programacioacuten utilizaban el acceso a ficheros para almacenar sus datos Asiacute los lenguajes COBOL Pascal o incluso C comenshyzaron a utilizar el manejo de archivos en aquellos programas que necesishytaban guardar datos para recuperarlos posteriormente

Actualmente la informacioacuten puede almacenarse en ficheros o en bases de datos Los ficheros pueden almacenar textos que pueden ser leiacutedos faacutecilshymente por nosotros y por un ordenador Ademaacutes existe una serie de utishyl idades que permiten al sistema operat ivo (gnuLinux o MacOSX) interactuar con ellos hacer buacutesquedas etceacutetera

Nota

El sistema operativo Windows tiene algunas restricciones con resshypecto al manejo de ficheros y no se recomienda para gestionar los archivos

Funciones de lectura y escritura de ficheros

Existen en PHP 5 un conjunto muy numeroso de funciones que permishyten manejar ficheros de diferentes formas La idea baacutesica para trabajar con ficheros es la siguiente

bull Abrir el fichero para su lectura escritura

bull Leer el fichero

bull Cerrar el fichero (puede hacerse maacutes tarde)

bull Realizar las operaciones necesarias en el contenido

bull Escribir los datos

Abrir el fichero

La funcioacuten f open () asigna a una variable un puntero (un descriptor) al fichero que quiera abrir La variable puede utilizarse despueacutes para hacer cualquier tipo de operacioacuten Si el fichero que intenta abrir no existe o no puede utilizarse en ese momento f open () devolveraacute un valor false

Ficheros y almacenamiento de datos 183

Los ficheros pueden abrirse en varios modos tal y como indica la tabla 101

Tabla 101 Modos de apertura de los ficheros

Modo Explicacioacuten

Soacutelo lectura (r) Soacutelo permite leer el fichero Si intenta hacer otra cosa le saldraacute un error

Lectura y escritura si existe el Permite leer y escribir un fichero que exis-fichero (r+) ta El contenido del fichero no se borra

sino que se escribe a continuacioacuten Soacutelo escritura (w) Soacutelo se puede escribir Sobrescribe cualshy

quier fichero afectado Escritura y lectura (w+) Si el fichero no existe intenta crearlo Escritura al final (a) Escribe siempre al final del fichero tanto si

existe como si no Lectura y escritura al final (a+) Escribe al final del fichero y permite leer

Desde la versioacuten 4 de PHP puede abrir ficheros remotos que esteacuten almashycenados en servidores Asiacute podraacute utilizar el protocolo HTTP o FTP para recuperar datos remotamente Puede ver como ejemplo varias formas de abrir un fichero con f open ()

ltphp Los ficheros HTTP solo pueden abrirse de lectura $descriptor = fopen(httpwwwluisyfernandanet noticiastxtr) FTP permite abrir ficheros de lectura y escritura $descriptor2 = fopen(ftp usuariocontrasentildealuisyfernandanetnoticiastxtr) Apertura normal de un fichero guardado en el ordenador local $descriptor3 = fopen(noticiastxt a+) gt

Lectura de ficheros

f r e a d () tiene como paraacutemetro un descriptor de fichero devuelto por la funcioacuten f o p e n () y el tamantildeo del bloque de datos que queremos leer

$variable = fread($descriptor 4000)

Normalmente no conoceraacute el tamantildeo del fichero y por lo tanto debe utishylizar alguna teacutecnica para leerlo correctamente Lo maacutes sencillo es apoyar-

184 Capiacutetulo 10

se en la funcioacuten f i l e s i z e () que devuelve el tamantildeo en bytes del fichero que pase como argumento Asiacute la lectura anterior quedariacutea

$variable = fread($descriptor filesize(noticiastxt))

Advertencia

Tiene que notar que el lector f i l e s i z e () no toma como paraacuteshymetro el descriptor devuelto por la funcioacuten f o p e n O sino el nombre del fichero que estamos tratando

La funcioacuten anterior devuelve un bloque completo de caracteres leiacutedos desde un fichero y puede hacerse poco manejable cuando intente buscar alguacuten dato especiacutefico PHP 5 posee algunas funciones para leer liacutenea a liacuteshynea desde un fichero f r e a d () tiene como paraacutemetros el descriptor del fichero y un bloque maacuteximo de caracteres a leer La utilizacioacuten praacutectica es la siguiente

ltphp $descriptor = fopen (librotxta +) $linea_numero = 1 while (feof($descriptor))

$linea = fgets ($descriptor4096) echo liacutenea nuacutemero $numero_linea es $linea $linea_numero++

f c l o s e ($desc r ip to r ) gt

El bucle actuacutea hasta que la funcioacuten f e o f () encuentra el final del fichero apuntado por el descriptor Mientras que no sea el fin del fichero la funshycioacuten f g e t s () iraacute leyendo liacutenea a liacutenea todo el contenido e imprimieacutendoshylo en pantalla

La forma ideal de trabajar con ficheros es ir leyendo poco a poco su conshytenido para poder buscar datos que nos interesen en cada liacutenea o conshyjunto de caracteres Existe una funcioacuten que nos permite almacenar todo el contenido de un fichero en un array para su posterior proceso con las funciones propias de las colecciones de datos La funcioacuten e x p l o d e () toma como paraacutemetros un caraacutecter por donde cortar la cadena y el nomshybre de la variable que contiene los datos Podemos ver su funcionamienshyto en el ejemplo

ltphp $descriptor = fopen (librotxta+) $linea__numero = 1

Ficheros y almacenamiento de datos 185

$archivo = while ( feof($descriptor) )

$linea = fgets($descriptor4096) $archivo = $archivo liacutenea nuacutemero $numero__linea es

$linea $1inea_numero++

fclose($descriptor) $lista = explode( $archivo) gt

En este caso e x p l o d e () busca en la variable $ a r c h i v o todos los espashycios en blanco y va almacenando en el array caracteres que esteacuten entre dos ocurrencias (entre dos espacios) Asiacute obtenemos una gran lista de palashybras almacenadas por separado que hacen muy faacutecil buscar ordenar o borrar cualquier contenido

Por uacuteltimo la funcioacuten f ge te () permite leer un fichero caraacutecter a caraacutecshyter Esto es muy uacutetil cuando construimos un parse (un programa que inshyterpreta el contenido de un fichero) y debemos ir evaluando las palabras letra por letra para actuar en consecuencia

Escritura de ficheros

Las funciones para escribir ficheros son tan sencillas de utilizar como las de lectura La funcioacuten principal f w r i t e () escribe en un fichero apuntashydo por un descriptor una cadena de caracteres Es imprescindible que el fichero esteacute abierto en uno de los modos de escritura para que no deacute error

Veamos ahora un ejemplo completo El coacutedigo siguiente es un pequentildeo libro de visitas donde todo aquel que navegue por nuestra Web puede dejar mensajes de agradecimiento y aacutenimo Aunque no es el mejor libro de visitas escrito nunca siacute es un buen ejemplo de coacutemo utilizar la lectura v escritura de archivos dentro de un entorno orientado a objetos

ltphp class libro_visitas

priacutevate $tamano priacutevate $nombre priacutevate $descriptor priacutevate $contenido function construct($nombre)

$this-gtnombre = $nombre

i

186 Capiacutetulo 10

public function leer_libro)

$this-gtdescriptor = fopen ($this-gtnombrea+) $this-gttamano=filesize($this-gtnombre) if ($this-gttamano gt 0)

$this-gtcontenido = fread($this-gtdescriptor $this-gttamano)

fclose ($this-gtdescriptor) return $this-gtcontenido

pub l i c funct ion esc r ib i r__ l ib ro ($riombre $texto)

$ t h i s - gt d e s c r i p t o r = fopen ($this-gtnombrea+) $nombre = lt t r x t d bgcolor=CCCCCCgt$nombrelttdgtlttrgt $texto = lt t r x t d bgcolor=FFFFFFgt$textolt tdx t rgt f w r i t e ( $ t h i s - gt d e s c r i p t o r $ n o m b r e ) f w r i t e ( $ t h i s - gt d e s c r i p t o r $ t e x t o ) f c l o s e ($ th i s -gtdesc r ip to r )

gt ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtralgt ltheadgt lttitlegtLibro de visitaslttitlegt ltmeta http-eguiv=Content-Type content=texthtml charset=iso-8859-lgt ltheadgt ltbodygt ltp align=centerxstronggtLibro de visitas ltstrongxpgt lttable width=100 border=0 cellspacing=0 cellpadding=0gt

ltphp if (isset ($_POST[nombre ] ) |] isset($_POST[texto]))

$libro = new libro_visitas(librotxt) $librogtescribir_libro($_POST[nombre]$_POST[texto])

$libro_ver = new libro__visitas(librotxt) echo $libro_ver-gtleer_libro() gt lttablegt ltform action=librophp raethod=POST gt Nombre ltinput name=nombre tYpe=text id=nombregt

ltpgt ltpgtTexto

Ficheros y almacenamiento de datos 187

lttextarea name=texto id= tex togtlt tex ta reagt ltpgt ltpgt

ltinput type=submit name=Submit value=Enviar gt ltpgt ltformgt ltbodygt lthtmlgt

La figura 101 muestra el resultado del libro de visitas Como puede ver el coacutedigo tiene dos partes diferenciadas La primera es la definicioacuten de una clase con tres meacutetodos que es la encargada de almacenar y recuperar los datos La segunda parte es el coacutedigo HTML que nos permite visualizar los comentarios de las personas que nos visitan Lo maacutes recomendable es seshyparar ambas partes en dos ficheros distintos y hacer uso de la funcioacuten r e q u i r e _ o n c e () para utilizar el coacutedigo PHP

Si se fija en el coacutedigo HTML hay una parte central escrita en PHP que comprueba si existen datos pasados mediante el meacutetodo POST es decir si existen datos para escribir en el fichero Si es asiacute creamos el objeto $1 lishyb r o y llamamos al m eacute t o d o e s c r i b i r _ l i b r o ( ) que se encarga de guarshydar los datos correctamente Si no hay datos que guardar simplemente se crea un objeto y se lee el archivo donde estaacuten los comentarios

188 Capiacutetulo 10

La clase l i b r o _ v i s i t a s escribe en el fichero filas de una tabla que desshypueacutes se interpretan en el HTML colocando todo correctamente

Sistema de ficheros y directorios

Existe un conjunto de funciones que permiten manejar ficheros y directoshyrios del sistema Estas funciones son muy parecidas a comandos de Unix gnuLinux y seguramente le resulten familiar al lector

Copiar borrar y renombrar

Las operaciones baacutesicas de manejo de ficheros y que se aprenden cuando comenzamos a utilizar un sistema operativo concreto son las de copia borrado y modificacioacuten

Para copiar un fichero se utiliza la funcioacuten copy ( ) que toma como paraacuteshymetros el fichero que quiere copiar y el destino donde quiere guardar la copia

Puede antildeadir un meacutetodo nuevo a la clase l i b r o _ v i s i t a s para que reashylice funciones de copia de seguridad

public function copia_seguridad()

c o p y ( $ t h i s - gt n o m b r e c o p i a t x t )

La siguiente funcioacuten u n l i n k ( ) toma como paraacutemetro el nombre de un fichero y lo borra Puede hacer uso de esta funcioacuten para ampliar su clase y permitir que se puedan borrar los ficheros que almacenan los libros de visitas

public function borrar_libro()

unlink($this-gtnombre)

Como el meacutetodo c o p i a _ s e g u r i d a d () soacutelo permite almacenar un fichero puede ampliar su gama de meacutetodos y antildeadir uno que le deacute la posibilidad de renombrar el fichero c o p i a t x t a otro nombre

public function renombrar_copia($nuevo_nombre)

rename ($this- gtnombre $nuevo__nombre)

Ficheros y almacenamiento de datos 189

Funciones de comprobacioacuten

Es necesario antes de borrar copiar o renombrar un fichero hacer una comprobacioacuten miacutenima para saber si el fichero existe

De esta forma evitaraacute errores innecesarios y tendraacute maacutes control en el flujo de su programa

La funcioacuten f i l e _ e x i s t s () comprueba si un fichero existe dando el valor tnte en caso afirmativo yfalse en caso contrario

El meacutetodo b o r r a r _ l i b r o () puede quedar de la siguiente forma

public function borrar_libro()

if (file_exists($this-gtnombre))

unlink($this-gtnombre)

En los sistemas operativos UNIX gnuLinux todos los recursos hardware se corresponden con un fichero Puede que alguna vez necesite saber el tipo de fichero con el que va a tratar (fichero directorio recurso) La funshycioacuten f i l e t y p e () devuelve un valor que indica el tipo de fichero que coshyrresponde al valor pasado como paraacutemetro

Tabla 102 Tipos de ficheros

Valor Descripcioacuten

fifo Es de tipo FIFO

char Dispositivo de caraacutecter

dir Directorio

block Dispositivo especial de bloques

link Enlace

file Fichero

unknown Tipo desconocido

Ademaacutes de la funcioacuten anterior existe un conjunto de funciones que preshyguntan directamente al archivo por su tipo y el resultado es true ofalse en funcioacuten de la veracidad de la pregunta Las funciones i s _ d i r ( ) i s__execu tab le () i s _ f i l e () y i s _ l i n k ( ) preguntan a su argumento si es del tipo directorio ejecutable fichero o enlace respectivamente

190 Capiacutetulo 10

Directorios

Es muy uacutetil disponer de un gestor de ficheros Web que nos permita naveshygar entre los archivos y directorios Para hacer esto en PHP existen dos meacutetodos El primero utiliza las funciones o p e n d i r ( ) r e a d d i r () y c l o -s e d i r ( ) muy parecidas en su funcionamiento a f open () f r e a d () y f c i oacute s e ( ) Lo mejor es ver coacutemo trabajan juntas con un ejemplo

ltphp $directorio = $descriptor = opendir($directorio) while ($entrada = readdir($descriptor) )

if (is_dir($directorio$entrada) ) echo [Directorio] $entrada ltbrgtbull

elseif ( is__f ile ($directorio $entrada) ) echo [Fichero] $entrada ltbrgt

closedir($descr iptor) gt

Como puede intuir no existe ninguna diferencia significativa entre abrir un fichero o abrir un directorio Lo primero es crear un puntero hacia el directorio que quiera observar y guardarlo en $ d e s c r i p t o r El bucle va leyendo entrada por entrada con la funcioacuten r e a d d i r () y dependiendo

Ficheros y almacenamiento de datos 191

del resultado de las funciones i s _ d i r () o i s _ f i l e () se imprimiraacute el directorio o el fichero pertinente

Existe una segunda forma de visualizar lo mismo pero utilizando proshygramacioacuten orientada a objetos PHP 5 provee un objeto que implementa toda la loacutegica vista anteriormente La funcioacuten d i r () devuelve un objeto que permite examinar el directorio pasado como paraacutemetro El objeto poshysee un meacutetodo llamado r e a d () que va leyendo todas las entradas y un meacutetodo c i oacute s e ( ) que cierra el objeto El ejemplo anterior puede verse asiacute

ltphp $directorio = $fichero = dir(directorio) while ($entrada = $fichero-gtread())

if (is_dir(directorioentrada)) echo [Directorio] $entrada ltbrgt

elseif (is_file($directorio$entrada)) echo [Fichero] $entrada ltbrgt

$ f i c h e r o - gt c l o s e ( ) gt

Ficheros de configuracioacuten

Cuando sea un excelente programador en PHP 5 necesitaraacute conocer teacutecshynicas para almacenar datos de configuracioacuten en un fichero Una teacutecnica habitual es crear un fichero con variables de PHP que toman los valores adecuados y en el transcurso del programa utilizar una llamada a la funshycioacuten r e q u i r e j o n e e () para poder utilizarlas De esta forma podriacuteamos utilizar el siguiente ejemplo como configuracioacuten para conectar a una base de datos

ltphp servidor = localhost usuario = luis $password = secreta $base_datos = anaya gt

Otra alternativa es utilizar un tipo de fichero de configuracioacuten que utiliza la misma estructura que el fichero php i n i La estructura es la siguiente

Los comentarios van despueacutes de un punto y coma

192 Capiacutetulo 10

[Base__datos] servidor=localhost usuario=luis password=secreta base_datos=anaya Creamos un nuevo apartado [Preferencias] color=rojo tamanio=medio fuente=verdana

Este archivo almacena las variables que necesite en el transcurso del proshygrama

Para leerlo existe una sentencia especial que almacena el resultado en un array Para acceder a cada uno de los campos hay que utilizar la notacioacuten de un array de dos dimensiones como muestra el ejemplo La figura 103 muestra el resultado de leer un archivo de configuracioacuten

ltphp $configuracion = parse_ini_file(configuracioacuteniniTRUE) Ejemplos de variables echo $configuracion[Base__datos] [servidor] echo $configuracion[Preferencias] [fuente] gt

Ficheros y almacenamiento de datos 193

Manejo de ficheros en el servidor

Conociendo todas las posibilidades que ofrece PHP 5 a la hora de controshylar archivos llega la hora de aplicar a la praacutectica casos reales de funcionashymiento Los dos usos maacutes comunes de manejo de ficheros en la Web tienen que ver con la subida de los mismos a un servidor o con la descarga desshyde una paacutegina Web

Subida de ficheros

Cuando utilice un formulario Web puede introducir los datos solicitados a traveacutes de cajas de texto listas desplegables o botones de seleccioacuten Adeshymaacutes existe una etiqueta HTML que permite elegir un fichero de nuestro ordenador local y subirlo al servidor Puede crear un formulario miacutenimo que contenga la etiqueta en el siguiente ejemplo

ltHTMLgt ltBODYgt ltform action=subirphp method=POST enctype=multipartform-datagt Introduce el fichero ltinput type=file name=fichero gtltbrgt ltinput type=hidden ntildeameTAMANIO valueacute = 1000gt ltinput type=subraitgt ltformgt ltBODYgt ltHTMLgt

Como puede ver el atributo e n c t y p e debe tener el valor m u l t i p a r t = f o r m - d a t a para que el formulario trabaje correctamente Ademaacutes heshymos antildeadido una etiqueta llamada TAMANIO que guarda el valor maacutexishymo en bytes que nuestro script va a permitir subir Esto debe controlarse en la Web que reciba los datos mediante PHP Puede ver el aspecto graacutefishyco en la figura 104

Cuando el formulario se enviacutea PHP detecta automaacuteticamente que hemos enviado un fichero y lo almacena en un directorio temporal del servidor La Web que recibe los datos introduce dentro de la variable suacuteper-global 3_FILES [ nombre_f i c h e r o ] un conjunto de propiedades tales como el nombre del fichero subido el nombre temporal del recurso el tamantildeo o si ha tenido alguacuten error la subida Vamos a ampliar el formulario con coacuteshydigo para el manejo de ficheros

ltHTMLgt ltBODYgt ltform action=subirphp method=POST enctype=multipartform-datagt

194 Capiacutetulo 10

Introduce el fichero ltinput type=file name=ficherogtltbrgt ltinput type=submit gt ltformgt ltPHP

$fichero = $_FILES[fichero] foreach ($_FILES[fichero] as $indice =gt $valor)

echo $indice $valorltbrgt if ($_POST[TAMANIO]lt$_FILES[fichero] [size])

echo ltbrgtEl fichero tiene un tamantildeo adecuado copy ($_FILES[fichero] [tmp_name]archivotxt)

else echo ltbrgtEl fichero es demasiado grande

gt

ltBODYgt ltHTMLgt

i n L )T^ M ^ ir 7~n l a

L- I r

1 1 1 4 t r 1 c c - 1 r

f - 1 tlf 1 4 4

1 l 1 1 4 4 1

directorios ocultos Cenes ar

Terminado

f f t Eacute f l U B M I - B [luis] v Moziacutella Firefc V E l GIMP bull $ ^ C 7

Figura 104 Formulario de entrada de ficheros

El resultado muestra un formulario donde debe introducir un fichero que puede ver en la figura 105

Cuando activa el botoacuten de subida la paacutegina vuelve a cargar pero esta vez muestra informacioacuten sobre el fichero y si el tamantildeo es adecuado o no para su almacenamiento Nos hemos apoyado en la construccioacuten foreach para averiguar las proshypiedades del fichero subido

Ficheros y almacenamiento de datos 195

Si el tamantildeo en bytes que tenemos puesto como liacutemite en el formulario es menor que el tamantildeo del archivo se utiliza la funcioacuten c o p y () para coshypiar el fichero y guardarlo en el servidor

Descarga de ficheros

Normalmente dejamos al lenguaje HTML el trabajo de enlazar los archishyvos que deseamos que los usuarios de nuestra Web puedan descargar Esto se puede hacer simplemente con un enlace del tipo

lthtmlgt ltBODYgt lta href=ejemplozipgtPincha aquiacute para descargarltagt ltBODYgt ltHTMLgt

Cuando hacemos clic en el enlace normalmente el navegador averigua el tipo de fichero que vamos a descargar (ZIP PDF imagen) y nos muestra una pequentildea ventana con informacioacuten sobre el fichero

Imagine ahora que los ficheros que queremos poner en descarga se geneshyran en ese mismo instante como los archivos PDF Tenemos que seguir una pauta distinta para permitir la descarga desde el sitio Web utilizanshydo cabeceras HTTP La figura 106 muestra la ventana del navegador que recibe la cabecera MIME

196 Capiacutetulo 10

ltphp $fichero = ejemplozip $mimeType = appliacutecationzip Si el navegador es Explorer u Opera cambiamos el tipo de cabecera if (strpos($_SERVER[HTTP_USER_AGENT]MSIE 5) |[

strpos($_SERVER[HTTP_USER_AGENT]Opera 7)) $mimeType = applicationx-download

Se genera la cabecera header(content-disposition attachment f ilename = ej emplo__personal zip) header(content-type $mimeType) header(content-length filesize($fichero)) Se enviacutea el archivo al navegador readfile($fichero) gt

Los tipo MIME identifican el tipo de fichero y lo asocian a una aplicacioacuten determinada en un sistema operativo determinado Si utiliza el tipo MIME de PDF en un sistema Windows la aplicacioacuten asociada puede ser Acrobat Reader de Adobe Casi todos los archivos llevan asociado un tipo MIME y sirve entre otras cosas para que el navegador reconozca el tipo de archishyvo que estaacute descargando y optar por mostrarlo directamente en pantalla o guardarlo en alguna ubicacioacuten del disco duro Si comprueba antes el nomshybre del navegador que ha solicitado la descarga puede cambiar el tipo para que sea compatible con distintas versiones Las cabeceras HTTP deshyben generarse con la funcioacuten h e a d e r () y debe ser lo primero que se enshyviacutea al navegador Si enviacutea alguacuten dato o etiqueta antes que la cabecera obtendraacute un error

Ficheros y almacenamiento de datos 197

La cabecera que utilizamos en este caso es la de enviacuteo de un fichero del tipo MIME indicado y tamantildeo calculado con la funcioacuten f i l e s i z e ( ) No es necesario que el archivo que vaya a enviar tenga el mismo nombre en la descripcioacuten de la cabecera que en el servidor

Finalmente la funcioacuten r e a d f i l e () lee el fichero completamente y lo enviacutea al navegador

Resumen

Situados ya en el ecuador del libro podemos asegurar que estaacute preparado para enfrentarse a programas serios Los conceptos baacutesicos los aprendioacute en los capiacutetulos 1 2 3 4 5 6 y 7 El capiacutetulo 8 le mostroacute la forma de utilishyzar las variables entre varias paacuteginas Web y el 9 la verdadera potencia de uso de PHP 5

Este capiacutetulo le ha mostrado la forma de guardar datos para que permashynezcan almacenados indefinidamente y meacutetodos para abrir cerrar copiar o borrar los ficheros que utilice Aunque no es el mejor meacutetodo para guarshydar los datos muchas aplicaciones existentes se sirven de las funciones de archivos en vez de la utilizacioacuten de bases de datos

Los dos capiacutetulos siguientes le guiaraacuten por el apasionante mundo de los gestores de bases de datos La potencia de estos gestores le permitiraacute errashydicar de sus scripts la gestioacuten de datos mediante ficheros A partir de enshytonces la gestioacuten de archivos quedaraacute relegada al manejo de ficheros graacuteficos copias o gestioacuten de la configuracioacuten

En este capiacutetulo aprenderaacute a

bull Crear sus propias bases de datos con el lenguaje SQL bull Realizar consultas con SQL para insertar modificar o borrar registros

bull Conocer las funciones baacutesicas de SQLite

bull Recuperar los datos de una tabla y el nuacutemero de registros bull Moverse entre los registros de una base de datos

200 Capiacutetulo 11

Introduccioacuten

Este capiacutetulo pretende ser una introduccioacuten al lenguaje estructurado de consulta (SQL) que es primordial conocer a la hora de utilizar alguna base de datos relacional Puesto que no es un libro dedicado a SQL soacutelo vereshymos las estructuras baacutesicas del lenguaje para poder realizar nuestros ejemshyplos por eso recomiendo leer alguacuten libro deciicado a consultas SQL para sacar el maacuteximo partido a las bases de datos

Tambieacuten conoceremos la nueva implementacioacuten de PHP 5 para bases de datos SQLite Lejos de ser un gestor de bases de datos es sencillamente una libreriacutea que nos permite tratar un fichero de iexcla misma forma que utishylizamos una base de datos SQLite viene instalado en los binarios de PHP 5 y no utiliza ninguacuten puerto de conexioacuten externo tan soacutelo funciona cuanshydo se hace una llamada a las funciones de SQLite

SQL

La estructura baacutesica de una base de datos SQL es muy sencilla Los datos de una base de datos se almacenan en tablas donde cada fila identifica uniacutevocamente a un elemento distinto Por ejemplo la tabla de usuarios tendraacute tantas filas como usuarios tenga la paacutegina Web Cada tabla puede definir varias columnas Las columnas hacen referencia a las propiedades de cada fila Por ejemplo la tabla de usuarios podriacutea tener como columshynas el coacutedigo de usuario el nombre los apellidos y la direccioacuten postal

Nota

Hoy en diacutea tedas las aplicaciones profesionales escritas en PHP se basan en la interaccioacuten entre el coacutedigo y los datos almacenados en alguna base de datos Recomiendo al lector que no escatime esfuerzos en aprender el lenguaje SQL pues le seraacute muy uacutetil para realizar despueacutes aplicaciones basadas en cualquier base de datos MySQL SQLite SQL Server o incluso Oracle

El lenguaje SQL nos permite elegir varias filas atendiendo a un criterio insertar nuevas filas actualizar los datos o borrarlas con las sentencias SELECT INSERT UPDATE y DELETE respectivamente Este lenguaje per-

Bases de datos con SQL y SQLite 201

mite soacutelo manipular los datos contenidos en las tablas Si quiere modificar la estructura tiene que apoyarse en el lenguaje de definicioacuten de datos que le permite crear nuevas tablas o bases de datos insertar nuevas propiedashydes en forma de columnas o borrar tablas con las sentencias CREacuteATE ALTER v DROP respectivamente Para seguir los ejemplos vamos a basarshynos en una pequentildea base de datos con tres tablas

Tabla 1 1 1 Usuario

id_usuario nombre cuenta

1 Luis Miguel 7011

2 Mariacutea Fernanda 3454

3 Pedro 3445

4 Javier 1123

La tabla de U s u a r i o s tiene 4 filas Cada una de ellas es diferente a las demaacutes y el paraacutemetro que las identifica uniacutevocamente es i d _ u s u a r i o En Espantildea todas las personas tienen un coacutedigo numeacuterico el DNI que las identifica y las hace distintas frente a otras personas que tengan el mismo nombre y apellidos En las tablas ocurre lo mismo Necesitamos un coacutedigo numeacuterico que nos identifique personas distintas Las dos propiedades sishyguientes son el nombre y la c u e n t a del banco para hacer los pagos

Tabla 112 Producto

id_producto nombre precio

1 ratoacuten 6

2 portaacutetil 1000

3 libro PHP5 20

La tabla de P r o d u c t o s es muy similar a la de U s u a r i o s e identifica toshydos los productos que se pueden encontrar en nuestra Web de venta

Tabla 113 Carrito

id_compra id_usuario Jd_producto

1 1 1

202 Capiacutetulo 11

idcompra iexcldusuario id_producto

2 1 2

3 2 1

4 3 3

La tabla C a r r i t o de la compra mantiene un listado que relaciona los usuashyrios con los productos que han comprado Si se fija en la primera fila el i d_compra es el nuacutemero de factura que debe ser distinto siempre en el antildeo actual el i d _ u s u a r i o es 1 lo que quiere decir que el usuario 1 Luis Miguel ha comprado el producto 1 un ratoacuten de PC Si ha entendido esto ya podemos empezar a ver las sentencias SQL para manejar los datos

SELECT

Este es el comando principal que usaraacute en todas sus aplicaciones de bases de datos La sintaxis baacutesica es la siguiente

SELECT campol campo2 campo3 FROM tabla WHERE condicioacuten

La sentencia SELECT permite escoger los campos que especifiquemos de un conjunto de filas que cumplan una condicioacuten escrita despueacutes de la claacuteushysula WHERE Por ejemplo para recuperar todos los nombres de los usuashyrios almacenados en la tabla U s u a r i o tendriacuteamos que hacer

SELECT nombre FROM Usuario

El resultado es una columna con todos los nombres

Luis Miguel Maria Fernanda Pedro Javier

Advertencia

Si se fija iexcla claacuteusula WHERE no aparece porque estamos seleccioshynando todas iexclas filas Si quisieacuteramos seleccionar todas las filas cuyo i d _ u s u a r i o sea mayor que 2 tendriacuteamos que antildeadir WHERE i d_usua r io gt 2

Bases de datos con SQL y SQLite 203

Si necesita utilizar todos los campos de una tabla puede utilizar el siacutemboshylo para seleccionar todos

SELECT FROM U s u a r i o

Un uacuteltimo truco permite conocer el nuacutemero de filas que cumplen la conshydicioacuten Si despueacutes de la sentencia SELECT escribimos c o u n t ( ) el gesshytor de bases de datos nos contaraacute el nuacutemero de filas implicadas en la seleccioacuten

SELECT c o u n t ) ) FROM U s u a r i o

El resultado devuelto es 4 el nuacutemero de usuarios dados de alta

Uniones

Imagine ahora que queremos conocer el nombre de los usuarios que han comprado un producto determinado Si nos fijamos en la tabla C a r r i t o soacutelo podemos sacar el i d _ u s u a r i o con lo aprendido hasta ahora

Existe la posibilidad de cruzar varias tablas Cuando unimos dos tablas lo que realmente pasa es que obtenemos como resultado una tabla mayor con la suma del nuacutemero de columnas de las tablas y tantas filas como inshydique la multiplicacioacuten de las filas de las tablas implicadas

Si hacemos algo asiacute

SELECT FROM Usuario Carrito

El resultado es la unioacuten de las tablas Usuario y Carrito cuyo resultado tiene la suma de las columnas (3 + 3) y la multiplicacioacuten de las filas (4 x 4)

Tabla 114 UsuarioxCarrito

idusuario nombre cuenta id_carrito id_usuario idproducto

1 Luis Miguel 7011 1 1 1

1 Luis Miguel 7011 2 1 2

1 Luis Miguel 7011 3 2 1

1 Luis Miguel 7011 4 3 3

2 Ma Fernanda 3454 1 1 1

2 Ma Fernanda 3454 2 1 2

2 Ma Fernanda 3454 3 2 1

2 Ma Fernanda 3454 4 3 3

204 Capiacutetulo 11

idusuario nombre cuenta id_carrito id_usuario id_producto

3 Pedro 3445 1 1 1

3 Pedro 3445 2 1 2

3 Pedro 3445 3 2 1

3 Pedro 3445 4 3 3

4 Javier 1123 1 1 1

4 Javier 1123 2 1 2

4 Javier 1123 3 2 1

4 Javier 1123 4 3 3

Aquiacute es donde realmente se necesita utilizar la claacuteusula WHERE Lo que queshyremos conocer es el nombre de los usuarios que han comprado el producto nuacutemero 1 Al hacer una unioacuten lo primero que tenemos que hacer es eliminar las filas repetidas mediante una sentencia que relacione las dos tablas Si se fija bien puede ver que la columna i d _ u s u a r i o aparece en las dos tablas por lo tanto es una buena referencia Observe la siguiente sentencia SQL

SELECT FROM Usuario Carrito WHERE Usuario id_usuario = Carrito id__usuario

Lo que hemos hecho es crear una unioacuten de dos tablas donde cada fila debe tener las dos columnas i d _ u s u a r i o iguales

Como las dos tablas tienen el mismo nombre para la columna i d _ u s u a r i o es necesario anteponer la tabla a la propiedad para que la consulta funshycione de la siguiente forma U s u a r i o i d _ u s u a r i o o C a r r i t o i d _ u s u a r i o

El resultado de la sentencia anterior es

Tabla 115 UsuarioxCarrito

idusuario nombre cuenta id_carrito idusuario id_producto

1 Luis Miguel 7011 1 1 1

1 Luis Miguel 7011 2 1 2

2 Ma Fernanda 3454 3 2 1

3 Pedro 3445 4 3 3

Bien ahora tenemos un conjunto de datos que nos da el nombre de los usuarios que han comprado algo en nuestra tienda Si queremos averi-

Bases de datos con SQL y SQLite 205

guar quieacuten ha comprado el producto nuacutemero 1 tendremos que modificar la sentencia

SELECT FROM Usuario Carrito WHERE Usuarioid_usuario - Carritoid_usuario AND id_producto = 1

El resultado ahora se acerca maacutes a la realidad de lo que necesitamos

Tabla 116 UsuarioxCarrito

id_usuario nombre cuenta id_carrito id_usuario id_producto

1 Luis Miguel 7011 1 1 1

2 Ma Fernanda 3454 3 2 1

Acotando un poquito maacutes la sentencia

SELECT nombre FROM Usuario Carrito WHERE Usuarioid_usuario = Carritoid_usuario AND id_producto = 1

Ahora el resultado siacute es el esperado

Tabla 117 Nombre de los usuarios que han comprado el producto 1

nombre

Luis Miguel

Ma Fernanda

Dominar la sentencia SELECT con todas sus variaciones es un trabajo duro de varios meses o antildeos pero la recompensa se recoge en los primeros pashysos cuando comenzamos a ver la potencia del lenguaje y el uso en los disshytintos gestores de bases de datos

INSERT

Para poder seleccionar los datos primero hay que poder insertarlos en las tablas La sentencia necesaria para introducir nuevos datos es

INSERT INTO tabla (columnal columna2 columna3) VALUacuteES (valorl valor2 valor3)

206 Capiacutetulo 11

El resultado de esta operacioacuten es la inclusioacuten de un registro nuevo en la tabla en las columnas indicadas y con los valores dados Aquellas columshynas que no aparezcan no tomaraacuten valor en ese registro o tomaraacuten el vashylor NULL Para insertar un nuevo cliente en la tabla de U s u a r i o puede utilizar la sentencia

INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (5 Feo Joseacute 78 98)

La tabla resultante quedaraacute de esta forma

Tabla 118 Usuario

idusuario nombre cuenta

1 Luis Miguel 7011

2 Ma Fernanda 3454

3 Pedro 3445

4 Javier 1123

5 Feo Joseacute 7898

UPDATE

Se utiliza para editar informacioacuten que ya estaacute almacenada en la base de datos En otras palabras podemos cambiar selectivamente cierta informashycioacuten sin tener que borrar un registro e insertarlo de nuevo

La sintaxis baacutesica es

UPDATE tabla SET carapol = valorl campo2 = valor2 campo3 = valor3 WHERE condicioacuten

La condicioacuten se utiliza para seleccionar el nuacutemero de filas a las que afectashyraacute el cambio Si no ponemos nada se supone que la actualizacioacuten de datos se hace sobre todas las filas de una tabla por eso es necesario poner algushyna condicioacuten

Podemos utilizar UPDATE para cambiar el nuacutemero de cuenta de uno de los usuarios

UPDATE Usuario SET cuenta = 4455 WHERE id_usuario = 2

Lo que hemos hecho es cambiar el nuacutemero de cuenta de Mariacutea Fernanda de 3454 a 4455

Bases de datos con SQL y SQLite 207

DELETE

Eacutes la sentencia maacutes peligrosa de las vistas Permite borrar de uno a varios registros de una tabla La sintaxis es

DELETE FROM tabla WHERE condicioacuten

Si se omite la claacuteusula WHERE se borran todas las filas de una tabla Es aconsejable no precipitarse en el uso de esta opcioacuten y detenerse antes un momento a recapacitar si se necesita realmente dejar la tabla vaciacutea La fila que contiene al usuario Javier puede borrarse de la siguiente forshyma

DELETE FROM Usuario WHERE nombre=Javier

Definicioacuten de tablas

El primer paso para poder interactuar con los datos de una tabla es su creacioacuten Para este fin se utiliza la sentencia CREacuteATE que define los campos y el tipo de datos que se va a almacenar en cada columna

Ll formato simplificado es CREacuteATE TABLE tabla (columnal tipo_dato columna2 tipo_dato columna3 tipo_dato)

Los tipos de datos de SQL estaacutendar pueden variar dependiendo del gesshytor de bases de datos que utilice pero baacutesicamente pueden ser

Tabla 119 Tipos de datos en SQL 92

Especificacioacuten Tipo de dato

INT INTEGER Entero grande

SMALLINT Entero pequentildeo

REAL FLOAT Coma flotante

DEC DECIMAL Decimal

CHAR(n) CHARACTER(n) Alfanumeacuterico de longitud fija n

208 Capiacutetulo 11

Especificacioacuten Tipo de dato

VARCHAR(n) Alfanumeacuterico de longitud variable como maacutexishy

mo n caracteres

DATE Fecha

TIME Hora

TIMESTAMP Instante Conjunto de Fecha y Hora de un momento determinado

Con estos datos podemos ver la definicioacuten de la tabla de U s u a r i o

CREacuteATE TABLE Usuario (id_usuario INTEGER nombre CHAR(255)

cuenta INTEGER)

Si alguno de los campos es obligatorio es decir si siempre que realice una insercioacuten de nuevos datos necesita que ciertos campos sean introducidos obligatoriamente puede utilizar la sentencia NOT NULL despueacutes de la deshyfinicioacuten del campo

El campo nombre es obligatorio en la tabla U s u a r i o ya que un registro de usuarios sin almacenar su nombre no tiene sentido

CREacuteATE TABLE Usuario (id_usuario INTEGER nombre CHAR(255) NOT

NULL cuenta INTEGER NOT NULL)

El i d _ u s u a r i o identifica un registro y soacutelo uno No puede haber en la misma tabla dos nuacutemeros iguales en esta columna La forma de encontrar raacutepidamente una fila determinada es preguntar por este dato

La clave primaria de una tabla es un identificador uacutenico en cada tabla y que puede utilizarse para relacionar una tabla con otra En nuestro ejemshyplo podemos ver claramente que i d _ u s u a r i o es la clave primaria de la tabla U s u a r i o

CREacuteATE TABLE Usuario (id_usuario INTEGER PRIMARY KEY nombre

CHAR(255) NOT NULL cuenta INTEGER NOT NULL)

SQLite

SQLite es una libreriacutea que implementa un conjunto de sentencias bastanshyte amplio de SQL 92 estaacutendar La libreriacutea es muy pequentildea y 2 oacute 3 veces maacutes raacutepida que los gestores de bases de datos MySQL o PostgreSQL Neshycesita muy poco tiempo de ejecucioacuten y muy poca memoria para el proceshyso No se necesita administrar la base de datos fuera del entorno de

Bases de datos con SQL y SQLite 209

programacioacuten ya que no es un servidor Existe un problema derivado de esto

SQLite se basa en el almacenamiento de datos en un fichero por lo tanto cada vez que se almacenan datos el fichero que contiene los registros se bloquea durante el tiempo de la actualizacioacuten y no permite a otros usuashyrios interactuar Si la base de datos se utiliza solamente para leer la veloshycidad seraacute muy elevada pero si la utilizamos para actualizar constanteshymente los datos SQLite perderaacute maacutes tiempo negociando los bloqueos del fichero que dando servicio

Entre las caracteriacutesticas de SQLite tenemos

bull Implementa muchas funcionalidades de SQL 92 incluido disparadoshyres y transacciones

bull Proteccioacuten de integridad de datos con cominit y r o l l b a c k

bull Los ficheros de datos pueden moverse de servidor y seguiraacuten funcioshynando

bull Soporta bases de datos de 2 Terabytcs

bull El coacutedigo fuente es de dominio puacuteblico

Creacioacuten de bases de datos

La interfnce de programacioacuten de la extensioacuten SQLite es muy similar al gesshytor de bases de datos MySQL y PostgeSQL La diferencia principal es que SQLite aunque acepta la definicioacuten de datos con la sentencia CREacuteATE internamente soacutelo diferencia entre valores alfanumeacutericos o valores numeacuteshyricos es decir que podemos omitir el tipo de los campos en la definicioacuten de las tablas

La funcioacuten s q l i t e _ o p e n () recibe como paraacutemetro el nombre de una base datos Si la base de datos no existe la crea Ademaacutes de esta funcioacuten neceshysitaremos otra para poder enviar consultas a la base de datos La funcioacuten s q l i t e _ s i n g l e _ q u e r y () toma como paraacutemetros la base de datos creada con s q l i t e _ o p e n () y un literal con la sentencia SQL que queremos ejeshycutar

El ejemplo siguiente crea la base de datos de usuario e inserta las filas que estamos utilizando para aprender el lenguaje SQL

ltphp

$base_datos = sqlite_single_open(Usuariodb) $consulta = CREacuteATE TABLE Usuario

(id_usuario PRIMARY KEY

210 Capiacutetulo 11

nombre CHARIacute2 55) NOT NULL

cuenta INTEGER NOT NULL)

sqlite__query ( $base_datos $ consulta)

$consultal = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (1 Luis Miguel7011)

$consulta2 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (2 Mariacutea Fernanda3454 )

$consulta3 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (3 Pedro3445)

$consulta4 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (4 Javier1123)

sqlite_single_query($base_datos$consultal)

sqlite_ single_query($base_datos$consulta2 )

sqlite_ single_query($base_datos$consulta3)

sqlite_ single_query($base_datos$consulta4)

gt

De esta forma se ha creado la tabla U s u a r i o pero hemos necesitado hashycer 4 consultas adicionales para antildeadir los datos Esto se puede simplifishycar utilizando la funcioacuten s q l i t e _ q u e r y ( ) que acepta maacutes de una liacutenea de SQL Vamos a crear de esta forma la tabla P r o d u c t o y C a r r i t o

ltphp

$consulta = CREacuteATE TABLE Producto

(Iacuted_producto INTEGER PRIMARY KEY

nombre CHAR(255) NOT NULL

precio INTEGER NOT NULL)

INSERT INTO Producto (id_producto nombre precio)

VALUacuteES (1 Ratoacuten 6)

INSERT INTO Producto (idjroducto nombre precio)

VALUacuteES (2 Portaacutetil1000)

INSERT INTO Producto (id_producto nombre precio)

VALUacuteES (3 Libro PHP520)

sqlite_query($base_datos$consulta)

consulta = CREacuteATE TABLE Carrito

(id^compra INTEGER PRIMARY KEY

id^usuario INTEGER NOT NULL

id^producto INTEGER NOT NULL)

INSERT INTO Carrito (id^compra id_usuario id_producto)

VALUacuteES (1 1 1)

INSERT INTO Carrito (id^compra id_usuario id_producto)

VALUacuteES (2 1 2)

INSERT INTO Carrito (id_compra id_usuario id_producto)

VALUacuteES (3 2 1)

INSERT INTO Carrito (id_compra id_usuario idjroducto)

VALUacuteES (4 3 3)

sqlite_query($base_datos$consulta)

gt

Bases de datos con SQL y SQLite 211

Algunos gestores de bases de datos necesitan antildeadir una sentencia espeshyciacutefica para que uno de los campos sea auto incremental es decir que su valor aumente poco a poco sin necesidad de antildeadirlo nosotros en realishydad es gestionado por la propia base de datos

Los campos enteros que llevan asociada la sentencia PRIMARY KEY autoshymaacuteticamente son tratados como campos auto incremeacutentales y en las oacutershydenes INSERT se puede omitir la inclusioacuten del valor porque SQLite le daraacute el valor correlativo de la fila que le corresponda

Uacuteltimos cambios en una tabla

Hay veces que necesitamos saber el uacuteltimo valor auto incremental que SQLite ha generado para asociar una imagen o un archivo a un registro de una tabla Para aver iguar este dato p o d e m o s usar la funcioacuten sqlite_last_insert_rowid()

ltphp $base_datos = sqlite_open(Usuariodb) sqlite_single_query($base_datosINSERT INTO Usuario (nombre cuenta) VALUacuteES (Joseacute A2677)) $ultimo_usuario = sqlite_last_insert_rowid($base_datos) sqlite_single_query($base_datosINSERT INTO Producto (nombre precio) VALUacuteES (Ibook1200)) $ultimo_producto = sqlite_last_insert__rowid($base_datos) sqlite_single_query($base_datosINSERT INTO Carrito (id_usuario id_producto) VALUacuteES ($id_usuario$id_producto)) gt

En el ejemplo puede ver la posible utilizacioacuten de la funcioacuten Con ella exshytraeraacute el uacuteltimo usuario y el uacuteltimo producto introducido y aprovecharaacute para insertarlos en la tabla de compras

Otra funcioacuten muy uacutetil es s q l i t e _ _ c h a n g e s ( ) que devuelve el nuacutemero de filas afectadas por una consulta anterior

Si borra varias filas esta funcioacuten le devolveraacute el nuacutemero de filas que han sido borradas como puede ver en la figura 1 1 1

lt php $base_datos = sqlite_open(Usuariodb)

sqlite_single_query($base_datosUPDATE Usuario set cuenta =

2 2 2 2) echo Nuacutemero de filas afectadas

sqlite_changes($base_datos) gt

Seleccioacuten de datos

Como hemos visto antes la funcioacuten s q l i t e _ q u e r y () da la posibilidad de hacer cualquier tipo de consulta vista al principio del capiacutetulo

Las sentencias CREacuteATE INSERT DELETE o UPDATE no necesitan devolshyver ninguacuten dato pero la sentencia SELECT tiene que devolver los datos requeridos

La variable que obtiene los datos se considera como un recurso y debe aplicarse una funcioacuten para recuperar las filas una a una

Lo podemos comprobar con un ejemplo cuyo resultado se muestra en la figura 112

lt php $base_datos = sqlite_open(Usuariodb) ^resultado = sqlite_query($base_datosSELECT FROM Usuario) if ( $resultado)

echo Parece que hay un error else

while ($fila = sqlite_fe tch__array ($resu l taaacuteo) ) foreach ($fila as $indice =gt $valor)

echo $indice $valorltbrgt

gt

Despueacutes de hacer una consulta con la funcioacuten s q l i t e _ q u e r y ( ) la vashyriable $ r e s u l t a d o recibe un tipo de dato que no es manejable La funshycioacuten s q l i t e _ f e t c h _ a r r a y () extrae de la variable $ r e s u l t a d o todas las filas devueltas en forma de array Para ello hemos construido un bucle w h i l e donde la variable $f i l a va recibiendo los registros

Para acceder a cada columna de un registro simplemente tenemos que hacer uso de la variable como si fuera un array y como iacutendice el nombre de la columna o el nuacutemero de registro de esta forma $f i l a [nombre] $ f i l a [ c u e n t a ] $ f i l a [ 0 ] $ f i l a [ l ]

Dentro del bucle hemos utilizado otro bucle f o r e a c h para mostrar por pantalla todos los valores del array

SQLite orientado a objetos

Puesto que la potencia de PHP 5 radica en la fuerte orientacioacuten a objetos es de agradecer que SQLite provea alguacuten objeto para la interaccioacuten con bases de datos SQLite tiene una potente interface orientada a objetos que puede ser usado para un eficaz manejo de los datos librando al progra-mador de crear su propio objeto con las funciones procedurales El objeto se llama S Q L i t e D a t a b a s e () y el constructor recibe como paraacutemetro la base de datos

214 Capiacutetulo 11

El ejemplo muestra coacutemo utilizarlo aunque el lector ya conoceraacute el funshycionamiento baacutesico de los objetos

lt php $base_datos = new SQLiteDatabase(Usuariodb) $consulta = CREacuteATE TABLE Usuario

(id^usuario INTEGER PRIMARY KEY nombre CHAR(2 55) NOT NULL cuenta INTEGER NOT NULL) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (1 VLuis Miguel7 011) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (2 VMariacutea Fernanda3454) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (3 Pedro3445) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (4 Javier1123)

$base_datos-gtquery($consulta) gt

El meacutetodo q u e r y ( ) funciona exactamente igua l que la funcioacuten s q l i t e _ q u e r y ( ) pero soacutelo recibe como paraacutemetro la consulta ya que la base de datos va impliacutecita en el objeto

Seleccioacuten de registros

Las consultas SELECT se tratan de manera parecida a lo visto anteriorshymente Puesto que estamos utilizando un objeto para recibir el resultado de una consulta tendremos que utilizar meacutetodos que nos permitan maneshyjarlos En la figura 113 puede ver el resultado

ltphp

$base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtquery($consulta) while ($resultado-gtvalid() )

$fila = $resultado-gtcurrent() echo $fila[0] ltbrgt echo $fila[l] ltbrgt echo $fila[2] ltbrgt $ resultado- gtnext () bull

gt

El meacutetodo v a l id () da un resultado true si existen valores que no se han mostrado si devuelve false es que ya hemos extraiacutedo todas las filas El meacutetodo c u r r e n t () nos da la fila actual deacutela consulta La variable $f i l a

Bases de datos con SQL y SQLite 215

obtiene un array con los datos del registro actual Para avanzar de registro en la consulta se utiliza el meacutetodo n e x t ( )

Funciones de Array para recuperar datos

SQLite ofrece tambieacuten un nuacutemero de nuevas funciones que simplifican y aceleran la recogida de informacioacuten de la base de datos Por ejemplo el meacutetodo A r r a y Q u e r y () devuelve un array de dos dimensiones donde la primera dimensioacuten indica el nuacutemero de la fila y la segunda dimensioacuten el nuacutemero de columna de esa fila Si la variable $ r e s u l t a d o recoge el resultado de A r r a y Q u e r y ( ) puede acceder a los registros de la siguienshyt e forma $ r e s u l t a d o [ 0 ] [ 0 ] $ r e s u l t a d o [ l ] [ 0 ] $ r e s u l t a -do [2] [3] Puede utilizar alguacuten bucle foreach para sacar todos los datos

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtArrayQuery($consulta) $filas = 0 while (isset ($resultado [$filas] ) )

foreach ($resultado[$filas] as $indice =gt $valor) echo $indice $valorltbrgt

$filas++

216 Capiacutetulo 11

gt

Ademaacutes de esta forma de trabajar puede hacer que el resultado de la consulshyta se devuelva en forma de objeto PHP 5 permite utilizar la construccioacuten fo-reach para interactuar con objetos v recuperar los datos de la siguiente forma

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario bullresultado = $base_datos-gtunbufferedQuerv($consulta) foreach ($resultado as $valor)

echo Svalor[0]ltbrgt echo $vaior[1]ltbrgt echo $valor[2]ltbrgt

gt

La construccioacuten unbuf f e r edQuery () devuelve las filas en forma de objeshyto y ademaacutes no almacena el resultado en buffer por lo que es muy raacutepida

Nuacutemero de filas

La extensioacuten SQLite posee un meacutetodo para determinar el nuacutemero de camshypos devueltos en una consulta en un resultado El meacutetodo n u m F i e l d s () se encarga de devolver este resultado Para poder utilizarlo debe recupeshyrar los datos con la funcioacuten unbuf f e r e d Q u e r y () y el objeto devuelto seraacute el que le indique el nuacutemero de campos que almacena

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtunbufferedQuery($consulta) $numero_filas = $resultado-gtnumFields() echo El nuacutemero de filas es $numero_filas foreach ($resultado as $valor)

echo $valorf0]ltbrgt echo $valor[1]ltbrgt echo $valor[2]ltbrgt

gt

Moverse entre registros

En muchos casos querraacute utilizar la menor memoria posible y se haraacute inshydispensable utilizar el meacutetodo unbuf f e r e d Q u e r y ( ) aunque esto hace perder funcionalidad y puede no resultar la mejor eleccioacuten

Bases de datos con SQL y SQLite 217

Por ejemplo imagine que quiere saber cuaacutentas filas devuelve un resulshytado

Usando unbuf f e r e d Q u e r y () tenemos que hacer un bucle para contar una a una las filas del resultado Con la funcioacuten q u e r y () tan soacutelo hay que llamar al meacutetodo numRows () para conocer el nuacutemero de registros implicados en la consulta

Las consultas con q u e r y () permiten ademaacutes recuperar la informacioacuten en el orden que queramos y no secuencialmente

El ejemplo siguiente muestra coacutemo utilizar una consulta para ver los reshygistros empezando desde el uacuteltimo hasta el primero

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtquery($consulta) $numero_filas = $resultado-gtnumRows() $resultado-gtseek($numero_filas-1) do

$fila = $resultado-gtcurrent () foreach ($fila as $valor)

echo $valorltbrgt

while ($resultado-gthasPrev() ampamp $resultado-gtprev()) gt

218 Capiacutetulo 11

El meacutetodo s e e k () se mueve a traveacutes del resultado y permite posicionar-nos en el registro que pasemos como paraacutemetro El meacutetodo h a s P r e v () es true si existe un registro previo y p r e v () es true si ha sido posible moshyverse a un registro anterior La figura 114 es un fiel reflejo del funcionashymiento

Resumen

SQLite es una de las caracteriacutesticas estrella de PHP 5 Se ha incluido para que no necesite instalar un gestor de bases de datos para sus proyectos Esto hace maacutes sencillo distribuir aplicaciones porque no dependen de un software adicional tan soacutelo de PHP 5

SQLite es a la vez un servidor de bases de datos y un cliente La libreriacutea permite operar con la mayor parte de las instrucciones de SQL posee un mayor juego de instrucciones que MySQL 4

Pero como todo lo bueno tiene una pequentildea pega Como SQLite trata las bases de datos como ficheros del sistema operativo cuando un usuario hace una conexioacuten para escribir datos el fichero queda bloqueado para inclusiones de otros usuarios Cuando termina la insercioacuten del primer usuario el segundo tendraacute acceso a escribir los datos Por lo tanto SQLite es muy recomendable cuando realice proyectos donde la mayor parte de las veces se hacen lecturas de la base de datos como un perioacutedico digital o un WebLog En otro caso es mejor utilizar un gestor de bases de datos como MySQL que veraacute en el siguiente capiacutetulo

En este capiacutetulo aprenderaacute a

bull Conocer la forma de conectarse a un servidor de bases de datos bull Realizar consultas y recuperar los datos de distintas formas bull Recuperar el nuacutemero de filas que intervienen en una consulta

bull Crear nuevas bases de datos y tablas

220 Capiacutetulo 12

Introduccioacuten

PHP 5 soporta muchos de los gestores de bases de datos relacioacutenales exisshytentes en el mercado Las dos alternativas maacutes comunes son ProstgreSQL y MySQL

Aunque PostgreSQL es mucho mejor en cuanto a caracteriacutesticas y funcioshynes soportadas del SQL 92 estaacutendar MySQL se ha hecho maacutes popular en el ambiente de los servidores Web Cuando los servidores Web ofrecen su sershyvicio como LAMP se refieren a Linux + Apache + MySQL + PHP

Este capiacutetulo cubre las operaciones maacutes comunes que los desarrolladores de PHP pueden hacer con MySQL desde recuperar o modificar datos buscar textos o hacer una copia de seguridad de la base de datos

Administracioacuten de usuarios

Una gran parte del uso de la seguridad y efectividad de MySQL tiene que ver con comprender el sistema de privilegios MySQL permite dar permishysos al detalle basaacutendose en grupos usuarios conexiones y comandos a utilizar En teoriacutea se puede dar privilegios a ciertos usuarios para que soacutelo puedan escribir en algunas columnas de varias tablas Es una buena idea dar a cada usuario los permisos miacutenimos necesarios para que pueda inte-ractuar con su base de datos En realidad en un mundo ideal no deberiacutea preocuparse por dar permisos a los usuarios o crear bases de datos Si su trabajo profesional se basa en el desarrollo de aplicaciones su adminisshytrador de bases de datos deberiacutea poner a punto el servidor de MySQL para facilitar su trabajo Si se estaacute interesado en conocer los entresijos del servishydor de bases de datos recomiendo al lector que lea la documentacioacuten o-line de la Web wwwmysql com o consiga uno de los muchos libros que tratan el tema

En el Apeacutendice A puede ver coacutemo instalar MySQL y dar los permisos neshycesarios para que pueda probar los ejemplos

Conexioacuten a MySQL

La conexioacuten no puede ser maacutes sencilla Es un proceso de dos pasos

bull Se conecta con el servidor de MySQL

PHP 5 y MySQL 221

bull Se solicita la conexioacuten a una base de datos especiacutefica Es importante recordar que MySQL es un servidor que puede estar alojashydo en el mismo ordenador que PHP 5 o en otro diferente Por eso la coshynexioacuten se hace de forma distinta a SQLite

Para conectar a MySQL es necesario enviar como paraacutemetros la direccioacuten del servidor el usuario y la contrasentildea

ltphp $servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras Conexioacuten al servidor de bases de datos $descriptor = mysql_connect($servidor$usuario $pass) Se selecciona la base de datos mysql_select_db($base_datos$descriptor) Se cierra la conexioacuten cuando terminemos mysql__close ( $descriptor) gt

La funcioacuten m y s q l _ c o n n e c t () permite conectar a un servidor En este caso hemos puesto como servidor a l o c a l h o s t porque estamos utilizanshydo nuestro ordenador local para hacer las pruebas

Otra cuestioacuten importante es que el servidor MySQL puede almacenar varias bases de datos de un mismo usuario por eso tenemos que utilizar la f u n c i oacute n m y s q l _ s e l e c t _ d b ( ) para seleccionar la que queremos utishylizar

Por uacuteltimo tenemos la funcioacuten m y s q l _ c l o s e () que se encarga de ceshyrrar una conexioacuten con el servidor

El ejemplo siguiente muestra coacutemo se puede crear una clase reutilizable en todos los proyectos que sirva para conectarse a una base de datos

ltphp class Servidor_Base_Datos

private $servidor private $usuario private $pass private $base_datos private $descriptor function construct($servidor$usuario$pass$base_datos)

$this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtpass = $pass

222 Capiacutetulo 12

$this-gtbase_datos = $base_datos $this-gtconectar_base_datos()

priacutevate function conectar_base_datos()

$this-gtdescriptor = mysql__connect($this-gtservidor$this-gtusuario$this-gtpass) mysql_select_db($this-gtbase_datos$this-gtdescriptor)

$servidor = localhost $usuario = luis $pass = secreto $base_datos = Usuario $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) gt

Nota

No he antildeadido al objeto ninguacuten tipo de control de errores ya que veremos ese tema con profundidad en el capiacutetulo 17

Seleccionar datos

Existen diferentes formas de recuperar datos desde MySQL pero los maacutes usados son seguramente m y s q l _ f e t c h _ q u e r y () y m y s q l _ q u e r y () Si leyoacute el capiacutetulo anterior sobre S Q L i t e no tendraacute ninguacuten problema para asimilar el funcionamiento de estas funciones

Vamos a antildeadir dos meacutetodos nuevos a la definicioacuten de la clase anterior para que nos pueda servir en otras aplicaciones

public function consulta($consulta)

$this-gtresultado = mysql_query($consulta$this-gtdescriptor)

public function extraer_registro ()

if ($fila = mysql_fetch_array($this-gtresultadoMYSQL_ASSOC)) bull return $fila

else return false

PHP 5 y MySQL 223

El meacutetodo c o n s u l t a () recibe una sentencia SQL que debe ejecutarse en la base de datos apuntada por el descriptor $ t h iacute s- gt d e s c r i p t o r

El meacutetodo e x t r ae r _ r eg i s t r o ( ) comprueba con la funcioacuten m y s q l _ f e t c h _ a r r a y () si existen ficheros en el resultado de la conshysulta

En caso afirmativo devuelve un arraxj con los datos de ese registro En el capiacutetulo anterior vimos que un registro pasado comoarray permitiacutea acceder a las columnas mediante un iacutendice numeacuterico ($f i la [0] ) o meshydiante el nombre de la columna (($f i l a [ i d _ u s u a r i o ]))

La directiva MYSQL_ASSOc elimina la posibilidad de extraer los datos con un Iacutendice numeacuterico mejorando la recuperacioacuten en Jos bucles del foreach El ejemplo siguiente muestra coacutemo utilizar los nuevos meacutetodos

ltphp Primero se antildeade el fichero que contiene la clase require_once(MySQLphp) $servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $usuario-gtconsulta (seslect from Usuario) while ($fila = $usuario-gtextraer_registro() )

foreach ($fila as $indice =gt $valor) echo $indice $valorltbrgt

gt

El coacutedigo anterior recupera la clase del fichero MySQL php e inicializa las variables necesarias para conectar con la base de datos

Tambieacuten podemos utilizar un fichero de configuracioacuten como el que vishymos en el capiacutetulo 10 para almacenar los datos de la conexioacuten

La variable $ u s u a r i o recoge la creacioacuten del objeto de conexioacuten y utiliza el meacutetodo c o n s u l t a () para recuperar el nombre de los usuarios de nuesshytra Web

Para extraer todos los datos nos encontramos con un bucle que va recupeshyrando un arraxj por registro almacenaacutendolo en $f i l a

Utilizando f o r e a c h podemos extraer todas las columnas de la fila indishycada

La figura 121 presenta el resultado del script

Manipulacioacuten de datos

Seleccionar datos de una base de datos es soacutelo el principio la potencia de SQL nos permite tambieacuten insertar actualizar y borrar filas de una tabla Con el objeto que hemos creado es muy sencillo hacer consultas del tipo INSERT UPDATE o DELETE llamando al meacutetodo c o n s u l t a ()

Insertar una fila

Para insertar una fila con nuestro objeto tendremos que definir la consulshyta y ejecutar el meacutetodo c o n s u l t a ()

ltphp require_once(MySQLphp) $servidor = localhost -$usuario = root $pass = $base_datos = Compras $insertar = INSERT INTO Usuario (nombrecuenta) VALUacuteES (Cristina2119) $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) ^usuario-gtconsuIta($insertar) gt

PHP 5 y MySQL 225

Actualizar una fila

Antes de actualizar una fila necesita identificar la fila o filas de la tabla que quiere cambiar En este ejemplo se ha utilizado una sentencia SE-LECT para averiguar primero el valor id_usuar io de Luis Miguel y desshypueacutes proceder a cambiar su cuenta bancaria

ltphp require_once(MySQLphp) $serviacutedor = localhost $usuario = root $pass = $base_datos = Compras $consulta = SELECT id_usuario FROM Usuario WHERE nombre=Luis Miguel $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $id_usuario = $fila[id_usuario] $actualizar = UPDATE Usuario SET cuenta=9999 WHERE id_usuario=$id_usuario $usuario-gtconsulta($actualizar) gt

En un caso praacutectico UPDATE puede utilizarse para modificar los datos introducidos en un formulario Web

Borrar una fila

Para borrar una fila puede seguir el mismo camino que se ha utilizado antes para actualizar Primero averiguumle el registro que quiere eliminar y despueacutes ejecute la consulta con la sentencia DELETE

ltphp require_once(MySQLphp) $servidor = localhost usuario = luis $pass = secreto $base_datos = Compras $consulta = SELECT id_usuario FROM Usuario WHERE nombre=Luis Miguel $usuario = new Servidor_Base_Datos$servidor$usuario$pass$base_datos) $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $id_usuario = $fila[id_usuario ]

226 Capiacutetulo 12

$borrar = DELETE FROM Usuario WHERE id_usuario = 1$id_usuario $usuario-gtconsulta($borrar) gt

Errores con las comillas

Examinemos ahora el coacutedigo siguiente ltPHP require_once(MySQLphp) if (isset ($_POST[nombre] ) ]| isset ($_POST[cuenta ]) )

$servidor = localhost $usuario = root $pass = $base_datos = Compras $nombre = $_POST[nombre ] $cuenta = $_POST[cuenta] $usuario = new Servidor_Base_Datos($servidor$usuario $pass$base_datos) $insertar = INSERT INTO Usuario(nombrecuenta) VALUacuteES ($nombre$cuenta) $usuario-gtconsulta ($insertar)

gt ltHTMLgt ltBODYgt ltform action=formulario_Usuario php method=POSTgt Nombre ltINPUT type=text name=nombregtltbrgt Cuenta ltINPUT type=text name=cuentagtltbrgt ltinput type=submit name=Enviar gt ltformgt ltBODYgt ltHTMLgt

El pequentildeo formulario que muestra la figura 122 permite insertar en la tabla Usuario nuevos clientes Los campos de texto que recogen el nombre y la cuenta pueden recibir cualquier tipo de caraacutecter hay ciertos siacutembolos que pueden provocar que un programa falle y son utilizados malintencionadamente por hackers para corromper el sistema Si en la casilla destinada a escribir el nombre escribe un nombre y en medio una comilla simple y otra doble tal y como muestra el ejemplo

Luis Migue1 Cabezas Granado

PHP 5 y MySQL 227

El meacutetodo c o n s u l t a () intentaraacute ejecutar

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Migue1 Cabezas Granado))

iquestPuede ver el problema Cuando MySQL lee la sentencia cree que es

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Migue

El resto de la sentencia causaraacute un error y fallaraacute la consulta La solucioacuten es antildeadir el siacutembolo de escape delante de la comilla simple para que MySQL tome el siacutembolo como un simple caraacutecter

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Miguel Cabezas Granado))

Existen tres soluciones para antildeadir el siacutembolo de escape a todas las comishyllas que aparezcan en campo de texto

bull Lo primero que puede hacer es configurar el archivo phpini activanshydo la opcioacuten m a g i c _ q u o t e s _ g p c Con esta opcioacuten a todos los datos pasados entre paacuteginas Web por los meacutetodos GET y POST se les inserta automaacuteticamente siacutembolos de escape en las comillas que aparezcan

bull Si m a g i c _ q u o t e s no estaacute activo en su servidor PHP 5 tiene la funshycioacuten a d d s l a s h e s ( ) que tiene el mismo cometido que la opcioacuten anshyterior Si m a g i c _ q u o t e s estaacute activo no podraacute utilizar esta funcioacuten porque se antildeadiriacutean dos siacutembolos de escape

228 Capiacutetulo 12

bull El tercer camino muy similar a a d d s l a s h e s usa la funcioacuten m y s q l _ e s c a p e _ s t r i n g Esta funcioacuten antildeade siacutembolo de escape a las comillas simples comillas dobles caracteres de final de fichero y reshytorno de carro Es un meacutetodo implementado por MySQL por eso es maacutes recomendable utilizar a d d s l a s h e s

Para saber si el fichero phpini tiene activado m a g i c _ q u o t e s existe la funcioacuten g e t _ m a g i c _ q u o t e s _ g p c ( ) Puede antildeadir algunas liacuteneas de coacutedigo a su formulario para que controle este tipo de error de la siguiente forma

ltphp require_once(MySQLphp) if (isset($_POST[nombre]) || isset($_POST[cuenta ]))

$servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras if (get_magic_quotes_gpc())

$nombre = $_POST[nombre] $cuenta = $__POST [cuenta ]

else $nombre = addslashes($_POST[nombre]) $cuenta = addslashes($_POST[cuenta])

$usuario = new Servidor_Base_Datos($servidor$usuario $pass$base_datos) $insertar = INSERT INTO Usuario(nombrecuenta) VALUacuteES ($nombre$cuenta ) $usuario-gtconsulta($insertar)

gt

Contando filas

A menudo es uacutetil conocer el nuacutemero de filas devueltas por una consulta antes de hacer cualquier cosa con el resultado Puede averiguar el nuacutemeshyro de filas mediante el uso de alguna funcioacuten de PHP o la utilizacioacuten de MySQL para obtener el nuacutemero de registros

Contar filas con PHP

La funcioacuten mysql_num_rows () devuelve el nuacutemero de filas seleccioshynadas

PHP 5 y MySQL 229

Su uso puede ampliar el objeto de bases de datos

public function numero_filas()

return mysql_num_rows($this-gtresultado)

Ademaacutes de esta funcioacuten tenemos mysql_num_f i e l d s ( ) que devuelve el nuacutemero de campos del una tabla es necesaria cuando hacemos una conshysulta de datos y no sabemos cuaacutentas columnas hemos seleccionado

Contar filas con MySQL

La alternativa es utilizar una consulta de SQL con la sentencia c o u n t ( ) Esto requiere hacer dos consultas una para obtener el nuacutemero de filas y otra para obtener el resultado

Utilicemos el objeto para realizar la operacioacuten

ltphp

require_once(MySQLphp) $servidor = localhost $usuario = root $pass = $base_datos = Compras $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $consulta = select count() as numero_filas from Usuario $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $numero_filas = $fila[numero_filas] $consulta = select from Usuario $usuario-gtconsulta($consulta) echo El nuacutemero de filas es $numero__f ilasltbrgt while ($fila = $usuario-gtextraer_registro())

foreach ($fila as $indice =gt $valor) echo $indice $valorltbrgt

gt

La primera sentencia SELECT cuenta el nuacutemero de filas y al resultado le da el nombre numero__f i l a s

Para acceder al nuacutemero se hace como siempre leyendo el resultado del irray $f i l a [ numero_f i l a s ]

La figura 123 muestra el resultado

Contar filas afectadas

Es posible que sea necesario saber cuaacutentas filas han sido afectadas desshypueacutes de antildeadir actualizar o borrar algunas filas

La funcioacuten m y s q l _ a f f e c t e d _ r o w s () devuelve el nuacutemero de registros afectados despueacutes de un cambio en las filas de una tabla Actualizando nuestra clase tenemos

public function filas_afectadas()

return mysql_affected_rows($this-gtdescriptor)

Uacuteltimo nuacutemero insertado

Cuando utilice campos auto numeacutericos en una tabla e inserte un nuevo registro seraacute uacutetil conocer el nuacutemero de la uacuteltima fila insertada

Para obtener este nuacutemero tan solo t iene que u t i l izar la funcioacuten m y s q l _ i n s e r t _ i d ( ) Se puede utilizar de la siguiente forma

public function ultima_fila()

PHP 5 y MySQL 231

return mysql_insert_id($this-gtdescriptor)

Buacutesquedas dentro de una tabla

La forma de buscar ocurrencias en una columna es utilizar la sentencia LIKE de SQL

SELECT FROM Usuario WHERE nombre LIKE Luis

El siacutembolo es un comodiacuten es decir puede sustituir a cualquier caraacutecter dentro de la columna donde busque

Definicioacuten de bases de datos

Como indicamos antes lo ideal es que un administrador de MySQL le genere las bases de datos y las tablas Despueacutes de esto con su usuario y contrasentildea podraacute hacer las consultas que tenga autorizadas

En muchos casos la figura del administrador de bases de datos no existe y es el desarrollador el que asume este papel En este caso le interesaraacute conocer la forma de crear desde un script sus bases de datos

Creacioacuten de bases de datos

Para crear una base de datos tiene que utilizar la funcioacuten m y s q l _ c r e a t e _ db () Recibe dos paraacutemetros el primero es el nombre de la base de datos que quiere crear y el segundo el descriptor devuelto por la funcioacuten m y s q _ c o n n e c t () La funcioacuten m y s q l _ d r o p _ d b () borra la base de dashytos del gestor de MySQL

ltphp $descriptor = mysq_connect($servidor $usuario $clave) mysql_create_db(Nueva_Base $descriptor) gt

Creacioacuten de tablas

La creacioacuten de tablas debe hacerse a traveacutes del lenguaje de consultas SQL como vimos en el capiacutetulo anterior Como ya sabe la funcioacuten m y s q l _

232 Capiacutetulo 12

q u e r y () acepta consultas de distintos tipos Aprovechando esto puede incluir una consulta para crear una tabla nueva

SQLite es una base de datos poco tipada es decir que soacutelo es capaz de almacenar dos tipos de datos nuacutemeros o caracteres En cambio MySQL es fuertemente tipada porque tiene un elevado conjunto de tipos para aplicar a sus columnas La tabla 121 muestra algunos tipos de datos que puede aplicar en la sentencia CREacuteATE

Tabla 121 Tipos de datos de MySQL

Nombre Tamantildeo Uso

BIT BOOLEAN 1 byte Almacena valores desde 0 a 255 sin

signo o -128 a 127 con signo SMALLINT 2 bytes De 0 a 65535 sin signo y de -32768 a

32767 con signo

MEDIUMINT 3 bytes De 0 a 16777215 sin signo o-8388608 a 8388607

INT INTEGER 4 bytes De0a4294967295ode-2147483648a 2147483647

BIGINT 8 bytes De 0 a 18446744073709551615 o -9223372036854775808a 9223372036854775807

FLOAT(precisioacuten) De 4 a Nuacutemero de coma flotante con precisioacuten

8 bytes

DATE 3 bytes Almacena una fecha

DATETIME 8 bytes Almacena una fecha con la hora y minutos

VARCHAR(nuacutemero) Nuacutemero Almacena tantos caracteres como indi-bytes ca el nuacutemero El tamantildeo es menor que

255 caracteres

TINYBLOB TINYTEXT Mayor que Almacena caracteres 255 bytes

BLOB TEXT Maacutes de Almacena un nuacutemero elevado de carac-64 kb teres

Como ejemplo puede ver el siguiente coacutedigo

lt $descriptor = mysq_connect($servidor $usuario $clave) mysql_create_db(Concesionario $descriptor) mysql_ select_db ( Concesionario) -

PHP 5 y MySQL 233

$consulta = CREacuteATE TAELE vehiacuteculos ( Iacuted_vehicul0 INT NOT NULL AUTO_INCREMENT PRIMARY KEY color VARCHAR(25) fecha_compra DATETIME)

$resultado = mysql_query($consulta) $mensaje = mysql_drop_db(Concesionario) gt

La columna i d _ v e h i c u l o identifica a un uacutenico vehiacuteculo de la tabla Como puede ver en MySQL tiene que antildeadir algunos modificadores a la columshyna para identificar sus caracteriacutesticas Estos modificadores son obligatoshyrios en MySQL Por ejemplo en SQLite no hace falta antildeadir ninguna propiedad para que el valor se incremente automaacuteticamente En MySQL es necesario especificar la propiedad AUTO_lNCREMENT Es obligatorio ademaacutes que todas las columnas tengan un tipo de dato definido

Resumen

MySQL es sin duda el sistema maacutes utilizado a escala mundial La mayor parte de las aplicaciones en PHP estaacuten escritas para MySQL porque da una fiabilidad y velocidad absolutas Hay que decir tambieacuten que la vershysioacuten 4 tiene bastantes restricciones con respecto a otros gestores de bases de datos como PostgreSQL pero se iraacuten solventando en las futuras vershysiones

Si terminoacute el capiacutetulo con eacutexito todaviacutea le queda un paso por andar La extensioacuten de MySQL que hemos utilizado es la que viene por defecto funshycionando con PHP 5 Recientemente se ha creado desde cero una nueva forma de interactuar con MySQL que permite hacer transacciones o conshysultas almacenadas (de la forma que lo hace Oracle) La extensioacuten se llashyma MySQLi y por su leve dificultad se escapa del objetivo de este libro

En este capiacutetulo aprenderaacute a

bull Diferenciar entre sesiones cookies y cabeceras HTTP bull Utilizar sesiones para ocultar variables entre usuarios y paacuteginas Web bull Almacenar la configuracioacuten de un usuario con cookies

bull Enviar informacioacuten de cabecera viacutea Web

236 Capiacutetulo 13

Introduccioacuten

Una sesioacuten es un periacuteodo de tiempo durante el cuaacutel una persona detershyminada ve un nuacutemero de diferentes paacuteginas Web de un determinado doshyminio

El protocolo HTTP no tiene forma alguna de distinguir un usuario que se conecte desde Espantildea de otro que se conecte desde Japoacuten PHP 5 proshyvee un mecanismo que permite antildeadir cierto nivel de diferenciacioacuten enshytre usuarios

Miremos un ejemplo

ltHTMLgt ltBODYgt ltphp switch ($_GET[opcioacuten ] )

case 1 echo La opcioacuten es 1 break

case 2 echo La opcioacuten es 2 break

case 3 echo La opcioacuten es 3 break

gt ltBODYgt ltHTMLgt

Esta paacutegina elige una de las opciones en funcioacuten del paraacutemetro GET que obtenga Como ya sabe GET pasa todos los valores junto a la direccioacuten Web y es visible para nosotros

El meacutetodo GET no es muy funcional cuando necesite pasar datos comproshymetidos a traveacutes de varias paacuteginas Web POST resuelve en parte este proshyblema

Este meacutetodo permite pasar entre paacuteginas las variables que quiera queshydando ocultas para el usuario A priori parece una buena forma de oculshytar datos pero nos encontramos que es necesario un formulario en cada paacutegina para utilizarla

Las sesiones y las variables de sesioacuten permiten pasar datos entre paacuteginas sin necesidad de utilizar formularios y es la mejor forma para ocultar dashytos comprometidos

Sesiones y Cookies 237

Sesiones en PHP 5

Las sesiones deben soportar

bull Detectar que durante el transcurso de la navegacioacuten por varias paacutegishynas Web la sesioacuten permanece invariable

bull Almacenar informacioacuten que formaraacute parte de una sesioacuten en concreto

PHP trabaja con una combinacioacuten de meacutetodos que son capaces de ocultar variables y cookies de las que hablaremos en un apartado posterior

Instanciando sesiones

El primer paso que nuestro script debe realizar es la llamada a la funcioacuten s e s s i o n _ s t a r t () Esta funcioacuten registra una sesioacuten en el servidor y la identifica con una cadena de 32 caracteres Cada persona que entre en ese mismo instante en la Web desde un ordenador diferente obtendraacute un iden-tificador distinto

La funcioacuten s e s s i o n _ s t a r t () debe incluirse en todas las paacuteginas Web que formen parte de la aplicacioacuten porque no soacutelo se encarga de iniciali-zar la sesioacuten sino que tambieacuten se encarga de mantener la misma sesioacuten durante el proceso La funcioacuten actuacutea de la siguiente forma

bull Si no existe una sesioacuten activa crea una nueva con un identificador

bull Si existe una sesioacuten que puede ser recuperada se extrae la sesioacuten y las variables asociadas ltphp session_start() gt ltHTMLgt ltBODYgt ltphp echo La variable de sesioacuten es SID gt ltBODYgt ltHTMLgt

La figura 131 muestra la variable de sesioacuten En el momento en que elscript escribe cualquier cosa el servidor termina de enviar las cabeceras HTTP y empieza a enviar el contenido No se puede enviar una nueva cabecera cuando ya estamos enviando el cuerpo de la Web Puesto que la funcioacuten s e s s i o n _ s t a r t () utiliza cabeceras para pasar la informacioacuten de sesioacuten

Sesiones y Cookies 239

La primera vez que instanciamos una sesioacuten seacute crea una constante llamashyda S ID que contiene el identificador de 32 caracteres que nos identifica

Variables de sesioacuten

Existe una variable suacuteper-global que se encarga de almacenar las variashybles que quiere pasar entre paacuteginas de una sesioacuten El array $_SESSION permite almacenar datos de cualquier tipo para recuperarlos en otras paacuteshyginas que tengan la misma sesioacuten El coacutedigo para propagar variables de sesioacuten puede ser tan sencillo como la paacutegina s e s i o n l php

ltphp session_start () gt ltHTMLgt ltBODYgt ltphp $_SESSION[nombre] = Luis Miguel Caberas $_SESSION[edad] = 29 echo lta href = sesion2phpgtPasar variablesltagt gt ltBODYgt ltHTMLgt

La vatvabie suacutepex-^toacutebal almacena valores de d-feteate tupo y creamas UTJ enlace a la paacutegina s e s i o n 2 php para poder recuperarlos

ltphp session_start () gt ltHTMLgt ltBODYgt ltphp echo Mostrar las variables de sesioacutenltbiacutegt foreach ($_SESSION as $indice =gt $valor)

echo $indice $valorltbrgt

echo Mostrar las COOKIESltbrgt foreach ($_COOKIE as $indice =gt $valor)

echo $indice $valorltbrgt gt ltBODYgt ltHTMLgt

Si se apoya en el bucle foreach podraacute extraer todos los valores pasados desde la Web s e s i o n l php Como curiosidad hemos introducido un bucle que extrae las variables almacenadas en c o o k i e s y puede ver en

Nota

Como veremos maacutes adelante iexclas cookies son pequentildeos contenishydos que se almacenan en el ordenador local Las cookies son muy utilizadas por los servidores Web para guardar las preferencias de un usuario o alguacuten dato interesante En realidad son variables que se guardan en el ordenador local del usuario y pueden ser resshycatadas por PHP en alguna otra ocasioacuten en la que se necesite

Problemas con los navegadores

Un problema muy comuacuten es que el usuario tenga por razones de segurishydad desactivada la opcioacuten de permitir c o o k i e s en su navegador El proshyb lema es que el o rdenador local no va a aceptar nuestra variable PHPSESSID y todas las paacuteginas creeraacuten que no existe sesioacuten activa y no podraacuten recuperar las variables Se puede resolver con unas pocas liacuteneas de coacutedigo para la paacutegina s e s i o n l php

ltphp

Sesiones y Cookies 241

session_start() gt ltHTMLgt ltBODYgt ltphp $_SESSION[nombre] = Luis Miguel Cabezas $_SESSION[edad] = 29 $id_sesion = SID echo lta href=sesion2php$id_sesiongtPasar variablesltagt gt ltBODYgt ltHTMLgt

Esta forma de trabajar implica tener que pasar en todos los enlaces el iden-tificador de sesioacuten La forma correcta de hacerlo es la que muestra el ejemshyplo ya que produce una URL de este tipo s e s i o n 2 phpPHPSESSID = 9 0 9 7 c 4 3 a a 8 6 d 3 4 5 9 b l 6 6 d 7 1 c 4 e a 4 c 9 3 0

Nota

Si quiere que PHP sea transparente manejando el paso de variashybles a traveacutes de c o o k i e s o viacutea el meacutetodo GET necesita tener configurado PHP 5 con las directivas - e n a b l e - t r a n s - s i d y - e n a b l e - t r a c k - v a r s Si estas opciones no estaacuten activashydas el uacutenico traacutemite para utilizar variables es pasar mediante GET o POST el identificado de sesioacuten corno en el ejemplo anterior

Funciones para el manejo de sesiones

La tabla 131 muestra algunas funciones interesantes con la descripcioacuten de uso

Tabla 131 Funciones relacionadas con las sesiones

Funcioacuten Descripcioacuten

session_start() Inicia una sesioacuten y permite almacenar variables en la

estructura $ _ S E S S I O N

session_destroy() Elimina todas las variables de sesioacuten

session_name() Devuelve el nombre de la sesioacuten normalmente PHPSES-SID

session_id() Devuelve los 32 caracteres que forman el identificador de sesioacuten

242 Capiacutetulo 13

Con las funciones relacionadas en la tabla anterior podemos construir un objeto que nos facilite el manejo de sesiones en nuestras aplicaciones

ltphp class sesioacuten

function constructor()

session_start() public function set($nombre$valor)

$_SESSION[$nombre] = $valor public function get($nombre)

if (isset ($_SESSION[$nombre] ) ) return $_SESSION[$nombre]

else return false

public function borrar_variable($nombre)

unset ($_SESSION[$nombre] ) public function borrarsesiacuteon()

$_SESSION = a r r a y O s e s s i o n _ d e s t r o y ( )

gt

Las paacuteginas s e s i o n l php y s e s i o n 2 php pueden manejarse ahora con la clase que hemos creado de la siguiente forma

ltphp require_once (clase__sesion php) $sesioacuten = new sesioacuten() gt ltHTMLgt ltBODYgt ltphp $sesioacuten-gtset(nombreLuis Miguel Cabezas) $sesioacuten-gtset(edad29) $id_sesion = SID echo lta href=sesion2php$id_sesiongtPasar variablesltagt gt ltBODYgt ltHTMLgt

Sesiones y Cookies 243

Cookies

Una cookie es una pequentildea parte de informacioacuten que queda almacenashyda en el ordenador local de los usuarios de una paacutegina Web Debe conteshyner siempre un nombre y un valor Es muy usual utilizar cookies para guardar preferencias de cada usuario en el uso de una Web pero hay que tener cuidado con el nuacutemero de variables que se pueden almacenar pues norshymalmente hay un maacuteximo de 20 por dominio seguacuten el navegador

En PHP 5 la funcioacuten s e t c o o k i e () se encarga de registrar las cookies durante el enviacuteo de las cabeceras Para recuperar el valor tiene que utilizar la variable suacuteper-global $_COOKIE

setcookie()

La funcioacuten s e t c o o k i e () normalmente tiene 2 argumentos el nombre de la variable y el valor Ademaacutes podemos pasar varios paraacutemetros que permiten dar un tiempo de vida a las variables asociar un dominio o aseshygurar el enviacuteo mediante HTTPS

La tabla 132 muestra en orden todos los argumentos que puede recibir una cookie

Tabla 132 Argumentos de la funcioacuten setcookie()

Argumento Tipo Descripcioacuten -

nombre caraacutecter El nombre de la variable cookie valor caraacutecter El valor que debe almacenar la variable Si este

valor no se indica la cookie seraacute automaacuteticashymente borrada

tiempo de vida entero Indica el tiempo de vida de unacookie Si el valor es 0 la variable nunca expiraraacute Si indica un nuacutemero entero tendraacute el tiempo que la variable permaneceraacute activa El valor hay que asignarlo en tiempo absoluto (como el devuelto por la funcioacuten mkt ime ())

ruta entero Permite distinguir entre dos variables con el mismo nombre pero llamadas desde distinta ruta en el servidor La cookie nombre llamada desde la ruta fo ro seraacute distinta a la cookie nombre llamada desde la ruta usuario

244 Capiacutetulo 13

Argumento Tipo Descripcioacuten

dominio caraacutecter Asegura el dominio de servidor que puede leerla cookie

Secure entero (0 Si el argumento es 1 la cookie soacutelo seraacute enviada oacute 1) a traveacutes de una conexioacuten segura HTTPS

Borrar una cookie

Borrar una cookie es faacutecil Si llama a la funcioacuten s e t c o o k i e () con los misshymos argumentos que para habilitarla excepto el valor la variable se elimishynaraacute del sistema local del usuario Si usa los paraacutemetros r u t a y dominio deben aparecer tambieacuten y con los mismos valores

Como de costumbre vamos a implementar una pequentildea clase para maneshyjar las cookies

ltphp

class Cookie

function constructor()

El constructor no hace nada

public function set($nombre$valor$expire=0$ruta= $dominio=$seguro=0)

setcookie($nombre$valor$expire$ruta$dominio$seguro)

public function get($nombre)

if (isset ($_COOKIE [$nombre] )) return $_COOKIE[$nombre] else return false

public function borrar_cookie($nombre)

setcookie($nombre$valor$expire$ruta$dominio$seguro

gt

El argumento tiempo de vida debe proporcionarse en valor de tiempo absoluto Esto a veces puede resultar incoacutemodo y seriacutea maacutes sencillo pro-

Sesiones y Cookies 245

porcionar el tiempo de vida de la variable en minutos o segundos La clase anterior solicita el tiempo en segundos y se encarga de antildeadir esos segundos al valor absoluto haciendo maacutes simple la asignacioacuten

Para ver coacutemo funciona podemos utilizar la Web c o o k i e l php

ltphp require_once(clase_cookiephp) $cookie = new CookieO $cookie-gtset(nombreLuis Miguel10) gt ltHTMLgt ltBODYgt ltphp echo La COOKIE es $cookie-gtget(nombre) echo lta href = cookie2phpgtPasar variablesltagt gt ltBODYgt ltHTMLgt

Como puede ver es muy sencilla la asignacioacuten de cookies y su recupeshyracioacuten

Cabeceras HTTP

Las funciones s e t c o o k iacute e () o s e s s i o n _ s t a r t () introducen su conteshynido en una cabecera HTTP sin necesidad de especificacioacuten por el usuashyrio Es posible enviar cabeceras desde PHP con la utilizacioacuten de la funcioacuten h e a d e r () La funcioacuten h e a d e r () es muy simple tan soacutelo toma como arshygumento un conjunto de caracteres que seraacute la cabecera a enviar Por ejemshyplo una forma muy uacutetil de redirigir una paacutegina a otra es utilizando la cabecera Location

lt php if (isset($_GET[usuario] ) ampamp $_GET[usuario] == Luis)

header(Location httpwwwluisyfernandanet)

gt lthtmlgt ltbodygt Si ve esta paacutegina su nombre no es Luis ltbodygt lthtmlgt

Este script evaluacutea si en la variable suacuteper-global $_GET existe un identifi-cador llamado u s u a r i o y si su valor es L u i s En caso afirmativo se enviacutea

246 Capiacutetulo 13

la cabecera al navegador que invita a cargar la Web especificada En caso negativo se enviacutea la paacutegina Web que hay despueacutes de la estructura if

Este tipo de uso de las cabeceras puede servir para redireccionar a una paacutegina de error cuando un usuario intente entrar sin permiso o cometa un fallo en la entrada de un nombre o correo electroacutenico

Resumen

Las sesiones resuelven los problemas muy comunes de seguridad El uso conjunto de sesiones cookies y cabeceras HTTP permiten un control absoshyluto sobre las variables de la aplicacioacuten Casi todos los programas que necesitan autentificar un usuario (como una tienda on-line) se sirven de estas teacutecnicas Pero el lector no debe quedarse aquiacute hay muchas cabeceras distintas que pueden ser uacutetiles en diferentes momentos como la autenticacioacuten viacutea HTTP

248 Capiacutetulo 14

Introduccioacuten

XML (Lenguaje de Marcas eXtensible) forma parte de SGML (Lenguaje de Marcas Generalizado eStandar) Auacuten asiacute no es necesario saber nada de SGML para utilizar XML El lenguaje XML define una estructura de documentos que pueden ser leiacutedos por personas y por ordenadores

El camino maacutes sencillo para comprender XML es pensar en coacutemo se utilishyzan los documentos HTML Estos documentos estaacuten estructurados y funshycionan con etiquetas y atributos Las etiquetas van encerradas entre siacutembolos de mayor y menor (ltbgt) y deben cerrarse de la misma forma antildeadiendo un siacutembolo de barra invertida (ltbgt) Los documentos HTML tienen una ortografiacutea especiacutefica es decir unas reglas que definen la forshyma correcta de estructurar un documento por ejemplo la etiqueta ltBODYgt debe ir siempre despueacutes de ltHEADgt o s ino existe eacutesta de ltHTMLgt Adeshymaacutes HTML contiene un diccionario cerrado de etiquetas que definen el lenguaje y no podemos utilizar otras que no esteacuten especificadas

En cambio XML no tiene un diccionario de etiquetas Las etiquetas que aparecen son las que nosotros mismos creamos La uacutenica norma que teneshymos que seguir es que toda etiqueta de inicio (ltcoche gt) debe tener una etiqueta de fin ( lt c o c h e gt )

El documento siguiente muestra un archivo XML bien formado

ltxml version=10 gt ltbibliotecagt lttema id=informaacuteticagt

ltlibrogt lttitulogtManual Imprescindible de PHP 5lttitulogt ltautorgtLuis Miguel Cabezas Granadoltautorgt

ltlibrogt ltlibrogt

lttitulogtDelphi 7lttitulogt ltautorgtMarco Cantultautorgt

ltlibrogt ltlibrogt

lttitulogtDelphi 6 y Kylixlttitulogt ltautorgtFrancisco Charte Ojedaltautorgt

ltlibrogt lttemagt

ltbibliotecagt

Como puede ver la estructura del documento es muy similar a la de una paacutegina Web Estaacute formado por etiquetas y atributos cuya definicioacuten pueshyde inventarse sobre la marcha es decir las etiquetas lt l i b r o gt lt t i t u -

Lectura y escritura de archivos XML 249

l o gt o lt s e c c i o n gt podriacutean tener un nombre totalmente diferente pero no asiacute en HTML que estaacute obligado a mantener el lenguaje definido Algushynos navegadores como Mozilla interpretan los ficheros XML como en la figura 141

Un documento XML estaacute obligado a cumplir ciertas normas que permishyten definir un texto bien formado

bull Debe tener un uacutenico elemento raiacutez Soacutelo puede haber un par de etishyquetas que diferencien el inicio y el final del documento como en HTML donde se utiliza ltHTMLgt y lt HTMLgt

bull Los elementos deben ser hereditarios La estructura lt A x B x B gt lt Agt se permite pero no la siguiente lt A x B x A x B gt En la primera forma la etiqueta ltAgt envuelve a la etiqueta ltBgt que es la forma coshyrrecta de escribir un documento XML HTML sin embargo permite la segunda forma de componer un documento ltA HREF=indexphpgt ltBxAx Bgt

bull Todos los elementos tienen que tener una etiqueta de cierre La pareja ltt i tulogtltt i tulo es correcta HTML permite etiquetas sin cerrar como ltBgt o ltLIgt

bull Los elementos pueden tener entre las dos etiquetas cualquier tipo de contenido como lttitulogtManual imprescindible de PHP 5lttitulogt

250 Capiacutetulo 14

bull Los caracteres amp lt gt las comillas simples y las comillas dobles estaacuten prohibidas como contenido y deben utilizarse siacutembolos de escape para utilizarlas

SAX DOM y SimpleXML

Lo primero que tenemos que hacer antes de leer archivos XML es conocer las tres formas existentes con sus ventajas e inconvenientes

bull SAX Es maacutes ligero y faacutecil de aprender trata los archivos XML como un flujo de datos que se leen poco a poco

bull DOM Lee el fichero completo y crea un objeto en memoria Permite crear archivos desde cero

bull SimpleXML Es el maacutes sencillo de utilizar Los elementos se pueden leer con un simple f o r e a c h

SAX

Se utiliza para parsear elementos XML Estaacute basado en eventos lo que sigshynifica que el parse hace llamadas a determinadas funciones dependiendo de los elementos que examina

Los eventos de SAX son proporcionados por PHP en forma de funcioacuten Al parsear se reconocen piezas de XML como etiquetas de inicio o fin datos o entidades externas y cada una de estas piezas hace una llamada a un evento El procedimiento para parsear un archivo XML con SAX debe seshyguir los siguientes pasos

bull Determinar queacute clase de eventos queremos manejar

bull Escribir una funcioacuten que maneje cada evento Es muy comuacuten escribir una funcioacuten para manejar los datos y las etiquetas de inicio y de fin

bull Crear el parse usando la funcioacuten x m l _ p a r s e r _ c r e a t e () y hacer la llamada con x m l _ p a r s e ()

bull Liberar la memoria usada con la funcioacuten x m l _ p a r s e r _ f r e e ( )

Hemos creado un objeto para leer archivos XML En principio no hace gran cosa tan solo examina las etiquetas de inicio y fin y las imprime en pantalla pero con esto bastaraacute para aprender la peculiar estructura de un parse SAX

ltphp

Lectura y escritura de archivos XML 251

class xml

function construct($fichero_xml)

$this-gtfichero_xml = $fichero_xml $this-gtxml_parser=xml_parser_create()

Puesto que el parse lo creamos desde un objeto debemos registrar la incidencia con xml_set_object

xml_set_obj ect($this~ gtxml_parser$this) Funciones de callback para manejar XML mediante SAX

xml_set_element_handler($this-gtxml_parserelemento_ inicioelemento_fin) if (($fp = fopen($this-gtfichero_xmlr)))

die (Error de Entrada y Salida)

while ($datos = fread($fpfilesize($this-gtfichero_xml)))

if (xml_parse($this-gtxml_parser$datos feof($fp)))

die (Fallo en el XML) xml_error_string(xml_get_error_ code($this-gtxml_parser))

xml_parser_free($this-gtxml_parser)

function elemento_inicio ($parser$nombre$atributos)

echo $nombreltbrgt

function elemento_fin ( $parser$nombre)

echo $nombreltbrgt

$biblioteca = new xml(bibliotecaxml) gt

Si guarda la clase en un archivo llamado c l a s e _ x m l php podraacute usarla en sus proyectos tan soacutelo con instanciar el objeto Si comienza por el consshytructor veraacute que el paraacutemetro que recibe es el archivo que quiere par-sear Debe crear el parse con la f u n c i oacute n x m l _ p a r s e _ c r e a t e () y despueacutes registrarlo en PHP como un objeto mediante la funcioacuten x m l _ s e t _ o b -j e c t () Si crea un parse fuera de la estructura de un objeto no haraacute falta hacer la llamada a la funcioacuten anterior

252 Capiacutetulo 14

La funcioacuten x m l _ s e t _ h a n d l e r () indica al parse que los eventos encarshygados de encontrar las etiquetas de inicio y de fin seraacuten manejadas con las funciones que se pasan como paraacutemetro En este c a s o e l e m e n t o _ i n i c i o ( ) se ejecutaraacute cada vez que se encuentre una etiqueta de inicio y e l e m e n t o _ f in ) cuando se encuentre la etiqueta de cierre

La uacuteltima parte del constructor lee el archivo pasado como argumento y analiza los datos a traveacutes de la funcioacuten x m l _ p a r s e ( ) que inicia la seshycuencia de anaacutelisis Si ejecuta una instancia de la clase comprobaraacute que el navegador muestra todas las etiquetas de inicio y de fin con una rigurosa herencia La figura 142 muestra las etiquetas leiacutedas del archivo XML

Para poder ver los datos tiene que antildeadir una nueva funcioacuten que maneje ese evento La f u n c i oacute n x m l _ s e t _ c h a r a c t e r _ d a t a _ _ h a n d l e r () permite manejar el evento que se dispara cada vez que se encuentra un dato entre dos etiquetas Esta funcioacuten tendraacute que antildeadirla al constructor despueacutes del meacutetodo que maneja los eventos de etiquetas

xml_set_character_data_handler($this-gtxml_parserdatos)

Ademaacutes de esto tendraacute que incluir una nueva funcioacuten que se encargaraacute de mostrar los datos

function datos($parser$valor)

Lectura y escritura de archivos XML 253

echo $v9lorltbrgt

Nota

Los eventos antildeadidos deben iexcllevar Jos argumentos necesarios para recuperar los datos Cada vez que cree un par se del tipo SAX las funciones tienen que tener los paraacutemetros que indicamos en nuesshytra clase de ejemplo

Despueacutes de comprobar el funcionamiento de la clase puede modificarla para que haga algo realmente uacutetil como mostrar ordenadamente los dashytos del fichero Las funciones de la clase pueden quedar de esta forma

function elemento_inicio ($parser$nombre$atributos)

switch($nombre) case TEMA

$tema = $atributos [ ID ] bull echo Tema $temaltbrgt break

case TITULO echo ltbgt break

case AUTOR echo - break

function elemento_fin ($parser$nombre)

switch($nombre) case TITULO

echo ltbgt break

case AUTOR echo ltbrgt break

function datos($parser$valor)

echo $valor

En este caso el parser iraacute analizando las etiquetas que nos interesan y reashylizaraacute una accioacuten determinada Por ejemplo cuando se comprueba la exis-

254 Capiacutetulo 14

tencia de una etiqueta TITULO escribimos en HTML la etiqueta de negrishyta ltBgt para resaltar este dato como muestra la figura 143

Elaborando un poco maacutes la clase obtendraacute un objeto de gran utilidad que podraacute recuperar informacioacuten de bases de datos o archivos de configurashycioacuten

DOM

Esta API define un completo camino para crear definir y parsear archivos XML D O M es una recomendacioacuten del consorcio World Wide Web

La idea baacutesica consiste en que todos los archivos XML pueden verse como un conjunto de nodos que forman parte de un aacuterbol Empezando desde el elemento raiacutez del que todos los elementos nacen como hijos cualquier programa deberiacutea ser capaz de crear una estructura loacutegica del documento

La API puede utilizarse para leer archivos en memoria modificarlos y volver a escribir el archivo con los nuevos datos

DOM estaacute escrito en metodologiacutea orientada a objetos y todos los nodos son instancias de diferentes objetos

Lectura y escritura de archivos XML 255

Usar DOM para leer archivos

El siguiente coacutedigo muestra un archivo XML muy simple

ltxml version=l0 gt lttema id=informaacuteticagt

lttitulogtManual Imprescindible de PHP 5lttitulogt lttemagt

Si parseamos este documento con DOM la etiqueta t i t u l o seraacute consideshyrada un nodo y ademaacutes un hijo del nodo raiacutez que en este caso es tema Esta parte queda maacutes o menos clara debido a la jerarquiacutea de etiquetas que tiene XML La controversia llega con el texto que hay en el nodo tema que no se considera como una parte sino como un nodo independiente cuyo valor es el texto Manual I m p r e s c i n d i b l e de PHP 5 Este nodo permite recuperar el valor con el meacutetodo n o d e V a l u e

Vamos a ver los pasos necesarios para leer el archivo b i b l i o t e c a xml ya que difiere bastante la metodologiacutea con respecto a SAX

Todo es un objeto

PHP 5 implementa una clase DOM para representar los archivos XML llashymada domDocument Como ya sabe para instanciar la clase soacutelo tiene que hacer uso del operador de objetos

$biblioteca = new domDocument

La extensioacuten D O M sigue las especificaciones de XML y trata los espacios en blanco como contenido Esto significa que si entre dos etiquetas existe un espacio el contenido seraacute tratado como un objeto de texto Para evitar fallos de este tipo puede ejecutar el siguiente meacutetodo

preserveWhiteSpace = f a l s e

Lo siguiente que tendraacute que hacer es leer el archivo b i b l i o t e c a xml con el meacutetodo l o a d () del objeto $ b i b l i o t e c a Si el contenido XML se almacena en una variable puede utilizar el meacutetodo loadXML ()

$biblioteca-gtload(bibliotecaxml)

A partir de aquiacute ya puede recuperar el contenido del fichero atendienshydo a sus preferencias En SAX teniacutea que leer el documento completo e ir preguntando etiqueta por etiqueta para averiguar todos los autores que estaban dados de alta en el archivo XML En D O M puede recupeshyrar esta informacioacuten usando g e t E l e m e n t s B y T a g n a m e () que devuelshyve un conjunto de objetos que coinciden con la etiqueta que pase como paraacutemetro

256 Capiacutetulo 14

ltphp Instanciamos el objeto $biblioteca = new domdocument Anulamos la posibilidad de que un espacio en blanco sea un obj eto $biblioteca-gtpreserveWhiteSpace = false Leemos el archivo XML $biblioteca-gtload(bibliotecaxml) Buscamos todas las etiquetas libro $libros = $biblioteca-gtgetElementsByTagname(libro) Imprimimos todos los libros foreach ($libros as $libro)

echo $libro-gtfirstChild-gtnodeVaiue ltbrgt

gt

La variable $ l i b r o s es en realidad un objeto de la clase d o m n o d e l i s t y guarda una relacioacuten de nodos cuya etiqueta es l i b r o es decir hemos seleccionado todos los libros del archivo Con un bucle f o r e a c h podeshymos sacar todos los valores Antes vimos que el texto asociado a un nodo es un nodo hijo con un valor determinado por eso debe llamar al meacutetodo f i r s t C h i l d

El hijo de la etiqueta l i b r o es el texto asociado y su valor lo podemos recibir llamando a n o d e V a l u e

El resultado es la lista de libros

Manual Imprescindible de PHP 5 Delphi 7 Delphi 6 y K y l i x

Atributos

Para recuperar los atributos de los nodos estaacute el meacutetodo g e t A t t r i b u -te ( ) al que tiene que pasar como argumento el nombre del atributo El archivo b i b l i o t e c a xml tiene una uacutenica etiqueta con el atributo id pero nos sirve para mostrar coacutemo funciona el meacutetodo

ltphp $biblioteca = new domdocument -$biblioteca-gtpreserveWhiteSpace = false $biblioteca-gtload(bibliotecaxml) $temas = $biblioteca-gtgetElementsByTagname(tema) foreach ($temas as $tema)

echo $tema-gtgetAttribute(id)

gt

El resultado es el nombre del tema o temas que esteacuten almacenados

Lectura y escritura de archivos XML 257

Buacutesquedas muacuteltiples

Nuestro objetivo final es mostrar todos los tiacutetulos con sus autores ordeshynados por temaacutetica Conociendo ya los meacutetodos principales para recorrer los objetos DOM es sencillo pensar en un coacutedigo que implemente lo que pedimos

ltphp $biblioteca = new domdocument Sbiblioteca-gtpreserveWhiteSpace = false $biblioteca-gtload(bibliotecaxml) $biblioteca-gtdocumentElement $temas = $biblioteca-gtgetElementsByTagname(tema)bull foreach ($temas as $tema)

echo Tema $tema-gtgetAttribute(id) ltbrgt $libros = $tema-gtgetElementsByTagname(libro) foreach ($libros as $libro)

echo ltbgt $libro-gtfirstChild-gtnodeValue ltbgt - $autores = $libro-gtgetElementsByTagname(autor) foreach ($autores as $autor)

echo $autor-gtfirstChild-gtnodeValue ltbrgt

gt

Aunque es un poco maacutes complejo el fundamento baacutesico es ir utilizando bucles para leer los hijos de un nodo determinado hasta recuperar todos los datos necesarios

Escribir archivos XML con DOM

D O M permite hacer maacutes cosas que la simple impresioacuten de los datos en pantalla Se puede utilizar para crear nuevos documentos con el nivel de jerarquiacutea que quiera Para hacer esto debe apoyarse en la creacioacuten de obshyjetos de la clase domElement ()

Vamos a crear un script para crear el siguiente archivo XML ltxml ve r s ion=1 0gt lt b i b l i o t e c a gt

lttemagtTextolttemagt lt b i b l i o t e c a gt

Para crearlo necesita instanciar una serie de objetos que empieza por la creacioacuten de un documento DOM mediante la utilizacioacuten del objeto d o shymdocument ()

ltphp

258 Capiacutetulo 14

$biblioteca = new doradocument(10) $raiz = new domelement(biblioteca) $raiz = $biblioteca-gtappendChild($raiz) $tema = new domelement(temaTexto) $tema = $raiz-gtappendChild($tema) $biblioteca-gtsave(bibliotecaxml) gt

La variable $ r a i z es el objeto que contendraacute todo el documento Para crear las etiquetas tiene que utilizar el meacutetodo a p p e n d C h i l d ( ) El objeto que llama al meacutetodo contendraacute como hijo al elemento que se pasa como paraacuteshymetro

Si se fija en el ejemplo $tema es un nuevo elemento que tendraacute la etiqueshyta tema

Para que $tema sea un hijo de la raiacutez debe hacer que el objeto padre $ r a i z llame al meacutetodo a p p e n d C h i l d () con el paraacutemetro $tema

Para grabar el resultado final el objeto D O M tiene que llamar al meacutetodo s a v e ( ) El fichero b i b l i o t e c a xml lo puede crear con el coacutedigo sishyguiente

ltphp $biblioteca = new domdocument(10) $raiz = new domelement(biblioteca) $raiz = $biblioteca-gtappendChild($raiz) $tema = new domelement(tema) $tema = $raiz-gtappendChild($tema) $tema-gtsetAttribute(idinformaacutetica) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloManual Imprescindible de PHP 5 bull $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autor Luis Miguel Cabezas Granado) $autor = $libro-gtappendChild($autor) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloDelphi 7 ) $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autorMarco Cantu) $autor = $libro-gtappendChild($autor) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloDelphi 6 y Kylix) $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autor Francisco Charte Ojeda) $autor = $libro-gtappendChild($autor) $biblioteca-gtsave(bibliotecaxml) gt

Lectura y escritura de archivos XML 259

El conjunto de liacuteneas de coacutedigo anterior crea un archivo completo XML Quizaacute sea mejor dividir el texto en funciones recursivas que permitan teshyclear menos a la hora de crear los documentos pero eso ya es trabajo para el lector El meacutetodo s e t A t t r i b u t e () antildeade un atributo al objeto que hace la llamada el primer argumento seraacute el nombre del atributo y el segundo su valor La llamada a domelement () puede tener uno o dos valores Si lleva un atributo significaraacute que el nombre de la etiqueta seraacute ese paraacutemeshytro Si se llama con dos paraacutemetros el primero seraacute el nombre de la etiqueta y el segundo un objeto de texto que se antildeadiraacute como texto hijo del nodo

Modificar archivos XML

La verdadera potencia de D O M reside en el poder de gestionar los archishyvos para antildeadir modificar o eliminar nodos La mayoriacutea de los algoritmos que realizan alguna de estas operaciones se basan en la buacutesqueda de los nodos para posteriormente antildeadir hijos nuevos o eliminar los encontrashydos Para antildeadir nuevos elementos se hace como cuando creamos el ficheshyro b i b l i o t e c a xml con el meacutetodo a p p e n d C h i I d ( ) Antes de antildeadir nuevos nodos tiene que localizar el lugar exacto donde quiere antildeadir las etiquetas El ejemplo siguiente muestra coacutemo antildeadir un nuevo nodo tema

ltphp $biblioteca = new domdocument(10) $biblioteca-gtload(bibliotecaxml) $raiz = $biblioteca-gtdocumentElement $tema_nuevo = new domelement(tema) $tema_nuevo = $raiz-gtappendChild($tema_nuevo) $tema_nuevo-gtsetAttribute (id ficcioacuten ) $biblioteca-gtsave(biblioteca2xml) gt

Los pasos son los que ya ha aprendido Cargue el documento y cree un objeto llamado $ r a i z que se convierta en la etiqueta raiacutez mediante el meacutetodo documentElement Cree un nuevo elemento del tipo tema y antildeaacuteshydalo para despueacutes insertar el atributo que se necesita Por uacuteltimo guarde el archivo en el fichero b i b l i o t e c a 2 xml

SimpleXML

Probablemente el punto maacutes fuerte de PHP 4 fue la incorporacioacuten de heshyrramientas para el soporte de XML PHP 5 le da una vuelta maacutes a la tuerca

260 Capiacutetulo 14

implementando nuevas herramientas de lectura elaboracioacuten y modificashycioacuten de archivos XML basado en la libreriacutea l i b x m l 2 y una nueva API llamada SimpleXML

Si XML es un lenguaje bien construido y legible por personas y ordenadoshyres los programas para manipular estos archivos deberiacutean ser tambieacuten sencillos de utilizar SimpleXML nace con esta premisa permitiendo leer un fichero completo con una sola instruccioacuten e inmediatamente despueacutes poder leer los datos como conjunto de variables PHP

El conjunto de funciones que pertenece a la API SimpleXML es nuevo en PHP 5 Mantiene una absoluta flexibilidad a favor de la simplicidad y bajo nivel de memoria usado SimpleXML utiliza el menor nuacutemero de liacuteneas de coacutedigo para leer o escribir datos en un fichero XML El e jemplo s iguiente muestra coacutemo p o d e m o s parsear el a rch ivo b i b l i o t e c a xml

ltphp $biblioteca = simplexTnl_load_fiie(bibliotecaxml) foreach ($biblioteca-gttema as $tema)

echo Tema es $tema[id] ltbrgt foreach ($tema-libro as $libro)

echo ltbgt $libro-gttitulo ltbgt -

echo $libro-gtautor ltbrgt

gt

Lo primero que llama la atencioacuten es que en apenas 10 liacuteneas de coacutedigo se ha conseguido extraer todos los datos necesarios a diferencia de SAX o DOM

La funcioacuten s implexml__load_f i le () crea un objeto con el archivo XML que pase como argumento

A partir de aquiacute puede acceder a todos los datos asiacute como acceder a las variables de los objetos

echo $biblioteca-gttema-gtlibro [0] -gttitulo echo $biblioteca-gttema-gtlibro[1]-gttitulo

Para extraer el contenido que necesita lo maacutes sencillo es crear una estrucshytura de bucles f o r e a c h para ir sacando los datos ordenados

El nombre SimpleXML es totalmente descriptivo aunque no hay que conshyfundir la palabra simple con baacutesico La prueba de su potencia estaacute en que los desarrolladores de PEAR van a utilizar SimpleXML para desarrollar su libreriacutea de SOAP

Lectura y escritura de archivos XML 261

Resumen

XML se ha convertido en un estaacutendar para el intercambio de informacioacuten en Internet Numerosas aplicaciones estaacuten construidas con alguacuten tipo de tecnologiacutea que implementa XML como XML-RPC RSS o SOAP

En este capiacutetulo ha aprendido a leer y escribir documentos de tres formas posibles La maacutes completa sin duda es DOM que permite ademaacutes de leer archivos escribir y modificarlos a nuestro antojo El problema es que pueshyde resultar algo complicado de entender al principio y quizaacute no merezca la pena en aplicaciones sencillas

En el capiacutetulo siguiente conoceraacute la verdadera aplicacioacuten praacutectica Basaacutenshydonos en SimpleXML y en DOM crearemos algunas clases para leer archishyvos de noticias o ejecutar funciones definidas en un ordenador remoto

264 Capiacutetulo 15

Introduccioacuten

Existen en el mercado muchas publicaciones que hablan sobre XML y sus tecnologiacuteas derivadas En estos libros que suelen ser de unas 1000 paacuteginas se hace un recorrido por todos los rincones de XML DTD XLST etceacutetera Si lee alguna publicacioacuten de este tipo puede quedar desencanshytado porque entre tantos conceptos no se ve una aplicacioacuten real de la tecnologiacutea

Como este libro es eminentemente praacutectico me gustariacutea que el lector aprenshydiera dos metodologiacuteas que se utilizan actualmente en la Web RSS y XML-RPC La primera describe una forma de exportar informacioacuten noticias o datos al exterior para que desde cualquier paacutegina Web puedan leerse La segunda es una forma de trabajar que permite ejecutar funciones que esshytaacuten almacenadas en un ordenador remoto

Compartir informacioacuten con RSS

RSS es un mecanismo para publicar informacioacuten sobre el contenido de un sitio Web y es muy comuacuten utilizarlo para dar las uacuteltimas noticias Esto permite introducir en su sitio Web un documento XML con noticias de otras paacuteginas

La versioacuten original de RSS la 090 fue creada por Netscape con el objetishyvo de crear portales servidores de noticias de distinta categoriacutea pero reshysultoacute algo complejo de utilizar La versioacuten 091 mucho maacutes simple la desarrolloacute la empresa UserLand Software quien lo comercializoacute como parte de sus productos basados en paacutegina Web como los Weblogs

Un tercer grupo de desabolladores independientes basaacutendose en los coshymienzos de RSS la versioacuten 090 escribioacute una nueva revisioacuten basada en RDF esta versioacuten recibe el nombre de RSS 10 Desde la aparicioacuten de la versioacuten 01 UserLand Software ha seguido desarrollando las versiones 092 093 094 y la 20

Distintos formatos

Existen 7 formatos distintos y como programador deberiacutea ser lo suficienshyte habilidoso como para manejar cualquiera de ellos Pero como el conteacute-

Aplicaciones praacutecticas de XML 265

nido lo produce la Web que desea exportar su informacioacuten tendraacute que tener en cuenta las caracteriacutesticas de cada formato

Tabla 151 versiones de RSS

Versioacuten Desarrollo Descripcioacuten Status Recomendacioacuten

090 Netscape Obsoleta No usar por la apashyricioacuten de 10

091 UserLand Simple Muy popular Sencilla y faacutecil de pero obsoleta migrar a la versioacuten por la aparicioacuten 20 de 20

092 UserLand Permite texto Obsoleto por Mejor usar la 20 093 enriquecido y la 20 094 metadatos

10 Grupo de Basado en Muy estable Usar si necesitamos desarrollo RDF y exten- especificaciones RSS-DEV sible con avanzadas

moacutedulos

20 UserLand Exter=Aacuteble corraquo EsteWe y ef Uso de caraacutecter moacutedulos Faacutecil continuo general con meta-de migrar desarrollo datos y texto enri-desde cualquier quecido versioacuten 09

Como ejemplo vamos a leer el RSS 10 de la Web del autor wwwluisy fernandanet que contiene esta informacioacuten

ltxml version=10 encoding=iso-8859-1 gt ltrdfRDF xmlnsrdf=httpwwww3org19990222 -rdf-syntax-ns xmlns=httpmynetscapecomrdfsimple09gt

ltchannelgt lttitlegtwwwluiacutesyfernandanetlttitlegt ltlinkgthttpwwwluisyfernandanetiacutendexphp

blogId=2ltlinkgt ltdescriptionxdescriptiongt

ltchannelgt ltitemgt

lttitlegtPHP 5 en la liacutenea de salidalttitlegt ltdescriptiorvgtiacuteuumladi Gutwampias dice que en 24 horas estaraacute lista la nueva versioacuten de PHP5 bull que nervios ampltbr

266 Capiacutetulo 15

ampgtPara el que no pueda esperar la Releacutease Candidate 4 estaacute en amplta href =ampquothttp snapsphpnet~andiampquotampgthttpsnapsphpnet ~andiampltaampgtampltbrampgt ampltbrampgtampltbrampgtlt descriptiongt

ltlinkgthttpwwwluisyfernandanetiacutendexphpop=View ArticleampamparticleId=41ampampblogId=2ltlinkgt ltitemgt

lt itemgt lttitlegtGalopiacuten 10lttitlegt ltdescriptiongt amplt a

href=ampquothttpwwwluisyfernandanetresserverphp blogId=2amp amp resource=DSCN0840 JPG ampquot ampgt amplt img align=ampquot rightampquot style=ampquotmargin 5pxampquot border=ampquotOampquot alt=ampquotRueda de prensaampquot src=ampquothttpwwwluisyfernandanetresserver phpblogId=2ampampresource=DSCN0 840JPGampampmode=previewampquot ampgtampltaampgt

Hoy se ha presentado en la AAVV de La Antigua en Meacuterida la versioacuten 10 de Galopiacuten una herramienta escrita en PHP por dos desarrolladores extrementildeos Tras los forcejeos con la prensa y las salidas con quite de los implicados nos quedamos con la miel en los labios deseando probar la aplicacioacuten y porqueacute no destriparla para ver como funciona el chismeampltbr ampgtEl que quiera descargarla puede hacerlo desde la Web de sinuh en amplta href=ampquothttp galopinsinuhorgampquotampgtgalopinsinuhorgampltaampgtampltbr

ampgtScltbxSiacutegpound ampltbr ampgtltdescriptiongt ltlinkgthttpwwwluisyfernandanet

indexphpop=ViewArticleampamparticleld=4 0ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtEL TIEMPO DE MERIDAlttIacutetlegt ltdescriptiongt Hace unos diacuteas empeceacute escribir alguna cosilla para averiguar

la temperatura que hay en Meacuterida Los datos los recojo de la Web del Instituto Nacional de Meteorologiacutea y los plasmo en una tabla Si quieres puedes utilizar los datos llamando a la Web amplt a href = ampquothttpwwwluisyfernandanet clase_tiempophpLOCALIDAD=MERIDAampquotampgthttp wwwluisyfernandanetclase_tiempophpLOCALIDAD=MERIDAamplt aampgtampltbr ampgtDonde pone LOCALIDAD se puede poner alguna poblacioacuten distinta como CORIA CACERES BADAJOZUNIVERSIDAD etcampltbr ampgtEl moacutedulo estaacute en fase alfa y el dibujito que aparece puede que no corresponda con la realidad pero es un avance )ampltbr ampgtEn unas semanas implementareacute el servicio en SOAP como lo hace weathercomampltbr ampgtSaludosampltbr ampgtampltbr ampgtampltbr ampgtampltbrampgt

Aplicaciones praacutecticas de XML 267

ampltbr ampgtltdescriptiongt ltlinkgthttpwwwluisyfernandanet

indexphpop=ViacuteewArticleampamparticleld=3 6ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtPHP 5 a punto de caramelolttitlegt ltdescriptiongtHace un par de diacuteas en la lista interna de

desarrolladores de PHP Andi Gutmans ha escrito que PHP5 ya estaacute horneado y le falta un poquito de chocolate para salir al mercado Estaacuten teniendo alguacuten problemilla con libreriacuteas que controlan el acceso a memoria pero se preveacute que la primera versioacuten estable salga esta semana ampltbr ampgtamplta href=ampquothttpwwwzendcomlistsphp-dev2004 07 msg00059htmlampquot ampgtNotica de Zend ampltaampgtampltbr ampgtampltbr ampgtltdescriptiongt

ltlinkgthttpwwwluisyfernandanet indexphpop=ViewArticleampamparticleld=3 3ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtOpenOffice2htm en Sourceforgelttitlegt ltdescriptiongt Acaban de aceptar el Proyecto OpenOffice2htm

en sourceforge ellos sabraacuten lo que hacen Lo que pasa es que tengo un pequentildeo problema entre tanto menuacute de administracioacuten de ficheros documentos etc me pierdo y por ahora no he podido subir ninguacuten fichero de la clase Espero aclararme estos diacuteas y tener listo la primera Releacutease en amplta href=ampquothttpwwwluisyfernandanet wwwsourceforgecomampquotampgtwwwsourceforgecomamplt aampgtampltbr ampgtampltbrampgtampltbr ampgtltdescriptiongt

ltlinkgthttpwwwluisyfernandanet indexphpop=ViewArticleampamparticleld=17ampampblogId=2ltlinkgt ltitemgt ltrdfRDFgt

El archivo anterior muestra las uacuteltimas noticias de la Web www lu i sy fernadanet sobre PHP y proyectos en los que el autor estaacute involucrado

Si se fija no es maacutes que un archivo XML con un formato determinado

Puede verlo en la figura 151

Tiene dos partes diferenciadas

bull Una parte de descripcioacuten del documento entre las etiquetas ltchan-n e l gt En esta zona puede encontrar el tiacutetulo de Web donde estaacuten las noticias la URL del archivo RSS y una descripcioacuten de la temaacutetica que aborda

bull Otra zona entre los nodos lt i t emgt que contiene todas las noticias que quiere exportar

Leer un archivo RSS

En el capiacutetulo anterior vimos coacutemo parsear un archivo XML creado por nosotros mismos Esta vez tenemos que extraer el contenido que nos inshyteresa de un archivo con un formato determinado Vamos a crear un peshyquentildeo objeto que sea capaz de insertar en nuestra Web las noticias de la paacutegina wwwluisyfernandanet Por supuesto vamos a utilizar SimpleXML por ser una de las herramientas estrella de PHP 5

ltphp class SimpleRSS

priacutevate $RSS function construct($fichero)

$this-gtRSS = simplexml_load_file($fichero)

public function parsea_item() foreach ($this-gtRSS-gtitem as $item)

$this-gtparsea_titulo($item) $this-gtparsea_descripcion($item) $this-gtparsea_enlace($item)

private function parsea_titulo($item)

Aplicaciones praacutecticas de XML 269

echo $item-gttitle bull ltbrgt echo lthrgt

priacutevate function parsea_descripcion ($item)

echo $item-gtdescription ltbrgt

priacutevate function prsea_enlace($item)

echo $item-gtlink bull ltbrgt

public function paiacutesea_cabecera()

ampc^o Titilo- laquo St^va-^SSS-gtet^trade^l-gttltLe -JaxV- echo Web $this-gtRSS-gtchannel-gtlink ltbrgt echo lthrgt

$RSS = new SimpleRSS(httpwwwluisyfernandanet rssphpcategoryId = 3ampblogId=2 ) $RSS-gtparsea_cabecera () $RSS-gtparsea_item() gt

Si ejecuta el programa tendraacute como resultado las uacuteltimas noticias sobre PHP del portal wwwluisyfernandanet separadas por liacuteneas horizontashyles El meacutetodo puacuteblico p a r s e a _ i t e m () es el encargado de extraer notishycia a noticia y mandarlas al navegador Este meacutetodo hace 3 llamadas a 3 meacutetodos distintos que se encargan de recuperar el tiacutetulo el enlace a la noticia y la descripcioacuten Hemos separado los meacutetodos para que cada lector personalice la forma de visualizar los distintos datos Mi forma particular puede verla en la fishygura 152 Por ejemplo el tiacutetulo podriacutea mostrarlo en azul y el texto en gris todo metido en una tabla-

Escribir archivos RSS

Los archivos XML y en particular los archivos RSS pueden generarse de la misma forma que creamos un fichero de texto antildeadiendo etiquetas con cierto criterio a un archivo de texto pero la opcioacuten maacutes correcta es utilizar DOM para generar nuestros propios documentos de noticias Como ya sabe la extensioacuten DOM permite antildeadir borrar y modificar eleshymentos a lo largo de un documento en cualquier orden

Para este cometido tenemos la siguiente clase que nos va a generar docushymentos RSS a partir de cualquier fuente de datos

ltphp class GeneraRSS

priacutevate documento private $raiz priacutevate $channel private $titulo private $enlace private descripcioacuten private $item function construct() $this-gtdocumento = new domdocument(1bull0 ) $this-gtinicio ( )

private function inicio() $this-gtraiz = $this-gtdocumento-gtcreateElement(rdfRDF ) $this-gtraiz-gtsetAttribute(xmlnsrdfhttpwwww3org1999 0222-rdf-syntax-ns) $this-gtraiz-gtsetAttribute(xmlnshttppurlorgrss10) $this-gtraiz = $this-gtdocumento-gtappendChild($this-gtraiz)

Aplicaciones praacutecticas de XML 271

pub l i c funct ion c a n a l ( $ t i t u l o $ e n l a c e $ d e s c r i p c i o n $ s o b r e )

$this-gtchannel = $this-gtdocumento-gtcreateacuteElement(channel) $this-gtchannel = $ th i s -gtra iz -gtappendChi ld ($ th i s -gtchanne l ) $ th i s -gt t i tu lo=$th i s -gtdocumento-gtcrea teElement ( t i t l e ) $ th i s -gt tex to t i t u lo=$ th i s -gtdocumen to -gtc rea t eTex tNode($ t i tu lo ) $ t h i s - gt t i t u l o - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o t i t u l o ) $ t h i s - gt c h a n n e l - gt a p p e n d C h i l d ( $ t h i s - gt t i t u l o ) $ t h i s - gt e n l a c e = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l s m e n t ( l i n k ) $ th i s -gt tex toen lace=$th i s -gtdocumento-gtcrea teTextNode($en lace) $ t h i s - gt e n l a c e - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o e n l a c e ) $ th i s -gtchanne l -gtappendChi ld ($ th i s -gten lace ) $ t h i s - gt d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( d e s c r i p t i o n ) $ t h i s - gt t e x t o d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e T e x t N o d e ( $ d e s c r i p c i o n ) $ t h i s - gt d e s c r i p c i o n - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o d e s c r i p c i o n $ th i s -gtchanne l -gtappendCh i ld ($ th i s -gtdesc r ipc ion )

pub l i c funct ion i t em_nuevo($ t i tu lo $en lace $descr ipcion)

$this-gti tem = $this-gtdocumento-gtcreateElltment( i tem) $ this-gti tem = $ th i s -gtra iz -gtappendChi ld ($ th i s -gt i t em) $ t h i s - gt t i t u l o = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( t i t l e ) $ th i s -gt t ex to t i t u lo=$ th i s -gtdocumen to -gtc rea t eTex tNode ($ t i t u lo ) $ t h i s - gt t i t u l o - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o t i t u l o )

$ t h i s - gt i t e m - gt a p p e n d C h i l d ( $ t h i s - gt t i t u l o ) $ t h i s - gt e n l a c e = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( l i n k ) $ th i s -gt tex toen lace=$th i s -gtdocumento-gtcrea teTextNode($en lace) $ t h i s - gt e n l a c e - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o e n l a c e ) $ t h i s - gt i t e m - gt a p p e n d c h i l d ( $ t h i s - gt e n l a c e ) $ t h i s - gt d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( d e s c r i p t i o n ) $ t h i s - gt t e x t o d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e T e x t N o d e ( $ d e s c r i p c i o n ) $ t h i s - gt d e s c r i p c i o n - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o d e s c r i p c i o n ) $ t h i s - gt i t e m - gt a p p e n d C h i l d ( $ t h i s - gt d e s c r i p c i oacute n ) $ th i s -gt i t ems [ ]=$ th i s -gt i t em

public function grabar($fichero) $this-gtdocumento-gtsave($fichero)

^documento = new GeneraRSS () ^documento-gtcanal (wwwluisyfernandanet httpwwwluisy fernandanet La Web del auto) $docimeito-gtitev1_YYievo VMaiwial Imprescindible de PHP 5 http- v iwwluisyfernandanet Ya a la v e n t a )

272 Capiacutetulo 15

$documento-gtitem_nuevo(Nueva releacutease de PHP 5http wwwiuisyfernandanetLa nueva releacutease corrige algunos fallos) Sdocumento-gtgrabar(miRSSxml) gt

La clase anterior se puede guardar en un archivo independiente y utilizar cuando sea necesario en el transcurso de un proyecto

Aunque no implementa todas las especificaciones de RSS 10 puede utilishyzarse para generar noticias de nuestra base de datos

Nota

Si desea modificar ia ciase para que contemple todas las opciones de Ja especificacioacuten RSS 10 puede visitar ia Web httpllpurtorgl rss10

En el capiacutetulo anterior vimos coacutemo se puede generar un archivo XML con una sucesioacuten de llamadas a meacutetodos Esta vez hemos encapsulado todas las llamadas en varios meacutetodos que se encargan de generar la parte de descripcioacuten del RSS y por otro lado las noticias

El meacutetodo c r e a t e E l e m e n t () se encarga de crear nuevos nodos para desshypueacutes encadenarlos c o n a p p e n d C h i l d () a los nodos padre Para crear un nodo de texto sin embargo tenemos que utilizar el meacutetodo c r e a t e T e x t -Node () una vez creado el nodo de texto tenemos que asociarlo a un nodo-elemento (una etiqueta)

El uacuteltimo paso es hacer una llamada al meacutetodo s a v e () con el nombre del fichero como paraacutemetro para guardar el archivo RSS

Servicios Web XML-RPC

El trabajo como programador puede llevarle a desarrollar aplicaciones para distintos Sistemas Operativos y en distintos lenguajes de prograshymacioacuten

Si en alguacuten momento necesita comunicar dos programas que estaacuten funshycionando en maacutequinas distintas (un servidor Windows y otro gnuLinux) y escritos con lenguajes diferentes puede que XML-RPC sea la solucioacuten perfecta

El mecanismo permite que el ordenador cliente pueda acceder a los meacutetoshydos del ordenador servidor y ejecutar rutinas almacenadas remotamente

Aplicaciones praacutecticas de XML 273

Este apartado muestra alguacuten ejemplo de coacutemo implementar y explotar un servicio Web con la libreriacutea de clase IXR creada por Simoacuten Willison bajo el auspicio de Open Source

Una llamada XML-RPC consiste en dos partes una pregunta y una resshypuesta

Cada una de las partes es un archivo XML que contiene los paraacutemetros solicitados al servidor o los datos devueltos

Una pregunta al servidor puede ser como la que sigue

ltmethodCalIgt ltmethodNamegtconteritgetNotiacuteciasltmethodNamegt ltparamsgt

ltparamgt ltvaluexintgt23ltiacutent gtltvaluegt

ltparamgt ltparams gt

ltmethodCallgt

Como puede ver es un archivo XML con una definicioacuten determinada La etiqueta ltmethodNamegt contiene el nombre del meacutetodo que debe llamarse en el servidor y ltparamgt contiene un paraacutemetro que se le pasaraacute al meacutetoshydo de la llamada

El documento anterior seraacute transmitido viacutea HTTP mediante POST al sershyvidor de XML-RPC que parsearaacute el documento ejecutaraacute la funcioacuten y devolveraacute un documento similar con los datos de la respuesta

Clase IXR

IXR es un conjunto de clases que implementa un servidor y un cliente de XML-RPC

Nota

Puede encontrar la libreriacutea en la Web httpscriptsiricutiocom xmlrpc o en la paacutegina del libro en httpunuzunnaiamulti-mediacom

Lo mejor de la programacioacuten orientada a objetos es que no necesita saber coacutemo funcionan las clases que utilice soacutelo conocer el uso correcto de los meacutetodos Asiacute puede utilizar la clase IXR de la manera que vamos a ver sin conocer siquiera el formato de los archivos XML-RPC

274 Capiacutetulo 15

Cliente XML-RPC

Los servicios XML-RPC tienen una direccioacuten Web con una paacutegina Web escrita en PHP Si escribe la direccioacuten completa en el navegador se proshyduciraacute un error porque la Web esperaraacute que mande mediante POST un archivo XML Para utilizar sus servicios Web o los servicios Web de alshyguna empresa como UserLand tiene que utilizar un cliente XML-RPC escrito en este caso en PHP 5 En este caso vamos a utilizar la clase IXR__Client de la libreriacutea IXR El ejemplo muestra coacutemo utilizar el cliente en varios pasos

bull Crear un objeto cliente con la URL pasada como paraacutemetro

bull Usar el meacutetodo q u e r y () para hacer la consulta al servicio Web

bull Extrae el resultado con el meacutetodo g e t R e s p o n s e ()

Lo primero que vamos a hacer es implementar un pequentildeo objeto para recuperar la fecha de un servidor remoto

ltphp require_once(IXR_Libraryincphp) class XMLRPCFechacliente

private $cliente function construct($url$debug=false) $this-gtcliente= new IXR__Client ($url) $this-gtcliacuteente-gtdebug=$debug

function getFecha($argumentol) if ($this-gtcliente-gtquery(fechagetFecha$argumentol)) trigger_error($this-gtcliente-gtgetErrorCode () $this-gtcliente-gtgetErrorMessage()) return false

return $this-gtcliente-gtgetResponse ()

gt

La clase X M L R P C F e c h a c l i e n t e implementa dos meacutetodos El construcshytor crea un objeto cliente IXR que recibe el servidor de servicios Web El meacutetodo g e t F e c h a () tramita la peticioacuten de la fecha con el servidor y obshytiene una respuesta que devuelve a la paacutegina Web Si todo va bien el sershyvidor enviaraacute la fecha del lugar donde esteacute

La llamada a q u e r y () tiene como paraacutemetro primero el nombre del meacuteshytodo que debe ejecutar el servidor y como segundo paraacutemetro un argu-

Aplicaciones praacutecticas de XML 275

mentoacute que puede pasarse La Web que quiera mostrar esta informacioacuten debe crear el objeto anterior maacutes o menos como se muestra en el siguiente ejemplo

ltphp require_once(XMLRPCFechaclientephp) $servidor=httpwwwluisyfernandanetFechaphp $fechaRemota= new XMLRPCFechacliente($servidor) echo $fechaRemota-gtgetFecha(Hoy) gt

Si evaluacutea el coacutedigo en tan soacutelo 4 liacuteneas puede recibir cualquier tipo de informacioacuten que el servidor tenga Para ello debe crear una variable que contenga el nombre del servidor y la paacutegina PHP que contiene el prograshyma de respuesta La instanciacioacuten del objeto X M L R P C F e c h a c l i e n t e y la llamada al meacutetodo g e t F e c h a () es suficiente para desencadenar la coshynexioacuten con el servidor

Servidor XML-RPC

En el apartado anterior ha visto que puede utilizar servicios Web ofrecishydos por otras empresas para averiguar la hora de un Paiacutes remoto el camshybio de moneda el tiempo o incluso el cataacutelogo de libros de una conocida tienda on-line Pero lo realmente interesante es poder crear sus propios servicios Web

La clase IXR_Server hace la mayoriacutea del trabajo por usted que puede emplear el tiempo en inventar nuevos servicios Web

Hemos creado una clase que implementa el servicio g e t F e c h a ( ) que el objeto cliente utiliza

ltphp require_once(IXR_Libraryincphp) class XMLRPCFechaservidor extends IXR_Server

function construct()

$this-gtIXR_Server(array(fechagetFecha =gt thisgetFecha)) function getFecha($argumentol)

if ($argumentol==Hoy) $fecha = La fecha remota es date(d-m-Y)

else

$fecha = Especifique un dia

2 7 6 Capiacutetulo 15

re turn $fecha

gt

La clave para entender el funcionamiento del servidor estaacute en el construcshytor Aquiacute se crea un array con el nombre de los meacutetodos que se pueden utilizar desde fuera

El primer valor f e c h a g e t F e c h a es el nombre que el cliente debe emshyplear para recuperar la Fecha del Servidor y el segundo valor t h i s g e t Fecha es el meacutetodo perteneciente al servidor que se ejecutaraacute cuando reciba una pregunta a esa funcioacuten

La figura 153 muestra el dato que obtiene el cliente

La definicioacuten del meacutetodo que enviacutea la fecha se hace como ya estamos acosshytumbrados

Lo que hemos visto es soacutelo la definicioacuten de la clase pero necesitamos una paacutegina Web de apoyo que instancie el objeto y lo ejecute Puede ser tan sencillo como

ltphp require_once(XMLRPCFechaservidorphp) $servidor= new XMLRPCFechaservidor() gt

Aplicaciones praacutecticas de XML 277

Usos de XML-RPC

Los ejemplos que hemos visto no son especialmente excitantes pero dan una idea de lo sencillo que es exportar cualquier tipo de informacioacuten La verdadera potencia de los servicios Web es que permiten disfrutar de nueshyvas funcionalidades de las que no disponemos Podriacuteamos crear un servishycio Web que permitiera a usuarios de PHP 4 utilizar nuestro objeto de SimpleXML pero esto lo dejo en manos del lector

Resumen

XML se ha convertido en los uacuteltimos antildeos en un estaacutendar libre para el inshytercambio de informacioacuten Incluso Microsoft poco amiga de los archivos abiertos estaacute implementando servicios en XML con su plataforma NET

Despueacutes de leer este capiacutetulo podraacute crear elegantes paacuteginas que contenshygan noticias relevantes sobre cualquier tema y exportarlas a otras paacuteginas amigas gracias a la tecnologiacutea RSS

En cuanto a la creacioacuten de servicios Web existe una controversia entre dos desarrollos principales XML-RPC y SOAP de Microsoft SOAP (Simshyple Object Access Protocol) es una implementacioacuten muy extensa de Microshysoft para la creacioacuten de servicios Web Pese a que su definicioacuten aboga por la simpleza (Protocolo Simple) la paradoja es que es mucho maacutes complishycada de utilizar que XML-RPC y por eso se escapa de los objetivos de este libro

Una de las nuevas caracteriacutesticas de PHP 5 es la inclusioacuten de una extenshysioacuten para la generacioacuten de servidores y clientes SOAP pero todaviacutea estaacute en fase experimental

El futuro cercano puede estar en SOAP asiacute que recomiendo al lector visishytar algunas paacuteginas Web sobre el tema para comenzar a entender su funshycionamiento

280 Capiacutetulo 16

Introduccioacuten

La construccioacuten de un sitio Web no soacutelo debe contar con textos bases de datos y funciones escritas en PHP para manejar los datos Existe un gran abanico de posibilidades que pueden dotar a la paacutegina de contenido multishymedia (imaacutegenes v sonidos) y que ademaacutes pueden ser procesados de alshyguna forma por PHP

Entre las funciones maacutes baacutesicas de interactuacioacuten con las imaacutegenes PHP puede realizar graacuteficos de barras para mostrar resultados estadiacutesticos antildeadir una marca de agua a todas nuestras fotografiacuteas o mostrar una reacuteshyplica de las imaacutegenes en un formato maacutes reducido para poder seleccionar entre un conjunto de ellas

La mayoriacutea de los ejemplos utilizan la libreriacutea graacutefica GD para PHP que puede instalarse faacutecilmente en los tres Sistemas Operativos maacutes comunes (gnuLinux MacOSX y Windows)

Graacuteficos HTML

Antes de entrar de lleno en las maravillas que ofrece la libreriacutea graacutefica GD vamos a realizar un pequentildeo ejemplo para aprovechar las posibilidades del lenguaje HTML para la creacioacuten de estadiacutesticas graacuteficas Esta posibilishydad nos permite realizar estudios graacuteficos baacutesicos sin tener que instalar ninguacuten paquete adicional a PHP

Puede decantarse por este meacutetodo o por utilizar la libreriacutea dependiendo de la complejidad de su proyecto

Vamos a crear como ejemplo un sistema de votacioacuten electroacutenico que cuente los votos de cada participante y los almacene en una base de datos Vashymos a utilizar el gestor SQLite visto en el capiacutetulo 11 Para tal fin hemos creado una clase de conexioacuten a SQLite muy parecida a la clase de conexioacuten de MySQL

ltphp

class Servidor_Base_Datos

priacutevate $base_datos priacutevate $descriacuteptor priacutevate ^resultado function construct($base_datos)

Generacioacuten de graacuteficos con PHP 5 281

$this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtpass = $pass $this-gtbase_datos = $base_datos $this-gtconectar_base_datos()

priacutevate function conectar_base_datos( )

$thiacutes-gtdescriptor = sqlite_open($this-gtbase_datos)

i public function consulta($consulta)

$this-gtresultado = sqlite_query($consulta $this-

gtdescriptor) public function extraer__registro ()

if ($fila = sqlite_fetch_array($this-

gtresultadoSQLITE_ASSOC)) return $fila

else return false

gt

Los meacutetodos son praacutecticamente iguales y la forma de utilizar el objeto es exactamente igual que en los ejemplos del capiacutetulo 12

Los datos que vamos a manejar en la encuesta son parte de una pequentildea tabla que almacenaraacute el nombre del Lenguaje de Programacioacuten que prefeshyrimos y el nuacutemero de votos que le hemos dado Podemos inicializar la base de datos con el siguiente script

ltphp requirejonee(clase_SQLitephp) $base_datos = new Servidor_Base_Datos(votacionesdb) $base_datos-gtconsulta(creacuteate table lenguaje (id_lenguaje INT PRIMARY KEY lenguaje CHAR(255) votos INT))

$base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees ( PHP 0) ) $base_datos-gtcoacutensulta(insert into lenguaj e (lenguaj evotos) valuacutees (JSPeuro)) $base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees (ASP 0) )

282 Capiacutetulo 16

$base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees (COLD FUSIOacuteN0)) $base_datos-gtconsulta(select from lenguaje)

while ($fila = $base_datos-gtextraer_registro ()) echo $fila [lenguaje] $fila[votos] ltbrgt

gt

Todo deberiacutea serle familiar Lo que hacemos es crear una tabla nueva en la base de datos e insertar los lenguajes objetivo de la encuesta Por uacuteltishymo hacemos una comprobacioacuten para ver si los datos estaacuten almacenados en la base de datos Lo siguiente que vamos a ver es una Web con un formulario para elegir el lenguaje que maacutes nos agrada En la zona inferior de la paacutegina tenemos un contador que nos indica el nuacutemero de votos

ltphp

Primero comprobamos si tenemos un voto

$base_datos = new Servidor_Base_Datos(votaciones2db)

Si hemos votado sumamos el valor al nuacutemero de votos almacenado

if (isset($_POST[voto] ) )

$voto = $_POST[voto] $base_datos-gtconsulta(select votos from lenguaje where id_lenguaj e=$voto) $numero_votos = $base_datos-gtextraer_registro() $numero_votos = $numero_votos[votos] $numero_votos + + $base_datos-gtconsulta(update lenguaje set votos= $numero_votos where id_lenguaje = $voto)

gt lthtmlgt ltbodygt iquestQueacute lenguaje de programacioacuten prefieres

Formulario que permite votar

ltform action=votophp method=post gt ltselect name=votogt ltphp $base_datos-gtconsulta (select from lenguaje) while ($fila = $base_datos-gtextraer_registro () )

$id_lenguaje = $fila[id_lenguaje] $lenguaje = $fila [lenguaje]

Generacioacuten de graacuteficos con PHP 5 283

echo ltoption value=$id_lenguajegt$lenguajeltoptiongt

gt ltselectgt ltinput type=submit name=Enviar value=Enviar gt ltformgt lttablegt ltphp $base_datos-gtconsulta(select from lenguaje) while ($fila = $base_datos-gtextraer_registro () )

$lenguaje = $fila [lenguaje] $votos = $fila [ votos] echo lt t rx tdgt$ lengua j e lt t d x t d gt $votos vo toslt tdgtlt

t r gt

gt lt t ab l egt ltbodygt lthtmlgt

Como puede ver es un mecanismo muy sencillo de entender La parte principal es el formulario que permite elegir entre los 4 lenguajes de script Si enviamos un voto la misma paacutegina recibiraacute el dato y actualizaraacute la base de datos mostrando posteriormente los votos que tienen los lenguajes En la figura 161 puede ver el resultado

284 Capitulo 16

Graacuteficos de barras

Despueacutes de todo este coacutedigo estaraacute preguntaacutendose por las imaacutegenes geshyneradas automaacuteticamente Todaviacutea no hemos hecho nada de eso pero en el coacutedigo siguiente tiene la clave de este apartado Baacutesicamente jugamos con 4 imaacutegenes r o j o png v e r d e p n g a z u l png y a m a r i l l o png Cada imagen tiene un tamantildeo de 1 piacutexel de ancho y alto El truco estaacute en hacer un caacutelculo porcentuado de los valores de votos con respecto al que mayor votos tiene

De ahiacute sacamos el ancho de la imagen Una vez encontrado este ancho se le pasa a la propiedad w i d t h de la etiqueta lt imggt y obtenemos un graacutefishyco con imaacutegenes de distintos anchos es decir obtenemos un graacutefico de barras estadiacutestico

El coacutedigo puede ser como el siguiente

ltphp $imagenes = array(rojopngazulpngverdepngamarillopng) $base_datos-gtconsulta(select from lenguaje) while ($fila = $base_datos-gtextraer_registro() )

$id_lenguaje = $fila [ id_lenguaje ] $lenguaje = $fila [lenguaje] $votos = $fila[votos] $ancho = dame_ancho($votos$id_lenguaje) $imagen = $ imagenes[$ id_ lengua je -1] echo lt t r x t d gt $ l e n g u a j e - $votos v o t o s lt t d x t d x i m g src=$imagen width=$ancho h e i g h t = 2 0 gt lt t d x t r gt

function dame_ancho($votos)

$base_datos2 = new Servidor_Base_Datos(votaciones2db) $base_datos2-gtconsulta(select max(votos) as maacuteximo from lenguaje) $numero_votos = $base_datos2-gtextraer_registro() $maximo_votos = $numero_votos[maacuteximo] return (intval($votos)300)intval($maximo_votos)

gt lttablegt

Antes generaacutebamos una tabla con los lenguajes y el nuacutemero de votos Ahora generamos los lenguajes y calculamos con la funcioacuten dame_an-cho () el porcentaje con respecto al mayor valor de cada uno de los votos de los lenguajes La figura 162 muestra los graacuteficos de barras de la votacioacuten electroacutenica

Libreriacutea GD

La libreriacutea graacutefica GD estaacute escrita en lenguaje C y permite crear y manipushylar graacuteficos faacutecilmente Permite importar y exportar graacuteficos de distinto tipo (GIF JPG y PNG) La filosofiacutea de los archivos GIF y PNG es casi la misma Estos dos archivos guardan en memoria el conjunto completo de piacutexeles con su color concreto y comprimen el resultado para que el archishyvo final no sea muy pesado Los archivos JPG tambieacuten estaacuten comprimishydos pero se basan en algoritmos complejos que permiten un mayor rendimiento y la hacen muy propicia para usarse con fotografiacuteas

Tipos MIME

El estaacutendar MIME se concibioacute originariamente para identificar los difeshyrentes contenidos que podemos enviar por correo electroacutenico Actualmente se utiliza para describir el tipo de archivo que enviamos a traveacutes de Intershynet Es importante conocer los tipos MIME para trabajar con las libreriacuteas GD

En general antes de recibir la respuesta del servidor eacuteste debe enviarnos una cabecera anunciando el tipo de contenido que vamos a recibir usando una cabecera especial C o n t e n t - T y p e PHP por defecto enviacutea el tipo

286 Capiacutetulo 16

MIME t e x t h t m l (documento HTML) Cuando utilice la libreriacutea GD necesitaraacute enviar una cabecera con el tipo de la imagen

ltphp header(Content-Type imagepng) gt

Tabla 161 Tipos MIME

Formato de imagen MIMEacute

JPG iexclmagejpeg

PNG imagepng

GIF imagegif

BMP imagebmp

SVG imagexml+svg

Mostrar una imagen en pantalla

Normalmente utilizamos la etiqueta ltimggt de HTML para mostrar una imagen en un lugar determinado de nuestra paacutegina Web La propiedad s r c debe indicar una imagen determinada con formato coshynocido La liacutenea siguiente mostraraacute en pantalla el logotipo de php

ltimg src=phppnggt

La libreriacutea graacutefica GD tambieacuten permite enviar imaacutegenes con el uso de unas funciones determinadas Como ejemplo vamos a ver coacutemo mostrar el misshymo logotipo esta vez utilizando GD

ltphp $imagen = imagecreatefrompng(phppng) header(Content-Type imagepng) imagepng($imagen) gt

Advertencia

La etiquete ltimggt de nuestra paacutegina Web debe apuntar ahora al

archivo PHP que genera la imagen ltimg s r c = imagen php gt

La funcioacuten i m a g e c r e a t e f rompng () recupera una imagen de un archishyvo y crea un descriptor en la variable $ imagen Para mostrar la imagen

Generacioacuten de graacuteficos con PHP 5 287

tiene que enviar la cabecera del tipo de archivo graacutefico que quiere mosshytrar y despueacutes enviar la imagen con imagepng ()

A simple vista parece demasiado esfuerzo para algo que resuelve perfecshytamente la etiqueta ltimggt pero examine el siguiente coacutedigo

ltphp

$imagenes = array(phppngzendpngparispng) Semilla aleatoria srand( (double)microtime 01000000) $aleatorio = rand(02) $fichero = $imagenes[$aleatorio] $imagen = imagecreatef rompng ($f ichero) header(Content-Type imagepng) imagepng($imagen) gt

El array $ i m aacute g e n e s contiene varios archivos graacuteficos en PNG Generashymos un nuacutemero aleatorio y recuperamos la imagen que ocupa la posicioacuten del nuacutemero

Los siguientes pasos son exactamente iguales a los vistos anteriormente El script muestra una imagen distinta cada vez que lo ejecutamos y puede servir para crear una Web con distintos banners aleatorios Puede ver el resultado en la figura 163

288 Capiacutetulo 16

Crear imaacutegenes en miniatura

Si su paacutegina Web permite enviar fotografiacuteas quizaacute necesite mostrar un gran nuacutemero de ellas en una sola paacutegina HTML permite poner un ancho determinado a la imagen aunque el tamantildeo permaneceraacute invariable Lo ideal es crear dos versiones de cada fotografiacutea Una en miniatura con poco peso en bites y otra la original que puede ser mostrada cuando se haga clic en la imagen pequentildea

Gracias a la libreriacutea GD podraacute modificar el tamantildeo de las fotografiacuteas que quiera Vamos a crear una clase para generar fotografiacuteas con la mitad de tamantildeo

ltphp class imagen

priacutevate $archivo priacutevate $ imagen priacutevate $dimensiones function construct($archivo)

$this-gtarchivo = $archivo $this-gtimagen = imagecreatefromjpeg($archivo) $this-gtdimensiones = getimagesize ($archivo)

i

public function imagen_original()

header(Content-Type imagejpeg) imagejpeg$this-gtimagen)

public function imagen_miniacuteatura()

$dimensionx = $thiacutes-gtdimensiones[0] 2 $dimensiony = $this-gtdimensiones[1] 2 $this-gtminiatura = imagecreatetruecolor($dimensionx $dimensiony) imagecopyresampled($this-gtminiatura $this-gtimagen 0 0 0 0 $dimensionx $dimensiony $this-gtdimensiones[0] $this-gtdimensiones[1])header (Content-Type imagejpeg) imagejpeg($tnis-gtminiatura)

$fotografia = new imagen($_GET[fotografiacutea])

if ($_GET[modo]==original)

$fotografia-gtimagen_original()

Generacioacuten de graacuteficos con PHP 5 289

else $fotografia-gtimagen_miniatura()

gt

La clase estaacute especializada en construir imaacutegenes con la mitad de tamantildeo Para que funcione tiene que hacer una l lamada a la url c l a s e _ imagen php pasando como paraacutemetros GET el nombre de la fotografiacutea y el modo (tamantildeo original o miniatura)

El constructor de la clase rescata el archivo graacutefico y averigua las dimenshysiones X e Y con la funcioacuten g e t i m a g e s i z e ()

El meacutetodo i m a g e n _ o r i g i n a l () funciona exactamente igual que el ejemshyplo anterior El meacutetodo i m a g e n _ m i n u a t u r a () divide entre 2 las dimenshysiones capturadas de la imagen y crea un entorno de trabajo con esas dimensiones con la funcioacuten i m a g e c r e a t e t r u e c o l o r ( ) En este momenshyto la variable $ m i n i a t u r a del objeto tiene un espacio de memoria asigshynado para almacenar un graacutefico pero estaacute vaciacuteo Lo que hacen las liacuteneas siguientes es redimensionar y copiar la imagen original a nuestro entorno de trabajo La funcioacuten i m a g e c o p y r e s a m p l e d () copia la imagen guarshydada en el segundo paraacutemetro en el espacio de trabajo del primer paraacuteshymetro

Los argumentos 3 y 4 son las coordenadas X e Y donde empezaraacute a pegarshyse la imagen copiada y el 5 y 6 las coordenadas desde las que se empezaraacute a copiar la imagen original Los siguientes paraacutemetros son el ancho y alto de las imaacutegenes destino y origen

Una vez copiada la imagen al espacio de trabajo ya podemos mostrarla enviando la cabecera y la imagen con la funcioacuten image j pg ( )

Vamos a crear una Web que haga uso de esta clase

lthtmlgt ltbodygt ltform action=imagenphp method=POST enctype=multipart form-datagt Elige un archivo de imagen jpg ltinput type=file name=ficherogt ltinput type=submit name=Enviar value=Enviargt ltformgt ltphp if (isset($_FILES[fichero] ) )

echo Imagen Originalltbrgt $fotografia = $_FILES[fichero][tmp_name] copy($fotografia$_FILES[fichero] [ntildeame]) $foto_copia = $_FILES[fichero] [ntildeame] ampmodo= original

290 Capiacutetulo 16

$url = clase_imagenphpfotografia=$foto_copia echo ltimg src=$urlgt echo Imagen Miniaturaltbrgt $foto_copia = $_FILES[fichero ] [ntildeame] ampmodo= miniatura $url = clase_imagenphpfotografia=$foto_copia echo ltimg src=$urlgt

gt ltbodygt lthtmlgt

La paacutegina Web muestra un formulario que nos da la posibilidad de enviar al servidor una fotografiacutea de nuestro ordenador

Si le damos a enviar la paacutegina nos mostraraacute la fotografiacutea en su versioacuten original y en su versioacuten reducida como puede comprobar en la figura 164

Generar una marca de agua

Otro problema comuacuten sencillo de resolver es la creacioacuten de marcas de agua sobre las fotografiacuteas que ofrecemos en nuestra Web La marca de agua puede ser un graacutefico o un texto que insertamos encima de la fotografiacutea original

Generacioacuten de graacuteficos con PHP 5 291

Una forma sencilla de implementar marcas de agua es antildeadiendo un meacuteshytodo nuevo a la clase

priacutevate function marca_agua()

$this-gtmarca_agua = imagecreatefrompngphppng) $dimensiones = getimagesize(phppng) $posicionx = $this-gtdimensiones [0] - $dimensiones [0] $posiciony = $this-gtdimensiones [1] - $dimensiones [1] imagecopy($this-gtimagen $this-gtmarca_agua $posicionx $posiciony 0 0 $dimensiones [0] $dimensiones[1] )

Podemos llamar al meacutetodo desde el constructor para que la imagen guarshyde la informacioacuten de la fotografiacutea grabada e inserte la marca en alguna parte de la misma Tambieacuten podemos generar un texto como marca de agua

Vamos a antildeadir un nuevo meacutetodo a la clase para poder marcar las fotoshygrafiacuteas

priacutevate function marca_texto()

$color = imagecolorallocate($this-gtiraagen 25500) iacutemagestriacuteng($thiacutes-gtimagen 4 0 0 Hecho con PHP5

$color)

La figura 165 muestra la inclusioacuten de una marca de agua graacutefica y otra marca de agua de texto

292 Capiacutetulo 16

La funcioacuten i m a g e a l l oacute c a t e () crea un color con los componentes RGB como paraacutemetros La funcioacuten devuelve un nuacutemero que identifica al color creado en la imagen La funcioacuten i m a g e s t r i n g () imprime un texto de color determinado en la imagen El segundo paraacutemetro es el tipo de fuenshyte que queremos introducir

Graacuteficos estadiacutesticos profesionales con JpGraph

JpGraph es una libreriacutea escrita en PHP que permite crear todo tipo de graacuteshyficos estadiacutesticos en dos y tres dimensiones Hace uso de la libreriacutea graacutefica GD en su versioacuten 2 Se puede descargar de la paacutegina wwwjpgraphorg

JpGraph tiene dos licencias de uso Una gratuita para proyectos no coshymerciales y con caraacutecter educativo y otra de caraacutecter comercial de pago Le recomiendo leer ambas licencias para comprobar que puede utilizarshylas

Para instalar la libreriacutea tiene que copiar el directorio con las clases en la ruta donde guarde su aplicacioacuten o en la ruta de buacutesqueda de PHP 5

Graacuteficos de barras

El ejemplo maacutes sencillo es la creacioacuten de un graacutefico con varios valores en el que podemos ver todos los valores interconectados entre siacute por unas liacuteneas

ltphp require_once (jpgraphjpgraphphp) require_once (jpgraph jpgraph_linephp) $datosy = array(11O81251913157) Creamos el graacutefico $grafico = new Graph(350250) $grafico-gtSetScale (textlin) Creamos una nueva linea de puntos $puntos =new LinePlot($datosy) $puntos-gtSetColor(blue) Antildeadimos los puntos al graacutefico $grafico-gtAdd($puntos) Se muestra el graacutefico $grafico-gtStroke ()

bull gt

Suponiendo que la libreriacutea esteacute guardada en la carpeta j p g r a p h haceshymos u n r e q u i r e _ o n c e () de la clase principal j p g r a p h php y de la clase que utilizaremos para graacuteficos de liacutenea j p g r a p h _ l i n e php La variable $ d a t o s y guarda diez valores que pueden identificar el nuacutemero de visishytas a nuestra Web o el nuacutemero de ventas por meses de un artiacuteculo Para crear un graacutefico tiene que crear el objeto Graph con el ancho y alto que quiere que tenga en la Web Lo siguiente es configurar la escala en la que apareceraacute el graacutefico Lo mejor es echar un vistazo al manual para eleshygir el que maacutes le convenga en cada momento

Seguidamente cree un conjunto de puntos con el meacutetodo L i n e p l o t () con los valores del array $ d a t o s y Puede elegir tambieacuten el color de la liacuteshynea resultado con el meacutetodo S e t C o l o r ()

Para finalizar antildeada los valores al graacutefico y mueacutestrelo con S t r o k e ()

Con estas liacuteneas hemos conseguido crear el graacutefico de la figura 166

Puede antildeadir algunas caracteriacutesticas maacutes a sus graacuteficos como tiacutetulos en

los ejes colores o varias liacuteneas de valores para comparar datos

Para antildeadir tiacutetulos a los graacuteficos le pueden servir las liacuteneas siguientes

$graf ico-gttitle-gtset (Graacutefico JpGraph) -

294 Capiacutetulo 16

$grafico-gtxaxis-gttitle-gtset(dia) $grafico-gtyaxis-gttitle-gtset(visitas)

El meacutetodo t i t l e genera un tiacutetulo asociado al objeto inmediatamente anshyterior Si el objeto es $ g r a f i c o el tiacutetulo seraacute el de la imagen completa Si el objeto anterior es el eje x o el eje y ( x a x i s o y a x i s ) el tiacutetulo corresshyponderaacute con cada uno de los ejes Puede ver el resultado en la figura 167

Ademaacutes puede antildeadir tantos datos como quiera para hacer un estudio comparativo de varios datos Para hacer esto debe repetir algunos pasos pero con distintos valores

$datosy2 = array(12378543127) $puntos2 = new LinePlot($datosy2) $puntos2-gtSetColor(red) $grafico-gtAdd($puntos2) $puntos-gtSetLegend(Europa) Spuntos2-gtSetLegend(America) $grafico-gtlegend-gtPos(00505rightcenter)

Como vimos en el ejemplo anterior podemos antildeadir otro array lleno de valores crear una nueva liacutenea de puntos con un color determinado y asoshyciarlo finalmente con el graacutefico que estamos creando como puede ver en

Graacuteficos en 3D

JpGraph realiza casi cualquier tipo de graacutefico estadiacutestico Uno de los maacutes utilizados es el graacutefico de quesito donde podemos evaluar por porcioshynes el dato de mayor amplitud soacutelo con un vistazo El ejemplo siguiente muestra coacutemo hacer un graacutefico de este tipo

ltphp include (jpgraph jpgraphphp) include (jpgraph jpgraph_piephp) include (jpgraph jpgraph_pie3dphp)

$datos = array(4 0So21 33)

$grafico = new PieGraph(300200) $grafico-gtSetShadow()bull

$grafico-gttitle-gtSet(Graacutefico de quesito) $pl = new PiePlot30($datos) $pl-gtSetAngle(20)

Generacioacuten de graacuteficos con PHP 5 295

la figura 168 Las uacuteltimas 3 liacuteneas antildeaden una leyenda en la parte derecha del graacutefico es decir un pequentildeo graacutefico explicativo de las liacuteneas de datos

296 Capiacutetulo 16

$pl-gtSetSize (05) $pl-gtSetCenter (045) $pl-gtSetLegends($gDateLocale-gtGetShortMonth())

$grafic0-gtAdd($pl) $grafic0-gtStroke ()

Para crearlo primero tiene que incluir los archivos j p g r a p h _ p i e php y j p g r a p h ^ p i e 3 d php que permitiraacuten instanciar el tipo de graacutefico P i e P l o t 3 D El meacutetodo SetShadowC) crea una sombra en eiacute contorno exterior del graacutefico La instanciacioacuten del graacutefico circular se hace sobre la variable $pi que empieza a tomar forma con las propiedades S e t A n -g l e () y S e t C e n t e r () que permiten definir el aacutengulo del graacutefico con respecto a la vista frontal y el centrado del graacutefico con respecto a la caja que lo contiene La fase final es antildeadir el quesito al graacutefico creado y mostrarlo en pantalla Una mejora del graacutefico anterior puede ser resaltar la porcioacuten del graacutefico que tiene mayor valor y separarlo notablemente Esto puede hacerse antildeadiendo la liacutenea siguiente

$ p l - gt E x p l o d e S l i c e ( 1 )

El graacutefico de quesito se muestra en la figura 169

Generacioacuten de graacuteficos con PHP 5 297

Resumen

El tratamiento de imaacutegenes desde PHP 5 nos da la posibilidad de crear proyectos muy profesionales Tanto la posibilidad de crear graacuteficos mas pequentildeos marcas de agua o texto sobreimpresos como la de generar esshytadiacutesticas en tiempo real crean un potencial que no todas las paacuteginas Web saben aprovechar

Existen algunos proyectos como K++ que permiten crear imaacutegenes del tipo Flash y que merece la pena indagar en la buacutesqueda de contenido orishyginales para nuestro portal

300 Capitulo 17

Introduccioacuten

Si estaacute familiarizado con otros lenguajes de programacioacuten como C o Java ya conoceraacute algunos mecanismos que permiten manejar errores y excepshyciones Una de las nuevas caracteriacutesticas que PHP 5 incluye es un objeto de manejo de excepciones con una sintaxis muy similar a Java El manejo de excepciones es una herramienta muy potente que podraacute apreciar una vez que comprenda el concepto y haga buen uso del objeto en su coacutedigo Estas funciones permiten depuiacutear condiciones de error reshycuperar situaciones inesperadas y presentar interfaces limpias de errores

Errores y Excepciones

Lo primero que tenemos que hacer es no pensar en una excepcioacuten como si fuera un error Una excepcioacuten es una condicioacuten que se experimenta en un programa inesperadamente y no puede ser manejada por el coacutedigo que hemos escrito Generalmente no causan la parada del programa pero siacute es posible detectarla para que continuacutee normalmente Las excepciones si son tratadas correctamente pueden dar maacutes fiabilidad a su aplicacioacuten y librarle de muchos dolores de cabeza Aunque si no son correctamente utilizadas pueden crear maacutes problemas que resolverlos Debe tomar un tiempo para determinar si necesita crear sus propios meacuteshytodos de manejo de errores y si es asiacute veraacute que a la larga resulta maacutes grashytificante Como ejemplo vamos a ver una pieza de coacutedigo que simula la recepcioacuten de un identificador de usuario y su posible comprobacioacuten en una base de datos Tal y como puede ver se comprueba que los tres prishymeros caracteres sean usr que el tamantildeo en caracteres sea al menos de 9 y que exista en una base de datos

ltphp extraemos el usuario por GET $usuario_id = $_GET[usuario_id ] Si existe el usuario escribimos el mensaje CORRECTO if (usuario_valido($usuario_id))

echo ERROR El usuario $usuario_id no existe else

echo CORRECTO El usuario $usuario_id existe

function usuario_valido($usuario_id)

Gestioacuten de errores en PHP 5 301

$cadena = usr Comprobaciones de usuario if ( (strstr ($usuario_id$cadena) == false) [[

(strpos($usuario_id$cadena) = 0)) return false

if (strlen ($usuario__id) lt 9) return false

if (existe__base_datos ($usuario_id) )

return true else

return false

gt

Como puede ver cualquier condicioacuten que estaacute dentro de la funcioacuten que valida los usuarios puede dar un resultado negativo y soacutelo uno de ellos daraacute un resultado positivo si el usuario existe en la base de datos

Las excepciones permiten distinguir entre distintos tipos de errores y manejarlos dependiendo de su naturaleza

La clase Exception

La clase Except ion se ha creado en PHP 5 para manejar las anomaliacuteas producidas En vez de utilizar comprobaciones que evaluacutean si es falso o verdadero una determinada condicioacuten se utiliza una instancia de la clase Except ion que captura los errores y permite mostrar un mensaje de error personalizado

ltphp extraemos el usuario por GET $usuario__id = $_GET [ usuario_id] Si existe el usuario escribimos el mensaje CORRECTO try

if ( lusuario_valido($usuario_id)) echo ERROR El usuario $usuario_id no existe

else echo CORRECTO El usuario $usuario_id existe

catch(Exception $ex)

Devuelve el mensaje de error $mensaje = ($ex-gtqetMessage() ) echo $mensaje

302 Capiacutetulo 17

function usuario_valido($usuario_id) $cadena = usr Comprobaciones de usuario if ( (strstr ($usuario_id$cadena) == false) |

(strpos($usuario_id $cadena) = 0)) throw new Exception ($usuario_id no contiene el

prefijo)

if (strlen($usuario_id) lt 9)

throw new Exception (El tamantildeo de $usuario_id es menor de 9 caracteres)

if (existe_base_datos($usuario_id) )

return false else

return false

Gestioacuten de errores en PHP 5 303

Como puede ver las excepciones se crean de una manera algo diferente En el momento en el que se escribe th row new E x c e p t i o n los errores que no se controlen con el flujo normal del programa son utilizados como excepciones separadas del resto de la aplicacioacuten

Bloque Try Catch

Las excepciones son controladas por el bloque t r y c a t c h Todo el coacutedishygo que escriba y que pueda generar un error se incluiraacute dentro de una estructura t r y Si dentro del bloque t r y se encuentra un error la ejecushycioacuten del coacutedigo se para y se pasa el control al bloque c a t c h Este bloque se consuita para encontrar la excepcioacuten que ha producido el error de acuershydo con el coacutedigo que hemos escrito

Una de las cosas maacutes convenientes de utilizar excepciones es que puede mostrar tanta informacioacuten o tan poca como quiera El objeto E x c e p t i o n tiene varios meacutetodos para manejar sus propios errores El coacutedigo siguiente muestra coacutemo utilizar t h row e inmediatamente capshyturar la excepcioacuten Podemos capturar tambieacuten algunos paraacutemetros uacutetiles

ltphp try

throw new Exception(Error de sintaxis) catch (Exception $ex)

Mensaje de error $mensaje = ($ex-gtgetMessage ()) Coacutedigo de error configurable $codigo = ($ex-igetCode()) Fichero del error $fichero = ($ex-gtgetFile ( ) ) Linea donde se ha producido el error $linea = ($ex-gtgetLine())

echo Error nuacutemero $codigo $mensaje en el fichero $fichero en la linea $linea

gt

El mensaje de error que se muestra es muy tiacutepico en PHP Como es totalshymente configurable puede generar su propio formato de Mensaje de Error que puede ver en la figura 172

Aunque en este ejemplo el coacutedigo que captura la excepcioacuten soacutelo tiene una liacutenea podraacute incluir dentro del bloque varias liacuteneas o funciones dentro que actuaraacuten de la misma forma

Heredar de (a clase Exception

PHP 5 permite definir sus propias clases qulta heredan de la clase E x c e p shyt i o n Puede hacerlo de la siguiente forma

ltphp class Excepcioacuten extends Exception

function construct($mensaje)

parent Exception($mensaj e)

gt

El siguiente ejemplo muestra coacutemo crear clases propias que manejan erroshyres a partir de la clase E x c e p t i o n

ltphp $usuario_id = $_GET[usuario_id] try

if f J usuario_valido ($usuario__id) ) [ echo ERROR El usuario $usuario id no existe

Gestioacuten de errores en PHP 5 305

else echo CORRECTO El usuario $usuario_id existe

catch(MiExcepcion $ex)

$cadena = usr if ((strpos($usuario_id$cadena) == false) |]

(strpos($usuario_id$cadena) = 0)) $mensaje = $ex-gtgetMessage()

catch(OtraExcepcion $ex)

if (strlen($usuario_id) lt 9) $mensaje = $ex-gtgetMessage()

Definicioacuten de las clases que heredan de Exception class MiExcepcion extends Excepcioacuten

function construct($mensaje)

parentException($mensaje)

class OtraExcepcion extends Excepcioacuten

function construct($mensaje)

parent Exception($mensaj e)

echo $mensaje function usuario_valido($usuario_id)

$cadena = usr if ((strpos($usuario_id$cadena) == false) ||

(strpos($usuario_id$cadena) = 0)) throw new MiExcepcion(Usuario $usuario_id no

contiene el prefijo )

if (strlen($usuario_id) lt 9) throw new OtraExcepcion(Usuario tiene menos de 9

caracteres)

gt

Limitaciones de PHP 5

El objeto de excepciones es totalmente nuevo en PHP 5 Debido a esto algunas funcionalidades creadas en otros lenguajes de programacioacuten como

306 Capiacutetulo 17

Java no han sido todaviacutea implementadas por ejemplo el uso de los meacutetoshydos f i n a l ly () y t h r o w s () Los errores comunes de PHP que se muesshytran en el navegador no son mapeados a excepciones automaacuteticamente Esta funcionalidad seraacute implementada en versiones posteriores de PHP Los errores que no pueden ser controlados por E x c e p t i o n pueden mashynejarse con otras teacutecnicas de programacioacuten

Control de errores sin excepciones

Si ya conoce algunas versiones de PHP sabraacute que hay multitud de funcioshynes capaces de controlar errores incluidos los errores nativos de PHP controladores personalizados de error y los errores de usuario

Errores nativos de PHP

PHP genera 3 tipos de error dependiendo de su seriedad

bull Notice No son errores severos y no crean problemas complejos Por defecto no se muestran en pantalla cuando suceden a menos que dishygamos lo contrario en el archivo de configuracioacuten php i n i

bull Warning Alguna parte del coacutedigo ha causado un error pero la ejecushycioacuten continuacutea

bull Fatal error Un problema serio que hace abortar la ejecucioacuten del proshygrama

Cada tipo de error es representado por una constante diferente E_USER_NOTICE E_USER_WARNING y E_USER_ERROR Puede elegir el nivel de error que quiere mostrar en pantalla con la funcioacuten e r r o r _ r e p o r t i n g ( )

ltphp Mostrar errores fatales error_reporting(E_USER_ERROR) Mostrar advertencias y notificaciones error_reporting(E_USER_WARNING | E_USER_NOTICE) Mostrar todos los errores error_reporting (E__USER__ALL) gt

El manejo de errores queda limitado la mayoriacutea de veces a los del tipo warn ing Los errores fatales se consideran tan criacuteticos que no pueden conshytrolarse y la ejecucioacuten del programa queda suspendida

Gestioacuten de errores en PHP 5 307

Controladores de error

Cuando suceda un error que no tenga contemplado en su aplicacioacuten pueshyden aparecer mensajes en la pantalla que no interesa mostrar La solucioacuten es crear su propia funcioacuten para controlar y mostrar errores

ltphp function errores($errormensaje$fichero$linea)

echo ltbgt ERROR ltbxbrgt echo Sentimos comunicarle que se ha producido un error echo Tipo de error $error $mensaje en $fichero en la linea $linea

gt

Con estas liacuteneas hemos creado una funcioacuten que muestra el error producishydo pero con un disentildeo acorde a nuestra paacutegina Web Puede mostrar tanta informacioacuten como quiera El siguiente paso es llamar a la funcioacuten s e t _ e r r o r _ h a n d l e r () para que PHP sepa que nuestra funcioacuten e r r o shyr e s () se va a encargar a partir de ahora de gestionar los posibles fallos en el flujo del programa

ltphp set_error_handler(errores) gt

308 Capiacutetulo 17

Con el coacutedigo anterior todos los errores producidos del nivel que tenga permitido ( f a t a l e r r o r w a r n i n g o n o t i c e ) seraacuten enviados a la funshycioacuten e r r o r e s () para mostrar su mensaje particular

Errores de usuario con trigger_error()

Desde PHP 4 puede usarse una funcioacuten para identificar los errores proshyducidos por los usuarios muy parecida a la funcioacuten de PHP 5 th row () La funcioacuten t r i g g e r _ e r r o r () genera un error del tipo que quiera ( f a shyt a l e r r o r warn ing o n o t i c e ) y seraacute gestionado por PHP o por su propio gestor de errores

ltphp error_reporting(E_ALL) function errores($error$mensaje$fichero$linea)

echo ltbgt ERROR ltbxbrgt

echo Sentimos comunicarle que se ha producido un error echo Tipo de error $error $mensaje en $fichero en la liacutenea $ linea

set_error_handler(errores)

if (1 = 0 ) trigger_error( Esto es falso E_USER_NOTICE)

gt

Es mejor u t i l izar s iempre la funcioacuten t r i gg e r _ e r r o r ( ) con s e t _ e r r o r _ h a n d l e r () El error que creemos puede ser de cualquiera de los 3 tipos existentes en PHP En este caso generamos un error no t i -ce para indicar que la condicioacuten es falsa

Depuracioacuten de errores

El manejo de errores puede ahorrar esfuerzos a la hora de depurar el funshycionamiento oacuteptimo de su coacutedigo pero tambieacuten puede crear algunos doshylores de cabeza si empieza a suprimir algunos fallos

La f u n c i oacute n e r r o r _ l o g () crea un archivo donde se iraacuten almacenando las ocurrencias de su coacutedigo Con el siguiente ejemplo podraacute capturar todos los errores producidos en el programa para despueacutes hacer un estudio de lo que ha pasado

ltphp

Gestioacuten de errores en PHP 5 309

try if ($usuario = Luis)

throw new Exception(El usuario no existe)

catch (Exception $ex)

$mensaje = ($ex-gtgetMessage() ) $codigo = ($ex-gtgetCode() ) $fichero = ($ex-gtgetFile()) $linea = ($ex-gtgetLine()) $log_mensaje =date(Hi d-m-Y) Error $codigo en

$fichero en la liacutenea $linea Error $mensaje error_log($log_mensaj e3 UsersluisSiteserrorlog) echo $log_mensaje

gt

Nota

Los ficheros l o g son muy utilizados en los Sistemas Operativos para mantener un registro de incidencias Los ficheros l o g guarshydan desde el nuacutemero de veces que ha entrado un usuario hasta los errores que se han producido en el inicio del sistema

La funcioacuten e r r o r _ l o g () puede pasar como segundo paraacutemetro un nuacuteshymero entero que identifica el tipo de error y queacute hacer con eacutel

bull 0 Se utiliza el mecanismo del sistema operativo bull 1 Enviacutea el error a una direccioacuten de correo especificada como cuarto

paraacutemetro (Debe formar parte de una cabecera) bull 2 Enviacutea el error a traveacutes de una sesioacuten de depuracioacuten de PHP (Debe

estar habilitado el modo depuracioacuten)

bull 3 Enviacutea el error a un fichero

Resumen

Como puede darse cuenta la mayoriacutea de los programas incluidos en el libro no tienen ninguacuten tipo de control de errores He preferido evitarlos para ganar en claridad y no tener que empezar explicando los bloques Try Catch desde el principio A partir de ahora sieacutentase libre para modifishycar todos los scripts a su antojo para que sean maacutes fiables y seguros

310 Capiacutetulo 17

El desarrollo de las posteriores versiones de PHP permitiraacute manejar los errores maacutes faacutecilmente El futuro de las excepciones no ha hecho maacutes que empezar con la versioacuten 5 de PHP y se esperan mejoras suculentas con respecto a las anteriores Pese a esto muchas libreriacuteas ya incluyen sus proshypios controles de error como la de MySQL o PEAR

312 Capiacutetulo 18

Introduccioacuten

Transferir ficheros de un ordenador a otro es una tarea que sucede milloshynes de veces a lo largo del diacutea en Internet Ya no es un problema comparshytir un fichero entre dos ordenadores ubicados entre distintos puntos del mundo Los dos meacutetodos maacutes utilizados son el protocolo FTP y el correo electroacutenico

Los ficheros pueden ser transferidos simplemente dejaacutendolos en alguacuten lugar puacuteblico de nuestro servidor Web o utilizando alguacuten programa para enviarlos El protocolo FTP y el correo electroacutenico son programas indeshypendientes que deben estar instalados en el servidor para poder usarse Son dos programas del tipo cliente servidor Para poder utilizar cualshyquiera de los dos servicios anteriores debe conectarse a un servidor en un ordenador remoto y enviar los datos

FTP

Para utilizar el protocolo FTP tiene que tener habilitada la opcioacuten cuando instale PHP Puede utilizar FTP para enviar ficheros en un script escrito en PHP desde alguna paacutegina Web Para conectar a un servidor tendraacute que utilizar la siguiente funcioacuten

$conexioacuten = f tp__connect ( www l u i s y f ernanda net)

Tambieacuten puede utilizar una direccioacuten IP para la conexioacuten $conexioacuten = f tp_connect (12 7 0 0 1)

Nota

La direccioacuten IP identifica un uacutenico ordenador dentro de Internet

La IP 127001 apunta a nuestro propio ordenador

El servidor FTP contiene un listado de usuarios a los que les permite la conexioacuten Dependiendo del usuario que se conecte el servidor le permitishyraacute descargar unos archivos u otros

El siguiente paso es autentificarse como usuario del servidor de FTP con la funcioacuten

ftp_login($conexioacuten $usuario $clave)

Conexiones desde PHP 5 313

Como paraacutemetros tiene que pasar la conexioacuten establecida anteriormente el usuario y la contrasentildea

Advertencia

El protocolo FTP no es seguro El usuario y la contrasentildea se enshyviacutean en formato de texto y podriacutean ser capturados por alguacuten proshygrama sniffer que se encuentre entre su ordenador y el servidor de destino

Como de costumbre puede encapsular todas las funciones para hacer una clase que permita conectar a un servidor

ltphp class ftp

priacutevate $serviacutedor priacutevate $usuario priacutevate $clave priacutevate $conexion priacutevate $login function construct($servidor$usuario $clave)

set_time_limit(0) $this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtclave = $clave $thiacutes-gtconectar($this-gtservidor)

priacutevate function conectar($servidor)

$this-gtconexion = ftp_connect($servidor21 30) priacutevate function loginFtp($usuario$clave)

$this-gtlogin = ftp_login($this-gtconexion usuario $clave)

$ftp = new ftp(127001luissecreto) gt

Como puede ver el meacutetodo constructor utiliza la funcioacuten set__t ime_ l i m i t () Normalmente los script de PHP tienen un tiempo de vida deshyterminado en el fichero de configuracioacuten php i n i Este tiempo suele ser de 30 segundos y es una proteccioacuten para que si un programa se queda

314 Capiacutetulo 18

bloqueado y su ejecucioacuten lleva maacutes de ese tiempo automaacuteticamente queshyde cancelada su ejecucioacuten

La funcioacuten s e t _ t i m e _ l i m i t () le da la posibilidad de ampliar el tiemshypo de ejecucioacuten al nuacutemero de segundos que indique como paraacutemetro Si el argumento es un 0 el tiempo de ejecucioacuten seraacute infinito

La funcioacuten f t p _ c o n n e c t () tambieacuten puede llevar como paraacutemetros el puerto de conexioacuten (por defecto es el 21) y el nuacutemero de segundos que tardaraacute PHP en volver a intentar la conexioacuten si el intento anterior ha sido fallido

Mostrar los archivos remotos

Despueacutes de conectar con el servidor de FTP lo maacutes usual es recuperar un listado de ficheros que estaacuten en el servidor La funcioacuten f t p _ n l i s t () extrae el nombre de los archivos del directorio que pasemos como paraacuteshymetro

El resultado es un array

public function ver($directoriacuteo = )

$this-gtarchivos = ftp_nlist($this-gtconexion$directorio) foreach ($this-gtarchiacutevos as $archivo)

echo $archivoltbrgt

Puede antildeadir el meacutetodo anterior a la clase f t p La funcioacuten f t p _ n l iacute s t () utiliza la conexioacuten almacenada en el constructor de la clase y recibe un listado de ficheros que guarda como array en la variable $this-gtarchivos

Maacutes adelante utilizando un bucle f o r e a c h podraacute extraer todos los nombres e imprimirlos en pantalla como puede comprobar en la figushyra 181

Si no es la primera vez que utiliza el protocolo FTP sabraacute que al conecshytar con un servidor lo maacutes comuacuten es que conecte en el sistema raiacutez donshyde encontraraacute los archivos y directorios que puede utilizar La funcioacuten f t p _ c h d i r () permite cambiar de directorio dentro del sistema de fishycheros

Si en alguacuten momento no sabe en queacute directorio se encuentra puede hashycer uso de la funcioacuten f tp_pwd ( ) que le daraacute la ruta completa de su situacioacuten

Descargar y Enviar ficheros

Puede descargar ficheros con la funcioacuten f tp_ge t () El siguiente ejemshyplo descarga un fichero despueacutes de hacer la conexioacuten

ftp_get($conexioacuten nuevoFicherotxtFicherotxtFTP_ASCII)

El nombre nuevoFichero t x t se corresponde con el nombre del ficheshyro que tendraacute el archivo despueacutes de ser descargado y F iche ro t x t es el archivo remoto que queremos descargar El uacuteltimo paraacutemetro FTP_ASCI I le dice al FTP el tipo de archivo que va a ser descargado Los modos que puede elegir son FTP_ASCI I o FTP_BINARY Los ficheros binarios son archivos escritos en el lenguaje maacutequina como los archivos graacuteficos Ademaacutes puede enviar archivos al servidor con la funcioacuten f tp_put () El siguiente ejemplo muestra coacutemo subir un archivo al servidor

ftp_put($conexion nuevoFicherotxtFicherotxtFTP_ASCII)

Como en el ejemplo anterior n u e v o F i c h e r o t x t seraacute el nombre del archivo en el servidor remoto y F i c h e r o t x t el archivo que vamos a enviar El ejemplo siguiente descarga todos los archivos con extensioacuten PHP en nuestro ordenador local

public function descargaPHP($directorio = )

316 Capiacutetulo 18

$this-gtarchivos = ftp_nlist($this-gtconexion$directorio) foreach ($this-gtarchivos as $archivo)

if (ereg(php$archivo)) if ( f ile__exists ($archivo) )

ftp_get($this-gtconexion$archivo$directorio $archivoFTP_ASCII)

else

echo Fichero $archivo ya existeltbrgt

else

echo El archivo $archivo no es de PHPltbrgt

Otras funciones de FTP

Ademaacutes de las funciones descritas en este capiacutetulo existen otras muchas para el manejo del protocolo FTP

Tabla 181 Funciones comunes al manejo de FTP

Funciones Descripcioacuten

ftp_cdup($conexion) Cambia al directorio inmediatamente

superior al directorio actual ftp_chdir($conexioacuten Cambia al directorio que pasemos como

nombre directorio) paraacutemetro

ftp_close($conexion) Cierra una conexioacuten FTP

ftpconnect(servidor) Establece una conexioacuten con el servidor

ftp_delete($conexioacuten ruta) Borra un fichero del servidor

ftp_exec($conexioacuten comando) Ejecuta un comando del sistema remoto

ftp_fget($conexioacuten $descriptor Descarga un fichero y vuelca los datos Ficherotxt FTP_ASCII) en un fichero abierto en el ordenador

local

ftp_fput($conexioacuten $descriptor Enviacutea un archivo a un fichero abierto Ficherotxt FTP_ASCII)

ftp_get($conexioacuten nuevoFicherotxt Recupera un fichero de un servidor Ficherotxt FTP_ASCII)

ftp_put($conexioacuten nuevoFicherotxt Enviacutea un fichero al servidor

Ficherotxt FTP_ASCII)

Conexiones desde PHP 5 317

Funciones Descripcioacuten

ftp_login($conexiexcloacuten $usuario $clave) Autentifica al usuario en el servidor ftp_mdtm($conexioacutenFicherotxt) Recupera la fecha de la uacuteltima actualishy

zacioacuten del fichero ftp_mkdir($conexioacuten directorio) Crea un directorio

ftp_nlist($conexioacuten directorio) Recupera la lista de archivos de un directorio

ftp_pwd($conexion) Obtiene el nombre del directorio actual ftp_rename($conexioacuten Cambia de nombre un archivo remoto ArchivoAntiguoArchivoNuevo) ftp_size($conexionFicherotxt) Devuelve el tamantildeo de un fichero ftp_systype($conexion) Permite obtener el tipo de sistema

Correo electroacutenico

La aplicacioacuten maacutes utilizada sin duda en Internet es el correo electroacutenico La explosioacuten de Internet y la expansioacuten de servidores gratuitos que ceden cuentas de correo a todos los usuarios ha permitido que el crecimiento de los e-tnail se dispare en estos uacuteltimos antildeos

Para lograr la comunicacioacuten a traveacutes del correo electroacutenico han de intershyvenir numerosas piezas de un puzzle

La mayor parte del modelo utiliza

bull Servidor TCP IP Se encarga de mantener activos para la conexioacuten diversos servicios como FTP SMTP o POP

bull MTA (Mail Transfer Agent) Acepta correo de otros servidores SMTP y busca una ruta para que los correos lleguen a su destino

bull Cola de correo Recipiente donde se almacenan todos los correos enshytrantes dirigidos a una persona

bull MUA (Mail User Agent) Programa muy liviano para leer el correo elecshytroacutenico normalmente desde el servidor

bull Servidor POP IMAP Recibe peticiones de lecturas de correo El sershyvidor chequea si hay correos nuevos y los enviacutea al cliente

bull MLM (Mailing List Manager) Este software ayuda a enviar grandes cantidades de correo

318 Capiacutetulo 18

Enviar correo desde PHP

Soacutelo existe una funcioacuten para enviar correo electroacutenico desde PHP 5 La funcioacuten mail () devolveraacute un valor true si los datos son enviados correcshytamente La forma maacutes sencilla de utilizar esta funcioacuten la puede ver en el ejemplo siguiente

ltphp $resultado = mail ( luisaacutenccextremadura org Ejemplo de Asunto Cuerpo del mensaje) if ($resultado)

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt

El primer paraacutemetro recibe el correo de la persona a la que quiere enviar el mensaje El segundo es un resumen del contenido de su carta electroacutenishyca y por uacuteltimo el tercer paraacutemetro es el mensaje que quiere transmitir Puede dividir la funcioacuten en variables para que sea maacutes sencillo de utishylizar

ltphp $correo = luisnccextremaduraorg $asunto = Ejemplo de Asunto $cuerpo = Cuerpo del mensaje $resultado = mail($correo $asunto $cuerpo) if ($resultado)

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt

Hay veces que necesitaraacute algo maacutes de control sobre lo que quiera enviar o necesite enviar un correo a varias personas a la vez Esto es posible antildeashydiendo cabeceras adicionales a la funcioacuten mail

ltphp $correo = luisnccextremaduraorg $asunto = Ejemplo de Asunto $cuerpo = Cuerpo del mensaje $cabecera = From fernandarnbccpedronccextremaduraorgrnContent-type textplainrnX-mailer PHP phpversion () $resultado = mail($correo $asunto $cuerpo $cabecera) if ($resultado)

Conexiones desde PHP 5 319

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

La cabecera muestra coacutemo enviar junto al correo la direccioacuten de la persoshyna que lo enviacutea y una copia del mismo mensaje al correo pedroncc extremaduraorg Es necesario antildeadir los separadores r y n para indishycar un salto de liacutenea entre los paraacutemetros de la cabecera

Las cabeceras adicionales pueden antildeadir muchos tipos de informacioacuten entre los que se encuentran

bull El nombre del emisor

bull Correo del emisor

bull Correo de respuesta

bull X-mailer y nuacutemero de versioacuten

bull versioacuten MIME

bull Content-type

bull Codificacioacuten

bull Campo de copia y copia oculta

La funcioacuten m a i l () estaacute preparada para emitir mensajes sencillos pero hay muchas caracteriacutesticas que debe implementar con cabeceras Por eso han nacido una serie de libreriacuteas escritas en PHP que facilitan el enviacuteo de correos

La libreriacutea PHPMailer antildeade a la funcioacuten m a i l () muchas funcionalidashydes como ficheros adjuntos o correos HTML

PHPMailer

PHPMailer estaacute basado en programacioacuten orientada a objetos Contiene varios ficheros que deben guardarse en el directorio de PHP dedicado a libreriacuteas o en nuestro espacio de trabajo

La construccioacuten maacutes baacutesica es la siguiente

ltphp require_once(phpmailerclassphpmailerphp) $correo = new phpmailer() Datos personales del emisor $mail-gtFrom = luisnccextremaduraorg

320 Capitulo 18

$mail-gtFromName = Luis Miguel Cabezas

$mail-gtSubject = Mensaje de prueba

$mail-gtBody = Cuerpo del mensaje Direccioacuten de destino $mail-gtAddAddress(zeevSphpzendcomZeev Suraski)

if ( l$mail-gtSend()) echo Correo enviado correctamente

else echo El correo no ha podido enviarse

gt

Como puede ver las propiedades de la clase p h p m a i l e r son auto explishycativas El ejemplo va asociando cada propiedad a un dato necesario para el enviacuteo El meacutetodo A d d A d d r e s s () antildeade una direccioacuten de correo a la que enviar el mensaje y Send () lo enviacutea a traveacutes de Internet

Antildeadir un fichero adjunto

Existen tres meacutetodos para antildeadir un fichero adjunto a un mensaje dos para archivos y otro maacutes especiacutefico para imaacutegenes

bull AddAttachment(ruta nombre) Antildeade un fichero localizado en el servidor Este archivo se puede subir antes al servidor mediante un formulario

bull AddStringAttachment(caracteres fichero) Se puede utilizar para enviar ficheros almacenados en variables

bull AddEmbeddedImage(ruta cid nombre) Antildeade una imagen y pershymite antildeadirla al cuerpo de un correo HTML

Las liacuteneas siguientes se pueden antildeadir al ejemplo anterior para enviar un fotografiacutea almacenada en el servidor

if ($mail-gtAddAttachment(abuelojpgabuelojpg))

echo Falloacute al antildeadir un fichero adjunto

Para demostrar la teoriacutea anterior vamos a crear un pequentildeo formulario que permita enviar correo Es un coacutedigo muy sencillo pero permite enshyviar mensajes escritos en HTML e incluir imaacutegenes

ltphp if (isset($_POST[nombre]))

require_once(phpmailerclassphpmailerphp)

Conexiones desde PHP 5 321

$correo = new phpmailer() Datos personales del emisor $mail-gtFrom = luisnccextremaduraorg $mail-gtFxowpoundawgte = Luis Miguel Cabezas $mail-gtSubject = $_POST [ asunte ] $mail-gtBody = $_POST[mensaje] Direccioacuten de destino $mail-gtAddAddress($_POST[nombre]$_POST[correo]) if ($mail-gtAddEmbeddedImage($_FILES[imagen] [tmp_name 12 34 5 imagen))

echo Falloacute al antildeadir un fichero adjunto

if ( $mail-gtSend() )

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt lthtmlgt ltbodygt ltform action=mailphp method=post enctype=multipartform-data name=formlgt lttable width=50 border=0 cellspacing=0

cellpadding=Ogt lttrgt

lttd width=28gtNombrelttdgt lttd width=72xinput name=nombre type=text

id=nombregtlttdgt lttrgt lttrgt lttdgtCorreolttdgt lttdxinput name=correo type=text id=correogtlttdgt

lttrgt lttrgt lttdgtAsuntolttdgt lttdxinput name=asunto type=text id= asuntogtlttdgt

lttrgt lttrgt lttdgtMensajelttdgt lttdxtextarea name= mensa j e rowS=5 id= mensa j e gtlt textareaxtdgt

lttrgt lttrgt lttdgtSelecciona imagen lttdgt lttdxinput name=imagen type=file id= imagen xtdgt

lttrgt lttablegt ltpgt

322 Capiacutetulo 18

ltinput type=submit name=Submit value=Enviargt ltPgt

lt formgt ltbodygt lthtmlgt

La figura 182 muestra un formulario capaz de enviar contenido HTML e imaacutegenes adjuntas

Resumen

PHP se ha promovido tanto debido a las numerosas extensiones que pershymiten hacer casi cualquier cosa En concreto las dos formas vistas para conectarse con un servidor le seraacuten muy uacutetiles para ofrecer servicios inshynovadores a sus usiiarios

La mayoriacutea de los portales Web que necesitan el registro de sus usuarios enviacutean por correo electroacutenico las contrasentildeas y los datos de inscripcioacuten La funcioacuten mail () le puede servir para hacer sus pequentildeos controles de usuarios

Conexiones desde PHP 5 323

Si se siente maacutes ambicioso tambieacuten puede utilizar PHPMailer para consshytruir una paacutegina Web que permita enviar o recibir correo electroacutenico La recomendacioacuten es que continuacutee investigando en la clase PHPMailer y en todo lo que ofrece que no hemos podido ver en este capiacutetulo

326 Capiacutetulo 19

Introduccioacuten

Como probablemente ya sabe el HTML no es el uacutenico formato para mosshytrar contenido en Internet Ademaacutes de los distintos tipos de imaacutegenes teshynemos varios formatos capaces de contener textos como Adobe PDF Macromedia Flash o algunos documentos alternativos escritos en XML como los archivos graacuteficos SVG (Graacuteficos Vectoriales Escalables) WML (Lenguaje de Marcas Inalaacutembrico) o XUL (Lenguaje de interfaz de Usuashyrio en XML con Mozilla) Cada uno de estos tipos de documentos tiene su propio terreno y de nosotros depende elegir cuaacutel o cuaacuteles utilizar para dotar a nuestra Web de mayores posibilidades

Los archivos Adobe PDF se han establecido como un estaacutendar en los doshycumentos de texto para la Web

Existen dos extensiones escritas para PHP PDFLib y C l ibPDF capaces de generar archivos PDF Desgraciadamente estas libreriacuteas son de uso coshymercial y requieren el pago de alguacuten tipo de licencia Ademaacutes de las extensiones anteriores tenemos una serie de aplicaciones escritas completamente en PHP que permiten llegar al mismo resultado como RampOS PDF o FPDF No son tan raacutepidas como las extensiones pero cumplen perfectamente nuestras expectativas

Libreriacutea FPDF

La libreriacutea FPDF creada en septiembre de 2001 no necesita licencia de uso ni tampoco alguna configuracioacuten especial de PHP Lo uacutenico que neshycesita es la libreriacutea que la puede descargar del sitio Web h t t p wwwfpdforg

La libreriacutea principal contiene la definicioacuten de una clase que debe instan-ciar para poder generar sus documentos Nuestro coacutedigo inicial deberiacutea ser algo parecido a

ltphp require__once ( f pdf fpdf php) $pdf = new FPDF() gt

El constructor se utiliza de esta forma con los valores por defecto que son paacutegina A4 con orientacioacuten vertical y el tamantildeo medido en miliacutemetros El primer paraacutemetro del constructor permite elegir entre orientacioacuten verti-

Creacioacuten de archivos PDF 327

cal (L) u horizontal (P) El segundo paraacutemetro sirve para que las medidas de referencia se hagan en base a puntos (pt) miliacutemetros (mm) centiacutemetro (cm) o pulgadas (in) El uacuteltimo paraacutemetro nos ofrece la oportunidad de elegir entre los diferentes formatos de paacutegina que existen A3 A4 A5 Let-ter y Legal

Nota

Hay que recordar que un punto es 172 pulgadas

$pdf = new FPDF( P cm A 4 )

Nuestro primer documento

El siguiente ejemplo muestra la creacioacuten baacutesica de un documento PDF de forma lineal

ltphp define(FPDF_FONTPATHfpdffont) require_once ( fpdffpdfphp) $pdf = new FPDF() $pdpound-gtAddPageU bull $pdf-gtSetFont(Arial 15) $pdf-gtWrite(155 Mi primer documento) $pdf-gtOutput() gt

La primera liacutenea define una constante que contiene la ruta donde estaacuten almacenadas las fuentes Despueacutes de las funciones que incluyen la clase y la instancia del objeto tenemos una serie de llamadas a meacutetodos que nos permiten manipular el documento a nuestro antojo

Advertencia

FPDF mantiene la posicioacuten de un cursor Las funciones que geneshyran texto imprimiraacuten los datos de acuerdo con la posicioacuten del curshysor en ese momento Es posible de todas formas cambiar de sitio el cursor con algunas funciones que veremos en este capiacutetulo

El meacutetodo AddPage () antildeade una paacutegina al documento con la orientashycioacuten que Le pida En este caso hemos antildeadido una con orientacioacuten vertical que es la elegida por defecto S e t F o n t () selecciona una fuente tomando

Funciones de texto

Meacutetodo Write()

Imprime el texto pasado como paraacutemetro en la posicioacuten que indica el curshysor La construccioacuten es

W r i t e ( a l t u r a t e x t o e n l a c e )

Los paraacutemetros son los siguientes

bull altura Altura de la celda bull texto Texto a imprimir bull enlace Podemos considerar el texto como un enlace a una paacutegina o a

una Web

Como ejemplo puede ver el primer coacutedigo que hemos realizado

328 Capiacutetulo 19

como paraacutemetro el tipo la propiedad (negrita cursiva) y el tamantildeo Por uacuteltimo tenemos una llamada a los meacutetodos Write () y Output () que escriben el texto en una posicioacuten determinada del documento y lo muesshytran en pantalla respectivamente como puede ver en la figura 191

Creacioacuten de archivos PDF 329

Meacutetodo Cell()

El meacutetodo c e l l () puede tomar hasta 8 paraacutemetros y es el encargado de imprimir en el documento PDF un cuadro de texto en la posicioacuten indicashyda El cuadro de texto puede tener un borde alrededor o en alguno de los lados

La construccioacuten es como sigue

cell(ancho altura texto borde liacutenea alineacioacuten relleno enlace)

Los dos primeros paraacutemetros son obligatorios los demaacutes opcionales A continuacioacuten vemos para queacute sirve cada paraacutemetro

bull ancho Ancho de la celda Si es 0 se considera el ancho total del folio

bull altura Altura de la celda

bull texto Texto a imprimir

bull borde Un 1 significa que llevaraacute borde Tambieacuten se pueden incluir algunos caracteres para indicar en cuaacutel de las partes de la celda debe llevar borde L R T y B significan Izquierda Derecha Arriba y Abajo respectivamente

bull liacutenea Cuando termine la llamada a la creacioacuten de la celda indica al generador de PDF doacutende debe colocar el cursor para continuar Un 0 indica a la derecha de la tabla un 1 en la siguiente liacutenea y un 2 seguido

bull alineacioacuten Acepta 3 caracteres L para alinear a la izquierda R a la derecha y C para texto centrado

bull relleno Indica con un 1 si la celda debe tener un relleno para diferenshyciarla del resto del folio

bull enlace Enlace devuelto por la funcioacuten A d d l i n k ()

Como ejemplo puede ver la forma de introducir un tiacutetulo en una paacutegina

lt php define(FPDF_FONTPATHfpdffont) require__once ( fpdffpdf php i $pdf = new FPDF()

$pdf-gtAddPage() $pdf-gtSetFont(Courier 1 0 ) $pdf-gtCell(80) $pdf-gtCell (2010 Titulo 11C) $pdf-gtOutput() gt

Una celda soacutelo puede contener el nuacutemero de caracteres que quepa en una liacutenea Si necesita mostrar maacutes liacuteneas de texto puede utilizar el meacutetodo

330 Capiacutetulo 19

Muiacute ti Ce 11 () que toma los mismo paraacutemetros que Ce 11 ( ) pero cuanshydo el texto llegue al final de la liacutenea se antildeade automaacuteticamente un salto a la liacutenea siguiente

Truco

Puede utilizar Ce 11 () para desplazar el cursor hacia la derecha antildeadiendo como paraacutemetro un ancho de 8 centiacutemetros (80 miliacuteshymetros) Despueacutes para imprimir el texto antildeada otra celda que inshycluya el literal Tiacutetulo centrado dentro de una celda con borde

Desplazamiento de los cursores

Existen varias funciones para colocar el cursor en distintas partes del doshycumento Se tX () y S e t Y () colocan el texto en el punto indicado en la medida seleccionada (centiacutemetros miliacutemetros etc)

Se tX () desplaza el cursor de izquierda a derecha tantas unidades como indique el paraacutemetro y S e t Y () de arriba hacia abajo Si se les pasa un nuacutemero negativo el origen se tomaraacute desde la derecha o desde abajo resshypectivamente

SetXY () toma dos valores y permite realizar las dos operaciones con una sola instruccioacuten

$pdf-gtSetXY(100100) $pdf-gtwrite(2Este texto se mostraraacute a 10 cm del margen)

Salto de paacutegina automaacutetico

El meacutetodo S e t A u t o P a g e B r e a k () activa o desactiva el salto de paacutegina automaacutetico

Esto quiere decir que si estaacute activado cuando el texto llegue al final de la paacutegina se crearaacute una paacutegina nueva para poder contener el resto El primer paraacutemetro debe ser true ofalse para activa o desactivar la proshypiedad

El segundo paraacutemetro indica la distancia desde la parte inferior que desshyencadena la llamada a una nueva paacutegina

Se tAutoPageBreak( t rue 20 )

El coacutedigo anterior activa el salto de paacutegina automaacutetico cuando el texto lleshygue a 2 centiacutemetros del margen inferior

Creacioacuten de archivos PDF 331

Sobrescribir los meacutetodos

La clase FPDF contiene algunos meacutetodos vaciacuteos que debe escribir usted si quiere que sus documentos queden profesionales Puede crear un objeto propio que herede del objeto FPDF e implementar algunas caracteriacutesticas avanzadas

Cabecera

La cabecera de un documento es un conjunto de texto escrito en la parte superior del folio y que debe aparecer en todas las paacuteginas La clase FPDF implementa el meacutetodo header () que se llama cada vez que existe un salto de paacutegina

Puesto que el meacutetodo estaacute vaciacuteo en FPDF tendraacute que crear un objeto nueshyvo que herede todos sus meacutetodos e implemente la cabecera

ltphp define ( FPDF_FONTPATH fpdffont ) requireonce(fpdffpdfphp) class PDF extends FPDF

function Header()

$this-gtSetFont(ArialB15) $this-gtSetX(70) $this-gtCell(100 10 Manual Imprescindible de PHP 510C) $this-gtLn(20)

$pdf = new PDF () for($i=l$ilt=200$i++) $pdf-gtCell(010Imprimiendo liacutenea nuacutemero $i0l)

$pdf-gtOutput () gt

El meacutetodo header () configura un tipo de letra determinado en negrita avanza el cursor 8 centiacutemetros hacia la derecha e imprime una celda con el tiacutetulo El meacutetodo Ln (2 0 ) inserta un salto de liacutenea cuya altura es determinada por el argumento

Para probar el objeto hemos hecho un bucle que imprime 100 liacuteneas y asiacute comprobar que la cabecera aparece invariable El resultado se puede obshyservar en la figura 192

Imagen de cabecera

Tambieacuten es posible antildeadir una imagen a la cabecera con el meacutetodo Ima-ge ( ) La construccioacuten es la siguiente

Image(fichero x y ancho alto tipo enlace)

Los paraacutemetros necesarios son fichero x e y La descripcioacuten de todos los argumentos es

bull fichero Indica la ruta hacia el fichero que va a insertar

bull x Posicioacuten en el eje x de la imagen

bull y Posicioacuten en el eje y de la imagen

bull ancho Ancho de la imagen

bull alto Alto de la imagen Si no se indica y el paraacutemetro ancho estaacute defishynido el alto se escala en funcioacuten del ancho

bull tipo El tipo de imagen Por ahora soacutelo se aceptan imaacutegenes JPG JPEG y PNG

bull enlace La imagen puede ser un enlace

Ahora que sabe coacutemo insertar imaacutegenes puede incluir en la cabecera el logotipo de su empresa o asociacioacuten

funct ion Header()

Creacioacuten de archivos PDF 333

$this-gtSetFontArialB15) $this-gtSetX(70) $this-gtCell(10010Manual Imprescindible de PHP 510C) $this-gtSetX(-20) $this-gtImage(phppng1705) $this-gtLn (20)

La figura 193 muestra una cabecera con una imagen insertada

Pie de paacutegina

De la misma forma puede sobrescribir el meacutetodo que imprime el pie de paacutegina de la clase FPDF

Este meacutetodo recibe el nombre de F o o t e r () y tiene el mismo tratamiento que la cabecera cada vez que existe un salto de paacutegina se hace una llamashyda al mismo Nuestro pie de paacutegina puede quedar de la siguiente forma

funct ion Footer()

$this-gtSetY (-15) $this-gtSetFont(Arial I 10) $this-gtCell (010 Paacutegina $this-gtPageNo() 00 C )

334 Capiacutetulo 19

S e t Y () nos coloca el cursor a 15 miliacutemetros del borde derecho Seguidashymente escoja el tipo de fuente Aria e imprima el nuacutemero de la paacutegina acshytual con el meacutetodo PageNo ()

Muchos documentos informan ademaacutes del nuacutemero de paacuteginas que tiene el texto Esto es complicado a primera vista porque a priori no podraacute saber cuaacutentas paacuteginas ocuparaacute su texto Existe un meacutetodo que se ejecuta cuando el documento es cerrado y sustituye una marca por el nuacutemero de folios con los que cuenta nuestro proyecto

function FooterO

$this-gtSetY(-15) $this-gtSetFont ( Anal I 10) $this-gtAliasNbPages() $this-gtCell(0 10 Paacutegina $this-gtPageNo()

nb 00 C)

El meacutetodo A l i a s N b P a g e s () cuenta el nuacutemero de paacuteginas cuando el doshycumento estaacute cerrado y sustituye la marca nb por este nuacutemero

Tablas

Una tabla no es maacutes que un conjunto de celdas colocadas en un orden determinado Podemos diferenciar entre la cabecera de la tabla que conshytendraacute las propiedades y los datos Si realiza una clase para escribir tashyblas puede hacer tambieacuten esa diferenciacioacuten cambiando el tipo de letra el tamantildeo o el color El coacutedigo siguiente muestra coacutemo se puede instaurar una clase para la creacioacuten de tablas faacutecilmente

ltphp define(FPDF_FONTPATHfpdffont) require_once(fpdffpdfphp) class PDF extends FPDF function tabla($cabecera$datos)

$this-gtcabecera ($cabecera) $this-gtdatos($datos)

function cabecera($cabecera) Cabecera

$this-gtSetFont(ArialB15)

Creacioacuten de archivos PDF 335

foreach($cabecera as $columna) $this-gtCell(407$columna1 0 C )

$this-gtLn()

function datos($datos) Datos

$this-gtSetFont(Arial12) foreach ($datos as $dato)

foreach ($dato as $columna) $this-gtCell(407$columna10 C )

$this-gtLn ()

$pdf = new PDF () $pdf-gtAddPage ()

$cabecera = array(UsuariosVisitasLocalidadTeleacutefono) $datos = array(array(Luis Miguel 12Badajoz555345678)

array(Mariacutea Fernanda 45 Meacuterida 234234654) array(Pedro Casas3Caacuteceres342123 890))

$pdf-gttabla($cabecera$datos) $pdf-gtOutput () gt

En este caso los datos se sacan de un array de dos dimensiones pero pueshyde utilizar la libreriacutea de bases de datos o la de XML creadas en los capiacutetushylos anteriores para extraerlos

Los datos los recibe el meacutetodo T a b l a ( ) que los enviacutea a sus corresponshydientes meacutetodos para ser tratados El funcionamiento baacutesico consiste en la creacioacuten repetitiva de celdas cuyo nuacutemero coincidiraacute con el nuacutemero de datos existentes en el array Todas las celdas se muestran seguidas dando sensacioacuten de ser una tabla como puede ver en la figura 194 Ahora que es casi un experto en la creacioacuten de tablas para facturas o alba-ranes en PDF puede dar un toque de color al relleno texto o liacuteneas de las celdas

Puede comprobar que con tan soacutelo tres liacuteneas de coacutedigo maacutes el aspecto visual del documento mejora considerablemente

function cabecera($cabecera)

Cabecera $this-gtSetFillColor (25500)

336 Capiacutetulo 19

$this-gtSetTextColor(255) $this-gtSetDrawColor(12 800) $this-gtSetFont(ArialB15) foreach($cabecera as $columna)

$this-gtCell(407$columna10C1)

$this-gtLn()

function datos($datos)

D a t o s $this-gtSetTextColor (1) $thiacutes-gtSetDrawColor (12 800) $this-gtSetFont ( Arial 12) foreach ($datos as $dato)

foreach ($dato as $columna) $this-gtCell(407$columna10C)

$this-gtLn ()

El resultado es mucho maacutes llamativo gracias a los meacutetodos que antildeaden color El meacutetodo S e t F i l l C o l o r () define el color de fondo de las celdas

Creacioacuten de archivos PDF 337

y los rectaacutengulos que no sean transparentes Puede ser expresado con un componente RGB o en escala de grises El valor se mantiene durante todo el documento hasta que se vuelva a invocar el meacutetodo

S e t T e x t C o l o r () y S e t D r a w C o l o r () funcionan de la misma forma actuando esta vez sobre el color del texto o el color de las liacuteneas y bordes de celda La figura 194 muestra los colores (tonos de grises en este caso) distintos que pueden tomar un archivo PDF

Enlaces

Una de las ventajas del formato PDF es que permite hacer enlaces intershynos es decir que si tiene un documento de 500 folios podraacute acceder a cada uno de los capiacutetulos haciendo clic en el iacutendice tal y como funcionan los enlaces en las paacuteginas Web

Un enlace externo es muy faacutecil de crear

$pdf-gtWrite(5wwwluisyfernandanethttpwwwluisyfernandanet)

Los meacutetodos dedicados a texto tienen un argumento para antildeadir un enlashyce que si es externo debe llevar la direccioacuten URL completa

338 Capiacutetulo 19

Crear un enlace interno es algo maacutes complicado Tiene que hacer uso del meacutetodo A d d l i n k ( ) que genera una referencia que debe ponerse en el lugar hacia donde quiere que se produzca el salto En ese lugar utilice el meacutetodo S e t L i n k () para cerrar el enlace

El coacutedigo de ejemplo puede aclarar el concepto

ltphp define(FPDF_FONTPATHfpdffont) require_once(fpdffpdfphp) $pdf = new FPDF() $pdf-gtAddPage () $pdf-gtSetFont(Arial 15) $enLace = $pdf-gtAddLink() $pdf-gtWrite(5Este texto contiene un enlace$enlace) $pdf-gtAddPage) $pdf-gtSetLink($enlace) $pdf-gtWrite (5 Enlace Interno) $pdf-gtOutput () gt

Lo uacutenico a destacar es la creacioacuten del enlace con AddLink ( ) La variable $ e n l a c e recoge el valor de referencia y se antildeade al texto de la liacutenea sishyguiente En este momento el texto contiene un enlace pero no sabemos hacia doacutende La solucioacuten estaacute en llamar al meacutetodo S e t L i n k () en la paacutegishyna de destino con la referencia de paraacutemetro

Resumen

Los archivos PDF se consideran desde hace unos antildeos ideales para la geshyneracioacuten de contenidos on-line As iacute revistas digitales como w w w phparchcom o wwwphpmagnet utilizan este sistema para vender su publicacioacuten

Ademaacutes de revistas digitales podemos encontrar empresas que hacen lleshygar las instrucciones de sus productos en PDF o realizan las facturas de los clientes on-line como el programa de facturacioacuten extrementildeo Galopiacuten (httpgalopinsinuhorg)

La generacioacuten de sus propios archivos ya no es un misterio y puede im-plementar clases muchos maacutes potentes que las mostradas en el libro para sus propios proyectos La inclusioacuten de colores imaacutegenes y tablas de disshytintos tipos haraacuten del lector un profesional de la edicioacuten Web

En este capiacutetulo aprenderaacute a

bull Conocer queacute es un sistema de plantillas con Smarty

bull Independizar el coacutedigo HTML de PHP bull Crear plantillas con variables y bucles bull Crear plugins propios y modificar los ya existentes bull Crear filtros para mejorar el proceso

340 Capiacutetulo 20

Introduccioacuten

Cuando PHP nacioacute fue considerado como un sencillo lenguaje para geneshyrar dinaacutemicamente etiquetas de HTML Tras la versioacuten 3 de PHP se antildeashydioacute un compendio de funciones complejas para el manejo de cadenas arrays y bases de datos lo suficientemente completas como para crear sishytios Web muy extensos

Despueacutes de la creacioacuten de entornos completos en PHP los desarrollado-res comenzaron a pensar que no era muy uacutetil mezclar coacutedigo PHP con coacutedigo HTML e inventaron una forma de independizar los dos lenguajes mediante el uso de plantillas El primer entorno de plantillas que apareshycioacute fue FastTemplate escrito originariamente en Perl

En un periacuteodo corto de tiempo aparecieron muchos programas que facilishytaban el uso de plantillas como vTemplate Xtemplate TemplatePower o SmartTemplate Todos permiten sustitucioacuten de variables bloques repetishytivos inclusioacuten de muacuteltiples plantillas y bloques opcionales con estructushyras del tipo i f La diferencia estaacute en que muchos de estos sistemas utilizan expresiones regulares y hace muy complicado su uso Ademaacutes la velocishydad con la que se generan las plantillas es una propiedad a tener en cuenshyta en un entorno de trabajo en produccioacuten

SmartTemplate aparecioacute en 1999 y es el predecesor de lo que hoy conoceshymos como Smarty Es un entorno muy similar a otros pero incluye caracshyteriacutesticas muy avanzadas que lo hacen uacutenico la compilacioacuten de plantillas Esto significa que Smarty lee la plantilla y crea un script escrito en PHP Una vez creado este script se ejecuta y muestra el resultado en pantalla Lo bueno es que la compilacioacuten soacutelo se hace la primera vez las veces sishyguientes Smarty comprueba si hay nuevos datos que mostrar y si no los hay se utiliza la plantilla escrita en PHP por lo que la ejecucioacuten se hace muy raacutepida Algunas de las caracteriacutesticas generales de Smarty son

bull Extremadamente raacutepido

bull Muy eficiente porque el parse de PHP hace todo el trabajo

bull Soacutelo se compilan las plantillas que cambien los datos

bull Podemos realizar funciones propias y modificadores de variables Esto hace que Smarty sea extensible por el usuario

bull Se pueden utilizar varios delimitadores como j ltmdashmdashgt

bull Las estructuras de control son manejadas directamente por el parse de PHP por lo tanto pueden ser tan complejas como quiera

Plantillas con Smarty 341

bull Se puede incluir coacutedigo PHP dentro de nuestras plantillas

bull Funciones configurables para el manejo de la cacheacute

bull Arquitectura de plugins ampliable

Instalacioacuten de Smarty

La instalacioacuten del entorno de Smarty es muy sencillo y pasa por descargar de la Web httpsmartyphpnet la uacuteltima actualizacioacuten del sistema El archivo comprimido consta de varias carpetas que deberiacutean estar dentro del directorio de libreriacuteas de PHP Tambieacuten es posible guardar la carpeta de Smarty junto con nuestros programas pero no es recomendable

Las libreriacuteas del sistema de plantillas incluidas dentro del directorio l i b s son

Smartyclassphp Smarty_Compilerclassphp Config_Fileclassphp debugtpl

Ademaacutes de estos archivos existen las carpetas c o r e y p l u g i n s que se encargan de controlar el flujo de los objetos de Smarty

Las plantillas que creemos las vamos a guardar en un directorio llamado t e m p l a t e s y las plantillas compiladas deberaacuten estar en t e m p l a t e s _ c

Advertencia

La carpeta t e m p l a t e s _ c debe permitir la escritura porque aquiacute se iraacuten guardando las plantillas compiladas

Utilizacioacuten baacutesica de Smarty

Durante el desarrollo del libro hemos visto algunas teacutecnicas para escribir limpiamente nuestro coacutedigo PHP mezclado con HTML Vamos a ver una clase implementada por nosotros que genera una Web desde PHP y desshypueacutes vamos a ver coacutemo hacer lo mismo desde Smarty

ltphp c l a s s PaginaWeb

342 Capiacutetulo 20

priacutevate $titulo function construct($titulo)

$this-gttitulo = $titulo

priacutevate function cabecera($titulo)

echo lthtmlgt echo ltheadgt -echo lttitlegt$tituloltheadgt echo ltheadgt echo ltbodygt

priacutevate function cuerpo()

echo Este es el cuerpo de nuestra Webltbrgt priacutevate function pie()

echo Pie creado con PaginaWeb class echo ltbodygt echo lthtmlgt

public function creaWeb()

$this-gtcabecera($this-gttitulo) $this-gtcuerpo () $this-gtpie ()

$pagina = new PaginaWeb(Pagina Web generada con PHP) $pagina-gtcreaWeb () gt

Lo que hace cada meacutetodo es generar las etiquetas necesarias para crear una paacutegina Web Imagine ahora un gran sitio Web con cientos de paacuteginas Web con distinto tipo de informacioacuten Cambiar el aspecto visual de esa Web seriacutea un trabajo muy laborioso de varios meses primero buscando doacutende se encuentran las etiquetas junto al coacutedigo PHP y segundo modishyficando todo el coacutedigo HTML para que cambie el aspecto visual Las planshytillas solucionan este problema en muy poco tiempo separando el coacutedigo de la presentacioacuten

El resultado se puede ver en la figura 201

La paacutegina Web siguiente p l a n t i l l a r t p l es la misma que genera la clase anterior pero esta vez creada como plantilla

plantillaltpl

Plantillas con Smarty 343

lthtmlgt ltheadgt lttitlegt$titulolttitlegt ltheadgt ltbodygt $cuerpo $pie ltbodygt lthtmlgt

Todas las etiquetas conservan el estilo de HTML antildeadiendo siacutembolos de llave donde debe aparecer contenido dinaacutemico $ t i t u l o $cuerpo y $pie son variables que reciben su valor desde el programa escrito en PHP

Nota

Todo lo que estaacute entre se considera un comentario

344 Capiacutetulo 20

Para poder asignar valores a la plantilla tiene que hacer una instancia de la clase Smar ty

Puede modificar el objeto anterior para que haga uso de plantillas

ltphp class PaginaWeb

priacutevate $titulo priacutevate $Web function construct($titulo)

$this-gttitulo = $titulo requiacutere_once(Smarty1 ibsSmartyclassphp) $this-gtWeb = new Smarty

priacutevate function cabecera($titulo)

$this-gtWeb-gtassign(titulo$this-gttitulo) priacutevate function cuerpo()

$this-gtWeb-gtassign(cuerpoEste es el cuerpo de nuestra Web)

priacutevate function pie ( )

$this-gtWeb-gtassiacutegn(pie Pie creado con PaginaWeb) public function creaWeb()

$this~gtcabecera($this-gttitulo) $this-gtcuerpo () $this-gtpie()

$this-gtWeb-gtdisplay(plantilla1tpl)

$pagina = new PaginaWeb(Pagina Web generada con PHP) $pagina-gtcreaWeb() gt

La clase es exactamente igual (con los mismos meacutetodos) pero ahora se encuentra libre de etiquetas HTML En su lugar aparecen asignaciones a variables de Smarty El constructor instancia un objeto desde la clase Smarshyty y lo guarda en $ t h i s - gtWeb Las asignaciones de variables se hacen con el meacutetodo a s s i g n () que tiene que recibir como primer paraacutemetro el nombre de la variable escrita en la plantilla y como segundo argumento el texto que debe aparecer en lugar de la variable

Plantillas con Smarty 345

Despueacutes de asignar todos los valores tendremos que llamar al meacutetodo d i s -p l a y () con la plantilla como argumento para que la Web aparezca en el navegador

Si se fija ahora en el directorio de las plantillas compiladas t e m p l a t e s _ c veraacute que ha aparecido un archivo que contiene el siguiente coacutedigo

ltphp Smarty versioacuten 263 created on 2004-08-15 130335

compiled from plantillaltpl gt lthtmlgt ltheadgt lttitlexphp echo $this-gt_tpl_vars [ titulo ] bull gt lttitlegt ltheadgt ltbodygt ltphp echo $this-gt_tpl_vars[cuerpo] gt

ltbrxbrgt ltphp echo $this-gt_tpl_vars[pie] gt

ltbodygt lthtmlgt

Como puede apreciar la compilacioacuten de una plantilla de Smarty consiste en cambiar los valores entre llaves por coacutedigo PHP que hace llamadas a las variables Esto lo convierte en un meacutetodo muy raacutepido porque es el mismo PHP el que se encarga de mostrar la plantilla ya compilada

Cuidado con los estilos CSS

Es muy uacutetil utilizar estilos CSS para definir los colores tipos de letra y demaacutes objetos de presentacioacuten que vamos a utilizar en nuestras paacuteginas Web

El problema surge porque su construccioacuten es de la siguiente forma

lts ty l e t y p e = t e x t c s s gt lt - -P colorgreen - - gt ltstylegt

Este estilo sirve para que los paacuterrafos sean por defecto de color verde El problema es que Smarty parsea todo lo que estaacute entre siacutembolos de llave como c o l o r g r e e n En este caso se produciriacutea un error porque el parse no identificariacutea ninguna funcioacuten estructura o variable de plantilla Para solucionar esto se pueden antildeadir las etiquetas l i t e r a l y l i t e -

346 Capiacutetulo 20

r a l que al ser parseadas su contenido se identifica como un comentashyrio y se salta hasta el siguiente juego de llaves

literal ltstyle type=textcssgt lt --P colorgreen mdash gt ltstylegt literal

Llamada a varias plantillas

Casi todas las paacuteginas Web pueden dividirse en varias partes bien difeshyrenciadas cabecera menuacute cuerpo pie

Con Smarty podraacute crear una Web simple que incluya todas las partes de la Web como un uacutenico archivo HTML o crear 4 plantillas distintas y 1 que las unifique por lo que seriacutea maacutes sencillo cambiar el aspecto de cada una de las partes

La funcioacuten i n c l u d e f i l e de Smarty permite antildeadir plantillas a un fishychero La plantilla principal puede ser de la siguiente forma

lthtmlgt ltheadgt lttitlegt$titulolttitlegt ltheadgt ltbodygt include file=cabeceratpl include file=cuerpotpl include file=$pie ltbodygt lthtmlgt

De esta forma podemos modificar alguna de las plantillas y automaacuteticashymente todas las Web que hagan referencia a la misma cambiaraacuten su asshypecto

Como puede ver la plantilla que genera el pie de paacutegina es una variashyble por lo tanto podemos pasar desde PHP el nombre de cualquier planshytilla en funcioacuten de alguacuten caacutelculo interno o de alguacuten dato de MySQL etceacutetera

Variables

Smarty acepta muchos tipos de variables diferentes

Plantillas con Smarty 347

Pueden ser utilizadas para mostrarse directamente o como paraacutemetro de alguna funcioacuten o modificador dentro de alguna estructura de control etshyceacutetera

$nombre $contactonombre $contacto [0] $persona-gtnombre config_load_file=configuracioacutenconf lttitlegttitulolttitlegt

El coacutedigo anterior contiene diferentes tipos de variables y la forma de imshyprimir el dato que nos interesa Para una variable del tipo array puede utilizar la forma asociativa $ c o n t a c t o nombre o la forma indicativa $ c o n t a c t o [0] Tambieacuten es posible mostrar las propiedades de un objeshyto haciendo referencia asiacute $ p e r s o n a - gtnombre

Por uacuteltimo Smarty posee una funcioacuten que permite cargar una configurashycioacuten de un fichero Con la instruccioacuten c o n f iacute g _ l o a d _ f iacute l e cargaraacute en memoria la configuracioacuten del fichero que deacute como argumento El fichero debe estar escrito de esta forma

titulo = Pagina Web con PHP nombre = Luis Miguel color = FFFFFF

Modificadores

Los modificadores se pueden aplicar a las variables funciones o cadenas de caracteres Eacutestos permiten embellecer el texto recortarlo o adecuarlo a un formato determinado Para utilizar un modificador tiene que especifishycar la variable seguido de un siacutembolo de tuberiacutea ( I ) y el nombre del modificador

lthtmlgt ltheadgt cambia el texto a mayuacutesculas lttitlegt$titulo|upperlttitlegt ltheadgt ltbodygt Recorta el texto a 10 caracteres y le suma tren puntos suspensivos $cuerpoiexcltruacutencate10 ltbrxbrgt $pie ltbodygt lthtmlgt

348 Capiacutetulo 20

La plantilla anterior contiene el modificador upper que convierte todos los caracteres que recibe en mayuacutesculas El modificador t r uacute n c a t e recorshyta el texto dejaacutendolo en 10 caracteres y le antildeade puntos suspensivos como puede apreciar en la figura 202 La tabla 201 contiene un conjunto de modificadores que pueden utilizarse en las plantillas

Tabla 201 Modificadores de Smarty

Modificador Descripcioacuten Paraacutemetros

capitalize Convierte la primera letra Ninguno de cada palabra a mayuacutescula

count_characters Se usa para contar los Ninguno caracteres de una variable

cat Concatena el paraacutemetro 1 El texto a concatenar pasado a la variable

count_paragraphs Cuenta el nuacutemero de paacuterrafos Ninguno que contiene una variable

count_words Cuenta el nuacutemero de palabras Ninguno

Plantillas con Smarty 349

Modificador Descripcioacuten Paraacutemetros

date_format Imprime en un formato 1 Formato de salida 2 Si determinado la fecha y hora la entrada estaacute vaciacutea acep-del sistema este paraacutemetro por defecto

default Valor por defecto de la 1 El valor por defecto variable Si no se asigna ninguacuten valor la variable tendraacute el valor por defecto

escape Antildeade caracteres de escape 1 html htmlall url quo-a la variable tes hex hexentity javas-

cript

indent Antildeade varios caracteres a 1 Nuacutemero de caracteres a la izquierda de la variable indentar 2 Caraacutecter elegishy

do para indentar

lower Convierte a minuacutescula todos Ninguno los caracteres

nl2br Convierte los saltos de liacutenea a ltbrgt

regexreplace Busca y reemplaza una 1 Expresioacuten regular 2 Ca-expresioacuten regular dena de texto a reemplazar

replace Reemplaza una cadena de 1 Cadena a reemplazar caracteres por otra 2 Cadena de texto que susshy

tituiraacute al paraacutemetro 1

spacify Inserta un caraacutecter determinado 1 Caraacutecter entre los caracteres de la variable Por defecto un espacio en blanco

string_format Formatea un texto 1 Formato del texto como lo usa s p r i n t f

strip Reemplaza todos los espacios Ninguno saltos de liacuteneas y fabuladores por un espacio en blanco

strip_tags Elimina todas las etiquetas Ninguno

truacutencate Recorta una variable el nuacutemero 1 Nuacutemero de caracteres a de caracteres que indiquen los recortar 2 Texto que debe paraacutemetros aparecer si se recorta 3

True permite recortar en mitad de una palabra

upper Convierte a mayuacutesculas todos los caracteres de una variable

350 Capiacutetulo 20

Es bueno saber que podraacute aplicar varios modificadores a una misma vashyriable Tiene que antildeadirlos en el orden en el que quiera que se ejecuten de izquierda a derecha

$cuerpo[upper|spacify j truacutencate20

Nota

Si la variable es un array se aplicaraacute el modificador a todos ss valores

Funciones

El gestor Smarty tiene varias funciones que se pueden utilizar dentro del aacutembito de las plantillas Ademaacutes puede crear sus propias funciones o modificar las que ya estaacuten construidas

foreach

El bucle foreach se utiliza para mostrar un array simple La sintaxis es algo distinta al bucle de PHP

lttablegt foreach from=$art is tas i tem=valor lt t r x t d gt $ v a l o r lt t d x t r gt foreach lt t ab legt

Lo puede utilizar para antildeadir los valores de un array a una tabla como en el coacutedigo anterior La construccioacuten maacutes baacutesica de fo reach recibe en el atributo f rom el array que contiene los valores El atributo item crea una variable de Smarty que recoge los valores del array y se puede utilizar para mostrar el valor unas liacuteneas maacutes abajo

Otra construccioacuten un poco maacutes compleja es lttablegt foreach name=buclel from=$artistas key=indice item=valor lttrxtdgt $indice $valor lttdxtrgt foreach lttablegt

Funciona exactamente igual que el anterior El atributo key recoge el vashylor del iacutendice del array y ntildeame da un nombre al bucle para poder acceder a eacutel desde las variables propias de Smarty

Plantillas con Smarty 351

Truco

Se puede acceder al bucle mediante la variable global de Smarty Esta variable es $ smar ty Para acceder al bucle puede hacerlo de la siguiente forma $ s m a r t y f o r e a c h b u c l e 1

El resultado de la ejecucioacuten de la plantilla es

0 Paquito DRivera 1 Michel Camilo 2 Jerry Gonzaacutelez

if elseif else

La construccioacuten i f es tan flexible como la sentencia de PHP Cada i f debe tener una pareja del tipo i f

if $artistas[0] = Michel Camilo El primer artista toca el saxofoacuten alto

else El primer a r t i s t a toca e l piano

i f

Ademaacutes de los operadores baacutesicos de PHP tambieacuten puede utilizar mushychos otros como eq ne neq g t l t l t e l e g t e g e i s even i s odd i s n o t odd no t mod d i v by e v e n by o odd by El coacutedigo siguiente es similar al anterior

if $artistas[0] ne Michel Camilo El primer artista toca el saxofoacuten alto

else

El primer artista toca el piano

if

php incluido en plantillas

Puede antildeadir a una plantilla coacutedigo PHP encerrado entre las etiquetas de Smarty php y phpiexcl Si recuerda la filosofiacutea de las plantillas separar el coacutedigo de la presentacioacuten no se me ocurre ninguna excusa para utilizar esta habilidad en alguacuten proyecto por si acaso alguien le encuentra alguacuten sentido su uso es muy sencillo

php Incluir aquiacute alguacuten coacutedigo escrito en PHP include_once(logotiposphp) Php

352 Capiacutetulo 20

assign

Crea una variable y le asigna un valor determinado

assign var=variable value=Michel Camilo El valor de $variable es $variable

Se utiliza en tiempo de ejecucioacuten de la plantilla

counter

Se utiliza para imprimir un contador en pantalla

counter start=0 skip=3 print=falseltbrgt counterltbrgt counterltbrgt counterltbrgt

El atributo s t a r t indica el nuacutemero desde el que va a empezar el contashydor y s k i p el nuacutemero que debe sumarse al contador cada vez que exista una ocurrencia Cada vez que el parse encuentre c o u n t e r se incremenshytaraacute el contador y el navegador mostraraacute el resultado Para el ejemplo anterior podemos obtener

3

6

9

cycle

Una funcioacuten interesante que permite alternar entre varios valores pasashydos Cada vez que se ejecuta se recupera un valor distinto hasta el final de los valores Cuando se llega al final de la lista se vuelve a empezar Es muy uacutetil cuando queremos mostrar valores en una tabla y que cada liacutenea de detalle muestre un color diferente

lttablegt foreach name=buclel from=$artistas key=indice item=valor lttr bgcolor=cycle valueacutes=EEEEEEd0d0d0gtlttdgt$indice $valorlttdxtrgt foreach lttablegt

En este caso el bucle genera nombres de artistas del Jazz Latino y los inshytroduce en una tabla Gracias a la funcioacuten c y c l e se pueden diferenciar unos de otros por tener los colores de fondo de cada liacutenea distintos

Plantillas con Smarty 353

Opciones avanzadas de Smarty

Existen muchos tutoriales en Internet sobre el sistema de plantillas Toshydos abarcan la forma de utilizar las funciones y variables del entorno pero pocos se ocupan de las caracteriacutesticas que lo hacen uacutenico

La arquitectura de Smarty estaacute escrita en PHP Los ficheros que contienen las funciones baacutesicas para que el parse pueda realizar su trabajo estaacuten dentro de c o r e Pero la mayoriacutea de las funciones de presentacioacuten estaacuten incluidas dentro de la carpeta de p l u g i n s

Plugins

Un plugin dentro de la estructura de Smarty es un pequentildeo programa que realiza una tarea determinada Por ejemplo todos los modificadores son plugins y cada uno se encarga de hacer algo con el texto Veamos la estructura del plugin c a p i t a l i z e que recordemos modifica la primera letra de cada palabra y la convierte a mayuacutescula

ltphp function smarty_modifiacuteer_capitalize($string)

return ucwords($string)

gt

El funcionamiento del plugin es obvio Tan soacutelo hace uso de una funcioacuten existente en PHP para mostrar el resultado Puesto que es tan sencillo vamos a crear un plugin que serviraacute para enfatizar nuestro texto en detershyminadas ocasiones

ltphp function smarty_modifier_enfatizar($string)

re turn ltbgt $ s t r ing ltbgt

gt

Para crear un plugin modi f icador cree un fichero con el nombre modif i e r nombre php y guaacuterdelo en el directorio d e p l u g i n s En este caso tendraacute que crear un archivo con el nombre modi f i e r e n f a t i z a r php El nombre de la funcioacuten tambieacuten debe llevar un nombre estructurado Nuestro modificador se llamaraacute s m a r t y _ m o d i f i e r _ e n f a t i z a r y reci-

354 Capiacutetulo 20

biraacute como paraacutemetro la cadena de caracteres que lo utilice Dentro de la funcioacuten puede antildeadir el coacutedigo que sea necesario para cumplir su propoacuteshysito y despueacutes devolver el valor con la funcioacuten re turn

En nuestro caso devolvemos la misma cadena pero antildeadiendo la etiqueta de HTML para mostrar el texto en negrita por lo que quedaraacute enfatizado Tambieacuten podemos antildeadir alguacuten paraacutemetro para elegir entre distintos tishypos de eacutenfasis

ltphp funetion smarty_modifier_enfatizar($string $parametrol)

switch ($parametrol)

case 1 return ltbgt $striacuteng ltbgt break-

case 2 return ltemgt $string ltemgt break

case 3 return i i iexcl $string break

default return ltbgt $string ltbgt

gt

Ahora tenemos tres formas distintas de mostrar un texto que llame la atenshycioacuten Para invocar desde la plantilla cualquiera de los tipos de eacutenfasis hashybraacute que separar el modificador con un siacutembolo de dos puntos ( )

$valor|enfatizar3

Filtros

Los filtros son funciones que realizan una tarea determinada en nuestra plantilla justo antes o despueacutes de que sea compilada Se pueden consideshyrar los pre-filtros y los post-filtros respectivamente Existe un tercer tipo de filtro que se ejecuta en el momento de la llamada al meacutetododisplay ()

Crear un filtro para Smarty es tan sencillo como crear un plugin Hay que seguir estrictamente la nomenclatura del archivo y del nombre de la funshycioacuten para que funcione correctamente

ltphp function smarty_jostfilter_HechoCon($compiled amp$smarty)

Plantillas con Smarty 355

return $compiled ltbgtHecho con Smartyltbgt

gt

El filtro HechoCon () es una funcioacuten que recibe como paraacutemetros la fuente de la paacutegina Web ya compilada y el objeto Smarty que estamos utilizanshydo Nuestro filtro HechoCon devuelve la Web y antildeade un pequentildeo texto que indica que ha sido creado con Smarty

Para poder utilizar el filtro tenemos que cargarlo antes de utilizar el meacuteshytodo d i s p l a y ( ) en nuestro coacutedigo Esto se hace con la funcioacuten l o a d _ f i l t e r ( )

$this-gtWeb- gtload__f ilter (pre trim) $this-gtWeb-gtload_filter(postHechoCon) $this-gtWeb-gtload_filter(outputcompress)

El primer paraacutemetro del meacutetodo l o a d _ f i l t e r () indica el tipo de filtro que vamos a cargar y el segundo el nombre que recibe

Resumen

Alguacuten lector se preguntaraacute despueacutes de entender correctamente lo bueno que es separar el coacutedigo de la presentacioacuten por queacute he esperado tanto tiempo en contar el secreto de Smarty La verdad es que es mejor aprenshyder PHP paso a paso haciendo pequentildeos programas con HTML embebishydo para despueacutes ir concibiendo la mejor forma de atajar los diferentes proyectos que nos propongan

Con Smarty tiene una viacutea libre de exploracioacuten maacutes porque muchas de sus caracteriacutesticas no han podido ser tratadas en este capiacutetulo Le queda aveshyriguar coacutemo utilizar la cacheacute los recursos (habilidad para leer de una base de datos una plantilla) y las numerosas funciones que hemos dejado en el tintero Una vez que conozca la potencia de Smarty no querraacute mezclar nunca maacutes su coacutedigo con HTML

358 Apeacutendice A

Antes de comenzar

El primer paso para desarrollar programas en PHP 5 es encontrar un sershyvidor donde hacer las pruebas del programa y posteriormente dejarlo almacenado para que los usuarios puedan utilizarlo Este servidor debeshyriacutea estar disponible las 24 horas del diacutea con una conexioacuten fija a Internet

Como esto puede ser algo complicado al principio vamos a ver los pasos necesarios para instalar un servidor de pruebas donde escribir nuestros primeros scripts

PHP 5 se distribuye como coacutedigo fuente listo para compilar en el sistema operativo que quiera El problema es que es algo complicado si nunca ha compilado un programa Por eso he elegido paquetes ya compilados que soacutelo necesitan ser instalados para comenzar a funcionar

Vamos a instalar los siguientes programas

bull Servidor Web Apache

bull PHP 5

bull MySQL 4

Instalacioacuten en MacOSX

Uno de los maacutes excitantes desarrollos Open Source ha sido la apertura parshycial del coacutedigo de la plataforma Macintosh Gracias a esto muchos usuashyrios estaacuten contribuyendo con la creacioacuten de paquetes de instalacioacuten como el de PHP 5

Apache

El servidor Web Apache es necesario para enviar las peticiones HTTP de los clientes

Afortunadamente Apache viene ya instalado en MacOSX Para ponerlo en funcionamiento tendraacute que seguir los siguientes pasos

bull Abra una Terminal

bull Entre como suacuteper usuario con el comando su

bull Introduzca la passzvord de suacuteper usuario

bull Escriba a p a c h e c t l s t a r t

La figura A l muestra los pasos realizados en el terminal para iniciar el servidor Web A partir de ahora puede probar si funciona Apache escribiendo en el nashyvegador la direccioacuten l o c a l h o s t como muestra la figura A2

360 Apeacutendice A

PHP5

Existe una Web dedicada al mundo de MacOSX que se actualiza todos los diacuteas

Su administrador L i y a n a g e es el encargado de crear paquetes con toshydas las versiones de PHP 5 que ven la luz que en el momento de redactar el libro es la 501

Para instalar PHP 5 tendraacute que descargar el paquete de

ht tp www2entropychdownloadEntropy-PHP-5-01-1dmg

Una vez copiado el archivo en su sistema soacutelo tiene que hacer doble clic en eacutel y seguir los pasos de instalacioacuten del sistema operativo como puede ver en la figura A3

MySQL 4

Los pasos son exactamente igual que en la instalacioacuten de PHP 5

El primer paso es descargar el paquete para MacOSXmysql - s t a n d a r d -4 0 2 0 - a p p l e - d a r w i n 7 3 0 -powerpc dmg que se encuentra en la seccioacuten de descargas de la Web wwwmysql com

El paquete se instala como cualquier paquete de MacOSX simplemente haciendo doble clic

Instalacioacuten de PHP 5 y MySQL 361

Comprobacioacuten final

Para comprobar que todo funciona correctamente tendraacute que seguir los pasos siguientes

bull Abra una Terminal

bull Entre como suacuteper usuario con el comando su

bull Introduzca la password de suacuteper usuario

bull Reinicie la ejecucioacuten de Apache para que acepte la nueva configurashycioacuten de PHP 5 con el comando a p a c h e c t l r e s t a r t

bull Inicie MySQL con el comando u s r l o c a l m y s q l - s t a n d a r d -4 0 2 0 - a p p l e - d a r w i n 7 3 O - p o w e r p c b i n m y s q l d - u r o o t

bull Cree una Web de prueba y guaacuterdela en la ruta del usuario para paacutegishynas Web Normalmente es U s e r s u s u a r i o S i t e s

bull Abra el navegador y escriba la direccioacuten del servidor junto con el nomshybre de la Web La direccioacuten seraacute parecida a esta l o c a l h o s t - u s u a shyr i o i n f o r m a c i oacute n php

El programa que hemos escrito para comprobar que todo funciona correcshytamente y muestra el contenido de la figura A4 es

ltphp

362 Apeacutendice A

p h p i n f o ( ) gt

En la figura A4 puede ver el funcionamiento de todo el sistema instalado

Instalacioacuten en Windows

Instalar un sistema completamente funcional en un sistema operativo Windows puede ser tan sencillo o tan complicado como quiera Existe un paquete de aplicaciones llamado XAMPP que contiene todo lo necesario para funcionar con Apache PHP 5 y MySQL

En la Web wwwapachefriendsorg puede encontrar un archivo de instashylacioacuten de Windows

Despueacutes de descargar el archivo tiene que hacer doble clic y seguir las instrucciones impresas en pantalla como muestra la figura A5

Una vez instalado en la ruta lniciogtProgramasgtapachefriendsgtxampp veraacute tres apartados importantes

bull xampp basic start Se encarga de iniciar Apache PHP 5 y MySQL

bull xampp basic stop Para la ejecucioacuten de los servidores

bull xampp httpdoc folder Carpeta donde tiene que guardar todos sus programas escritos en PHP 5

Para probar que todo funciona puede ejecutar el programa xampp bashys i c s t a r t abrir un navegador y escribir como direccioacuten l o c a l h o s t Si

Instalacioacuten en gnuuumlnux

Existen en el mercado varias versiones de gnuLinux como gnuLinEx 2004 SuSe RedHat Gentoo Cada una de ellas posee un sistema de paquetes distinto Puesto que no tenemos espacio para describir 3 formas diferenshytes de instalar PHP 5 nos conformaremos con describir un tema general que sirve para todos los sistemas gnuLinux

Como ya puede imaginar nos vamos a apoyar en X A M P P para gnushyLinux

Una vez descargada la versioacuten para gnuLinux en el disco duro tendraacute que descomprimirla en un directorio El archivo comprimido deberiacutea llamarse x a m p p - l i n u x - 1 4 7 t a r g z Para instalarlo debe seguir los pasos sishyguientes

bull Descomprima con el comando g z i p -d x a m p p - l i n u x - 1 4 7 t a r g z

bull Vuelva a descomprimir el archivo esta vez con t a r x v f x a m p p - l i -n u x - 1 4 7 t a r

Instalacioacuten de PHP 5 y MySQL 363

todo se instaloacute correctamente podraacute ver una Web parecida a la de la figushyra A6

364 Apeacutendice A

bull Se crearaacute una carpeta llamada lampp

bull Copie la carpeta al directorio op t con el comando cp -r lampp opt

bull Ya lo tiene instalado Para ejecutarlo debe ser suacuteper usuario e invocar el comando opt lampp lampp s t a r t

La figura A7 muestra un terminal con el comando de inicio

En la figura A8 puede ver la paacutegina de inicio de XAMPP tras poner en el navegador l o c a l h o s t como direccioacuten Web Todas las paacuteginas Web que genere tendraacute que guardarlas en el directorio op t l ampp h tdocs para poder verlas a traveacutes del navegador

Recomendacioacuten final

La forma maacutes raacutepida y sencilla de hacer funcionar PHP 5 en su sistema es la que hemos visto pero no es la mejor La forma maacutes recomendable que se escapa del enfoque de este libro es compilar su PHP 5 De esta manera tendraacute la posibilidad de antildeadir los

Instalacioacuten de PHP 5 y MySQL 365

moacutedulos y extensiones que realmente vaya a utilizar La recomendacioacuten es que navegue por la Web wwwphpnet e investigue la forma de compishylar su sistema

368 Apeacutendice B

Introduccioacuten

El archivophp i n i contiene informacioacuten de configuracioacuten que puede moshydificar a su antojo Es un fichero de texto que se lee cada vez que se inicia el servidor Web Apache Para averiguar la ruta del disco duro donde se almacena el archivo php i n i soacutelo tiene que fijarse en el apartado Conf i g u r a t i o n F i l e (php i n i ) Path de la Web que recibioacute al ejecutar phpinf o () La configuracioacuten contiene parejas de variables valores separadas por puntos y comas Los valores que tenemos que asignar suelen ser rutas del disco duro 10 Yes No On Off o True False Cada vez que cambie alguna parte de la configuracioacuten tendraacute que reini-ciar Apache para que los cambios surtan efecto

short_open_tag

Permite la forma corta de antildeadir scripts de PHP de la forma lt gt Si quiere utilizar funciones XML es mejor dejarlo a Off

disable_functions

Desactiva funciones que nos resulten peligrosas como el enviacuteo de correos funciones de red etceacutetera

max_execution_time

Tiempo maacuteximo de ejecucioacuten de un script PHP en el servidor

error_reporting

Muestra el nivel de error que configure cuando un script falla Los tipos de errores los puede ver en el capiacutetulo 17

register_globals

Esta configuracioacuten ya no se utiliza a partir de la versioacuten PHP 42 y estaacute destinada a desaparecer

Configuracioacuten de phpini 369

Si la activa todas las variables seraacuten pasadas como globales y no dentro de las variables suacuteper globales

magic_quotes_runtime

Antildeade el siacutembolo de escape cuando se pasan variables con los siacutembolos de comillas simples o dobles

include_path

Antildeade rutas donde puede almacenar libreriacuteas que pueda utilizar sus proshygramas

Resumen

Hemos visto las principales opciones de configuracioacuten del archivo php i n i La configuracioacuten es mucho maacutes extensa pero no merece la pena indagar en otras opciones a menos que vaya a dedicarse a la administrashycioacuten del Sistema

372 Apeacutendice C

Bibliografiacutea

El desarrollo del libro ha sido posible gracias a la consulta de numerosas publicaciones escritas paacuteginas Web y revistas profesionales que han dado una visioacuten actual de la programacioacuten en PHP 5 La bibliografiacutea presente en este libro muestra un compendio de libros revistas y paacuteginas Web que pueden ser uacutetiles al lector si decide ampliar sus conocimientos una vez terminado este libro

Libros de PHP 5

bull PHP5 and MySQL Bible Tim Converse y Joyce Park Completo libro que abarca numerosos temas Especializado en generar bases de datos con MySQL y PHP 5

bull The PHP Anthology Harry Fuecks El mejor libro sobre PHP esshycrito nunca Abarca casi todos los temas importantes a la hora de crear un sitio Web profesional Todos los scripts estaacuten cuidadosashymente pensados y orientados a objetos El autor es uno de los proshypulsores de los patrones de disentildeo

bull Learning PHP5 David Sklar Contenido muy sencillo pero direcshyto Para aprender PHP 5 desde 0

bull PHP5 for Dummies Janet Valade Un buen libro para aprender y profundizar en varias aacutereas Desde luego el teacutermino Dummies no le hace justicia porque a veces se hace algo complicado de seguir

bull Proyectos Profesionales PHP Ashish Wilfred Meeta Gupta Kartik Bhatnagar Proyectos orientados a PHP 4 pero muy bien construidos

bull PHP 4 Esteban Trigos Libro muy sencillo para iniciarse en PHP 4 bull PHP 5 Power Programming Andi Gutmans De uno de los creashy

dores de PHP Muy bien enfocado y con muacuteltiples temas bull Beginning PHP 5 Equipo Wrox Libro extenso sobre PHP 5 Cubre

todo lo que se puede conocer sobre PHP 5 En Octubre saldraacute la seshygunda parte llamada Proffesional PHP 5

Revistas profesionales

bull PHP Solutions Revista polaca traducida al espantildeol Contiene muy buenos artiacuteculos sobre desarrollo actual con PHP

Bibliografiacutea 373

bull PHP Magazine Revista alemana de gran alcance bull PHP Architect Revista canadiense donde habitualmente escriben

desabolladores como Harry Fuecks Marco Tabini o Andi Gutmans La misma editora de esta revista ha sacado el libro de estudio para preshysentarse al examen de Certificacioacuten de PHP

Paacuteginas Web

bull wwwphpsolmagorg Web de la revista PHP Solutions bull wwwphpmagnet Web de la revista PHP Magazine bull wwwphparchcom Web de la revista PHP Architect bull wwwsinuhorg Comunidad GnuLinux de Extremadura

bull wwwphpbuildercom Comunidad de usuarios con mucho coacutedishygo libre

bull wwwluisyfernandanet Web del autor bull wwwphppatternscom La Web de Harry Fuecks bull wwwphpnet Web oficial de PHP

bull wwwzendcom La empresa que hay detraacutes de PHP Ofrece curshysos y seminarios on-line

bull wwwcodewalkerscom Web con mucho coacutedigo libre

Page 4: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo

A mi mujer Mariacutea Fernanda por creer en nuestro Proyecto de vida

Agradecimientos

Finalizar este libro ha sido una odisea donde han intervenido muchas personas y factores mudanza incluida Para empezar me gustariacutea agradecer a Marta Camarero y a Eugenio Tuya su fe en miacute como escritor Me dieron aacutenimos desde el principio y un poquito de prisa A Zeev Suraski y Andi Gutmans creadores de PHP 5 por crear el lenguashyje y tratarme como a uno de los suyos en los iquestseminar de wwwzendcom Ademaacutes tengo que agradecerles la rapidez con la que escribieron el proacuteshylogo del libro A Marco Tabini director de la revista canadiense PHParchitect por enshyviarme el manual de Certificacioacuten PHP en papel y no en PDF A Tim Converse y Joyce Park por escribir PHP5 and MySQL Bible cuyos conocimientos me bebiacute en apenas 3 diacuteas A Harry Fuecks por escribir el mejor libro de PHP de todos los tiempos The PHP Anthology que me hizo reorientar todos los esfuerzos a la innoshyvacioacuten

A la Asociacioacuten Regional de Universidades Populares de Extremadura (AUPEX) por probar todos mis programas escritos en PHP (libros de visita foros nccproject newton etceacutetera) Espero dar alguacuten diacutea con la tecla A mis compantildeeros de trabajo Pako Palomo Javi y Pedro por las largas horas de discusioacuten en torno a Delphi Java C y por supuesto PHP A Justo Cabezas porque todo lo que me regaloacute fueron libros de informaacuteshytica y encima escritos por eacutel Sigo tus pasos A los grupos de usuario de gnuLinux de Extremadura wwwsinuhorg y wwwgulexorg por ser una fuente inagotable de conocimientos Por uacuteltimo A mi padre Ramoacuten que ya no estaacute a mi madre Felisa y a mi hermano Felipe porque nunca entendieron nada de informaacutetica pero me animashyron a seguir adelante con todo lo que me propuse Al resto de la familia porque cada uno de ellos ha tenido algo que ver en miacute vida y forman parte de lo que soy

iacutendice

Coacutemo usar este libro 19 Destinatarios de este libro 20 Organizacioacuten del libro 20 Convenios que emplea este libro 25 Los ejemplos en la Web de Anaya 26

Proacutelogo 27

Introduccioacuten 29 Historia de PHP 30 Nuevas Caracteriacutesticas de PHP 5 31

Faacutecil de usar 31 Embebido en HTML 32 Multiplataforma 33 Licencia Open Source 34 Multitud de Extensiones 34 Velocidad e incorporacioacuten de objetos 34 Popularidad 35 Gran Comunidad de apoyo 35

Objetivos del libro 36

1 Introduccioacuten a PHP 5 39 Introduccioacuten 40

8 iacutendice

HTML estaacutetico 40 Tecnologiacuteas del lado del cliente 42 Tecnologiacuteas del lado del servidor 43 Etiquetas de PHP 45 Nuestro primer programa en PHP 5 46 Repaso de HTML 47

Cabecera y cuerpo de una paacutegina Web 47 Cabecera 48 Cuerpo del documento 48 Paacuterrafos y saltos de liacuteneas 49 Estilo de texto 49 Enlaces de texto 51 Listas 51 Imaacutegenes 52 Tablas 53

Resumen 54

2 Variables constantes y tipos de datos 55 Variables en PHP 5 56

Tipos de Variables 56 Asignacioacuten de variables 57

Tipos simples 57 Enteros (integer) 58 Nuacutemeros de coma flotante (double) 59 Cadena de caracteres (string) 59 Boolean 61 NULL 62

Variables de variables 62 Constantes 63

defined() 63 Constantes predefinidas 64

Funciones relacionadas con variables 65 isset() 65 unsetQ 66 gettype() 66 settype() 67 empty() 67 is_integer() is_double() is_string() 67 intvalQ doublevalQ strvalQ 68

Resumen 68

iacutendice 9

3 Operadores 69

Introduccioacuten 70 Operador de asignacioacuten 70 Operador Unario 71 Operadores Aritmeacuteticos 71 Operadores de comparacioacuten 71 Operadores Loacutegicos 73 Operador Ternario 74 Operadores bit a bit 74 Operadores de asignacioacuten combinados 75 Operador de ejecucioacuten 76 Operador de supresioacuten de errores 77 Precedencia de Operadores 78 Resumen 80

4 Estructuras de control 81

Introduccioacuten 82 Estructuras de eleccioacuten 82

if-else 82 elseif 83 switch 84

Bucles 86 while 86 do-while 89 for 89

break y continueacute 92 Finalizar la ejecucioacuten de un programa 93 Sintaxis alternativa 93 Resumen 94

5 Funciones 95 Introduccioacuten 96 Valores de las funciones 96 Funcioacuten de ejemplo Obtencioacuten de la fecha actual 97 Documentacioacuten sobre funciones 98 Funciones de usuario 99

Definicioacuten de funciones 99 Paraacutemetros insuficientes 101 Paraacutemetros en exceso 102

10 iacutendice

Aacutembito de las variables 102 Variables estaacuteticas 104

Include() y require() 105 Recursividad 105 Funciones con nuacutemero de argumentos variables 106

Argumentos por defecto 106 Argumentos mediante un array 107 Muacuteltiples argumentos con func_num_args() 109

Llamadas por valor 110 Llamadas por referencia 111

Referencia a variables 112 Funciones variables 113 Resumen 114

6 Cadenas de caracteres y expresiones regulares 115 Introduccioacuten 116 Propiedades de las cadenas 116

iacutendices de string 116 Operadores 118 Sintaxis para muacuteltiples liacuteneas 118

Funciones de string 119 Tamantildeo de la cadena 120 Posicioacuten de los caracteres 120 Comparacioacuten 121 Buacutesqueda de caracteres 122 Seleccioacuten de subcadenas 122 Funciones de limpieza de cadenas 124 Sustitucioacuten de cadenas 126 Funciones de mayuacutescula y minuacutescula 126

Expresiones regulares 127 Comprobar expresiones regulares 129 Reemplazar patrones 131

Resumen 131

7 Conjuntos de datos del tipo array 133

Introduccioacuten 134 Creacioacuten de arrays 134

Asignacioacuten directa 134 array() 135 Funciones que devuelven arrays 136

iacutendice 11

Arrays multidimensionales 136 Propiedades de arrays 137

count() 1 3 7

in_array() 137 Borrar ocurrencias 138 Interactuar con arrays 138

Funciones para avanzar en un array 140 Funciones para retroceder en un array 142 Intercambio de valores 143 Inversioacuten del contenido 144 Mezcla de los valores 145

Pilas 145 Ordenacioacuten de los valores 146 Resumen 148

amp Paso de informacioacuten entre formularios 149

Introduccioacuten 150 Argumentos GET 150

Formularios con GET 151 Paso de informacioacuten con GET 155

Argumentos POST 157 Variables suacuteper-globales 158 Resumen 159

9 Programacioacuten orientada a objetos bull bull 1 6 1

Introduccioacuten 162 Definicioacuten de clases 163

Instancia de clase 164 Funcioacuten constructor 165

Herencia 165 Meacutetodos o funciones de objeto 166 Herencia encadenada 168 Valores y alcance de variables 168

Miembros puacuteblicos privados y protegidos 170 Meacutetodos privados 170 Meacutetodos protegidos 171 Meacutetodos puacuteblicos 171

Interfaces 172 Clases abstractas 172 Clases con meacutetodos estaacuteticos 173

12 iacutendice

Llamadas a funciones padre 174 Sobrecarga de meacutetodos 176 Sentildealizacioacuten 176 Funciones de manejo de clases 177 Resumen 179

10 Ficheros y almacenamiento de datos 181 Introduccioacuten 182 Funciones de lectura y escritura de ficheros 182

Abrir el fichero 182 Lectura de ficheros 183 Escritura de ficheros 185

Sistema de ficheros y directorios 188 Copiar borrar y renombrar 188 Funciones de comprobacioacuten 189 Directorios 190

Ficheros de configuracioacuten 191 Manejo de ficheros en el servidor 193

Subida de ficheros 193 Descarga de ficheros 195

Resumen 197

11 Bases de datos con SQL y SQLite 199 Introduccioacuten 200 SQL 200

SELECT 202 Uniones 203

INSERT 205 UPDATE 206 DELETE 207

Definicioacuten de tablas 207 SQLite 208

Creacioacuten de bases de datos 209 Uacuteltimos cambios en una tabla 211 Seleccioacuten de datos 212

SQLite orientado a objetos 213 Seleccioacuten de registros 214 Funciones de Array para recuperar datos 215 Nuacutemero de filas 216 Moverse entre registros 216

Resumen 218

iacutendice 13

12 PHP 5 y MySQL 219 Introduccioacuten 220 Administracioacuten de usuarios 220 Conexioacuten a MySQL 220

Seleccionar datos 222 Manipulacioacuten de datos 224

Insertar una fila 224 Actualizar una fila 225 Borrar una fila 225

Errores con las comillas 226 Contando filas 228

Contar filas con PHP 228 Contar filas con MySQL 229

Contar filas afectadas 230 Uacuteltimo nuacutemero insertado 230 Buacutesquedas dentro de una tabla 231 Definicioacuten de bases de datos 231

Creacioacuten de bases de datos 231 Creacioacuten de tablas 231

Resumen 233

13 Sesiones y Cookies 235 Introduccioacuten 236 Sesiones en PHP 5 237

Instanciando sesiones 237 Variables de sesioacuten 239 Problemas con los navegadores 240 Funciones para el manejo de sesiones 241

Cookies 243 setcookie() 243 Borrar una cookie 244

Cabeceras HTTP laquo 245 Resumen 246

14 Lectura y escritura de archivos XML 247 Introduccioacuten 248 SAXDOMySimpleXML 250 SAX 250 DOM 254

14 iacutendice

Usar DOM para leer archivos 255 Todo es un objeto 255 Atributos 256 Buacutesquedas muacuteltiples 257

Escribir archivos XML con DOM 257 Modificar archivos XML 259

SimpleXML 259 Resumen 261

15 Aplicaciones praacutecticas de XML 263 Introduccioacuten 264 Compartir informacioacuten con RSS 264

Distintos formatos 264 Leer un archivo RSS 268 Escribir archivos RSS 269

Servicios Web XML-RPC 272 Clase IXR 273 Cliente XML-RPC 274 Servidor XML-RPC 275 Usos de XML-RPC 277

Resumen 277

16 Generacioacuten de graacuteficos con PHP 5 279 Introduccioacuten 280 Graacuteficos HTML 280

Graacuteficos de barras 284 Libreriacutea GD 285

Tipos MIME 285 Mostrar una imagen en pantalla 286 Crear imaacutegenes en miniatura 288 Generar una marca de agua 290

Graacuteficos estadiacutesticos profesionales con JpGraph 292 Graacuteficos de barras 292 Graacuteficos en 3D 295

Resumen 297

17 Gestioacuten de errores en PHP 5 299 Introduccioacuten 300 Errores y Excepciones 300

iacutendice 15

La clase Exception 301 Bloque Try Catch 303 Heredar de la clase Exception 304 Limitaciones de PHP 5 305

Control de errores sin excepciones 306 Errores nativos de PHP 306 Controladores de error 307 Errores de usuario con trigger_error() 308

Depuracioacuten de errores 308 Resumen 309

18 Conexiones desde PHP 5 311

Introduccioacuten 312 FTP 312

Mostrar los archivos remotos 314 Descargar y Enviar ficheros 315 Otras funciones de FTP 316

Correo electroacutenico 317 Enviar correo desde PHP 318

PHPMailer 319 Antildeadir un fichero adjunto 320

Resumen 322

19 Creacioacuten de archivos PDF 325

Introduccioacuten 326 Libreriacutea FPDF 326

Nuestro primer documento 327 Funciones de texto 328

Meacutetodo Write() 328 Meacutetodo Cell() 329

Desplazamiento de los cursores 330 Salto de paacutegina automaacutetico 330

Sobrescribir los meacutetodos 331 Cabecera 331 Imagen de cabecera 332 Pie de paacutegina 333

Tablas 334 Enlaces 337 Resumen 338

16 iacutendice

20 Plantillas con Smarty 339

Introduccioacuten 340 Instalacioacuten de Smarty 341 Utilizacioacuten baacutesica de Smarty 341

Cuidado con los estilos CSS 345 Llamada a varias plantillas 346 Variables 346 Modificadores 347

Funciones 350 foreach 350 if elseif else 351 php incluido en plantillas 351 assign 352 counter 352 cycle 352

Opciones avanzadas de Smarty 353 Plugins 353 Filtros 354

Resumen 355

Apeacutendice A Instalacioacuten de PHP 5 y MySQL 357

Antes de comenzar 358 Instalacioacuten en MacOSX 358

Apache 358 PHP 5 360 MySQL 4 360 Comprobacioacuten final 361

Instalacioacuten en Windows 362 Instalacioacuten en gnuLinux 363 Recomendacioacuten final 364

Apeacutendice B Configuracioacuten de phpini 367 Introduccioacuten 368

short_open_tag 368 disable_functions 368 max_execution_time 368 error_reporting 368 register_globals 368 magic_quotes_runtime 369

iacutendice 17

include_path 369

Resumen 369

Apeacutendice C Bibliografiacutea 371 Bibliografiacutea 372

Libros de PHP 5 372 Revistas profesionales 372 Paacuteginas Web 373

Glosario 375

iacutendice alfabeacutetico 381

Coacutemo usar este libro

20 Coacutemo usar este libro

Destinatarios de este libro

Este libro estaacute dirigido a usuarios noveles que no sepan programar en ninshyguacuten lenguaje de desarrollo y a usuarios que ya conocen PHP pero desean tener una base soacutelida sobre la nueva versioacuten

PHP 5 estaacute ligado a Internet por lo tanto todas las aplicaciones praacutecticas del lenguaje estaacuten orientadas a realizar contenidos dinaacutemicos para paacutegishynas Por eso el lector debe conocer los aspectos baacutesicos de disentildeo en HTML

El libro puede dividirse en dos partes Una primera en la que se detallan los conceptos principales del lenguaje como las variables estructuras de control manejo de cadenas de caracteres creacioacuten de objetos y conectivi-dad con bases de datos que daraacute al lector novel una visioacuten general de PHP 5 y le permitiraacute comenzar a desarrollar sus primeras aplicaciones La segundaparte algo maacutes compleja haraacute las delicias del usuario novel y del medio Esta cuenta con teacutecnicas avanzadas para la lectura escritura de archivos XML creacioacuten de imaacutegenes en tiempo de ejecucioacuten conexioshynes de FTP y correo electroacutenico o disentildeo de plantillas con Smarty

El Software Libre estaacute presente en el aacutembito de la programacioacuten Por eso podemos utilizar algunos programas libres como base para construir aplishycaciones maacutes complejas El disentildeo de plantillas o la creacioacuten de llamadas a procedimientos remotos no seriacutea posible sin las libreriacuteas Smarty o IXR para XML-RPC desarrolladas por la comunidad de PHP para su uso libre

Por tanto el libro va dirigido a usuarios noveles que no saben nada de PHP Pero tambieacuten a usuarios medios o avanzados que desean conocer las nuevas caracteriacutesticas de PHP 5 y manejar teacutecnicas avanzadas de coshymunicacioacuten y disentildeo

Organizacioacuten del libro

Este libro estaacute dividido en 20 capiacutetulos con los siguientes contenidos

bull Capiacutetulo 1 Introduccioacuten a PHP 5 La introduccioacuten a PHP hace un reshycorrido por las nociones baacutesicas de HTML Ademaacutes aprenderaacute coacutemo crear su primera paacutegina en PHP y coacutemo mezclar el coacutedigo HTML con PHP

bull Capiacutetulo 2 Variables constantes y tipos de datos Los valores que manejamos en los programas deben ser almacenados en zonas de me-

PHP 5 21

moria reservadas por PHP Estas zonas reciben el nombre de variables y pueden ser tratadas de diferentes forma dependiendo de los valores que guarden (nuacutemeros enteros cadenas de caracteres valores boolea-nos) Este capiacutetulo contiene todo lo necesario para comprender coacutemo maneja PHP 5 las variables y las constantes estableciendo una diferenshycia con otros lenguajes fuertemente tipados como Java o C

bull Capiacutetulo 3 Operadores Otro aspecto de los lenguajes de programashycioacuten tiene que ver con los siacutembolos que se utilizan para realizar operashyciones aritmeacuteticas loacutegicas o de asignacioacuten Cada uno de los siacutembolos recibe el nombre de operador Este capiacutetulo muestra por grupos todos los operadores con los que se puede encontrar en PHP 5 Asiacute podraacute ver operadores especializados en sumas restas multiplicaciones o dishyvisiones (aritmeacuteticos) operadores de igualdad desigualdad o asignashycioacuten (de comparacioacuten) incluso operadores de manejo a nivel de bits (binarios)

bull Capiacutetulo 4 Estructuras de control El flujo de los programas viene deshyterminado siempre por las estructuras de control Estas indican en cada momento el rumbo que debe llevar el coacutedigo y lo que debe mostrar nuesshytra paacutegina basaacutendose en el valor contenido en las variables Las estrucshyturas de control y los operadores estaacuten iacutentimamente relacionados y su unioacuten permite desviar a evolucioacuten del programa en uno u otro sentido Las estructuras de control que veraacute en este capiacutetulo le daraacuten la potencia suficiente para crear sus primeros programas funcionales

bull Capiacutetulo 5 Funciones Si su coacutedigo se hace muy extenso a medida que avanza en la comprensioacuten del libro en este capiacutetulo aprenderaacute a remeshydiarlo Las funciones permitiraacuten al lector agrupar fragmentos de coacutedishygo repetitivo y aislarlo en ficheros independientes Este capiacutetulo no soacutelo cubre los aspectos teoacutericos para la creacioacuten de funciones sino que adeshymaacutes es un compendio de buenas praacutecticas a tener en cuenta para que sus proyectos se desarrollen ordenadamente Los aspectos baacutesicos a trashytar son la creacioacuten de funciones propias y el paso de paraacutemetros entre funciones de varias formas diferentes

bull Capiacutetulo 6 Cadenas de caracteres y expresiones regulares La mayor parte de la informacioacuten que puede encontrar en las paacuteginas es texto Conocer todas las teacutecnicas para concatenar medir cortar y buscar texshytos es baacutesico para crear un proyecto basado en contenido dinaacutemico Un perioacutedico digital un Log o incluso su propio CMS ya no tendraacuten seshycretos despueacutes de leer este capiacutetulo Ademaacutes la gran potencia de buacutesshyqueda de patrones viene de la mano de las expresiones regulares Eacutestas

22 Coacutemo usar este libro

permiten encontrar palabras frases y patrones dentro de un texto deshyterminado para manipularlo a nuestro antojo

bull Capiacutetulo 7 Conjuntos de datos del tipo array Este capiacutetulo trata a fonshydo las colecciones de datos PHP 5 maneja los conjuntos de datos como arrays asociativos Es posible acceder a los valores de un array de forma simple utilizando un iacutendice como en C y de forma asociativa asocianshydo una palabra a un valor determinado dentro del array Los arrays tieshynen un incalculable valor en los posteriores capiacutetulos usaacutendose como valor de retorno de muchas funciones de conectividad de bases de dashytos lectura de archivos XML o creacioacuten de plantillas

bull Capiacutetulo 8 Paso de informacioacuten entre formularios Si en el capiacutetulo 1 pudo ver los conceptos baacutesicos de la creacioacuten de paacuteginas en este podraacute conocer las teacutecnicas para enviar informacioacuten a traveacutes de formularios La mayoriacutea de las paacuteginas utilizan formularios para interactuar con los usuashyrios Aprenderaacute a pasar variables y arrays entre dos paacuteginas y coacutemo recoshyger desde PHP 5 los valores que se enviacutean Ademaacutes podraacute saber la diferencia entre los meacutetodos GET y POST y las variables suacuteper-globales

bull Capiacutetulo 9 Programacioacuten orientada a objetos El gran avance queacute ha sufrido PHP 5 desde su versioacuten anterior ha sido la total incorporacioacuten de la sintaxis y teacutecnica orientada a objetos Esto permite desarrollar proshygramas reutilizables en varios proyectos Una de las ventajas de la proshygramacioacuten orientada a objetos es que nos permite utilizar software de otras personas simplemente conociendo los meacutetodos que implementa no es necesario conocer coacutemo funciona el objeto para utilizarlo En este capiacutetulo el usuario novel y medio aprenderaacute las nuevas caracteriacutesticas de la programacioacuten orientada a objetos de PHP 5 A partir del capiacutetulo 9 casi todos los ejemplos estaraacuten basados en esta metodologiacutea de trabajo

bull Capiacutetulo 10 Ficheros y almacenamiento de datos La forma maacutes natushyral de almacenar datos persistentes es guardarlos en un fichero de dashytos Es una tarea muy sencilla y no dependemos de la instalacioacuten de alguacuten programa externo como una base de datos El capiacutetulo 10 mueacutes- tra coacutemo almacenar variables y textos dentro de un archivo para desshypueacutes recuperarlo en nuestra paacutegina Ademaacutes aprenderaacute una serie de teacutecnicas para recuperar ficheros enviados a traveacutes de un formulario y para poner en descarga archivos del servidor

bull Capiacutetulo 11 Bases de datos con SQL y SQLite Sin duda la mejor forma de almacenar datos masivos es utilizar una base de datos PHP 5 incorshypora una API de gestioacuten de bases de datos SQLite que permite almaceshynar millones de registros de diferentes tipos en un archivo binario Lo

PHP 5 23

mejor de utilizar SQLite es que no necesita instalacioacuten de una base de datos ni su administracioacuten todo estaacute contenido dentro de la API Aunshyque este libro no estaacute dedicado a la programacioacuten con bases de datos se da una referencia de los usos maacutes comunes del lenguaje de consultas estructurado (SQL) para que se pueda iniciar en este complejo mundo

bull Capiacutetulo 12 PHP 5 y MySQL MySQL ha sido siempre la panacea del desarrollo en el aacutembito profesional Es una base de datos robusta que permite administracioacuten de usuarios y seguridad a nivel de tablas y celshydas Es algo compleja de administrar pero muy sencilla de manejar desde PHP 5 Su utilizacioacuten ha sido tal que en el mundo de desarrollo se habla de las paacuteginas LAMP (Linux + Apache + MySQL + PHP) En este capiacutetulo aprenderaacute a manejar las funciones maacutes caracteriacutesticas de MySQL y a utilizarlas por medio de objetos en sus aplicaciones La proacutexima aparicioacuten de MySQL 5 hace prever que la combinacioacuten con PHP seraacute perfecta (MySQL 5 + PHP 5 = 10)

bull Capiacutetulo 13 Sesiones y Cookies En este capiacutetulo se detallan las teacutecnishycas necesarias para grabar informacioacuten en el equipo de los usuarios Estas pequentildeas variables (Cookies) permiten crear un pequentildeo control de asistencia de sus usuarios o guardar configuraciones especiales En cuanto a las sesiones son muy necesarias a la hora de crear espacios de venta de productos Las sesiones identifican a un usuario en concreto dentro de una paacutegina y permiten asociar variables concretas a ese usuashyrio aunque la paacutegina esteacute siendo visitada por muchas personas a la vez

bull Capiacutetulo 14 Lectura y escritura de archivos XML Frente a una inmenshysa cantidad de tipos de archivos propietarios como los documentos DOC o XLS nos encontramos a una serie de archivos basados en el lenguaje XML Este tipo de archivos como SXW (Openoffice) o SVG (graacuteficos vectoriales) estaacuten creados para ser entendidos por las personas y por los ordenadores Por lo tanto crear programas que interpreten estos archivos no es nada complejo El capiacutetulo 14 muestra tres caminos disshytintos para leer archivos XML Dos de ellos que vienen funcionando desde versiones anteriores SAX y DOM Y uno nuevo implementado en PHP 5 para facilitar esta tarea al programados Ademaacutes se incluyen las pautas necesarias para que cree sus propios archivos XML con la metodologiacutea DOM

bull Capiacutetulo 15 Aplicaciones praacutecticas de XML Si en el capiacutetulo anterior sentaacutebamos las bases para la lectura de informacioacuten desde archivos XML en este capiacutetulo crearemos objetos que implementen aplicacioshynes reales y actuales para compartir informacioacuten Es muy habitual hoy

24 Coacutemo usar este libro

en diacutea que las paacuteginas lleven asociados un panel de noticias que se generan en portales diferentes Esta informacioacuten se puede mostrar grashycias a teacutecnicas como RSS

Ademaacutes de crear sus propios objetos de generacioacuten de contenido RSS y su lectura haremos hincapieacute en lo que actualmente se llaman servicios Los servicios son pequentildeos programas almacenados en alguacuten servidor que informan acerca de algo concreto Aquiacute aprenderaacute a crear sus sershyvicios con las teacutecnicas ya adquiridas en el capiacutetulo 14

bull Capiacutetulo 16 Generacioacuten de graacuteficos con PHP 5 La generacioacuten de graacuteshyficos desde PHP 5 es posible gracias a la utilizacioacuten de libreriacuteas extershynas como GD Esto le permite manipular archivos graacuteficos que sus usuarios puedan subir a traveacutes de un formulario Con esta libreriacutea pueshyde generar graacuteficos en miniatura para despueacutes de hacer clic en eacutel antildeashydir una marca de agua a todas las imaacutegenes antildeadiendo el logo de su empresa o asociacioacuten

Otra gran libreriacutea es JpGraph que permite crear todo tipo de graacuteficos estadiacutesticos Esto le serviraacute para conocer el nuacutemero de visitas por diacutea mes o antildeo comparativas anuales de ventas de productos y todo un abanico de posibilidades

bull Capiacutetulo 17 Gestioacuten de errores en PHP 5 Una vez terminada la aplishycacioacuten tendraacute que tener en cuenta las partes del coacutedigo donde puede tener problemas Algunos usuarios pueden introducir caracteres no permitidos o nuacutemeros donde se esperaban letras La gestioacuten de errores permite mostrar al desarrollador y al usuario doacutende aparece el error y el tipo de fallo que se ha producido Una buena gestioacuten de errores haraacute que su programa sea maacutes fiable

bull Capiacutetulo 18 Conexiones desde PHP 5 La conectividad de PHP con otras aplicaciones o servicios ha sido siempre una preocupacioacuten de sus desarrolladores Asiacute desde anteriores versiones puede encontrar coshynectividad con servicios LDAP POP3 SMTP o FTP

Este capiacutetulo trata de abarcar dos servicios muy utilizados por la coshymunidad de usuarios El FTP en primer lugar para enviar y recuperar informacioacuten de otros servidores desde un programa escrito en PHP Y en segundo lugar el manejo de las funciones necesarias para enviar informacioacuten por correo electroacutenico

bull Capiacutetulo 19 Creacioacuten de archivos PDF El formato de texto maacutes difundishydo en Internet es el PDF Tanto se ha extendido este formato que la mayoshyriacutea de las paacuteginas profesionales contienen archivos PDF con diferentes contenidos Desde paacuteginas de contenido tecnoloacutegico hasta las de cocina

PHP 5 25

exportan sus contenidos en PDF para que sus usuarios puedan disfrutar desde su ordenador del manual del video o la receta de la semana

En este capiacutetulo veraacute paso a paso coacutemo generar un archivo PDF comshypleto desde la cabecera hasta el pie de paacutegina pasando por todo tipo de textos e imaacutegenes

bull Capiacutetulo 20 Plantillas con Smarty La uacuteltima aportacioacuten de este libro tiene que ver con la tendencia de separar el coacutedigo PHP de la presentashycioacuten en HTML Smarty provee unos sencillos mecanismos desde PHP que permiten realizar sencillamente esta separacioacuten Ademaacutes de las caracteriacutesticas baacutesicas de las plantillas la potencia de Smarty reside en la compilacioacuten del disentildeo cada vez que cambian los datos hecho que otorga a Smarty el puesto nuacutemero 1 en velocidad en el ranking de sisteshymas de plantillas En este capiacutetulo aprenderaacute a crear plantillas con Smarty que permitiraacuten cambiar el aspecto graacutefico de su aplicacioacuten sin tocar el coacutedigo escrito en PHP 5

bull Apeacutendice A Instalacioacuten de Apache y PHP 5 en distintos Sistemas Opeshyrativos La instalacioacuten de PHP 5 es muy sencilla en gnuLinux MacOSX y Windows El Apeacutendice muestra los pasos necesarios para instalar un servidor Apache con el parse de PHP 5 listo para ser utilizado con los ejemplos En cada caso la instalacioacuten se hace de una forma distinta Hemos buscado para cada Sistema Operativo la opcioacuten maacutes sencilla que es utilizando alguacuten paquete compacto que se instale y deje listo el sistema Puesto que es un libro para principiantes hemos huido de crear PHP 5 desde el coacutedigo fuente compilando el programa

bull Apeacutendice B Configuracioacuten baacutesica de phpini El archivo de configurashycioacuten php i n i contiene aspectos de funcionamiento de PHP 5 que pueshyden cambiarse sin necesidad de compilar el programa Este Apeacutendice contiene algunos paraacutemetros de configuracioacuten que pueden ser uacutetiles

bull Apeacutendice C Bibliografiacutea Este libro estaacute basado en el conocimiento adquirido tras la lectura de numerosos libros sobre la temaacutetica paacutegishynas Web y revistas profesionales del sector Este Apeacutendice cubre todas las posibilidades dando al lector un camino a seguir despueacutes de termishynar el presente libro

Convenios que emplea este libro

El nombre de los comandos funciones meacutetodos u objetos aparecen resalshytados en el libro de la siguiente forma ob j e t o

26 Coacutemo usar este libro

Algunas palabras teacutecnicas que no tienen una traduccioacuten faacutecil al castellano o simplemente estaacute fuertemente asentada en el idioma teacutecnico aparecen de la siguiente forma array true ofalse

En el libro aparecen resaltados una serie de temas circunstancias o aconshytecimientos extraordinarios de la siguiente forma array true ofalse

Nota

Anotaciones sobre el texto

Advertencia

Informacioacuten importante a tener en cuenta a la hora de desarrollar un programa Explican de alguna manera posibles equivocacioshynes o ayudas para no caer en errores frecuentes

Truco

Consejo o informacioacuten importante que puede facilitar el trabajo

Los ejemplos en la Web de Anaya

La mayoriacutea de los ejemplos del libro se pueden obtener en la Web de Anashyya Multimedia en la direccioacuten siguiente

httpwwwanayamultimediaes Seleccionando los menuacutes Atencioacuten a clientegtComplementosgtManuales lmprescindiblesgtManual Imprescindible de PHP 5 Ademaacutes de los ejemplos puede encontrar las aplicaciones externas o enshylaces a las mismas que utilizamos para desarrollar algunos ejemplos como Smarty FPDF JpGraph o la libreriacutea IXR

Todos los ejemplos han sido probados en el servidor Apache para MacOSX con el paquete de PHP 501 y en un servidor Apache sobre gnuLinEx Todas las capturas de pantalla se han realizado con el navegador Grulla (Mozilla Firefox) de gnuLinEx 2004

Proacutelogo

28 Proacutelogo

Una de las preguntas maacutes interesantes que nos hacen es queacute hace que PHP tenga tanto eacutexito Distintas personas nos han dado respuesta a esta preshygunta Algunos sostienen que es su excelente conexioacuten con bases de dashytos otros que se debe al coacutedigo abierto por el contrario otros mantienen que es su funcionamiento Sin embargo nuestra opinioacuten difiere PHP pershymite que cualquier usuario obtenga raacutepidamente resultados de forma senshycilla incluso aquellos que no posean experiencia en programacioacuten Al mismo tiempo a diferencia de las herramientas RAD PHP permite el deshysarrollo de proyectos tan complejos como se desee En nuestra opinioacuten esta combinacioacuten ausente en la mayoriacutea de las plataformas Web actuales es lo que hace que PHP sea especial

Lograr el equilibrio entre estas dos liacuteneas (la potencia y la sencillez) no ha sido faacutecil pero siacute imprescindible para el eacutexito de PHP como tambieacuten lo son las nuevas caracteriacutesticas que permiten al desarrollador aprovechar la uacuteltima tecnologiacutea

PHP 5 es el producto de este importante equilibrio Aunque dotado de muchas funciones nuevas esta versioacuten es tan accesible como lo fueron PHP 3 y PHP 4 con lo que permite un raacutepido aprendizaje para aquellos que se inicien De hecho algunas de las novedades basadas en la interfaz de Zend Engine II como SimpleXML SQLite y SOAP hacen maacutes sencillo el uso de PHP al tiempo que incrementa el potencial de aquellos usuarios noveles pues les permite trabajar con XML SQL y Web Services sin esfuerzo

La nueva generacioacuten PHP tambieacuten supone una buena noticia para desashybolladores experimentados En primer lugar por simplificar todas aqueshyllas funciones que ya se han indicado (al contrario de lo que normalmente se piensa ni siquiera a los desabolladores avanzados les gusta trabajar a menos que sea imprescindible) y en segundo lugar por poner a su disposhysicioacuten funciones mejoradas Las nuevas opciones orientadas a objetos de Zend Engine II son un regalo para el desarrollo de aplicaciones de media y gran escala como la nueva extensioacuten mysqli y el nuevo moacutedulo de inteshygracioacuten NET que permite la creacioacuten de aplicaciones hiacutebridas de PHP que emplean la estructura NET

Este libro es una gran introduccioacuten a PHP en general y de PHP 5 en partishycular Si no tiene experiencia previa con PHP e incluso si no tiene ningushyna experiencia en programacioacuten en breve podraacute trabajar con eacutel

Zeev Suraski Tel A v i v

Andi Gutmans Cupertino

Introduccioacuten

30 Introduccioacuten

Historia de PHP

Rasmus Lerdorf miembro del equipo de desarrollo de Apache creoacute PHP (Personal Home Page) en 1994 Su uacutenica intencioacuten fue la de crear un pequeshyntildeo sistema de control para verificar el nuacutemero de personas que leiacutean su curriculum vitae en la Web

En los meses siguientes a su creacioacuten PHP se desarrolloacute en torno a un grushypo de programadores que comprobaban el coacutedigo y sus revisiones Para dar maacutes potencia al sistema Rasmus creoacute funciones en lenguaje C para permitir conexioacuten a bases de datos Este fue el comienzo de la potencia real del leguaje

En 1995 aparecioacute un conjunto de herramientas sobre PHP Esta biblioteca se llamoacute Herramientas para paacuteginas personales y conteniacutean un analizashydor de coacutedigo muy sencillo un libro de visitas un contador y algunas macros que facilitaban el trabajo de los disentildeadores

A mediados de 1995 aparecioacute una revisioacuten puacuteblica llamada PHPFI 20 Esta nueva versioacuten contaba con un analizador sintaacutectico reescrito desde 0 ademaacutes de unas herramientas escritas para el tratamiento de datos desshyde un formulario (de ahiacute el nombre aacuteeFI Form iacutenterpreter) y conectividad con mSQL (Gestor de bases de datos)

Hacia 1997 PHPFI se estaba usando en maacutes de 50000 paacuteginas en todo el mundo En este periacuteodo de tiempo Zeev Suraski y Andi Gutmans decishydieron crear una nueva versioacuten de PHPFI para solventar unos probleshymas con una aplicacioacuten de comercio electroacutenico que estaban desarrollando PHP 30 nacioacute con suculentas innovaciones como la conectividad con vashyrios gestores de bases de datos protocolos y una API ampliada La vershysioacuten oficial de PHP 30 vio la luz en junio de 1998 donde se contemplaba ya la programacioacuten orientada a objetos

En 1999 se realizoacute la primera revisioacuten del motor Zend (Zend Engine) que aportaba modularidad claridad y herramientas de optimizacioacuten para paacuteshyginas de gran escala Zend viene de la unioacuten de Zeev y Andi

PHP 40 vio la luz en mayo de 2000 dividida en 3 partes El motor Zend la API de servidor y los moacutedulos de funcionas El motor Zend es el responshysable de analizar el coacutedigo PHP definir la sintaxis y del lenguaje de proshygramacioacuten La API permite la comunicacioacuten con el servidor Con esta API es posible utilizar PHP desde varios servidores Los moacutedulos contienen funciones para el manejo de cadenas archivos XML o tratamiento de imaacuteshygenes

PHP 5 31

La orientacioacuten a objetos no estaacute muy lograda en PHP 40 Los objetos tieshynen un tratamiento muy pobre e iloacutegico La definicioacuten de las variables miembro (propiedades) y los meacutetodos son siempre puacuteblicos por lo que la encapsulacioacuten es nula Todos los objetos se pasan por valor por defecto cuando deberiacutean pasarse por referencia

Todas estas propuestas realizadas por el equipo de desarrollo de PHP han desembocado en la creacioacuten del motor Zend 20 y su consecuencia PHP 5

PHP 5 incorpora una verdadera orientacioacuten a objetos Antildeadiendo las pashylabras reservadas public protected y priacutevate a la definicioacuten de las propiedashydes y meacutetodos de los objetos se permite una verdadera encapsulacioacuten Ademaacutes del considerable avance con respecto a los objetos PHP 5 incorshypora un control de errores muy mejorado al estilo de los lenguajes de proshygramacioacuten maacutes avanzados

Nota

Despueacutes de una encuesta entre desarrolladores y usuarios de PHP se decidioacute cambiar el significado de PHP a PHP Hypertext Pre-processor Este cambio sigue los pasos de Richard Stallman al nombrar a su sistema operativo GNU (GNU is not Unix) doshytando a la palabra PHP de recursividad Es un juego de palabras muy utilizado en el ambiente hacker

Nuevas Caracteriacutesticas de PHP 5

Existen muchas razones para elegir PHP 5

Faacutecil de usar

PHP 5 es un lenguaje muy faacutecil de aprender con respecto a otros lenguashyjes utilizados para el mismo propoacutesito como JAVA o ASP Debido a esto no es necesario hacer un estudio muy concienzudo de sus funciones para realizar programas sencillos que nos resuelvan la mayoriacutea de los probleshymas diarios

La mayoriacutea de las funciones maacutes usuales estaacuten disponibles por defecto como la conexioacuten a bases de datos o la utilizacioacuten de servidores IMAP Existe una gran cantidad de paacuteginas con documentacioacuten y programas heshychos por desarrolladores que se pueden leer y modificar libremente

32 Introduccioacuten

Embebido en HTML

Las paacuteginas escritas en PHP son simples paacuteginas en HTML que contieshynen ademaacutes de las etiquetas normales el programa que queremos ejecushytar Por ejemplo

ltHTMLgt ltBODYgt ltHEADgt ltTITLEgtEjemplo de PHP5 embebidoltTITLEgt ltHEADgt ltBODY ltPgtEsto es HTML del buenoltPgt ltphp Aquiacute comienza el coacutedigo PHP Lo siguiente es una simple asignacioacuten de variables y su salida por pantalla $nombre=Luis Miguel $apellidos=Cabezas Granado $fecha_hoy=date(d-ra-Y1) gt ltPgtEste paacuterrafo contiene HTML y PHP El autor del script es ltphp echo ($nombre $apellidosgt gtlt Pgt ltPgtLa fecha de ejecucioacuten del script es ltphp echo($fecha_hoy)gtltPgt ltBODYgt ltHTMLgt

Cuando un cliente solicita esta paacutegina el servidor preprocesa los datos y ejecuta las instrucciones de PHP En este caso las variables (las palabras que tienen el signo $ delante) se llenan con los valores que hay a la dereshycha del signo igual Una vez resuelto todo el proceso el servidor le enviacutea al cliente una paacutegina soacutelo con etiquetas de HTML La figura 11 muestra este proceso

Si inspeccionamos ahora el coacutedigo que tenemos en el navegador nos dareshymos cuenta de que las etiquetas de PHP han desaparecido

ltHEAD ltTITLEgtEjemplo de PHP5 embebido-TITLEgt ltHEADgt ltBODYgt ltPgtEsto es HTML del buenoltPgt ltPgtEste paacuterrafo contiene HTML y PHP El autor del script es Luis Miguel Cabezas GranadoltPgt ltPgtLa fecha de ejecucioacuten del script es 05-07-2004ltPgt ltBODYgt ltHTMLgt

higura ii Kesuitaao ae ejecutar un scnpi sencillo

La consecuencia maacutes inmediata es que no es necesario compilar el prograshyma en coacutedigo binario antes de poder testar si funciona o no PHP es un lenshyguaje interpretado como otros muchos en el mercado (ASP Python o JSP)

Multiplataforma

PHP 5 se ejecuta en multitud de plataformas Sistemas Operativos y Sershyvidores existentes Es compatible con los tres servidores liacutederes del mershycado Apache Microsoft Internet Information Server y Netscape Enterprise Server

Tabla 11 Sistemas Operativos y Servidores para PHP 5

Basados en UNIX Windows

Sistema Operativo AIX AUX BSDI Digital UNIXTru64 FreeBSD HP-UX IacuteRIX MacOS X gnuLinux gnuLinEx NetBSD OpenBSD SCO UnixWare Solaris SunOS Ultrix Xenix y muchos maacutes Windows 98Me Windows NT 2000XP2003

Servidores Apache fhttpd Netscape US PWS Netscape Apashyche Omni

Puesto que PHP se ejecuta en todos los Sistemas Operativos indicados en la tabla 11 y en la mayoriacutea de las plataformas hardware existentes (Intel

PHP 5 33

34 Introduccioacuten

A M D PowerPc SPARC etceacutetera) nos seraacute muy sencillo conseguir un lashyboratorio de pruebas para nuestros script

Licencia Open Source

La licencia de Coacutedigo Abierto implica que el coacutedigo fuente de PHP 5 es libre de ser descargado e inspeccionado por nosotros La consecuencia principal es que el coste del producto en la mayoriacutea de los casos es de 0 Euros Tener el coacutedigo fuente de PHP 5 sirve entre otras cosas para poshyder hacer nuestro servidor a medida es decir podemos compilar el proshygrama con las opciones que realmente utilicemos (base de datos LDAP)

Si acompantildeamos Apache el servidor maacutes popular a la instalacioacuten de PHP 5 y antildeadimos alguna base de datos Open Source como PostgreSQL tendreshymos un sistema completo de script de servidor cuyo coste es nulo frente a otras opciones en las que es necesario el uso de licencias

Multitud de Extensiones

PHP 5 se desarrolla para dar la mayor versatilidad y flexibilidad a los usuashyrios que lo utilizan Es por esto por lo que existen muchas extensiones del lenguaje que permiten utilizar nuevas bases de datos protocolos enlaces a libreriacuteas etceacutetera

El acceso a bases de datos tiene una gran potencia implementando soporshyte nativo para 15 Sistemas Gestores de Bases de Datos muy populares En cuanto a los protocolos podemos contar con extensiones que controlan el acceso a LDAP IMAP o POP3 Tambieacuten se ha cuidado el soporte para crear imaacutegenes en tiempo de ejecucioacuten gracias a la libreriacutea GD

Dada la importancia del desarrollo del lenguaje XML en los uacuteltimos antildeos PHP 5 incorpora tres meacutetodos de acceso a este tipo de archivos SAX D O M y simpleXML Ademaacutes se incorpora a PHP 5 la gestioacuten de errores mediante el manejo de excepciones

En esta versioacuten se han antildeadido facilidades para utilizar los repositorios de coacutedigo de PEAR

Velocidad e incorporacioacuten de objetos

El nuevo motor Zend 20 acelera los procesos de ejecucioacuten del coacutedigo Ademaacutes incorpora un nuevo modelo de objetos que permite crear ciacutea-

Figura 12 Uso de PHP desde el antildeo 2000

Gran Comunidad de apoyo

PHP 5 se ha escrito bajo el auspicio del Coacutedigo Abierto Por lo tanto exisshyte una comunidad que apoya su desarrollo en colaboracioacuten La ventaja principal es que existen multitud de paacuteginas listas de correo y foros de debate cuyo tema de conversacioacuten es el manejo de este lenguaje de proshygramacioacuten

Esta comunidad sirve de apoyo para todos los que necesitamos conocer desde los aspectos maacutes baacutesicos hasta las implementaciones maacutes complishycadas Tan pronto como hagamos uso de esta ayuda nos sentiremos oblishygados a prestar la nuestra a usuarios principiantes y asiacute la Comunidad se

PHP 5 35

ses y meacutetodos privados protegidos y puacuteblicos clases abstractas e inter-faces

Popularidad

El uso de PHP se ha disparado desde el antildeo 1999 como puede verse en la figura 12

36 Introduccioacuten

iraacute ampliando Si nuestros conocimientos llegan a superar alguacuten diacutea los objetivos de este libro podemos pensar en contribuir enviando fallos en el lenguaje respondiendo a mensajes de las listas de correo participando en foros de debate o escribiendo extensiones en lenguaje C

Objetivos del libro

A la hora de seleccionar este libro o cualquier otro sobre PHP 5 creo que es esencial que conozca los objetivos que marcan sus capiacutetulos Este libro en concreto estaacute pensado para

bull Tener una visioacuten general de los lenguajes de script para desarrollo

bull Conocer las ventajas de PHP 5 frente a otros lenguajes similares Tener una visioacuten general de las nuevas caracteriacutesticas que ofrece PHP 5

bull Aprender los conceptos baacutesicos para empezar a desarrollar aplicacioshynes sencillas que muestren contenido dinaacutemico

bull Identificar claramente todas las caracteriacutesticas de la orientacioacuten a objeshytos y aprender a desarrollar aplicaciones divididas en partes con moacuteshydulos reutilizables en distintos proyectos

bull Sacar partido de la API SQLite y del gestor de bases de datos MySQL para crear aplicaciones maacutes profesionales que nutran de contenido las paacuteginas

bull Crear formularios que enviacuteen informacioacuten y ficheros entre varias paacuteshyginas de distinta forma

bull Aprender a generar archivos para Internet de distintos formatos Los archivos XML o PDF se han vuelto indispensables en esta era y muy uacutetiles para exportar informacioacuten a los usuarios

bull Conocer las funciones baacutesicas para la creacioacuten de paacuteginas que controshylen y manipulen imaacutegenes Ademaacutes conoceraacute herramientas para geshynerar en el momento graacuteficos estadiacutesticos de diferentes formas

bull Controlar todos los errores que puedan producir los programas evishytando mostrar en el navegador mensajes de error geneacutericos para mosshytrar errores controlados por nosotros

bull Generar plantillas con libreriacuteas para separar el coacutedigo escrito en PHP de la presentacioacuten creada con HTML o alguacuten programa de disentildeo

El libro crea una base muy fuerte para comenzar a realizar aplicaciones profesionales Es evidente que la creacioacuten de archivos XML PDF genera-

PHP 5 37

cioacuten de graacuteficos o plantillas Smarty necesitan un libro entero para cubrir todas las caracteriacutesticas que ofrecen Este libro da una visioacuten general a los lectores y permite conocer las herramientas que actualmente se utilizan para que cada uno pueda investigar por su cuenta las que maacutes le interese

Capiacutetulo 1

Introduccioacuten aPHP5

En este capiacutetulo aprenderaacute a

bull Diferenciar entre scripts de cliente y servidor bull Utilizar diferentes tipos de etiquetas de inicio de PHP bull Escribir su primer programa en PHP bull Conocer las etiquetas HTML

40 Capiacutetulo 1

Introduccioacuten

El mundo de los desarrolladores de paacuteginas ha cambiado de forma vertishyginosa en los uacuteltimos antildeos En poco tiempo han surgido tecnologiacuteas y reshyvisiones de esas tecnologiacuteas que hacen que los programadores tengamos que reciclarnos continuamente

Hace unos antildeos el desarrollo de grandes paacuteginas era complicado de manshytener El lenguaje existente era uacutenicamente HTML y solo permitiacutea crear las paacuteginas y subirlas a un servidor El problema de esto es que modificar alguacuten dato de una de las paacuteginas implicaba un trabajo extra que incluiacutea descargarla modificarla maquetarla de nuevo y subirla al servidor

Actualmente existe un conjunto de lenguajes que permiten desarrollar paacutegishynas Web dinaacutemicas es decir que el contenido puede variar muy raacutepidamente sin ninguacuten esfuerzo por parte de los desarrolladores Eacutestos se denominan lenguajes de script de servidor porque la ejecucioacuten del programa se realiza en el servidor Web donde se encuentra alojada la paacutegina Existe un largo compendio de lenguajes que se pueden utilizar para la creacioacuten de paacuteginas Web dinaacutemicas ASP de Microsoft Java y JSP de Sun Perl Python PHP

HTML estaacutetico

El tipo maacutes baacutesico de paacutegina Web es completamente estaacutetico basado en texto plano y completamente escrito en HTML La paacutegina siguiente es un ejemplo de Web estaacutetica

ltHTMLgt ltHEADgt

ltTITLEbLibros sobre PHP 5 y gnuLinuxltTITLEgt ltHEADgt ltBODYgt ltTABLE BORDER-lgt ltTRgt

ltTDgtTiacutetulo de libros americanos sobre PHP 5ltTDgt ltTRgt ltTABLEgt ltulgt ltlixbgt Advanced PHP Programmingltbxbrxligt ltlixbgtPHP5 and MySQL bibleltbxbrxligt ltlixbgtLearning PHP 5ltbgtltbrxligt ltlixbgtUpgrading to PHP 5ltbxbrxligt ltlixbgtBeginning PHP 5 and MySQLltbxbrxligt

Introduccioacuten a PHP 5 41

ltlixbgtPHP 5 Power Programmingltfcgtgtltbrgtltligt lt u lgt ltTABLE border=lgt ltTRgt ltTDgtTiacutetulo de libros americanos sobre gnuLinuxltTDgt ltTRgt ltTABLEgt ltulgt ltlixbgtRunning Linuxltbxbrxligt ltlixbgtLinux in a Nutshellltbxbrxligt ltlixbgtHow Linux Worksltbxbrxligt ltlixbgtLinux for Non-Geeksltbxbrxligt ltulgt ltBODYgt ltHTHLgt

Figura 11 Ejemplo de paacutegina Web estaacutetica

La figura 11 muestra el ejemplo de una Web estaacutetica El funcionamiento de Internet es algo complejo para explicarlo en este capiacutetulo pero vamos a dar vinas nociones baacutesicas sobre lo que pasa tras la peticioacuten de una paacutegina Web por un cliente Los pasos que sigue nuestro navegador de Internet son

bull Nuestro ordenador solicita al servidor una paacutegina Web a traveacutes de Inshyternet

bull El servidor enviacutea los datos solicitados en formato de texto

42 Capiacutetulo 1

bull El navegador recibe estos datos interpreta la paacutegina Web enviada y la muestra en la pantalla de acuerdo con la resolucioacuten del monitor las preferencias del usuario y alguacuten otro factor

En la figura 12 podemos ver todo el proceso

Figura 12 Esquema de peticioacuten de una Web estaacutetica

Las paacuteginas Web estaacuteticas no permiten apenas una interactividad con el usuario final Por eso han aparecido numerosas tecnologiacuteas que hacen maacutes usable las paacuteginas y eliminan algunas restricciones o limitaciones Los lenshyguajes Javascript Vbscript CSS o los ap-plet de Java ofrecen una mayor interactividad pero son dependientes del navegador que utilicemos o de programas externos

Tecnologiacuteas del lado del cliente

Muchas de las mejoras antildeadidas al lenguaje HTML pertenecen a tecnoloshygiacuteas del lado del cliente es decir que se descargan junto con la paacutegina Web solicitada al servidor y se ejecutan en nuestro ordenador local La tabla 11 todas las tecnologiacuteas aparecidas hasta ahora del lado del cliente Estas tecnologiacuteas aunque son maacutes llamativas y permiten desarrollar la imashyginacioacuten en pro del disentildeo dependen totalmente de las caracteriacutesticas del navegador Por ejemplo si tiene un ordenador ibook de Apple con un Sisshytema Operativo gnuLinux Debiacutean (como el autor) le seraacute complicado obshytener una maacutequina virtual de Java y un inteacuterprete de Flash Las tecnologiacuteas de cliente no pueden rescatar datos de servidores porque su ejecucioacuten es uacutenicamente en local Eacutesto los imposibilita para recuperar informacioacuten de bases de datos o servicios

introduccioacuten a PHP 5 43

Tabla 11 Tecnologiacuteas del lado del cliente

[Tecnologiacutea Descripcioacuten Efecto de ejemplo

CSS HTML Sirve para dar formato a las Enlaces con movi-Dinaacutemico paacuteginas color tamantildeo capas efectos miento Javascript Manejo de eventos del navegador Imaacutegenes que Vbscript cambian cuando

se aproxima el ratoacuten Applets Aplicaciones pequentildeas Puzzles conectivi-de Java dad con bases de

datos Animaciones Animaciones graacuteficas Peliacuteculas iexclnteracti-Flash vas

Tecnologiacuteas del lado del servidor

Los lenguajes del lado del servidor son invisibles para los clientes Las paacuteginas que utilicen scripts de este tipo contienen el coacutedigo entre etique-fas parecidas a las de HTML pero eacutestas desaparecen cuando el cliente reshycibe la paacutegina

Los pasos que debe seguir nuestro navegador de Internet son

bull Nuestro ordenador solicita al servidor una paacutegina Web a traveacutes de Inshyternet

bull El servidor comprueba si la paacutegina solicitada contiene scrvpt del lado del servidor (PHP ASP JSP etceacutetera)

bull Ejecuta los posibles scripiacutes y antildeade el resultado final a la paacutegina Web resultante

bull El navegador recibe estos datos interpreta la paacutegina Web enviada y la muestra en la pantalla de acuerdo con la resolucioacuten del monitor las preferencias del usuario y alguacuten otro factor

La figura 13 muestra el proceso Los lenguajes del lado del servidor necesitan un motor (un programa) que interprete el coacutedigo Este programa puede formar parte o no del servidor Web En nuestro caso utilizaremos el motor Zend Engine 20 para parsear (interpretar) los proshygramas escritos en PHP 5

Figura 14 Zend Studio 351 para MacOSX

Suponiendo que ya tiene un servidor para probar los programas o ha leiacuteshydo el Apeacutendice A para instalar su propio servidor Web con PHP 5 vamos a crear nuestro primer programa del lado del servidor Para escribir los programas puede utilizar cualquier editor de texto plano

44 Capiacutetulo 1

Introduccioacuten a PHP 5 45

En gnuLinux tiene algunos editores libres que funcionan muy bien Sus nombres son Bluefish o Anjuta En entornos propietarios como Windows o MacO^X existen editores proshyfesionales que ademaacutes de disentildear paacuteginas Web permiten antildeadir todo tipo de coacutedigo PHP eso siacute los programas no son gratuitos y hay que pagar una elevada licencia por su uso Para los tres sistemas operativos tenemos una impresionante herramienta de edicioacuten y depuracioacuten creada por los programa^ores de PHP 5 La herramienta Zend Studio tiene dos versiones una de pago bajo licenshycia con muacuteltiples opciones de depuracioacuten y otra gratuita con opciones de desarrollo tan interesantes como el auto completado de funciones y variables

Etiquetas de PHP

Lo primero que debe saber es que todo prograrr1^ escrito en PHP debe empezar por unas etiquetas determinadas

ltphp gt

Ademaacutes aacutee esta iacuteoxma oacutee iacutemciax xm programa pu^dt ^urf^cam -iquesti -hiti iquesti-vo php i n i para que sus programas puedan empezar entre

lt gt

Nota

El archivo php i n i contiene la configuracioacuten de PHP en ese moshymento Cambiando algunos paraacutemetros podraacute cambiar la forma de funcionar del parser

El paraacutemetro s h o r t - o p e n - t a g puede igualarse a off o a on Si contiene el valor on PHP permitiraacute el uso de la etiqueta cofta Otra forma posible de empezar un programa escrito en PHP es utilizando las etiquetas de ASP Mucha gente que desarrolla con programas de Microsoft como Fron-tPage para generar paacuteginas Web utiliza esta forma de empezar el coacuteshydigo

lt gt

46 Capiacutetulo 1

Nuestro primer programa en PHP 5

Despueacutes de estas pequentildeas nociones ya estaacute preparado para crear su prishymer programa Eacuteste le va a permitir tener una visioacuten de la configuracioacuten global de PHP 5

Puede escribir el programa siguiente en cualquier editor de texto como vimos anteriormente

ltHTMLgt

ltHEADgt ltTITLEgtMi primer programa en PHP 5ltTITLEgt ltHEADgt ltBODYgt ltphp echo Este es el tiacutepico Hola Mundo ltbrxbrgt phpinfo() gt ltBODYgt ltHTMLgt

Como puede ver el programa contiene la estructura normal de una paacutegishyna Web La etiqueta ltHTMLgt define el comienzo y el final de la paacutegina Esta puede dividirse en dos partes La primera estaacute separada por la etishyqueta ltHEADgt y contiene informacioacuten sobre el autor tiacutetulo y meta datos que pueden servir para antildeadir coacutedigo Javascript o CSS La segunda parte es el cuerpo de la paacutegina Web es decir contiene todos los datos que veraacute el usuario en el navegador Estaacute separada entre etiquetas ltBODYgt

Dentro del BODY puede ver que empleamos las etiquetas de inicio y fin de programa PHP Dentro de estas etiquetas hay dos funciones que hacen cosas distintas Las funciones son programas ya creados y funcionales que pueden utilizarse en el transcurso de nuestro programa Existen en PHP 5 una infinidad de funciones uacutetiles para el manejo de cadenas de caracteshyres funciones aritmeacuteticas o funciones para mostrar texto en pantalla La funcioacuten echo ) se encarga de mostrar los datos en pantalla en este caso se encargaraacute de mostrar la frase Este es el tiacutepico Hola Mundo Ademaacutes imprime dos etiquetas ltbr gt que no se muestran porque tienen sentido dentro de HTML La etiqueta ltbrgt antildeade un salto de liacutenea a la paacutegina Web

La funcioacuten phpinf o () enviacutea al navegador la configuracioacuten de PHP que estamos utilizando en el servidor Aquiacute aparece la configuracioacuten que se ha utilizado para compilar el parser las libreriacuteas auxiliares que contiene el sistema que se estaacute utilizando etceacutetera

Introduccioacuten a PHP 5 47

Nota r Durante el proceso de aprendizaje del libro conoceraacute muchas funshyciones y sus aplicaciones inmediatas En el capiacutetulo 5 del libro aprenderaacute a crear sus propias funciones

El resultado de la ejecucioacuten del programa lo muestra la figura 15

Figura 15 Resultado de nuestro primer script

Repaso de HTML

El lenguaje de marcas de hipertexto se ha convertido en el principal refeshyrente de la Web Para seguir adecuadamente los contenidos del libro neshycesitaraacute conocer el funcionamiento de HTML para insertar sus programas escritos en PHP 5

Cabecera y cuerpo de una paacutegina Web

Todo documento escrito en HTML estaacute contenido entre las etiquetas ltHTMLgt y ltHTMLgt Se pueden estructurar en

bull Cabecera Entre las etiquetas ltHEADgt y ltHEADgt Contiene informashycioacuten relativa al documento

48 Capiacutetulo 1

bull Cuerpo Entre las etiquetas ltBODYgt y ltBODYgt Debe contener la inshyformacioacuten que el usuario veraacute en el navegador

Cabecera

El tiacutetulo del documento debe ir entre las etiquetas ltTITLEgt y ltTITLEgt Este tiacutetulo se mostraraacute en la parte superior del navegador Ademaacutes se utiliza como descripcioacuten si guarda la paacutegina en el apartado de Favoritos

Para antildeadir informacioacuten sobre el autor fecha de expiracioacuten o el programa con el que hemos disentildeado la Web puede utilizar la etiqueta ltMETAgt

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODYgt ltBODYgt

ltHTMLgt

Algunas etiquetas permiten la inclusioacuten de atributos La etiqueta ltMETAgt contiene el atributo NtildeAME y CONTENT para sentildealar en el documento el autor de la paacutegina Los buscadores haraacuten buen uso del contenido de estas etishyquetas para enlazarlas en sus motores de buacutesqueda

Cuerpo del documento

La etiqueta ltBODYgt tambieacuten puede contener atributos que modifiquen el aspecto exterior de la paacutegina

Los principales atributos son

bull BGCOLOR Indica el color de fondo de la Web

bull TEXT Color general del texto

bull LINK Color del texto de los enlaces

bull VLINK Color de los enlaces que ya han sido utilizados

bull ALINK Color de activacioacuten del texto

bull BACKGROUND Imagen de fondo de un documento

En el siguiente ejemplo puede ver la utilizacioacuten de los atributos de la etishyqueta del cuerpo

ltHTMLgt ltHEADgt

introduccioacuten a PHP 5 49

ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODY BGCOLOR=FF0 0 00 LINK=000000 VLINK=FF00FFgt ltBODYgt ltHTMLgt

Nota

El color se escribe en formato RGB Esto quiere decir que un color puede dividirse en tres componentes (rojo verde y azul) y elishygiendo la intensidad de cada componente se forma el color deseashydo Cada componente tiene 2 cifras en hexadecimal Asiacute el color FF0000 tiene al nuacutemero FF hexadecimal (255 en decimal) en su componente rojo y los demaacutes a 0 por lo tanto el color resulshytante seraacute Rojo intenso

Paacuterrafos y saltos de liacuteneas

Los textos pueden escribirse dentro de la etiqueta ltBODYgt en el orden que quiera los navegadores no interpretan los saltos de liacuteneas o liacuteneas en blanshyco eliminando todos los espacios vaciacuteos Para crear un salto de liacutenea tiene que utilizar ltBRgt escrito despueacutes del texto Para crear paacuterrafos tendraacute que escribir el texto entre las etiquetas ltPgt ltpgt

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltHEADgt ltB0DYgt ltPgt Esto es paacuterrafo y tambieacuten un salto de liacuteneasbrgt ltPgt ltBODYgt ltHTMLgt

Estilo de texto

Podemos resaltar partes del texto con algunas etiquetas

bull ltBgt Bloque de texto en negrita bull ltIgt Texto en cursiva

Figura 16 Diferentes estilos de textos

Ademaacutes puede elegir el formato de las fuentes de cada bloque de texto

50 Capiacutetulo 1

bull ltUgt Bloque de texto subrayado bull ltBIGgt Texto con su mayor tamantildeo bull ltSMALLgt Texto con m tamantildeo pequentildeo bull ltCENTERgt Texto centrado

bull ltSUPgtSuperiacutendice bull ltSUBgt Subiacutendice

El ejemplo siguiente que tambieacuten se muestra en la figura 16 muestra la utilizacioacuten de alguna de las etiquetas anteriores

ltHTMLgt

ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODYgt ltCENTERgtTexto centrado-CENTERxBRgt ltUxIxBIGgtTexto subrayado y cursivaltBIGxIgtltUxBRgt ltBgtTexto en negritaltBxBRgt ltSUPgtTexto superiacutendiceltSUPxBRgt Este cont iene un ltSUBgtsubiacutendiceltSUBgt ltBRgt ltBODYgt ltHTMLgt

Introduccioacuten a PHP 5 51

La etiqueta ltFONTgt permite seleccionar entre varios atributos para utilishyzar distintas fuentes colores o tamantildeos Entre los atributos que podemos utilizar

bull COLOR Color de la fuente

bull SIZE Tamantildeo de la fuente

bull FACE Tipo de fuente ltFONT SIZE=1 FACE=ComicgtTexto con tamantildeo y fuente determinadosltFONTgt

Enlaces de texto

Un enlace es un mecanismo que permite dirigirse a una paacutegina determishynada despueacutes de hacer clic en el texto Si entre las etiquetas ltAgt y ltAgt aparece alguacuten contenido (texto o imagen) al hacer clic en la situacioacuten denshytro de navegador la paacutegina seraacute dirigida a la nueva direccioacuten

El atributo HREF contiene la direccioacuten del enlace

ltA HREF=pagina2htmgtenlaceltAgt

Listas

Las listas son capaces de presentar ordenadamente una serie de concepshytos Los tipos de lista son

bull ltULgt Lista desordenada

bull ltOLgt Lista ordenada

bull ltDLgt Lista de definicioacuten

La diferencia entre los tipos de lista radica en el caraacutecter que aparece en la zona izquierda de cada liacutenea de la lista Las listas desordenadas tendraacuten un graacutefico formal (una forma geomeacutetrica) las ordenadas tendraacuten un nuacuteshymero de orden y las listas de definicioacuten una letra

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltHEADgt ltBODYgt ltBgtLiacutesta desordenada-BxBRgt ltULgt

ltLIgtLiacutenea 1 laquoLis-Liacutenea 2 ltLIgtLiacutenea 3

Figura 17 Listas ordenadas y desordenadas

52 Capiacutetulo 1

ltUI-igt

ltLIgtLiacutenea 31 ltLIgtLiacutenea 32

ltULgt ltLIacutegtLiacutenea 4

ltULgt ltBgtLiacutesta ordenadaltBgtltBRgt ltOLgt

ltLIacutegtLiacutenea 1 ltLJgtLiacutenea 2 ltLlgtLiacutenea 3 ltotgt

ltLIgtLiacutenea 31 ltLIgtLiacutenea 32

ltOLgt ltLIacutegtLiacutenea 4

ltOLgt ltBODYgt ltHTMLgt

Cada liacuteitea de una lista debe estar precedida de la etiqueta ltLIgt El coacutedishygo anterior genera la Web de la figura 17

Imaacutegenes

La etiqueta lt IMGgt utiliza el atributo SRC para insertar la imagen seleccioshynada en el documento

Introduccioacuten a PHP 5 53

Ademaacutes puede utilizar ALT para antildeadir una descripcioacuten a la imagen Entre las imaacutegenes que se pueden incluir en la Web estaacuten los tipos de archishyvos GIF PNG y JPG

ltIMG SRC=fo to l jpg ALIGN=centergt

La alineacioacuten de la imagen con respecto a la pantalla se puede controlar con el atributo ALIGN

Tablas

El elemento estrella en una paacutegina Web es la tabla Actualmente las tashyblas se utilizan para colocar en lugares determinados de la pantalla texshytos imaacutegenes o el menuacute de seleccioacuten Para definir u n a tabla tiene que insertar todos los datos entre las etiquetas ltTABLEi y ltTABLEgt

A continuacioacuten antildeada las filas y las columnas de nuestras tablas Para antildeadir una fila tendraacute que utilizar la etiqueta ltT^gt y para incluir una nueva columna la etiqueta ltTDgt

Para disentildear una tabla de 3 filas y 4 columnas siga los pasos que muestra el ejemplo

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author COMTENT=Luis Miguel Cabltbzas Granadogt ltHEADgt ltBODYgt ltTABLE B0RDER=1gt ltTRgt ltTDgtColumna 11ltTDgt ltTDgtColumna 12ltTDgt ltTDgtColumna 13ltTDgt ltTDgtColumna 14ltTDgt ltTRgt ltTRgt ltTDgtColumna 2 1ltTDgt ltTDgtColumna 2 2ltTDgt ltTDgtColumna 2 3ltTDgt ltTDgtColumna 24ltTDgt ltTRgt ltTRgt ltTDgtColumna 31ltTDgt ltTDgtColumna 3 2ltTDgt ltTDgtColumna 33ltTDgt ltTDgtColumna 34ltTDgt ltTRgt

Figura 18 Tabla de 3 filas y 4 columnas

54 Capiacutetulo 1

ltTABLEgt ltBODYgt ltHTMLgt

Como muestra el coacutedigo la etiqueta ltTABLEgt puede contener atributos como BORDER que antildeade un borde a todas las celdas de la tabla Esta forshyma de actuar la vemos en la figura 18

Resumen

Es muy importante para la lectura de los capiacutetulos del libro que conozca el lenguaje HTML en profundidad PHP 5 se encarga de generar datos dinaacutemicamente desde una base de datos archivos o haciendo caacutelculos complejos pero al final seraacute una etiqueta HTML la que muestre esos dashytos en pantalla Puesto que el objetivo de este libro no es conocer los asshypectos de HTML invito al lector a indagar en otras publicaciones o en Internet para suplir las posibles carencias que pueda tener

Los ejemplos del libro se han escrito directamente en un editor de textos pero esta no es la uacutenica posibilidad Tambieacuten puede utilizar para realizarshylos alguacuten programa de disentildeo Web con la ventaja de que las etiquetas HTML seraacuten antildeadidas a golpe de clic

Capiacutetulo 2

Variables constantes y tipos

de datos

En este capiacutetulo aprenderaacute a

bull Almacenar informacioacuten en variables bull Manejar variables constantes y constantes predefinidas por PHP 5

bull Utilizar funciones de manejo de datos

56 Capiacutetulo 2

Variables en PHP 5

Como en todos los lenguajes de programacioacuten PHP 5 permite almacenar datos de distintos tipos en memoria Estas zonas de memoria se llaman variables Las variables comienzan por el siacutembolo de doacutelar ($) y no necesishytan ser declaradas antes de comenzar el programa como en otros lenguashyjes

Tipos de Variables

Existen varios tipos de variables

bull Entero (integer) Almacena nuacutemeros sin decimales Se puede utilizar la notacioacuten decimal (83) octal (0123) o hexadecimal (0x12)

bull Coma Flotante (double) Nuacutemeros con decimales bull Caraacutecter (string) Texto o informacioacuten numeacuterica escrita entre comillas

dobles () o simples () bull Bootean Soacutelo tiene dos posibles valores Verdadero o Falso bull Nulo NULL) Es un tipo especial que solo contiene un valor NULL bull Vectores (array) Colecciones de datos

bull Objetos (object) Conjunto de datos y funciones independientes

Los 5 primeros tipos son simples y los 2 siguientes (array y object) son comshypuestos Trataremos los tipos compuestos en capiacutetulos sucesivos

ltphp Asignacioacuten de nuacutemeros enteros de coma flotante y cadenas de caracteres $numero_entero = 12343 $numero_flotante = 12343123 $cadena_caracter = 12 34 3 Asignacioacuten de los tipos especiales boolean y NULL $verdadero = TRUE $vacio = NULL gt

Hay que tener en cuenta que el nombre de las variables no puede empeshyzar por un nuacutemero pero siacute puede contenerlos Tambieacuten pueden empezar por un guioacuten bajo (__) Puesto que PHP 5 es sensible a las mayuacutesculas y minuacutesculas las variables $numero y $NUMERO seraacuten distintas

ltphp $4numero = 23 Esta liacutenea da error

Variables constantes y tipos de datos 57

$_numero = 45 Las liacuteneas siguientes muestran que PHP 5 es sensible a mayuacutesculas $numero = 23 $NUMERO = 24 $Numero = 25 echo (numero es $numeroltbrgt) echo (NUMERO es $NUMEROltbrgt ) echo (Numero es $Numeroltbrgt) gt

Nota

Es una buena praacutectica de programacioacuten llamar a las variables de una forma descriptiva Si tenemos un formulario que intenta pashysar datos sobre el nombre y apellido de una persona lo maacutes coshyrrecto es llamar a las variables $nombre y $ ape l l i do en vez de $n y $a Hay que buscar siempre la similitud entre el dato que pasamos y el nombre de la variable para que el programa resulte legible

Asignacioacuten de variables

La asignacioacuten es simplemente dar un valor a la variable Esto se hace poshyniendo un siacutembolo = entre la variable y el dato que queremos asignar

ltphp $numero_pi = 314159 Aproximadamente gt

Si se fija en el ejemplo acabamos de asignar un nuacutemero de coma flotante a la variable $numero_pi En este momento podemos cambiar el valor de la variable asignando un nuevo valor que puede ser de un tipo difeshyrente

ltphp $numerojiacute = 314159 El tipo se convierte a cadena de caracteres gt

Tipos simples

Los tipos de variables simples (enteros coma flotante cadenas de caracteshyres boolean y NULL) deberiacutean ser familiares si conocemos alguacuten lenguaje

58 Capiacutetulo 2

de programacioacuten como C Puesto que la base de la programacioacuten consiste en almacenar datos correctamente vamos a ver las peculiaridades de los diferentes tipos

Enteros (integer)

Corresponde a un nuacutemero entero sin decimales pudiendo ser negativo o el nuacutemero cero Pueden ser almacenados en diferentes formatos corresshypondiendo con las bases decimal (base 10) octal (base 8) y hexadecimal (base 16) Por defecto se utiliza la numeracioacuten decimal Para utilizar base 8 debe ponerse un 0 delante del nuacutemero asignado y un Ox si queremos utilizar base 16 Para antildeadir un nuacutemero negativo basta con poner el signo menos (-) delante del nuacutemero

ltphp $entero_baselO = 1234 $entero_base8 = 01234 $entero_basel6 = 0x1234 $entero_negativo = -1234 echo (Decimal $entero_baselOltbrgt) echo (Octal $entero_base8ltbrgt) echo (Hexadecimal $entero_basel6ltbrgt) echo (Negativo $entero_negativoltbrgt) gt

La salida del navegador es

Figura 21 Asignacioacuten de enteros en decimal octal y hexadecimal

Variables constantes y tipos de datos 59

La salida de los nuacutemeros se hace en decimal aunque la asignacioacuten se haya hecho en hexadecimal o en octal Esto es asiacute porque PHP trabaja internashymente en binario y hace la conversioacuten a decimal de todos los nuacutemeros enteros y de coma flotante

Nuacutemeros de coma flotante (double)

Este tipo de dato contiene nuacutemeros enteros con decimales Se almacenan de forma diferente a los nuacutemeros enteros por lo que las sumas de cantishydades de coma flotante con cantidades enteras daraacuten como resultado un nuacutemero de coma flotante

ltphp Nuacutemeros de coma flotante $numero__double = 1234123 $numero_double2 = 01213 $numero_double3 = -12 3 40 echo (Salida de la funcioacuten echo() $numero_double3ltbrgt) gt

La salida en el navegador seriacutea S a l i d a de echo -1234

Como puede comprobar parece que el nuacutemero que se muestra en pantashylla es del tipo entero Esto es porque la funcioacuten echo 0 no muestra el forshymato del dato Para que esto ocurra debemos utilizar otro tipo de funcioacuten

ltphp $numero_double3 = -12340 echo (Salida de printft) ) printf(f$numero_double3) gt

El coacutedigo anterior muestra ahora una salida por pantalla maacutes coherente Salida de printf() es -1234000000

Cadena de caracteres (string)

Es un conjunto de caracteres encerrados entre comillas dobles () o sim-pies ( )bull

ltphp Definicioacuten de variables de tipo string $cadenal = Esto es una cadena de caracteres $cadena2 = Esto es una cadena entre comillas simples $cadena3 = Cadena con 0 caracteres gt

60 Capiacutetulo 2

La diferencia entre las comillas simples y las comillas dobles radica en

bull Comillas simples Permiten imprimir el contenido iacutentegro de caracteshyres que esteacute entre las dos comillas

bull Comillas dobles Permiten incluir variables para imprimirlas junto al texto ltphp $dato = IMPRIMIBLE $texto_simple = No puede imprimir la variable $dato $texto_doble = Imprime la variable dato como $dato echo ($texto_simpleltbrgt) echo ($texto_doble) gt

Existen algunos caracteres especiales que no pueden ser antildeadidos a una variable de tipo string a menos que avisemos antes a PHP para que tenga cuidado a la hora de manejar el dato Este aviso se conoce como secuenshycia de escape y no es maacutes que la inclusioacuten delante del caraacutecter especial de un siacutembolo Asiacute si quiere insertar unas comillas dobles entre un texto tendraacute que escribir para que no se produzca un error

ltphp Secuencias de escape $cadenal = Aquiacute se pueden antildeadir comillas doblesltbrgt $cadena2 = Aquiacute se pueden antildeadir comillas simplesltbrgt $cadena3 = Esta cadena da errores por las comillas doblesltbrgt $cadena4 = Esta cadena no da errores por las comillas doblesltbrgt echo $cadenal echo $cadena2 echo $cadena3 echo $cadena4 gt

El resultado muestra la impresioacuten de las cadenas excepto la cadena3 que da un error por no incluir la secuencia de escape para las comillas

Tabla 21 Secuencias de escape comunes

Secuencia Valor

$ Signo de doacutelar $

Comillas dobles

V Comillas simples

Bar ra invert ida

Variables constantes y tipos de datos 61

Secuencia Valor

n Nueva liacutenea

r Retorno de carro

t Tabulador

Boolean

Una variable de tipo boolean soacutelo puede contener dos valores Verdadero o Falso Se suelen utilizar para comprobar si se cumple una condicioacuten en el programa

ltphp $variable_booleana = TRUE if ($variable_booleana) echo (El resultado es VERDADERO)

gt

El resultado se muestra en la figura 22

Aunque todaviacutea no hemos visto las estructuras de control podemos adshyvertir que la salida del programa anterior da como resultado la impresioacuten en pantalla del texto que contiene la funcioacuten echo () Ademaacutes de las vashyriables boolean podemos tomar otros tipos de datos como Verdaderos o Falsos para hacer nuestras comprobaciones

62 Capiacutetulo 2

bull Los nuacutemeros enteros o decimales positivos o negativos son todos Verdashyderos El 0 se considera Falso En cualquier caso se recomienda no utilishyzar variables de coma flotante para comprobar si son Verdaderos o Falsos

bull Las cadenas de caracteres son Verdaderas excepto cuando no contieshynen ninguacuten dato o contienen uacutenicamente el caraacutecter 0

bull Las variables del tipo NULL son siempre Falsas

NULL

Es un tipo especial de datos que soacutelo contiene el valor NULL Aunque se suele utilizar por norma en mayuacutescula PHP 5 lo acepta escrito de divershysas formas NULL nuil NuLl

ltphp $variable_nula = NuLl if ($variable_nula) echo (La comprobacioacuten es VERDADERA)

else echo (La comprobacioacuten es FALSA) gt

Variables de variables

Las variables son en definitiva nombres descriptivos que asocian un esshypacio en memoria del servidor con una palabra entendible por nosotros En ese espacio de memoria podemos almacenar diferentes tipos de datos Podemos definir una variable de la siguiente forma

ltphp $variablel = hola gt

En este momento tenemos un espacio de memoria llamado $ v a r i a b l e l donde se aloja el dato hola iquestQueacute pasa si queremos tratar la palabra hola como una variable Podemos hacerlo antildeadiendo un signo de $ delante de $ v a r i a b l e l por lo que se reservaraacute otro espacio en memoria para aloshyjar el nuevo contenido esta vez con el nombre $hola

ltphp $variablel = hola $$variablel = mundo

Variables constantes y tipos de datos 63

Las dos liacuteneas siguientes producen la misma salida echo ($variablel $$variablelltbrgt) echo ($variablel $holaltbrgt) gt

La salida por pantalla nos da el siguiente resultado hola mundo hola mundo

Constantes

Las constantes son tipos de datos que no variacutean en el desarrollo de un programa En la vida real existen muchos tipos de constantes el nuacutemero pi la temperatura de congelacioacuten del agua el nombre de la Empresa etshyceacutetera Para crear una constante tiene que usar la funcioacuten de f ine () de la siguiente forma

ltphp define(EMPRESAZendSA) define(AutorLuis Miguel Cabezas Granado) gt

Para mostrar el valor de las constantes uacutenicamente hay que invocar su nombre esta vez sin utilizar el siacutembolo de $

ltphp Definimos primero la constante define (COLOR_ROJO FF0000) Y ahora escribimos en pantalla su resultado echo COLOR_ROJO Hay que destacar que el signo de $ no hace falta ponerlo Existe otra funcioacuten que nos permite averiguar el valor de la constante echo constant ( C0L0R_R0JO) gt

defined()

Puede utilizar def ined () para averiguar si una constante ya se ha creado

ltphp define(EditorialAnaya) if (defined(Editorial) ) echo La Editorial es Editorial

gt

64 Capiacutetulo 2

Constantes predefinidas

PHP 5 define varias constantes cada vez que se ejecuta un script y que son accesibles por nosotros

Tabla 22 Algunas constantes definidas por PHP 5

Nombre Descripcioacuten

PHP_VERSION Versioacuten del parse de PHP que estamos utilizando

PHP_OS Sistema operativo del servidor de PHP

PEAR_EXTENSION_DIR Ruta donde estaacute instalada la extensioacuten PEAR

PHP_LIBDIR Ruta donde estaacuten almacenadas las libreriacuteas de PHP 5

Finalmente tenemos 5 constantes maacutegicas tal y como las definen en el sishytio Web wwwphpnet que cambian de valor dependiendo del lugar donshyde se usen Por ejemplo el valor de la constante LINE depende de la liacutenea donde la estemos usando en nuestro programa

Tabla 23 Constantes maacutegicas

Nombre Descripcioacuten

LINE Indica el nuacutemero de liacutenea desde la que imprimimos el

valor

FILE Ruta completa al fichero

FUNCTION Nombre de la funcioacuten que la contiene

CLASS Nombre de la clase

_ M E T H O D _ Nombre del meacutetodo

Advertencia

Hay que tener cuidado con el nombre de las constantes maacutegicas Los siacutembolos que hay a la izquierda y ala derecha del nombre son dos guiones bajos seguidos (_)

ltphp echo LINE - VERSIOacuteN de PHP 5PHP_VERSION echo ltbrgt

Variables constantes y tipos de datos 65

echo LINE - SISTEMA Operativo Servidor PHP_OS echo ltbrgt echo LINE - Ruta de las extensiones PHP_EXTENSION_DIR echo ltbrgt echo LINE - API de Servidor PHPJ3API gt

Funciones relacionadas con variables

PHP 5 brinda al programador una serie de funciones para el manejo de variables

isset()

Con esta funcioacuten podemos averiguar si una funcioacuten existe dentro de nuesshytro programa Si existe devuelve true y si no existe false

ltphp $DNI = 8868543-Z if (isset($DNI)) echo (La variable DNI existe)

66 Capiacutetulo 2

gt

unset()

Libera la memoria ocupada por una variable destruyendo su nombre y su contenido Despueacutes de usar unset () la variable destruida apareceraacute comoase al utilizar la funcioacuten i s s e t ()

ltphp $Nombre = Mariacutea Fernanda if (isset($Nombre)) echo (El nombre existe)

Podemos comprobar queacute pasa si liberamos la variable $Nombre unset($Nombre)iexcl if (isset($Nombre)) echo (El nombre existe) else echo (El nombre ya no existe) gt

El resultado es el siguiente El nombre e x i s t e El nombre ya no e x i s t e

gettype()

Con esta funcioacuten podemos averiguar el tipo de dato almacenado en la variable Nos puede devolver uno de los siguientes valores

bull integer

bull double

bull string

bull array

bull object

bull class

bull unknown type ltphp $correo = luisnccextremaduraorg echo la variable correo es del tipo

Variables constantes y tipos de datos 67

echo g e t t y p e ( $ c o r r e o ) gt

settype()

Convierte el tipo de la variable al especificado en la funcioacuten El tipo debe especificarse eligiendo uno de los siguientes array double integer object o string Si la funcioacuten no es capaz de convertir el tipo de la variable devuelshyve el valor false

ltphp $correo = luisnccextremaduraorg if (settype($correointeger))

echo (Variable correo convertida a Enteroltbrgt)

else

echo (Imposible convertir al tipo Enteroltbrgt)

echo (Valor actual de correo es $correo) gt

Al tratar de convertir un tipo string (una cadena de caracteres) a un enteshyro PHP 5 comprueba si existe alguacuten nuacutemero Si no existe cambia el valor a O y la funcioacuten s e t t y p e () la evaluacutea como correcta

empty()

Comprueba si una variable estaacute vaciacutea no existe o su valor es 0 ltphp $correo = luisnccextremaduraorg if (empty($nombre))

echo (La variable nombre no existe)

$numero_entero = O if (empty($numero_entero))

echo (La variable numero_entero no existe o tiene el valor O) gt

isjntegerf) is_double() is_string()

Estas funciones devuelven true si la variable pasada coincide con el tipo que indica la funcioacuten

68 Capiacutetulo 2

Si la variable $numero_en te ro se evaluacutea con la funcioacuten i s _ i n t e g e r ( ) devolveraacute true

ltphp $numero_entero = 0 if (is_integer()($numero_entero))

echo (numero_entero es del tipo integer)

gt

intval() doublevalQ strval()

Convierte el valor de una variable al tipo indicado en la funcioacuten Esta funshycioacuten no permite la conversioacuten a tipos object o array

ltphp Conversioacuten de un tipo string a un integer $cadena = 232 echo El tipo de la variable cadena es gettype($cadena)ltbrgt $numero = intval($cadena) echo (el numero es $numero) gt

Resumen

La base de la programacioacuten reside en la creacioacuten de datos y su procesashymiento En este capiacutetulo hemos visto coacutemo declarar variables de diferenshytes tipos y coacutemo utilizar funciones para averiguar las propiedades de cada una de ellas Ademaacutes de las variables las constantes juegan un papel muy importante sobre todo las predefinidas por PHP 5 que nos dan informashycioacuten muy uacutetil con la que poder trabajar

En este capiacutetulo aprenderaacute a

bull Utilizar los diferentes tipos de operadores existentes bull Distinguir entre operadores unarios binarios y ternarios

bull Comprender la preferencia de ejecucioacuten entre operadores

70 Capiacutetulo 3

Introduccioacuten

En el capiacutetulo anterior hemos visto ejemplos de coacutedigo escrito en PHP que utilizan siacutembolos muy comunes en el ambiente matemaacutetico e inforshymaacutetico Estos siacutembolos que aparecen entre variables o dentro de funciones son conocidos como operadores Existen varios tipos de operadores

bull De asignacioacuten bull Unario bull Aritmeacuteticos bull De comparacioacuten bull Loacutegicos bull Ternario bull Bit a bit bull Asignacioacuten combinados bull De ejecucioacuten bull Supresioacuten de errores

Operador de asignacioacuten

El maacutes baacutesico es el siacutembolo de asignacioacuten (=) utilizado para dar valores a las variables que usamos en nuestro coacutedigo

ltphp $variable = 34 $variable2 = Asignacioacuten de valores gt

Las variables que estaacuten a la izquierda del operador toman el valor que se encuentra en la expresioacuten de la derecha

Advertencia

No hay que confundir el operador de asignacioacuten (=) con el operashydor de comparacioacuten (==) sobre todo en bucles de control donde seriacutea difiacutecil encontrar alguacuten fallo

Operadores 71

Operador Unario

El signo menos (-) se utiliza delante de un nuacutemero o variable numeacuterica Este operador tiene la propiedad de hacer a los nuacutemeros negativos o poshysitivos dependiendo del signo actual

ltphp $entero = 23 $entero_negativo = -$entero El valor es ahora -23 entero2 = -$entero__negativo El valor cambia ahora a 23 gt

Operadores Aritmeacuteticos

Este tipo de operadores forman parte de la aritmeacutetica baacutesica Nos resultashyraacute familiar porque son siacutembolos muy utilizados en el aprendizaje de las matemaacuteticas

Tabla 31 Operadores aritmeacuteticos

Ejemplo Nombre Resultado

$a + $b suma Suma las dos variables $a - $b resta Hace la diferencia de las dos variables Sa $b multiplicacioacuten Producto de las variables $a $b divisioacuten Cociente entre las dos variables $a $b Moacutedulo Resto de la divisioacuten de $a entre $b

Nota

-rr PHP 5 ignora los espacios en blanco entre las variables y los opeshyradores Aunque $a + $b es equivalente a $a + $b es preferible utilizar la primera forma de escribir porque se hace maacutes legible

Operadores de comparacioacuten

En algunos ejemplos del capiacutetulo anterior puede ver que se utiliza la esshytructura de control if el se Como veremos maacutes adelante esta estructu-

72 Capiacutetulo 3

ra compara dos valores y elige el camino a seguir El valor de la comparashycioacuten siempre es true ofalse

Tabla 32 Operadores de comparacioacuten

Ejemplo Nombre Resultado

$a == $b Igualdad Devuelve true si $a y $b son iguales $a === $b Identidad Verdadero si son iguales y del mismo tipo $a = $b Distinto True si son distintos $a ltgt $b Distinto True si son distintos $a lt $b Menor que Cierto si $a es menor que $b $a gt $b Mayor que Cierto si $a es mayor que $b $a lt= $b Menor o igual Correcto si $a es menor o igual que $b $a gt= $b Mayor o igual Correcto si $a es mayor o igual que $b

ltphp $a = 23 Asignacioacuten de los valores $b = 75 if ($a gt= $b) La condicioacuten no se cumple El resultado es false

echo Esta parte no se ejecuta else

echo La comparacioacuten es false porque $a es menor que $b

gt

Operadores 73

Operadores Loacutegicos

Durante el desarrollo de su proyecto puede encontrarse con situaciones en las que necesite hacer varias comparaciones seguidas para que se cumshypla una determinada condicioacuten PHP 5 permite unir todas las comparashyciones en una mediante el uso de los operadores loacutegicos

Tabla 33 Operadores loacutegicos

Ejemplo Nombre Resultado

expresionl and expresion2 Y Si las dos expresiones son vershydaderas el valor es true

expresionl or expresion2 O Si una de las expresiones es vershydadera el valor es true

expresionl xor expresion2 O exclusivo True si una expresioacuten es verdashydera y la otra falsa

expresionl Negacioacuten Verdadero si la expresioacuten no es cierta

expresionl ampamp expresion2 Y Si las dos expresiones son vershydaderas el valor es true

expresionl || expresion2 O Si una de las expresiones es vershydadera el valor es true

El listado siguiente muestra dos condiciones anidadas lt php $a = 2 3 Sb = 75 $c = true if ($a lt $b)

if ($c) echo (Se cumplen las dos condiciones)

gt gt

Egtta expresioacuten se puede hacer maacutes legible utilizando alguacuten operador loacuteshygico

ltphp $a = 23 3b = 75 $c = t rue

74 Capiacutetulo 3

i f ($a lt $b and $c) echo Se cumplen l a s dos cond ic iones

gt

Operador Ternario

Los operadores que hemos visto hasta ahora son capaces de manejar un operando (Unarios) o dos operandos (binarios) El operador ternario o de comparacioacuten evaluacutea un operando y dependiendo de si es falso o vershydadero evaluacutea el segundo operando o el tercero La expresioacuten que se quiere evaluar se escribe delante de un siacutembolo () despueacutes la expresioacuten que tiene que ejecutarse si la evaluacioacuten anterior es true seguida del siacutembolo () con la expresioacuten que debe ejecutarse si es false

ltphp $valor = false $valor == true $resultado = OK $resultado = FALLO Si $value es true $resultado seraacute OK Si es false $re sultado seraacute FALLO echo $resultado gt

Operadores bit a bit

Estos operadores son complicados de entender si no conoce la loacutegica bishynaria Afortunadamente se utilizan en muy pocas ocasiones Los operashydores de bit utilizan las variables a nivel bajo tal y como se almacenan en memoria fiacutesica y comparan bit a bit los valores Lo mejor es verlo con un ejemplo

ltphp bull$a = 4 Valor binario 100 $b = 5 Valor binario 101 $c = $a amp $b echo $c El valor de c es 100 gt

El operador binario Y (siacutembolo amp) compara bit a bit las variables $a y $b Si los bits de una misma posicioacuten son true (tienen el valor 1) el bit resultashydo es 1 En este caso soacutelo existe una pareja de bits que es igual a true (sus

Operadores 75

dos valores son 1) por lo tanto el valor de la variable $c es 4 (en binario 100)

Tabla 34 Operadores bit a bit

Ejemplo Nombre Resultado

$a amp $b Y Si las parejas de bits son verdaderas el resultado es

verdadero

$a | $b O Si alguacuten bit de la pareja es verdadero el resultado es

verdadero

$a A $b O Si un bit de la pareja es true y el otro false el resultado exclusiva es verdadero

~$a No Los bits 1 se vuelven 0 y viceversa Tambieacuten cambia el bit que se refiere al signo positivo o negativo

$a ltlt $b Desplaza- Desplaza a la izquierda los bits de la variable $a tantos miento a bits como indique la variable $b la izquierda de bits

$a gtgt $b Desplaza- Desplaza a la derecha los bits de la variable $a tantos miento a bits como indique la variable $b la derecha

Nota

Puesto que la notacioacuten binaria se escapa del enfoque de este libro le recomiendo algunas lecturas posteriores referidas a la loacutegica de bit si es que tiene curiosidad Probablemente no utilizaraacute estos operadores nunca pero eso depende de la magnitud de los proyecshytos a los que se enfrente

Operadores de asignacioacuten combinados

En numerosas ocasiones se nos presentan situaciones en las que una va-riable debe incrementar o disminuir su valor en 1

ltphp

$a =23

$a = $a +1 Incrementamos en 1 el valor de la variable gt

HP 5 provee operadores combinados que permiten asignar raacutepidamente crementos de valor concatenaciones de caracteres etceacutetera

76 Capiacutetulo 3

Tabla 35 Operadores de asignacioacuten combinados

Ejemplo Nombre Equivalencia

$a++ Incremento $a = $a +1

$a~ Decremento $a = $a -1

++$a Incremento $a = $a +1

~$a Decremento $a = $a -1

$a += $b Suma $a = $a + $b

$a -= $b Resta $a = $a - $b

$a = $b Multiplicacioacuten $a = $a $b

$a = $b Divisioacuten $a = $a $b

$a = $b Moacutedulo $a = $a $b

$a amp= $b Y $a = $a amp $b

$a |= $b O $a = $a | $b

$a A= $b O exclusiva $a = $a A $b

$a = $b Concatenacioacuten $a = $a $b

$a gtgt= $b Desplazamiento a la derecha $a = $a gtgt $b

$a ltlt= $b Desplazamiento a la izquierda $a = $a ltlt $b

Advertencia

Como vemos en la tabla 35 iexclos operadores de incremento y deshycremento pueden aparecer a la derecha o a la izquierda de un vashyriable La posicioacuten del operador influye en el orden en el que la variable se asigna o se incrementa Mejor verlo en un ejemplo ltphp $a = 23 $b = $a++ $b es igual a 23 porque $a se incrementa despueacutes de la asignacioacuten

$a = 2 3 $c = + + $a $c es igual a 24 porque $a se incrementa antes de la asignacioacuten

echo la variable b es $b y c es $c gt

Operador de ejecucioacuten

Si tiene experiencia con la programacioacuten en shell de Unix o gnuLinux sabraacute que el apostrofe invertido sirve para ejecutar comandos del sis-

Operadores 77

tema PHP 5 ha adoptado esta nomenclatura y funciona exactamente igual

ltphp $listado_archivos = Is -la~ Hacemos un listado de los ficheros del directorio actual echo $listado_archivos y lo sacamos por pantalla gt

Nota

El comando ls del ejemplo anterior es propio de sistemas Unix y gnuLinux Siacute hace pruebas sobre un sistema basado en el Sistema Operativo Windows el ejemplo anterior no funcionariacutea tendriacutea que cambiar el comando por dir

Operador de supresioacuten de errores

La mayoriacutea de las funciones que se utilizan en PHP 5 muestran errores en el navegador cuando algo falla

Si intenta abrir un fichero que no existe PHP mostraraacute un mensaje de error v continuaraacute la ejecucioacuten del programa

78 Capiacutetulo 3

El operador () colocado delante de una funcioacuten evitaraacute que se muestre el error

ltphp $fichero = fopen(pruebatxt r) Muestra un error en el navegador echo (El programa sigue ejecutaacutendose) gt

El coacutedigo siguiente oculta la salida de error por pantalla

ltphp $fichero = fopen(pruebatxtr) echo (El programa sigue ejecutaacutendose) gt

Precedencia de Operadores

Vamos a echar un vistazo al coacutedigo siguiente

ltphp $resultado = 20 + 10 10 echo $resultado gt

Aparentemente es un coacutedigo muy simple pero encierra un problema mashytemaacutetico

Existen dos resultados posibles en funcioacuten del operador que debe ejecushytarse antes

Si la suma se ejecuta antes la variable $ r e s u l t a d o tendraacute el valor 300 y si la multiplicacioacuten se ejecuta antes tendremos q u e $ r e s u l t a d o equivashyle a 120

Si comprobamos el coacutedigo el resultado que nos muestra es 120 por lo tanto el operador de multiplicacioacuten () es preferente con respecto al operador de suma (+)

Si los operadores que aparecen son ideacutenticos existe un orden de ejecushycioacuten que puede ser desde la izquierda a la derecha o derecha a izquierda

ltphp $resultado = 2 0 1 0 2 echo $resultado gt

El valor de $ r e s u l t a d o es ahora 1 porque primero se calcula 20 10 y despueacutes ese mismo resultado se divide entre 2 es decir la asociacioacuten enshytre operadores de divisioacuten es desde la izquierda

Operadores 79

Tabla 36 Orden de preferencia de los operadores

Operador Operacioacuten Asociacioacuten

() Pareacutentesis de preferencia NA

new Instancia de objeto NA

[] array Derecha

NO loacutegico Derecha

Signo menos Derecha

++ -- Incremento decremento Derecha

Supresioacuten de errores Derecha

Multiplicacioacuten divisioacuten y moacutedulo Izquierda

+ - Suma resta concatenacioacuten Izquierda

ltlt gtgt Desplazamiento izquierda y derecha Izquierda

lt lt = gt gt = Menor que menor o igual NA

mayor que mayor o igual

== = Igual no igual NA

amp Y izquierda A O exclusivo Izquierda

| O Izquierda

ampamp Y loacutegico Izquierda

|| O loacutegico Izquierda

condicional Derecha = += = = = Asignacioacuten Derecha = = amp= = -= ltlt= gtgt=

and Y loacutegico Izquierda

xor O exclusivo loacutegico Izquierda

or O loacutegico Izquierda

El operador pareacutentesis tiene la propiedad de dar preferencia en la evaluashyron a todos los operadores que contiene El siguiente ejemplo muestra oacutemo podemos utilizar correctamente el operador pareacutentesis

ltphp $resultado = 2 0 1 0 + 2 echo $resultado El resultado es 4 $resultado = 20 (10 + 2) echo $resultado El resultado es 166666667 gt

Resumen

Los operadores son responsables de todas las operaciones que realizamos en nuestros programas Por eso es importante conocer las propiedades v los casos de uso de cada uno de ellos para poder sacarles el maacuteximo partishydo Sin embargo si ya conoce alguacuten lenguaje de programacioacuten la intuishycioacuten le haraacute utilizarlos adecuadamente sin pararse a pensar en el tipo de operador

Por uacuteltimo debe prestar un especial intereacutes a la preferencia de uso ya que una mala utilizacioacuten redundaraacute en un error muy difiacutecil de controlar

En este capiacutetulo aprenderaacute a

bull Utilizar las estructuras de control de eleccioacuten simple y muacuteltiple bull Crear bucles de diferentes tipos bull Crear sus primeros programas bull Conocer las sentencias para interrumpir un bucle

82 Capiacutetulo 4

Introduccioacuten

Es difiacutecil imaginar un programa sin estructuras de control Eacutestas nos permishyten elegir diferentes caminos en funcioacuten de los datos que evaluamos en cada momento En este capiacutetulo trataremos dos tipos de estructuras de control

bull Estructuras de eleccioacuten

bull Estructuras de bucle

Las estructuras de eleccioacuten permiten evaluar una condicioacuten o varias y eleshygir el camino correcto Las de bucle repiten un nuacutemero determinado de veces un conjunto de instrucciones

Estructuras de eleccioacuten

Existen dos tipos

bull Eleccioacuten simple bull Eleccioacuten muacuteltiple

if-else

La sintaxis de esta estructura es if (condicioacuten) instruccioacuten

Si se cumple la condicioacuten se ejecuta la instruccioacuten que le sigue Si quiere que se ejecuten varias instrucciones debe utilizar el siacutembolo llave ( insshytrucciones iexcl )

if (condicioacuten) instruccionl instruccion2iexcl

instruccion3

La estructura if puede ampliarse para que se pueda elegir entre condishycioacuten verdadera y falsa

if (condicioacuten) instruccionl instruccioacuten2 instruccion3

else

Estructuras de control 83

instruccionl -instruccioacuten2 instruccion3

Si la condicioacuten es verdadera se ejecutan las instrucciones inmediatamente despueacutes del if y si la condicioacuten es falsa se ejecutan las instrucciones disshypuestas despueacutes de la palabra e l s e Puede ver un ejemplo completo

ltphp $valor = 23 $valor2 = 27 if ($valor lt $valor2)

echo La variable valor es menor que valor2 else

echo La variable valor es mayor que valor2

gt

elseif

Es muy comuacuten hacer comparaciones en cascada para comprobar varios valores

ltphp $ d i a = 4 if ($d ia == 1)

84 Capiacutetulo 4

echo El diacutea es Lunes else

if ($dia == 2) echo El diacutea es Martes

else if ($dia == 3)

echo El diacutea es Mieacutercoles else

if ($dia == 4) echo El diacutea es Jueves

gt

El patroacuten anterior es tan comuacuten que existe una estructura especial para manejarlo

Puede escribir el ejemplo anterior con la palabra reservada e l s e i f de la siguiente forma

ltphp $dia=4

if ($dia == 1) echo El diacutea es Lunes

elseif ($dia == 2) echo El diacutea es Martes

elseif ($dia == 3) echo El diacutea es Mieacutercoles

elseif ($dia == 4) echo El diacutea es Jueves

gt

El ejemplo anterior evaluacutea la variable $dia hasta que encuentra el valor correcto y ejecuta las instrucciones

switch

La construccioacuten swi t ch comprueba el valor de una expresioacuten y permite elegir entre un conjunto de instrucciones El formato es el siguiente switch (expresioacuten)

case valorl instruccionl instruccion2 instruccion3 break

Estructuras de control 85

case valor2 instruccionl instruccion2 instruccion3 break

case valor3 instruccionl instruccion2 instruccion3 break

default instruccionl instruccion2

instruccion3

La expresioacuten puede ser de cualquier tipo siempre que devuelva un valor de tipo entero de coma flotante o de cadena de caracteres Una vez evashyluada la expresioacuten se busca el valor en la instruccioacuten case y si coincide se ejecutan todas las instrucciones hasta la palabra reservada break Si no coincide ninguacuten valor se ejecutan las instrucciones por defecto Veamos un ejemplo completo

ltphp $dia = 4 switch ($dia)

case 1

echo El diacutea es Lunes break

case 2 echo El diacutea es Martes break

case 3 echo El diacutea es Mieacutercoles break

case 4 echo El diacutea es Jueves break

case 5 echo El diacutea es Viernes break

case 6 echo El diacutea es Saacutebado break

case 7 echo El diacutea es Domingo break

default

Bucles

Los bucles son estructuras de control que permiten repetir varias veces las mismas instrucciones

while

El bucle while es el maacutes baacutesico de todos La construccioacuten baacutesica es la sishyguiente

while (condicioacuten) instruccioacutenlbull instruccioacuten2 instruccioacuten3

La condicioacuten se evaluacutea al principio

Si es verdadera se ejecutan las instrucciones que estaacuten dentro del bucle y se vuelve a evaluar la condicioacuten

86 Capiacutetulo 4

echo El diacutea de la semana es incorrecto

gt

Estructuras de control 87

Si la condicioacuten es falsa no se ejecutan las instrucciones y se continuacutea con el desarrollo del programa

Puesto que la condicioacuten se evaluacutea antes de ejecutar las instrucciones es posible que algunos bucles no se ejecuten ninguna vez

El siguiente ejemplo muestra una instruccioacuten while que no se ejecuta nunshyca porque la condicioacuten es falsa

ltphp $variable = false while ($variable)

echo Esta linea no se ejecuta nunca

gt

Existe la posibilidad de que un bucle se ejecute infinitas veces si dentro de las instrucciones no existe nada que cambie la condicioacuten que se evaluacutea al principio

ltphp $variable = true while ($variable)

echo CUIDADO Esta liacutenea se ejecuta siempre

gt

88 Capiacutetulo 4

El bucle while se puede utilizar para ejecutar un nuacutemero determinado de veces las instrucciones que implica

Veacutease el ejemplo de la serie de Fibonacci

ltphp $numero_anterior = 1 $numero_posterior = 1 $serie = 1 $fin = 10000 echo Serie de Fibonacci while ($serie lt $fin) echo $serie $serie = $numero_anterior + $numero_posterior $numero_anterior = $numero_posterior $numero_posterior = $serie

gt

Cada nuacutemero de la serie de Fibonacci se forma sumando los dos nuacutemer -anteriores

En el ejemplo la condicioacuten es que el nuacutemero de la serie sea menor que t

nuacutemero que marca la variable $f i n es decir si el nuacutemero que indica iquest serie es mayor que 10000 el bucle finaliza

La variable $f in sirve de valor maacuteximo y puede cambiarlo en funcioacuten la cantidad de nuacutemeros que quiera tener en pantalla

Estructuras de control 89

do-while

Este bucle es igual que el anterior pero la condicioacuten se evaluacutea al final de las instrucciones Por lo tanto el coacutedigo que estaacute entre las llaves se ejecuta al menos una vez El formato baacutesico es el siguiente

do instruccioacutenl instruccioacuten2 instruccioacuten3

while (condicioacuten)

Puede comprobar que la diferencia es miacutenima cuando utiliza esta estrucshytura de control para la serie de Fibonacci

ltphp $numero_anterior = 1 $numero_posterior = 1 $serie = 1 $fin = 6765 echo Serie de Fibonacci do

echo $serie $serie = $numero_anterior + $numero_posterior $numero_anterior = $numero_posterior $numero_posterior = $serie

whi le ($ser ie lt $ f i n ) gt

for

La construccioacuten de bucle maacutes complicada es la del for Tiene la siguiente sintaxis

for (expresioacuten inicial condicioacuten de fin expresioacuten de fin) instruccioacutenl instruccioacuten2

instruccioacuten3

El funcionamiento es muy sencillo La expresioacuten inicial se ejecuta una sola vez al principio del bucle La condicioacuten de fin se evaluacutea cada vez que se ejecuta el bucle Si es verdashydera se continuacutea la ejecucioacuten y si es falsa se sale del bucle Al final de cada interaccioacuten se ejecuta la expresioacuten de fin

90 Capiacutetulo 4

Puede simular la instruccioacuten f or con una instruccioacuten w h i l e de esta forma

expresioacuten inicial

while (condicioacuten de fin)

instruccioacutenl

instruccioacuten2

instruccioacuten3

expresioacuten de fin

Otra forma poco corriente es eliminar alguna o todas las expresiones de bucle Si quita todas las expresiones se crea un bucle infinito

fOr ( )

instruccioacutenl

instruccioacuten2

instruccioacuten3

equivale a

while (true)

instruccioacutenl

instruccioacuten2

instruccioacuten3

El caso contrario es antildeadir maacutes de una condicioacuten en cada clase de expreshysioacuten separadas por comas En este caso la condicioacuten de fin se evaluara falso si alguna de las claacuteusulas es falsa En realidad funciona como un C loacutegico

ltphp

for ($x = 1 $y = 1 $z = 1 $y lt 10 $z lt 10 $x++ $y = $y -

2 $z = $z + 3)

echo ($x $y $zltbrgt)

gt

Un ejemplo claacutesico es la tabla de multiplicar lthtmlgt ltbodygt ltbgtTABLA DE MULTIPLICARltbgt lttable border=lgt ltphp echo (lttrgt) echo (ltthxthgt ) for ($cabecera = 1 $cabecera lt= 10 $cabecera++)

echo (ltthgt) echo $cabecera

Estructuras de control 91

echo (ltthgt)

echo (lttrgt) for ($x = l$x lt= 10 $x++ )

echo (lttrgt) echo (ltthgt) echo $x echo (ltthgt) for ($y = l$y lt= 10 $y++ )

$multiplicacion = $x $y echo (lttdgt) echo ($multiacutepliacutecaciacuteon) echo (lttdgt)

echo (lttrgt) gt gt lttablegt ltbodygt lthtmlgt

[ ejemplo se sirve de un bucle for que crea una cabecera de tabla con la queta especial ltthgt donde inserta los nuacutemeros del uno al diez Estos umeros escritos en horizontal se podraacuten cruzar con los verticales para atener asiacute el resultado de una multiplicacioacuten

92 Capiacutetulo 4

El siguiente paso es un conjunto de dos bucles anidados El primer bucle almacena en la variable $x los valores numeacutericos que apareceraacuten como cabecera de la columna uno El segundo bucle seraacute el encargado de multishyplicar el valor actual de $x por los valores del 1 al 10

Cada vez que se ejecuta el segundo f o r se obtiene una celda nueva con un valor determinado por la multiplicacioacuten y cada vez que se ejecuta el primer bucle aparece una nueva fila cuya cabecera es un nuacutemero del 1 al 10

break y continueacute

El camino ordinario para salir de un bucle es que la condicioacuten se evaluacutee a false Existe una forma especial de salir de un bucle utilizando las palashybras reservadas b r e a k y c o n t i n u eacute Su forma de actuar es la siguiente

bull break Sale del bucle actual y continuacutea el programa

bull continueacute Salta hasta el final de la interaccioacuten y continuacutea la ejecucioacuten desde el principio del bucle

El coacutedigo siguiente muestra la forma de utilizar b r e a k

ltphp for ($x = 1 $x lt 20 $x++)

if ($x == 10) break

else echo $xltbrgt

La salida por pantalla es una sucesioacuten de nuacutemeros del 1 al 9 Al llegar la variable $x al nuacutemero 10 la condicioacuten del if se cumple y se ejecuta la instruccioacuten b r e a k saliendo del bucle Veamos ahora el mismo ejemplo pero utilizando c o n t i n u eacute

ltphp for ($x = 1 $x lt 20 $x++)

if ($x == 10) continueacute

else echo $xltbrgt

gt

Estructuras de control 93

En este caso cuando $x alcanza el valor 101o que hace la instruccioacuten conshyt i n u eacute es ir hacia el final de bucle y volver al principio comprobando la condicioacuten

El resultado por pantalla es una sucesioacuten de nuacutemeros desde el 1 hasta el 19 sin incluir el nuacutemero 10

Finalizar la ejecucioacuten de un programa

Hay veces que necesitamos parar la ejecucioacuten de un programa por divershysas causas ha ocurrido un error un fallo en la entrada del nombre y la conshytrasentildea La funcioacuten para la ejecucioacuten es e x i t () o d i e () Estas dos funciones aceptan un paraacutemetro que se imprime en pantalla Por ejemplo considere el siguiente coacutedigo que asume la conexioacuten a una base de datos

ltphp $conexion = conectar_base_datos(libros) if ( $conexion)

die (Se ha producido alguacuten error en la conexioacuten)

gt

Se puede apreciar que si la variable $ c o n e x i oacute n se evaluacutea false (no se ha conseguido la conexioacuten) se detiene la ejecucioacuten del programa Una vershysioacuten maacutes compacta se consigue utilizando el operador or

ltphp $conexion = conectar_base_datos(libros) or die (Se ha producido alguacuten error en la conexioacuten) gt

Nota

e x i t () y d i e () eran iexclas uacutenicas alternativas para el control de errores criacuteticos en versiones anteriores de PHP En PHP 5 aforshytunadamente se ha incluido un potente manejo de excepciones que hace la ejecucioacuten maacutes flexible

Sintaxis alternativa

Algunas estructuras de control pueden escribirse de una forma distinta Las estructuras i f w h i l e f or y s w i t c h pueden escribirse sustituyen-

94 Capiacutetulo 4

do la llave de inicio por un siacutembolo de dos puntos () y la llave de cierre por e n d i f e n d w h i l e endf or y e n d s w i t c h respectivamente

Como ejemplo podemos ver la estructura i f

ltphp $variable = 10 if ($variable == 10)

echo Nueva estructura de control gt

El coacutedigo siguiente es equivalente al anterior

ltphp $variable = 10 if ($variable == 10)

echo Nueva estructura de control end i f

gt

Resumen

Si ha llegado hasta aquiacute ya conoceraacute los secretos baacutesicos de la programashycioacuten en PHP 5 Como puede darse cuenta lo uacutenico necesario para hacer un programa es tener claro la forma de utilizar las variables los operadoshyres y las estructuras de control Una vez dominado esto lo demaacutes es aprenshyder funciones de PHP y teacutecnicas de recuperacioacuten e insercioacuten de datos

Los capiacutetulos siguientes hacen un estudio maacutes concienzudo de las variashybles y las funciones que facilitan el proceso de interaccioacuten entre ellas

En este capiacutetulo aprenderaacute a

bull Crear sus propias funciones bull Utilizar paraacutemetros fijos y variables

bull Realizar funciones recursivas bull Separar el coacutedigo fuente en varios ficheros

96 Capiacutetulo 5

Introduccioacuten

Las funciones son grupos de instrucciones independientes que tienen un propoacutesito determinado

Asiacute tenemos funciones que calculan la raiacutez cuadrada de un nuacutemero nos dan un nuacutemero aleatorio o permiten contar los caracteres de una palabra La sintaxis baacutesica de una funcioacuten es la siguiente

nombre_funcioacuten (paraacutemetrol paraacutemetro2 paraacutemetro3paraacutemetro_n)

Las funciones pueden ser llamadas con varios paraacutemetros o con ninguno dependiendo de su definicioacuten

Cuando PHP encuentra en el coacutedigo la llamada a una funcioacuten primero evaluacutea cada argumento y los utiliza como paraacutemetro de entrada Despueacutes ejecuta la funcioacuten y devuelve el valor solicitado o realiza alguna accioacuten sin enviar ninguacuten valor de salida

El siguiente ejemplo contiene un conjunto de llamadas a funciones con 01 oacute 2 paraacutemetros de entrada

ltphp echo sqrt(9) Raiacutez cuadrada de 9 es 3 echo rand(1020) Nuacutemero aleatorio entre 10 y 20 echo pi() Nuacutemero pi gt

Valores de las funciones

Cada funcioacuten en PHP se considera como una expresioacuten Se pueden utilishyzar las funciones para lo mismo que se utilizan las expresiones como alshymacenar su resultado en una variable o formar parte de una expresioacuten maacutes compleja

ltphp $numero_aleatorio = rand (1100) Se almacena en una variable $numero_aleatorio = rand (1100) + rand (1100) sqrt(9) Expresioacuten compleja gt

No todas las funciones devuelven un valor numeacuterico Tambieacuten pueden devolver caracteres array o truefalse si la funcioacuten ha tenido eacutexito o no Este tipo de funciones se utiliza para conectar a bases de datos escribir a ficheros de texto manipular imaacutegenes etceacutetera

Funciones 97

Funcioacuten de ejemplo Obtencioacuten de la fecha actual

Existen un conjunto de funciones que permiten averiguar la fecha actual del sistema Una de estas funciones es d a t e ( ) que permite recuperar el antildeo diacutea mes etceacutetera del momento en el que se hace la consulta Para averiguar el diacutea de hoy podemos utilizar la construccioacuten

lt d a t e (d) gt

El paraacutemetro que pasamos entre pareacutentesis indica a la funcioacuten el formato de fecha que queremos obtener En este caso la d indica que queremos obtener el diacutea en formato numeacuterico La siguiente tabla relaciona los caracshyteres dentro de la funcioacuten d a t e () con su aplicacioacuten praacutectica

Tabla 51 Formato de fecha con date()

Caraacutecter Valor

a Imprime am o pm

A AM o PM

h La hora en formato (01-12)

H Hora en formato 24 (00-23)

g Hora de 1 a 12 sin un cero delante

G Hora de 1 a 23 sin cero delante

i Minutos de 00 a 59

s Segundos de 00 a 59

d Diacutea del mes (01 a 31)

j Diacutea del mes sin cero (1 a 31)

w Diacutea de la semana (0 a 6) El 0 es el domingo

m Mes actual (01 al 12)

n Mes actual sin ceros (1 a 12)

Y Antildeo con 4 diacutegitos (2004)

y Antildeo con 2 diacutegitos (04)

z Diacutea del antildeo (0 a 365)

t Nuacutemero de diacuteas que tiene el mes actual

98 Capiacutetulo 5

Se pueden utilizar varios caracteres dentro de la funcioacuten indicando el forshymato de fecha que nos interesa

ltphp $meses = array (Enero Febrero Marzo Abril Mayo

Junio Julio Agosto Septiembre Octubre Noviembre Diciembre)

echo Fecha actual date(d-m-Y) ltbrgt echo Diacutea del antildeo date(z) ltbrgt echo Estamos en el mes $meses[date(n) ] ltbrgt gt

El resultado en pantalla es el siguiente

Documentacioacuten sobre funciones

Desde sus inicios PHP se disentildeoacute para que fuera sencillo de utilizar y de extender por la comunidad de desarrolladores La potencia reside en la gran cantidad de funciones escritas de todo tipo Este libro cubre las funciones maacutes utilizadas en el desarrollo de un proshyyecto profesional pero seriacutea imposible cubrir todas las funciones existenshytes con detalle Por esta razoacuten es imprescindible tener como referencia la

Funciones 99

guiacutea on-line de PHP en wwwphpnet donde podemos encontrar clasifishycadas por temaacutetica todas las funciones existentes hasta ahora

Ademaacutes contamos con un buscador de apoyo que nos permite buscar la definicioacuten de una funcioacuten y ejemplos de uso escritas por usuarios de PHP

Para los usuarios que no conocen la forma de trabajar con el lenguaje C se hace necesario explicar coacutemo aparecen las funciones descritas en el mashynual de wwwphpnet El formato es el siguiente

tipo_devuelto nombre_funcioacuten (tipol argl tipo2 arg2) -

El t i p o - d e v u e l t o es el tipo de valor que la funcioacuten daraacute como salida Puede ser un integer double array etceacutetera El nombre de la f u n c i oacute n es la forma correcta de ejecutar el coacutedigo Los p a r aacute m e t r o s de e n t r a d a (arshygumentos) deben pertenecer al tipo que define la funcioacuten Un ejemplo de definicioacuten es

string substr (string string int start[ int length] )

Puede ver que la funcioacuten s u b s t r () devolveraacute como resultado una cadeshyna de caracteres y que tiene 2 argumentos de entrada como miacutenimo El paraacutemetro que se encuentra entre dos corchetes es opcional y puede decishydir usarlo o no

Funciones de usuario

Para realizar programas complejos en PHP 5 no es necesario escribir funshyciones Se pueden escribir programas utilizando todo lo aprendido hasta ahora

A medida que el proyecto se haga maacutes complejo el coacutedigo se haraacute maacutes extenso y menos legible En este punto deberiacutea comenzar a pensar en crear funciones que realicen determinadas tareas

Definicioacuten de funciones

El formato es el siguiente

function nombre_funcioacuten($argumentol $argumento2 )

instruccioacutenl instruccioacuten2 instruccioacuten3

100 Capiacutetulo 5

Como puede ver se comienza con la palabra reservada f u n c t i o n seguishyda del nombre de la f u n c i oacute n y el nuacutemero de p a r aacute m e t r o s n e c e s a shyr i o El bloque de coacutedigo que pertenece a nuestra funcioacuten debe introducirse entre dos siacutembolos de llave ( ) Un ejemplo claacutesico consiste en calcular el factorial de varios nuacutemeros El factorial del nuacutemero x se obtiene multishyplicando el nuacutemero x por el factorial de (x-1) teniendo en cuenta que el factorial de 1 es 1 Por ejemplo el factorial de 3 seriacutea 3 por el factorial de 2 es decir 3 2 1 El coacutedigo sin utilizar funciones es

ltphp $resultado = 1 $factorial = 3 Queremos calcular el factorial de 3 for ($x = $factorial $x gt 0 $x--)

^resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt bull

$resultado = 1 $factorial = 4 Queremos calcular el factorial de 4 for ($x = $factorial $x gt 0 $x--)

$resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt

$resultado = 1 $factorial = 5 Queremos calcular el factorial de 5 for ($x = $factorial $x gt 0 $x--)

$resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt

gt

Si se fija en el coacutedigo anterior podraacute comprobar que sigue un patroacuten muy evidente El caacutelculo del factorial se realiza en un bucle que va disminushyyendo el valor de una variable y multiplicando todos los valores entre siacute Aprovechando este patroacuten puede crear una funcioacuten que realice el factoshyrial del nuacutemero x ahorrando liacuteneas de coacutedigo

ltphp function factorial($numero)

$resultado = 1 for ($x = $numero $x gt 0 $x--)

$resultado = $resultado $x return $resultado

echo El factorial de 3 es factorial(3)ltbrgt

Funciones 101

echo El factorial de 4 es factorial(4)ltbrgt echo El factorial de 5 es factorial(5) ltbrgt gt

Si comparamos los dos ejemplos podemos llegar a la conclusioacuten de que el segundo es mucho maacutes legible y maacutes sencillo de realizar Como puede ver la funcioacuten f a c t o r i a l () hace uso de la palabra reservada r e t u r n que es la encargada de devolver el valor que estamos solicitando cuando se invoca la funcioacuten

Nota

Aunque en el ejemplo la funcioacuten f a c t o r i a l () recibe como pashyraacutemetro el nuacutemero 3 4 oacute 5 tambieacuten es posible llamarla con una variable del tipo integer o double

Paraacutemetros insuficientes

Si llama a una funcioacuten con menos paraacutemetros de los que debe utilizar por definicioacuten apareceraacute el siguiente error por defecto

Warning Missing argument 1 for factorial()

Este tipo de error no es criacutetico y puede controlarse con excepciones como veremos en capiacutetulos sucesivos Ademaacutes de las excepciones podemos utilishyzar el operador de supresioacuten de error delante de la funcioacuten de esta forshyma f a c t o r i a l ( )

No se recomienda eliminar los mensajes de error en este caso ya que hace complicado la correccioacuten de los posibles fallos

Paraacutemetros en exceso

Si al contrario que en el apartado anterior le pasa a una funcioacuten maacutes paraacuteshymetros que los definidos eacutestos seraacuten omitidos y la ejecucioacuten continuaraacute normalmente sin ninguacuten mensaje de error Esta propiedad de PHP 5 pershymite utilizar variables con un nuacutemero de paraacutemetros variable

Aacutembito de las variables

Las variables definidas en un archivo de PHP permanecen declaradas en todo el fichero menos en las funciones Las funciones crean un entorno de ejecucioacuten donde soacutelo pueden ver las variables que estaacuten dentro de las mismas Aunque no parece muy loacutegico esto nos permite tener variables

Funciones 103

con el mismo nombre en diferentes funciones haciendo el coacutedigo reutili-zable

Si nos fijamos en el ejemplo

ltphp $pi = 3 1 4 funct ion v a l o r _ p i ( )

if ( uuml s s e t ($pi) ) $pi = p i ()

re turn $pi

echo v a l o r _ p i ( ) gt

Se puede observar que definimos al comienzo del coacutedigo la variable $pi como un valor aproximado del nuacutemero pi (314) La funcioacuten v a l o r _ p i () comprueba si la variable $pi estaacute definida y si no lo estaacute recupera ese valor con una funcioacuten de PHP 5 Para entender el alcance de las variables vamos a ir paso a paso viendo queacute es lo que ocurre

bull Se define $pi a nivel global en el programa

bull Se define la funcioacuten v a l o r _ p i () que por ahora no se utiliza

bull Se lanza la ejecucioacuten de la funcioacuten

bull La funcioacuten evaluacutea si existe la variable $pi y da como resultado false Esto es asiacute porque la variable estaacute definida fuera de la funcioacuten y no dentro de ella por lo tanto se considera que la variable $p i dentro de la funcioacuten es distinta (entorno local) a la variable $pi definida fuera de la funcioacuten (entorno global)

bull El resultado por pantalla es 31415926535898

Esta forma de programar se considera la correcta en la comunidad de de-sarrolladores de PHP Auacuten asiacute existen mecanismos que permiten que una variable definida fuera de una funcioacuten pueda ser utilizada dentro de la misma simplemente anteponiendo la palabra reservada g l o b a l a la vashyriable definida dentro de la funcioacuten

Utilizando el ejemplo anterior tenemos

ltphp $pi = 3 1 4 funct ion v a l o r _ p i ( )

g l o b a l $pi if ( Uuml s s e t ($pi) )

$pi = pi ()

104 Capiacutetulo 5

re turn $pi

echo v a l o r _ p i ( )

gt

Si vemos paso a paso el ejemplo

bull Se define $pi a nivel global en el programa bull Se define la funcioacuten v a l o r _ p i () que por ahora no se utiliza bull Se lanza la ejecucioacuten de la funcioacuten

bull Dentro de la funcioacuten la variable $pi se define como global es decir se utiliza la variable creada al principio del coacutedigo

bull La funcioacuten evaluacutea si existe la variable $p i y da como resultado true

bull El resultado por pantalla es 314

Variables estaacuteticas

Por defecto las funciones que creamos en PHP 5 no retienen en memoria el valor de las variables que se utilizan Cada llamada a una funcioacuten imshyplica la nueva creacioacuten de las variables locales con su valor inicial La deshyclaracioacuten static antildeadida a una variable causa que la funcioacuten retenga en memoria el valor de esa variable en cada llamada Como puede ver en el ejemplo las 100 llamadas a la funcioacuten c o n t a d o r () dan siempre el misshymo resultado porque la variable $ c o n t a d o r se crea con cada llamada

ltphp function contador()

$contador = 0 $contador = $contador +1 return $contador

for ($x = 1 $X lt= 100 $x++)

echo contador() gt

Sin embargo podemos hacer que la funcioacuten recuerde los valores antildeadienshydo la palabra s t a t i c a la definicioacuten de la variable

ltphp function contador()

static $contador = 0 $contador = $contador + 1 return $contador

for ($x = 1 $x lt= 100 $x++)

Funciones 105

echo contador()

gt

iacutenclude() y require()

A medida que su proyecto se hace maacutes complejo comenzaraacute a crear funshyciones muy uacutetiles para conectar a bases de datos crear imaacutegenes al vuelo conectar por FTP etceacutetera y seguramente quiera emplear estas funcioshynes en otros proyectos distintos para ahorrar tiempo El camino para hashycer esto es muy sencillo Soacutelo tiene que guardar las funciones necesarias en un fichero con extensioacuten php htm c s s i n c etceacutetera y utilizar las directivas i n c l u d e () o r e q u i r e f ) desde la Web que vaya a utilizarlas

En PHP 5 no existen apenas diferencia entre ambas funciones salvo que la funcioacuten i n c l u d e () es maacutes tolerante a fallos que r e q u i r e () y permishyte continuar la ejecucioacuten del programa aunque se haya encontrado un fashyllo

La conclusioacuten es que debe utilizarse r e q u i r e () para aplicaciones que necesiten obligatoriamente alguacuten archivo criacutetico y no pueda continuarse la ejecucioacuten sin eacutel

Si en el desarrollo de nuestro proyecto nos encontramos con que vamos a utilizar varios archivos que hacen llamadas unos a otros podriacutea pasar que hagamos varias inclusiones del mismo archivo en distintos puntos proshyvocando alguacuten fallo difiacutecil de detectar Las funciones r e q u i r e _ o n c e () e i n c l u d e _ o n c e () solucionan eacuteste problema ya que si se intenta incluir un fichero varias veces con dichas funciones PHP 5 simplemente ignorashyraacute las llamadas El formato es el siguiente

require base_datosphp include contador_vistasphp require_once test php-include_once visitasphp

Recursividad

El paradigma de la programacioacuten nos lleva a los desarrolladores a invenshytar foacutermulas que minimicen el esfuerzo en nuestros programas pecando

106 Capiacutetulo 5

algunas veces de complejidad Las funciones recursivas son aquellas cashypaces de llamarse a siacute mismas Como uacutenico requisito es que haya una forshyma de salir en la llamada recursiva Si volvemos al ejemplo del nuacutemero factorial nos encontramos en que se puede escribir de la siguiente forma

ltphp function factorial($numero)

if ($numero == 1) return $numero

else return $numero factorial($numero-l)

echo El factorial de 7 es factorial(7) ltbrgt gt

Lo primero que llama la atencioacuten es que carece de un bucle f or para ir disminuyendo los nuacutemeros implicados en el factorial Lo que hace la funshycioacuten es multiplicar el nuacutemero que se pasa por el factorial del nuacutemero-1 Si el nuacutemero que se pasa es igual a 1 la funcioacuten deja de hacer llamadas reshycursivas y comienza a devolver los valores hasta llegar al resultado final

Funciones con nuacutemero de argumentos variables

Es habitual que el nuacutemero de paraacutemetros que se le pase a una funcioacuten dependa de la situacioacuten en la cual es llamada Hay tres formas de hacer esto en PHP

bull Definiendo la funcioacuten con argumentos por defecto Este meacutetodo pershymite hacer llamadas con menos paraacutemetros sin que aparezca un error

bull Usando un array para pasar las variables

bull Usando las funciones de argumento variable f unc_num_args () f u n c _ g e t _ a r g () y f u n c _ g e t _ a r g s () ya utilizadas en PHP 4

Argumentos por defecto

Para definir paraacutemetros de este tipo se sustituyen las variables por exshypresiones de asignacioacuten El formato es el siguiente

function nombre_funcioacuten($argumentol=valorl $argumento2=valor2 )

Funciones 107

De esta forma al llamar a la funcioacuten podemos hacerlo con varios paraacutemeshytros Si alguno de los paraacutemetros es obviado la variable tendraacute como vashylor el valor por defecto de la definicioacuten

ltphp function capitales($Pais$Capital = Madrid$habitantes = muchos)

re turn (La c a p i t a l de $Pais es $Capi ta l y t i ene $habi tantes hab i tan tes ltbrgt)

echo capitales(Espantildea) echo capitales(PortugalLisboa) echo capitales(FranciaParismuchiacutesimos) gt

La salida por pantalla es la siguiente

La capital de Espantildea es Madrid y tiene muchos habitantes La capital de Portugal es Lisboa y tiene muchos habitantes La capital de Francia es Paris y tiene muchiacutesimos habitantes

La funcioacuten c a p i t a l e s () tiene un paraacutemetro fijo y dos paraacutemetros por defecto El paraacutemetro $ P a i s es obligatorio pero los demaacutes pueden queshydarse en blanco recibiendo el valor por defecto La limitacioacuten de este meacutetodo es que los argumentos tienen un orden y no podemos saltarnos ninguno es decir no podemos dar los valores $ C a p i t a l y $ h a b i t a n -t e s porque en medio hay otro paraacutemetro

Argumentos mediante un array

Si no encontroacute alguna utilidad a la anterior forma de pasar valores variashybles quizaacutes necesite utilizar un array para pasarlos El ejemplo siguiente usa esta estrategia y algunos trucos maacutes como el operador ternario y los array asociativos

ltphp function capitales($datos)

$Pais = isset ($datos[Pais ] ) $datos [Pais] Espantildea $Capital = isset ($datos[Capital] ) $datos [Capital] Madrid $habitantes = isset ($datos[habitantes] ) $datos [habitantes] muchos return (La capital de $Pais es $Capital y tiene $habitantes habitantesltbrgt)

Introducimos en el array los datos uno por uno para que sea maacutes faacutecil de entender $datos [Pais] = Espantildea echo capitales($datos) $datos [Pais] = Portugal

108 Capiacutetulo 5

$datos [Capital] = Lisboa echo capitales($datos) $datos [Pais] = Francia $datos [Capital] = Paris $datos [habitantes] = muchiacutesimos echo capitales($datos) gt

Como puede ver la funcioacuten tiene un uacutenico argumento que contiene toshydos los datos que nuestro programa necesita Esta vez los valores por defecto los introducimos mediante el operador ternario que chequea si existe el dato referido al P a i s C a p i t a l o h a b i t a n t e s y si no existe se antildeaden los datos E s p a ntilde a Madr id y muchos El ejemplo utiliza la funcioacuten con 0 2 y 3 paraacutemetros La ventaja de este meacutetodo es que podraacute utilizar los argumentos que quiera y en el orden que necesite sin encasishyllarse en una forma especial de pasar los datos

Nota

Jgt Aunque todaviacutea no hemos visto el capiacutetulo 7 que trata con detalle el manejo dearrays el lector puede hacerse una idea de coacutemo funshycionan en el aacutembito de los paraacutemetros defunciones Si queda alshyguna duda de coacutemo utilizarlos siempre puede echar un breve vistazo al capiacutetulo 7 para aclarar esas lagunas

Funciones 109

Muacuteltiples argumentos con func_num_args()

Desde la versioacuten 4 PHP ofrece algunas funciones que pueden ser utilizashydas para recuperar los argumentos

Son muy similares al lenguaje C

bull func_num_args() Devuelve el nuacutemero de argumentos que recibe la funcioacuten desde la que es llamada

bull func_get_arg() Devuelve uno a uno los argumentos pasados de la sishyguiente forma func_get_arg(0) func_get_arg(l) func_get_arg(5)

bull func_get_args() Devuelve un array con todos los argumentos pasashydos a la funcioacuten con los iacutendices del array empezando desde 0

Cualquiera de estas funciones daraacute un error si son llamadas fuera del enshytorno de una funcioacuten y f u n c _ g e t _ a r g () produciraacute un fallo si es llashymada con un nuacutemero maacutes alto que los argumentos que se reciben

Las funciones anteriores dan una ventaja a largo plazo ya que si durante el periacuteodo de vida de una funcioacuten necesita antildeadir alguacuten argumento maacutes puede capturar sin necesidad de cambiar el coacutedigo de las llamadas o el de definicioacuten de la funcioacuten

En el ejemplo siguiente puede comprobar coacutemo se utiliza este meacutetodo

ltphp function capitales()

$numero_argumentos = func_num_args() $Pais = $numero_argumentos gt 0 func_get_arg(0) Espantildea $Capital = $numero_argumentos gt 1 func_get_arg(1) Madrid $habitantes = $numero_argumentos gt 2 func_get_arg (2) muchos return (Nuacutemero de argumentos es $numero_arguraentos La capital de $Pais es $Capital y tiene $habitantes habitantesltbrgt)

echo capitales() echo capitales(Portugal Lisboa) echo capitales(Francia Paris muchiacutesimos) gt

Esta forma de utilizar los argumentos sigue teniendo una limitacioacuten Los argumentos deben ser pasados en un lugar determinado sino la funcioacuten no haraacute bien su trabajo Utilizar los paraacutemetros como array es el meacutetodo maacutes flexible y el maacutes utishylizado en los programas PHP Auacuten asiacute es muy uacutetil cuando no sepa cuaacutentos datos necesita manejar una funcioacuten Podemos utilizarlo para funciones que sumen todos los parame-

110 Capiacutetulo 5

tros que introduzca o concatenen todas las palabras como el ejemplo sishyguiente

ltphp function concatenar()

$resultado = $numero_argumentos = func_num_args() $array_parametros = func_get_args() for ($x = 0 $x lt= $numero_argumentos $x++)

$resultado = $resultado $array_parametros[$x]

return $resultadoltbrgt

echo concatenar(Hola Mundo) echo concatenar(Esto es una prueba dela potencia de este meacutetodo) gt

Llamadas por valor

Por defecto las llamadas a funciones se hacen por valor Esto quiere decir que las variables que se utilizan como paraacutemetros se copian al entorno de la funcioacuten

Todos los cambios de valor que sufra la variable en este entorno no afecshytaraacuten al programa fuera de la funcioacuten

ltphp function elevado($nuraero$ iacutendice)

$resultado = $numero for ($x = $indice $x gt 0 $x--)

$resultado = $resultado $nuraero

$numero = $resultado return $numero

$numero = 2 $indice = 5 echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt echo $numero elevado a $indice es igual a elevado ($numero$ indice) ltbrgt gt

El resultado por pantalla es

2 elevado a 5 es igual a 64 2 elevado a 5 es igual a 64

Funciones 111

El ejemplo anterior calcula el resultado de $numero elevado a $ Iacute n d i c e La funcioacuten e l e v a d o () crea un bucle para multiplicar $numero por las veces que indica el $ iacute n d i c e y lo va almacenando en la variable temporal $resultado

Cuando el bucle termina este resultado se vuelve a pasar a la variable $ numero que es devuelta como salida de la funcioacuten Cuando volvemos a ejecutar la funcioacuten con los mismos paraacutemetros vemos que la variable $nu-mero no ha cambiado en la ejecucioacuten anterior porque en realidad lo que se pasa es una copia del valor y todas las modificaciones se hacen sobre la copia y no sobre la variable original

Llamadas por referencia

PHP 5 ofrece actualmente dos caminos diferentes para cambiar sus argushymentos en la definicioacuten de la funcioacuten y en la llamada a la misma

Las variables pasadas por referencia pueden ser modificadas durante el proceso de una llamada porque lo que se pasa no es una copia sino la variable en siacute misma

Para pasar variables por referencia hay que utilizar el operador (amp) deshylante de la variable

Lo mejor es verlo en un ejemplo

ltphp function elevado(amp$numeroamp$indice)

$resultado = $numero for ($x = $iacutendiacutece $x gt 0 $x--)

$resultado = $resultado $numero

$numero = $resultado return $numero

$numero = 2 $ iacutendice = 5 echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt gt

El resultado por pantalla es ahora

2 elevado a 5 es igual a 64 64 elevado a 5 es igual a 68719476736

El funcionamiento es exactamente igual pero el resultado es distinto El operador (amp) hace que la variable $numero pueda ser modificada dentro de la funcioacuten y guarde este nuacutemero fuera de ella

Tambieacuten puede forzar a una funcioacuten a tomar argumentos por referencia aunque esta capacidad de PHP puede desaparecer en futuras versiones del lenguaje Las llamadas pueden hacerse de la siguiente forma

$numero = 2 $indice = 5 echo $numero elevado a $indice es igual a elevado(amp$numeroamp$indice)ltbrgt echo $numero elevado a $indice es igual a elevado(amp$numeroamp$indice)ltbrgt

El resultado es exactamente igual que al poner la referencia en la definishycioacuten de la funcioacuten

Referencia a variables

Las referencias pueden usarse tambieacuten fuera de las funciones en el aacutembishyto de las variables El ejemplo siguiente muestra coacutemo trabaja el operador (amp) con las variables

ltphp $nombre = Luis Miguel

Funciones 113

$apelliacutedos = Cabezas Granado $nombre auxiliar es simplemente una copia de $nombre $nombre_auxiliar = $nombre-$nombre_referencia es una referencia a la variable $nombre_referencia = amp$nombre echo $nombre $apellidosltbrgt $nombre_auxiliar = Alberto echo $nombre $apellidosltbrgt $nombre_referencia = Felipe echo $nombre $apellidosltbrgt gt

$nombre__aux i l i a r es una copia de la variable $nombre y por mucho que la cambiemos $nombre permaneceraacute con el mismo valor En cambio la variable $nombre_ref e r e n c i a es un alias de $nombre por lo tanto todos los cambios que se hagan en cualquiera de las dos variables les afecshytaraacute por igual

Funciones variables

Uno de los trucos que se pueden hacer con PHP es utilizar variables para almacenar el nombre de funciones Si una variable almacena el nombre de una funcioacuten simplemente tendraacute que antildeadir unos pareacutentesis al final de la variable para hacer la llamada correctamente

ltphp function saludo_maniana()

return (Buenos Diacuteas)

function saludo_tarde()

return (Buenas Tardes)

function saludo_noche()

return (Buenas Noches) $horario = tarde $funcion_variable = saludo_$horario echo $funcion_variable () gt

En el ejemplo anterior tenemos tres funciones que nos saludan depenshydiendo del horario en el que ejecutemos el programa Este valor se recoge en la variable $ h o r a r iacute o Sabemos que todas las funciones comienzan con la palabra saludo_ Si a la variable $f u n c i o n _ v a r iacute a b l e le concatenashymos el valor de $ h o r a r i o tenemos como resultado el nombre de la fun-

1 1 4 Capiacutetulo 5

cioacuten que nos daraacute el saludo Para que esto funcione antildeadimos dos siacutemboshylos de pareacutentesis al final de la expresioacuten

Resumen

Si el capiacutetulo anterior daba rienda suelta a su imaginacioacuten para comenzar con el desarrollo de pequentildeos scripts despueacutes de leer este capiacutetulo estaraacute en situacioacuten de realizar un gran proyecto Ahora que conoce el secreto para almacenar en distintos archivos funciones y partes de un programa escrishyto en PHP podraacute crear aplicaciones maacutes extensas y complejas

Ahora bien debe tener en cuenta que hay que tener cuidado con el alcanshyce de las variables y los pasos por valor y referencia aspecto muy relevanshyte en el capiacutetulo referido a los objetos

En este capiacutetulo aprenderaacute a

bull Diferenciar entre las comillas simples y las comillas dobles bull Trabajar con cadenas de muacuteltiples liacuteneas bull Concatenar varias cadenas bull Generar nuevas cadenas de caracteres a partir de una original bull Eliminar los espacios en blanco de las cadenas bull Convertir a mayuacutesculas o minuacutesculas bull Definir patrones de verificacioacuten de cadenas

116 Capiacutetulo 6

Introduccioacuten

Si pensamos en los tipos de datos que circulan por la red llegaremos a la conclusioacuten de que una gran porcioacuten la ocupan las imaacutegenes animaciones en Macromedia Flash videos o subprogramas escritos en Java La otra gran porcioacuten mayoritaria son los textos o las cadenas de caracteres

Las cadenas de caracteres o string son secuencias de caracteres que pueshyden ser tratadas como una unidad asignadas a variables pasadas como paraacutemetros a funciones o enviadas como salida al navegador Un string se diferencia de otro tipo de dato en PHP 5 porque va encerrado entre comishyllas dobles ( ) o simples ( )

Cadena entre comillas dobles Cadena entre comillas simples

PHP interpreta de distinta forma las cadenas que van entre comillas doshybles y las que van entre comillas simples Losstrings entre comillas dobles pueden sustituir ciertos siacutembolos por acciones como la inclusioacuten del vashylor de una variable Las comillas simples simplemente muestran todo el contenido sin atender a caracteres especiales Podemos ver un ejemplo donde sucede esto

ltphp $variable = Domingo $frase_l = Hoy es $variable el cielo estaacute gris $frase_2 = Hoy es $variable el cielo estaacute gris echo $frase_l echo $frase_2 gt

El resultado en el navegador es

Hoy es Domingo el cielo estaacute gris Hoy es $variable el cielo estaacute gris

Como se puede observar la cadena $f r a s e _ l es capaz de sustituir la vashyriable por su valor por el simple hecho de estar entre comillas dobles

Propiedades de las cadenas

iacutendices de string

Si pensamos en las cadenas como una sucesioacuten de caracteres en un orden determinado podemos llegar a desear acceder libremente a parte de los

Cadenas de caracteres y expresiones regulares 117

caracteres Esto es posible gracias a los siacutembolos de llave ( ) y un iacutendice numeacuterico que se corresponderaacute con la posicioacuten del caraacutecter que buscamos El ejemplo muestra coacutemo crear una funcioacuten que duplica las letras de una cadena aprovechando esta forma de acceder a los caracteres

ltphp function duplicar_caracteres($cadena)

$tamanio = strlen ($cadena) $cadena_auxiliar = for ($x = 0$x lt $tamanio $x++)

$cadena_auxiliar = $cadena_auxiliar $cadena$x $cadena$x

return $cadena_auxiliar

$cadena = Duplicar las letras echo duplicar_caracteres($cadena)iexcl gt

La salida por pantalla como puede adivinar es

118 Capiacutetulo 6

Operadores

En este punto aprovecharemos para hacer un breve repaso de los operashydores de string vistos en el capiacutetulo 3 En otros lenguajes como Java se utiliza el operador suma (+) para unir dos cadenas En PHP este mismo resultado se obtiene con el operador punto ( ) Asiacute podemos concatenar varias cadenas de la forma siguiente

ltphp $cadenal = Hola $cadena2 = Mundo $cadena3 = iexclQueacute tiacutepico $supercadena = $cadenal $cadena2 $cadena3 echo $supercadena gt

Es faacutecil intuir que el operador puede concatenar caracteres y variables de tipo string de forma conjunta Es posible que desee ahora antildeadir texto a una cadena ya existente esto se puede hacer de dos formas muy similashyres La primera es asignando a la variable su valor maacutes el valor a antildeadir de la siguiente forma

ltphp $cadenal = Hola $cadena2 = Mundo $cadenal = $cadenal $cadena2 echo $cadenal gt

O utilizando el operador de concatenacioacuten y asignacioacuten ( = ) como en el ejemplo

ltphp $cadenal = Hola $cadena2 = Mundo $cadenal = $cadena2 echo $cadenal gt

Sintaxis para muacuteltiples liacuteneas

Existe en PHP una forma maacutes de introducir cadenas aparte de las comishyllas muy recomendable para largos textos o un considerable conjunto de etiquetas HTML La sintaxis es muy sencilla y comienza con el operador (ltltlt) seguido de una etiqueta que indica el principio del texto Despueacutes de esto podemos escribir un conjunto de caracteres muy numerosos y para

Cadenas de caracteres y expresiones regulares 119

finalizar la etiqueta de fin El ejemplo muestra coacutemo almacenar un forshymulario en una variable

ltphp $formulario = ltltltINICIO ltformgt ltiacutenput type=text name=Nombre value=Luiacutes Miguel Cabezasgt ltbrgt ltinput type=submit name=submit value=Enviar gt ltformgt INICIO echo $formulario gt

Siempre debe comenzar por el operador (ltltlt) seguido de un identifica-dor por ejemplo INICIO Despueacutes se incluye el texto en este caso un forshymulario y para finalizar la misma etiqueta de inicio Esta forma de almacenar datos permite utilizar indistintamente comillas simples o doshybles dentro de una variable La imagen 62 muestra el resultado del script

Funciones de string

Si conoce el lenguaje C podraacute comprobar que las funciones de manejo de caracteres son muy parecidas en nombre y uso Los desarrolladores de PHP

120 Capiacutetulo 6

siempre han querido que exista esta similitud para facilitar el aprendizaje del lenguaje

La mayoriacutea de las funciones existentes en PHP 5 tienen una homologa en C

Tamantildeo de la cadena

La funcioacuten s t r l e n () devuelve como resultado el tamantildeo en caracteres de la cadena que pasemos de paraacutemetro Este valor puede asignarse a una variable como indica el ejemplo

ltphp $cadena = Esta cadena tiene muchas letras $numero_letras = strlen($cadena) echo cadena tiene $numero_letras caracteres gt

Simplemente imprime

cadena tiene 31 caracteres

Posicioacuten de los caracteres

Para crear buenos motores de buacutesqueda en nuestros sitios Web necesitashyremos potentes herramientas que sean capaces de buscar caracteres cashydenas o patrones coincidentes dentro de textos extensos La funcioacuten s t r p o s () encuentra en un string la posicioacuten de un caraacutecter determinado

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de a es strpos($cadena a) ltbrgt echo La primera ocurrencia de m es strpos($cadena m) ltbrgt gt La s a l i d a en el navegador no es o t ra que La primera ocur renc ia de a es 3 La primera ocur renc ia de m es 18

Si s t r p o s () se utiliza para averiguar la posicioacuten de la primera L mashyyuacutescula de $ cadena vemos que nos devuelve un 0 esto es asiacute porque el iacutendice de caracteres comienza en 0 como pasa en muchos lenguajes de programacioacuten Si no se encuentra ninguna ocurrencia del caraacutecter buscashydo el resultado seraacutease

Cadenas de caracteres y expresiones regulares 121

La funcioacuten s t r p o s () tambieacuten puede utilizarse para buscar varios caracshyteres seguidos en una misma cadena

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de tiene es strpos($cadenatiene) ltbrgt gt

Si lo que nos interesa es encontrar caracteres buscando desde el final de la cadena la funcioacuten que tenemos que utilizar es s t r r p o s () (la letra r que se antildeade viene del ingleacutes reverse) El ejemplo anterior nos sirve para comshyprobar el funcionamiento de la funcioacuten

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de a es strpos($cadena a ) ltbrgt echo La primera ocurrencia desde atraacutes de a es strrpos($cadena a) ltbrgt gt

siendo el resultado

La primera ocurrencia de a es 3 La primera ocurrencia desde atraacutes de a es 29

Comparacioacuten

El operador (==) nos puede servir para evaluar si dos cadenas de caracteshyres son iguales dentro de una estructura de control Ademaacutes tenemos la funcioacuten s t r c m p ( ) que compara bit a bit dos cadenas de caracteres Atenshydiendo al valor de salida de la funcioacuten podemos obtener los siguientes resultados

bull Si el valor que se obtiene es 0 las dos cadenas son exactamente igual

bull Si obtenemos un valor negativo el primer string es maacutes pequentildeo que el segundo

bull Si obtenemos un valor positivo el primer string es maacutes grande que el segundo ltphp $cadenal = Prueba $cadena2 = Prueba if (strcmp($cadenal$cadena2) == 0)

echo Las dos cadenas son iguales elseif (strcmp($cadenal$cadena2) lt 0)

echo La cadenal es menor que la cadena2

122 Capiacutetulo 6

else echo La cadenal es mayor que la cadena2

gt

La comparacioacuten anterior soacutelo da como resultado dos cadenas iguales si las dos cadenas son exactamente iguales haciendo distincioacuten entre mashyyuacutesculas y minuacutesculas

Para evitar este problema podemos utilizar la funcioacuten s t r c a s e c m p ( ) que no es sensible a mayuacutesculas Asiacute s t r c a s e c m p (HoLa hOlA) da como resultado 0 es decir las dos cadenas son iguales

Buacutesqueda de caracteres

Siguiendo con las buacutesquedas de texto la funcioacuten s t r s t r () recibe como paraacutemetros una cadena de caracteres donde buscar y otra con un conjunshyto de caracteres que queremos encontrar Si se encuentra el patroacuten de buacutesshyqueda el resultado seraacute una cadena de caracteres que comenzaraacute justo en el patroacuten hasta el final del string primero Si no se encuentra el patroacuten el resultado seraacutefalse

lt php $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de cadena es strstr ($cadenacadena) ltbrgt

gt

Como cabe esperar el resultado es La primera ocurrencia de cadena es cadena tiene muchas letras

Seleccioacuten de subcadenas

La funcioacuten s u b s t r () permite seleccionar un conjunto de caracteres de una cadena quedando intacto el string original Puede tomar varios paraacuteshymetros

bull s u b s t r ( c a d e n a iacute n d i c e ) Cadena es el conjunto de caracteres que queremos cortar e iacute n d i c e la posicioacuten a partir de la cual se cortaraacute la cadena hasta el final

bull s u b s t r ( cadena iacute n d i c e numero) Cadena es el conjunto de cashyracteres que queremos cortar e iacute n d i c e la posicioacuten a partir de la cual se cortaraacute la cadena tantas posiciones como indique el nuacutemero

Cadenas de caracteres y expresiones regulares 123

Por ejemplo

ltphp $cadena = Esta cadena tiene muchas letras Devuelve la cadena completa echo substr($cadena 0) echo ltbrgt Desde el caraacutecter 12 hasta el final echo substr($cadena 12) echo ltbrgt Devuelve 6 caracteres desde el caraacutecter 18 echo substr($cadena 186) echo ltbrgt Devuelve los 6 uacuteltimos caracteres echo substr($cadena -6) echo ltbrgt Desde la posicioacuten 26 contando desde atraacutes 6 caracteres echo substr($cadena -266) echo ltbrgt Empezando en el caraacutecter 4 y terminando en el 7 desde atraacutes echo substr($cadena 4-7) gt

El resultado lo podemos ver maacutes abajo Recuerde que la variable $ cade -na queda intacta

124 Capiacutetulo 6

Dependiendo de la posicioacuten del nuacutemero negativo s u b s t r () actuaraacute de una forma u otra

Tabla 61 Respuestas de la funcioacuten substr ()

Ejemplo Resultado

substr(Hola2) Devuelve la cadena completa empezando por el caraacutecter 2 substr(Hola-2) Devuelve la cadena completa empezando por el caraacutecter

2 esta vez empezando a contar desde atraacutes

substr(Hola13) El resultado son 3 caracteres empezando desde el caraacutecshyter 1

substr(Hola-32) Doscaracteres empezando desde el caraacutecter 3 contando desde la uacuteltima letra

substr(Hola2-1) Devuelve un conjunto de caracteres que estaacuten desde la posicioacuten 2 a la posicioacuten 1 comenzando desde atraacutes

substr(Hola-2-3) No tiene aplicacioacuten posible

Funciones de limpieza de cadenas

Sirven para limpiar espacios en blanco al principio de la cadena al final o en cualquier parte desde el principio al final y son respectivamente l t r i m ( ) chop () y t r i m () Su aplicacioacuten es tan sencilla que bastaraacute un ejemplo para entender su funcionamiento

ltphp $salto_linea = n $cadena = cadena con varios espacios en blanco echo $salto_linea $cadena tamantildeo strlen($cadena) echo ltbrgt echo $salto_linea ltrim($cadena) tamantildeo strlen(ltrim($cadena)) echo ltbrgt echo $salto_linea chop($cadena) tamantildeo strlen(chop($cadena)) echo ltbrgt echo $salto_linea trim($cadena) tamantildeo strlen(trim($cadena)) gt

Cada liacutenea realiza una de las operaciones vistas e imprime el resultado de la cadena en el navegador junto con el tamantildeo de la cadena

La figura 64 muestra el resultado por pantalla

126 Capiacutetulo 6

Sustitucioacuten de cadenas

La funcioacuten s t r _ r e p l a c e () toma como paraacutemetros un conjunto de cashyracteres a buscar un grupo que debe sustituirse por el anterior y una cashydena de caracteres sobre la que actuar

ltphp $cadena = Esta cadena tiene muchas letras $cadena = str_replace(EstaEste$cadena) echo str_replace(cadenaconjunto$cadena) gt

Si en la cadena existiera maacutes de una instancia del conjunto buscado todas las ocurrencias quedariacutean cambiadas

ltphp cadena = Esta cadena tiene muchas letras y cadenas $cadena = str_replaceacute(EstaEste$cadena) echo str^replace(cadenaconjunto$cadena) gt

El resultado es Este conjunto tiene muchas letras y conjuntos

Truco

Puede probar esta funcioacuten para cambiar todos iexclos caracteres de un tipo de una cadena de iexcla siguiente forma s t r _ r e p l a c e (h j hola h o l a )

Funciones de mayuacutescula y minuacutescula

Las funciones s t r t o l o w e r () y s t r toupper () devuelven la cadena que se pasa como argumento completamente en minuacutescula o mayuacutescula resshypectivamente

ltphp $cadena = Hay palabras en MAYUacuteSCULAS y en minuacutesculasltbrgt echo strtolower($cadena) echo strtoupper($cadena) gt

El resultado es hay palabras en mayuacutesculas y en minuacutesculas HAY PALABRAS EN MAYUacuteSCULAS Y EN MINUacuteSCULAS

Si lo que realmente nos interesa es que la primera letra de un texto apashyrezca como letra Capital o que letras iniciales de cada palabra en una fra-

Cadenas de caracteres y expresiones regulares 127

se aparezcan en mayuacutescula tenemos las funciones u c f i r s t ( ) y u c w o r d s ( )

ltphp $cadena = habiacutea una vezltbrgt echo ucfirst($cadena) $cadena2 = linux user group echo LUG significa ucwords($cadena2) gt

Expresiones regulares

Las funciones vistas anteriormente basan su potencia en la buacutesqueda o susshytitucioacuten de los caracteres de una cadena pero son poco uacutetiles cuando tratashymos de comprobar si un conjunto de caracteres cumple un formato determinado Si solicitamos mediante un formulario un correo electroacutenico necesitamos saber a priori si ese correo por lo menos estaacute bien construido

luisnccextremaduraorg luiszendcom

La idea es poder descartar de alguna forma los correos escritos de esta manera

l u i s (Snccextremaduraorg E s p a c i o en medio

128 Capiacutetulo 6

LUISzendcom En mayuacutesculas luisaupexorg Dos

Las expresiones regulares son patrones de buacutesqueda dentro de cadenas Estos patrones se construyen mediante caracteres especiales que cumplen unas reglas determinadas

Tabla 62 Reglas de expresiones regulares

Ejemplo Regla

aabb Los caracteres no especiales como un grupo de letras se escriben como de costumbre

A Indica que hay que buscar el patroacuten desde el principio de la cadena $ Este simbolo obliga al patroacuten a cumplirse hasta el final de la

cadena Simboliza cualquier caraacutecter

Indica que puede haber O o maacutes instancias de una expresioacuten + Indica que puede haber 1 o maacutes instancias de una expresioacuten [ab] Indica que se puede encontrar el caraacutecter a o el b y la expresioacuten

seriacutea correcta Lo podemos acompantildear de [ab] para evaluar si hay varias letras seguidas del tipo a o b

[a-z] Indica que se puede elegir entre un rango de caracteres que va desde la a hasta la z

Si queremos utilizar cualquiera de los anteriores caracteres como parte del patroacuten tendremos que utilizar eacuteste siacutembolo para indicarle a PHP que es un literal

Como ejemplo vamos a intentar hacer un patroacuten que verifique si un coshyrreo electroacutenico estaacute correctamente construido o no Seriacutea faacutecil pensar en una expresioacuten parecida a la siguiente

[ a - z ] + [ a - z ] + o r g

La primera parte [ a - z ] + nos dice que aceptaraacute una letra o conjunto de letras sin espacios y en minuacutesculas que pueden corresponderse con el nombre de usuario de la cuenta de correo Despueacutes aceptaraacute un siacutembolo seguido de otro conjunto de caracteres correspondientes al servidor de correo La uacuteltima parte de la expresioacuten la componen los siacutembolos que indican que tiene que aparecer un punto que separe la descripcioacuten del servidor del dominio y la cadena o r g que obliga a que todos los correos sean de dominio no gubernamental

Cadenas de caracteres y expresiones regulares 129

La expresioacuten anterior tiene algunas limitaciones que veremos como solshyventar La primera es que se puede aplicar a cualquier texto con indepenshydencia del tamantildeo Si en alguna parte de ese texto aparece un conjunto de caracteres que cumpla con la expresioacuten la validacioacuten seriacutea true Esto no es bueno cuando queremos chequear si un correo es introducido correctashymente La solucioacuten es aplicar las reglas de inicio y fin que obligan a que el comienzo de la cadena y el final sean parte de la expresioacuten

[ a - z ] + [ a - 2 ] + o r g $

Tambieacuten podemos encontrarnos con que existen correos introducidos coshyrrectamente pero el dominio es otro distinto a org Esta vez la solucioacuten es introducir el operador O loacutegico | que permite elegir entre varias opcioshynes

^ [ a - z ] + [ a - z ] + ( o r g | c o m | n e t ) $

Por uacuteltimo un problema menor aunque habitual en el aacutembito de los coshyrreos electroacutenicos es la utilizacioacuten de signos de puntuacioacuten para separar nombres y apellidos y servidores de servidores virtuales Por ejemplo el correo siguiente es correcto pero no seriacutea evaluado por la expresioacuten anteshyrior

l u iacute s c a b e z a s n c c a u p e x o r g

Una posible solucioacuten es

[ a - z | ] + [ a - z | ] + ( o r g | c o m ( n e t ) $

Comprobar expresiones regulares

La funcioacuten e reg () es capaz de comprobar si una cadena se corresponde con el patroacuten que se pasa como paraacutemetro Toma dos argumentos obligashytorios una expresioacuten regular y una cadena de caracteres donde buscar el patroacuten Seguidamente puede ver un ejemplo completo de utilizacioacuten de expresiones regulares y la funcioacuten

ltphp $correo = luiscabezasnccaupexorg $correol = LUISnccaupexorg $correo2 = luiscabezasnccaupexorg if (ereg ( [a-z|]+[a-z|]+ (org|com|net)$$correo))

echo El correo $correo se aceptaltbrgt else

echo El correo $correo no cumple el patroacutenltbrgt

iacutef (ereg(^ [a-z|]+ [a-z|]+ (org|comjnet)$$correol) )

echo El correo $correol se aceptaltbrgt

130 Capiacutetulo 6

else echo El correo $correol no cumple el patroacutenltbrgt

if (ereg(A [a-zj]+ [a-zj]+ (org|com|net)$$correo2))

echo El correo $correo2 se aceptaltbrgt else

echo El correo $correo2 no cumple el patroacutenltbrgt gt

El resultado por pantalla es

Puesto que hay muchos usuarios acostumbrados a escribir su correo elecshytroacutenico completamente en mayuacutesculas se hace necesario comprobar este contratiempo tambieacuten Lo maacutes raacutepido es utilizar la funcioacuten e r e g i () que funciona exactamente igual que e r e g ( ) pero no es sensible a mayuacutescula o minuacutescula El ejemplo anterior lo podemos arreglar de la siguiente forma

ltphp $correo = LUISnccaupexorg if (ereg([a-z|]+[a-z|]+(org|com|net)$$correo$pepe))

echo El correo $correo se aceptaltbrgt else

echo El correo $correo no cumple el patroacutenltbrgt

gt

Cadenas de caracteres y expresiones regulares 131

Nota

e reg () y e r e g i () tienen un tercer argumento opcional del tipo array Si iexcla expresioacuten regular la dividimos en pequentildeas parshytes entre pareacutentesis cada ocurrencia encontrada en la cadena se va almacenando como un elemento del array

Reemplazar patrones

e r e g _ r e p l a c e () y e r e g i _ r e p l a c e () tiene tres paraacutemetros El prishymero es una expresioacuten regular el segundo un string por el que se cambiashyraacuten todas las ocurrencias del patroacuten y por uacuteltimo una cadena donde buscar Como antes la diferencia entre las dos es uacutenicamente que la prishymera es sensible a mayuacutesculas El siguiente ejemplo muestra el funcionashymiento

ltphp $texto = El correo es de luisnccaupexorg echo ereg_replace([a-z|]+[a-z|]+(org|com|net)Luis Miguel$texto) gt

Asiacute da como resultado el cambio del correo electroacutenico por el nombre de la persona asociada

Resumen

Desde hace unos antildeos se ha puesto de moda una serie de productos donshyde prima el contenido frente al disentildeo Los CMS (Content Manager System) son programas la mayoriacutea escritos en PHP que permiten gestionar mushycho contenido escrito por diferentes personas El tratamiento de los textos se agudiza al maacuteximo en este caso siendo indispensable la utilizacioacuten de expresiones regulares para verificar los datos nuevos que puedan incor- porarse Ademaacutes suelen llevar un buscador capaz de encontrar patrones determishynados dentro de las noticias expuestas Este capiacutetulo le ha servido para conocer funciones para concatenar recorshytar o verificar cadenas Con esto bien aprendido ya puede comenzar a crear su propio CMS

En este capiacutetulo aprenderaacute a

bull Comprender queacute es un array y coacutemo se define bull Trabajar con funciones que definen listas de datos bull Diferenciar entre los distintos meacutetodos para recorrer los array

bull Ordenar los conjuntos de datos con diferentes meacutetodos bull Crear pilas y colas

134 Capiacutetulo 7

Introduccioacuten

Un array es una coleccioacuten de valores con un uacutenico nombre Para acceder a los distintos valores de la variable se utiliza un iacutendice numeacuterico o alfanu-meacuterico Nos vamos a servir de la definicioacuten de un array en el lenguaje C para ver la potencia de este tipo de datos en PHP La definicioacuten es la siguiente

int mi_array[100] Esto es C

Lo primero que debe llamarnos la atencioacuten es que la variable estaacute predefishynida como i n t (entero) En PHP los arrays no tienen que definirse de una forma concreta sino que pueden tomar distintos tipos de valores enteshyros caracteres objetos etceacutetera Lo siguiente es que en C se necesita sashyber de antemano el nuacutemero de valores maacuteximo que podraacute tomar el array Esto no es necesario en PHP ya que podraacute ir creando valores nuevos a medida que lo vaya necesitando Lo uacuteltimo es que en C el iacutendice para acshyceder a los 100 valores distintos debe ser numeacuterico en cambio en PHP el iacutendice puede ser numeacuterico o alfanumeacuterico

ltphp $mi_array[l] = 23 $mi_array[2] = Este valor es un string $mi_array[ejemplo] = Esto es un array asociativo gt

Creacioacuten de arrays

Vamos a ver tres formas distintas de crear un array dentro de un script de PHP

Asignacioacuten directa

El camino maacutes simple y por otro lado loacutegico es asignar valores cuando se necesiten La primera vez que asignemos un valor el array se crearaacute en el entorno

ltphp $mi_array[l] = 23 Asignacioacuten directa gt

De esta forma tenemos un valor asignado al iacutendice 1 del array Puede asigshynar cualquier iacutendice en la creacioacuten de este tipo de dato e incluso no asig-

Conjuntos de datos del tipo array 135

nar ninguno de forma que PHP se encarga de asociar un iacutendice distinto para cada valor

ltphp $mi_array[] = 23 Empieza en el iacutendice 0 $mi_array[] = 54 iacutendice 1 gt

array()

Esta funcioacuten crea un array con los valores que pase como datos de entrashyda Los iacutendices seraacuten antildeadidos automaacuteticamente empezando desde 0

Si no asigna paraacutemetros a a r r a y ( ) la funcioacuten le devolveraacute un array vaciacuteo

ltphp $mi_array = array(2345762365) gt

El meacutetodo es similar a

ltphp $mi_array[0] = 23 $mi_array[l] = 4 5 $mi_array[2] = 76 $mi_array[3] = 23 $mi_array[4] = 65 gt

La funcioacuten a r r a y () permite tambieacuten antildeadir iacutendices a los valores que se introducen

Para ello se utiliza el operador =gt de esta forma

ltphp $mi_array = array0 =gt 23 1 =gt 45 2 =gt 76) gt

Tambieacuten es posible antildeadir iacutendices que no sean correlativos o iacutendices alf-anumeacutericos incluso mezclar los dos tipos

ltphp $mi_array = a r r a y ( c e r o =gt 23 uno =gt 45 2 =gt 7 6 ) gt

Para recuperar cualquier valor se utiliza el iacutendice dentro de los corchetes

ltphp $mi_array = array(cero =gt 23 uno =gt 45 2 =gt 76) echo $mi_array [ uno] ltbrgt echo $mi_array[2] gt

136 Capiacutetulo 7

Funciones que devuelven arrays

La uacuteltima forma de obtener un array es utilizando alguna de las funcioshynes que devuelven este tipo de datos

Es muy frecuente que las funciones que manejan bases de datos devuelshyvan las ocurrencias dentro de un array

Por ejemplo la funcioacuten r a n g e () devuelve un array con valores numeacuterishycos que van desde un nuacutemero de inicio hasta un nuacutemero final tal y como se muestra en el ejemplo

ltphp $mi_array = range(120130) gt

Esta funcioacuten crea un array empezando desde el iacutendice 0 y el valor 120 hasta el iacutendice 10 y el valor 130

Arrays multidimensionales

Hasta aquiacute hemos visto ejemplos de arrays de una sola dimensioacuten PHP soporta el uso de arrays de varias dimensiones faacutecilmente aunque son complejos de entender y de usar El array siguiente es de 5 dimensiones

ltphp $ m i _ a r r a y [ l ] [ 1 ] [ 2 3 ] [ 4 3 ] [ 0 ] = A r r a y de 5 d i m e n s i o n e s gt

Cada iacutendice encerrado entre corchetes corresponde a una dimensioacuten disshytinta En realidad cada dimensioacuten es un array que se introduce como vashylor dentro de la dimensioacuten anterior

Asiacute podraacute crear un array multidimensional de la siguiente forma

ltphp $colores = array(fuertessuaves) $colores [fuertes] = array ( rojo =gt FF0000 verde =gt 00FF00 azul =gt 0000FF)

$ c o l o r e s [ s u a v e s ] = a r r a y ( r o s a =gt FE9ABC a m a r i l l o =gt FDF189 malva =gt 9 A 2 F 6 8 ) echo $colores[fuertes] [rojo] gt

Para recuperar los valores se utilizan un iacutendice del primer array (fuertes o suaves) y un iacutendice de alguno de los dos arrays secundarios

Conjuntos de datos del tipo array 137

Otra forma de definir el array anterior es

ltphp

$colores = array( fuertes =gt array ( rojo =gt FF0000 verde =gt 00FF00 azul =gt 0000FF)

suaves =gt array ( rosa =gt FE9ABC amarillo =gt FDF189 malva =gt 9A2F68))

echo $colores[fuertes] [rojo] gt

Propiedades de arrays

Existen numerosas funciones que son capaces de averiguar datos de los arrays tales como el tamantildeo si un valor forma parte del conjunto o si un determinado iacutendice estaacute registrado

count()

Cuenta el nuacutemero de elementos que contiene un array

ltphp echo elementos de 1 dimensioacuten count ($colores) ltbrgt echo elementos de 2 dimensiones count ($colores[fuertes]) gt

El ejemplo anterior se basa en la definicioacuten del array de colores inicializa-do antes Para contar el nuacutemero de elementos debe ponerse tambieacuten la dimensioacuten Si el array es de una sola dimensioacuten no hace falta La funcioacuten s i z e o f () actuacutea de la misma forma

in_array()

Busca dentro de un array un valor pasado como paraacutemetro y si lo encuenshytra devuelve el valor true si no devuelve false Toma dos argumentos el valor a buscar y el array doacutende buscar

ltphp $colores = array (rojoverdeamarilloazul) if (in_array(rojo$colores))

echo Se ha encontrado el valor rojo

138 Capiacutetulo 7

e l s e echo No se ha encontrado

gt

Borrar ocurrencias

Para borrar un elemento simplemente se utiliza la misma funcioacuten que borra las variables definidas unset ()

ltphp $colores = array (rojoverdeamarilloazulrosa) echo El nuacutemero de elementos de colores es count ($colores) ltbrgt unset ($colores[2]) echo El nuacutemero de elementos de colores es count ($colores) ltbrgt gt

Se puede observar que para borrar un elemento hay que conocer el iacutendishyce El resultado del ejemplo por pantalla es

El nuacutemero de elementos de colores es 5 El nuacutemero de elementos de colores es 0

Advertencia

Debe tener cuidado el lector con utilizar unset () con el nombre de un array sin iacutendice pues esto causaraacute el borrado del conjunto de datos en su totalidad Unset ($colores) borra el array comshypleto unset ($colores [2] borra soacutelo el iacutendice 2 del conjunto

Interactuar con arrays

Anteriormente tuvo la oportunidad de conocer las estructuras de control existentes en PHP La estructura f oreach quedoacute en el aire para tratarlo a fondo en el presente capiacutetulo El uso es asiacute

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) foreach ($colores as $valor)

echo (El valor es $valorltbrgt)

gt

Conjuntos de datos del tipo array 139

La construccioacuten anterior recorre el array desde el principio En el ejemplo se puede ver que f oreach toma el array a recorrer y sus valores los va almacenando en la variable $ v a l o r a medida que el bucle se ejecuta Existe una segunda construccioacuten que permite recuperar el iacutendice y el valor Veashymos un ejemplo de esto

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) foreach ($ciacuteudades as $iacutendiacutece =gt $valor)

echo (El iacutendice $indice tiene el valor $valorltbrgt)

gt

La salida en el navegador nos la muestra la figura 71

Es un meacutetodo muy bueno para imprimir los valores de un array que tiene iacutendices numeacutericos y alfanumeacutericos

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia] = Paris foreach ($ciudades as $indice =gt $valor)

echo (El Iacutendice $indice tiene el valor $valorltbrgt)

gt

140 Capiacutetulo 7

Funciones para avanzar en un array

Cada vez que creamos un array dentro de un programa PHP se crea un puntero que permite recorrer en su totalidad el conjunto de valores Este puntero se inicializa al valor inicial del array La funcioacuten c u r r e n t () deshyvuelve el valor al que apunta el puntero La funcioacuten n e x t () hace avanshyzar el puntero una posicioacuten en el conjunto de datos

Si el puntero se encuentra al final del conjunto n e x t () devuelve un vashylor false El ejemplo siguiente muestra coacutemo utilizar estas funciones para recorrer un array

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia] = Paris do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

while (next($ciudades) ) gt

Podemos crear una funcioacuten que realice este traacutemite

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) Sciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia ] = Paris

function recorre($ciudades) do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

Jwhile (next($ciudades))

recorre($ciudades) recorre($ciudades) gt

La funcioacuten r e c o r r e () utiliza un array como paraacutemetro y va utilizando las funciones de introspeccioacuten para sacar los resultados Puesto que los valores son pasados por valor la funcioacuten r e c o r r e () crea una copia de los datos que recibe y genera el resultado de la figura 72

De esta forma no hay manera de controlar el puntero porque siempre que pase la variable $ c i u d a d e s el puntero comenzaraacute desde el principio

Conjuntos de datos del tipo array 141

La forma de arreglar esto es hacer las llamadas por referencia r e c o r r e (Sc$ciudades) r e c o r r e (amp$ciudades)

142 Capiacutetulo 7

Ahora ya no es una copia de $ c iudades lo que se pasa como paraacutemetro sino una referencia al valor real Esto hace posible tener una memoria de la situacioacuten del puntero Una vez recorrido elarray el puntero queda fijado al final del conjunto de datos Para volver al principio se puede utilizar la funcioacuten r e s e t () que enviacutea al puntero al principio La funcioacuten puede quedar asiacute

function recorre($ciudades) if (current($ciudades))

reset($ciudades)

do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

Jwhile (next($ciudades))

Ahora lo que hacemos es comprobar si el puntero estaacute al final del array si esto es asiacute se llama a la funcioacutenreset 0 y el puntero se coloca al prinshycipio

Funciones para retroceder en un array

La funcioacuten prev () retrocede una posicioacuten el puntero y la funcioacuten end () se coloca al final de una lista de valores Esto puede ser uacutetil para mostrar el contenido en sentido inverso como puede ver en la nueva funcioacuten que hemos creado

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal ] = Lisboa $ciudades[Francia ] = Paris function recorre($ciudades)

if ( lcurrent($ciudades)) reset($ciudades)

do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

jwhile (next($ciudades))

function recorre_atras($ciudades)

end($ciudades) do

$valor = current($ciudades)

Conjuntos de datos del tipo array 143

echo (El valor es $valorltbrgt) while (prev($ciudades))

recorre(amp$ciudades) recorre_atras(amp$ciudades) gt

El navegador muestra El valor es Badajoz El valor es Meacuterida El valor es Caacuteceres El valor es Plasencia El valor es Madrid El valor es Lisboa El valor es Paris El valor es Paris El valor es Lisboa El valor es Madrid El valor es Plasencia El valor es Caacuteceres El valor es Meacuterida El valor es Badajoz

Por uacuteltimo para obtener el valor del iacutendice puede utilizar la funcioacuten key() La funcioacuten r e c o r r e () la puede actualizar de la siguiente forma

function recorre($ciudades) if ( current($ciudades) )

reset($ciudades)

do

$valor = current($ciudades) $indice = key($ciudades)

echo ($indice valor $valorltbrgt)

while (next($ciudades))

Intercambio de valores

La funcioacuten a r r a y _ f l i p () intercambia los valores de iacutendices y datos es decir los iacutendices seraacuten guardados como datos y los valores seraacuten sus nueshyvos iacutendices

ltphp function recorre ($numero)

foreach ($numero as $indice =gt $valor) echo $indice $valorltbrgt -

144 Capiacutetulo 7

$numero = array(uno =gt ldos =gt 2 tres =gt 3cuatro =gt 4) echo (Nuacutemerosltbrgt ) recorre($numero) echo (Nuacutemeros intercambiadosltbrgt) recorre(array_fliacutep$numero)) gt

El resultado es el esperado

Nuacutemeros uno 1 dos 2 tres 3 cuatro 4 Nuacutemeros intercambiados 1 uno 2 dos 3 tres 4 cuatro

Puede ver el resultado en la figura 74

Inversioacuten del contenido

Tambieacuten es posible ordenar a la inversa una lista de datos Esto se consishygue con la funcioacuten a r r a y _ r e v e r s e ()

Conjuntos de datos del tipo array 1 4 5

Si modifica el coacutedigo anterior tendraacute

echo (Nuacutemeros intercambiadosltbrgt ) recorre(array^reverse($numero))

Dando como resultado

Nuacutemeros uno 1 dos 2 tres 3 cuatro 4 Nuacutemeros intercambiados cuatro 4 tres 3 dos 2 uno 1

Mezcla de los valores

Si necesita alguna vez elegir un valor aleatorio de un array la funcioacuten shu-f f le () puede ser de gran ayuda ya que mezcla todos los valores cada vez que se ejecuta Parte del coacutedigo puede ser este

echo (Nuacutemeros mezcladosltbrgt ) shuffle($numero) recorre($numero)

Pilas

Las pilas son estructuras de datos que se utilizan mucho en el mundo de la informaacutetica La filosofiacutea baacutesica de las pilas es que todos los valores deshyben introducirse en un orden especiacutefico y soacutelo podemos recuperar esos valores en el orden inverso estricto al que fueron insertados Las pilas LIFO (Last ln First Out el uacuteltimo en entrar es el primero en salir) utilizan unas funciones especiacuteficas que permiten manejar todos los datos A r r a y _ p u s h () permite insertar en la pila un dato y a r r a y _ p o p () exshytrae un valor Es necesario antes que nada definir la variable como array pues ninguna de las funciones descritas lo hace

A r r a y _ p u s h () y a r r a y _ p o p () toman como argumento la variable array y los valores a introducir

lt php $pila = array() array_push($pilaunodostres)

146 Capiacutetulo 7

array_jpush($pilacuatrocinco) while ($valor = arrayjop($pila) )

echo valor extraiacutedo es $valorltbrgt

gt

El resultado por pantalla muestra que la extraccioacuten de los valores se hace en orden inverso del que fueron introducidos

valor extraiacutedo es cinco valor extraiacutedo es cuatro valor extraiacutedo es tres valor extraiacutedo es dos valor extraiacutedo es uno

Ordenacioacuten de los valores

Finalmente PHP ofrece una gran variedad de funciones para ordenar arrays Las funciones pueden verse en la tabla siguiente

Tabla 71 Funciones de ordenacioacuten

Funcioacuten Explicacioacuten

asort() Ordena de forma ascendente el array pasado como argumento Ordena las parejas iacutendicevalor atendiendo al dato Es un buen meacutetodo para los arrays asociativos

arsort() Igual que asort () pero ordena en sentido descendente ksort() Ordena de forma ascendente el array pasado como argumento

Ordena las parejas iacutendicevalor atendiendo esta vez al iacutendice

krsort() Igual que ksort () pero ordena en sentido descendente

sort() Ordena de forma ascendente el array pasado como argumento Se pierde el valor asociativo entre el iacutendice y el valor

rsort() Igual pero en orden descendente

Puede ver actuar todas las funciones de ordenacioacuten en el ejemplo sishyguiente

ltphp function recorre ($numero)

foreach ($numero as $indice =gt $valor) echo $indice $valorltbrgt

Conjuntos de datos del tipo array 147

$pi la = array(cinco = gt5uno = gtl cuatro = gt4dos = gt2 tres = gt3) echo Array sin ordenarltbrgt recorre($pila) echo Ordenacioacuten asort()ltbrgt asort($pila) recorre($pila) echo Ordenacioacuten arsort)ltbrgt arsort($pila) recorre($pila) echo Ordenacioacuten ksort()ltbrgt ksort($pila) recorre ($pila) echo Ordenacioacuten krsort()ltbrgt krsort ($pila) -recorre($pila) echo Ordenacioacuten sort()ltbrgt sort($pila) recorre($pila) echo Ordenacioacuten rsort()ltbrgt rsort($pila) recorre($pila) gt

La figura 75 muestra todos los tipos de ordenacioacuten que puede utilizar sobre un array

148 Capiacutetulo 7

Resumen

En este capiacutetulo ha conocido el tipo de variable estrella de PHP el array Controlar los meacutetodos y las funciones para extraer la informacioacuten le daraacute ventaja en los capiacutetulos posteriores Muchas funciones que tienen que ver con el manejo de datos como funciones de bases de datos XML o generashycioacuten de plantillas devuelven un array como respuesta El tipo array es el vehiacuteculo estaacutendar para la recuperacioacuten de datos estrucshyturados como veremos en los proacuteximos capiacutetulos

En este capiacutetulo aprenderaacute a

bull Crear formularios para pasar datos entre paacuteginas

bull Utilizar las variables suacuteper-globales para recibir la informacioacuten de un formulario

bull Diferenciar entre los meacutetodos de enviacuteo GET y POST

bull Encontrar posibles errores revisando las variables suacuteper-globales

150 Capiacutetulo 8

Introduccioacuten

Hasta ahora en los capiacutetulos anteriores hemos visto coacutemo construir dishyversos programas en PHP con un limitado radio de accioacuten La verdadera potencia del lenguaje reside en la aplicacioacuten de las teacutecnicas aprendidas a traveacutes de varias paacuteginas Web pasando informacioacuten de unas a otras Como veremos maacutes adelante las dos teacutecnicas principales son el uso de formulashyrios y la utilizacioacuten de la barra de direccioacuten para pasar los valores

Argumentos GET

Los argumentos GET pasan la informacioacuten como parte de la URL Cuando utilice esta forma de trabajar las parejas de variable valor podraacuten verse en la casilla de direccioacuten del navegador Para probar esto podemos escrishybir un pequentildeo script que guardaremos como paacutegina Web

lthtmlgt ltbodygt ltphp echo Variables pasadas mediante GETltbrgt foreach ($_GET as $indice =gt $valor)

echo $indice $valor

gt ltbodygt lthtmlgt

Si ejecuta el coacutedigo anterior veraacute que uacutenicamente se imprime en pantalla el texto que muestra la orden echo En realidad esto es correcto puesto que no hemos introducido ninguna variable tipo GET a la Web Para hashycerlo debemos escribir el nombre de la paacutegina Web seguido de un siacutembolo de interrogacioacuten () y el conjunto de parejas de variable valor separadas del siacutembolo (amp)

La direccioacuten queda algo asiacute f o r m u l a r i o php v a r i a b l e l = H o l a M u n d o amp v a r i a b l e 2 = 1234 Ahora el resultado es diferente El bucle f o shyr e a c h inspecciona el array $_GET e imprime en pantalla

Variables pasadas mediante GET variablel Hola Mundo variable2 1234

El array $_GET es considerado en PHP 5 una variable suacuteper-global Este en concreto almacena todas las variables pasadas entre paacuteginas mediante

Paso de informacioacuten entre formularios 151

el meacutetodo GET Para extraer el valor de una variable pasada por este meacuteshytodo soacutelo hay que escribir $_GET [ n o m b r e _ v a r i a b l e ] en la paacutegina que recibe los datos

Advertencia

En versiones anteriores de PHP para recuperar el valor de una variable simplemente habiacutea que escribir un siacutembolo $ delante del nombre como $ n o m b r e _ v a r i a b l e Esto es porque el paraacutemeshytro register_globals del fichero de configuracioacuten php i n i estaacute en PHP 5 a off

Formularios con GET

La forma maacutes utilizada para recabar informacioacuten acerca de los usuarios es emplear formularios HTML Los formularios pueden hacerse escribiendo en un editor de texto las etiquetas HTML o utilizando alguacuten editor Web profesional como Macromedia Dreamweaver Netscape Composer o Nvu La siguiente paacutegina Web llamada f o r m u l a r i o php muestra coacutemo reshycoger informacioacuten

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt

ltpgtIntroduzca sus datos personales ltpgt ltform name=formulario method=GET action=formulario2 php gt lttable width=50 border=0 cellspacing=0 cellpadding=0gt lttrgt lttd width=24gtNombrelttdgt lttd width=76xinput name=nombre type=text id=nombrextdgt

lttrgt lttrgt lttdgtApellidoslttdgt lttdxiacutenput name=apellidos type=text id=apellidos2gtlttdgt

lttrgt lttrgt lttdgtCorreolttdgt lttdxinput name=correo type=text id= correo xtdgt

lttrgt lttrgt lttdgtEstado civil lttdgt lttdxselect name= estado id= estado gt ltoption value=SolterogtSolteroltoptiongt ltoption value=CasadogtCasadoltoptiongt

152 Capiacutetulo 8

bullcoption value=DivorciadogtDivorciadoltoptiongt ltoption value=ViudogtViudoltoptiongt

ltselectgtlttdgt lttrgt lttrgt lttdgtNampuacutemero hijos lttdgt lttdgt 0 ltinput name=hijos type=radio value=0 checkedgt

1 ltinput name=hijos type=radio value=lgt 2 ltinput name=hijos type=radio value=2gt 3 ltinput name=hijos type=radio value=3gtlttdgt

lttrgt lttrgt lttdgtGustoslttdgt lttdgt Informampaacutetica ltinput type=checkbox name=gustos []

value=Informaacuteticagt Buceo ltinput type=checkbox name=gustos [] value=Buceogt Magia ltinput type=checkbox name=gustos [ ] value=Magiagt Jazz ltinput type=checkbox name=gustos [] value=Jazzgtlttdgt

lttrgt lttrgt lttdxinput type=submit name=Submit value=Enviargtlttdgt lttdgtampnbsplttdgt

lttrgt lttablegt

ltformgt ltpgtampnbsp ltpgt ltbodygt lthtmlgt

La figura 81 muestra el aspecto en el navegador Hay varios aspectos a tener en cuenta Lo primero es que el apartado a c t i o n de la etiqueta ltFORMgt contiene la paacutegina Web a la que se enviaraacuten los datos y el apartashydo method permite seleccionar el meacutetodo de enviacuteo por ahora utilizareshymos el meacutetodo GET La paacutegina f o r m u l a r i o 2 php recoge la informacioacuten del formulario y la imprime en pantalla utilizando un bucle f o r e a c h a la variable suacuteper-global $_GET

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidosltpgt ltphp foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

gt ltbodygt lthtmlgt

Para sacar los datos hemos utilizado un bucle que busca todos los valores dentro de $__GET Otra forma de hacerlo es imprimir los datos uno a uno

154 Capiacutetulo 8

si sabemos el nombre de las variables definidas en el formulario anterior de la siguiente forma $_GET [ n o m b r e ] $_GET [ a p e l l i d o s ] $_GET [ c o r r e o ]

Existen en el formulario visto varias teacutecnicas de recogida de informacioacuten Los cuadros de texto que permiten escribir valores alfanumeacutericos lista de seleccioacuten y botones de opcioacuten es donde podemos elegir una de las opciones existentes y casillas de verificacioacuten que permiten elegir 0 o maacutes opciones existentes Todas estas partes del formulario tienen una variable asociada que puede buscarse en $_GET

El uacutenico meacutetodo que puede plantear alguacuten problema es el que utiliza cashysillas de verificacioacuten Puesto que podemos elegir varias opciones eacutestas son enviadas como un array y deben recuperarse atendiendo a esta razoacuten

Advertencia

Para que los valores de las casillas de verificacioacuten sean enviados como array hay que declararlas en el formulario como tal escrishybiendo dos siacutembolos de corchetes en la propiedad ntildeame asociada a las casillas por ejemplo lt i n p u t t y p e = c h e c k b o x n a m e = g u s t o s [] v a l u e = I n f o r m aacute t i c a gt

La paacutegina f o r m u l a r i o 2 php queda de esta forma para que pueda recishybir los gustos de los usuarios

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidos ltpgt ltphp foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

echo ltbrgtGUSTOSltbrgt $gustos = $_GET[gustos] foreach ($gustos as $indice =gt $valor)

echo $indice $valorltbrgt gt ltbodygt lthtmlgt

La figura 83 muestra la mejora incluida en el programa Ahora es capaz de recuperar los gustos de los usuarios e imprimirlos en pantalla Para esto

Paso de informacioacuten entre formularios 155

hemos antildeadido un bucle nuevo que inspecciona los valores enviados al array $gustos

Paso de informacioacuten con GET

Si se fija en la barra de direccioacuten de los navegadores cuando visita paacutegishynas Web sobre noticias o carritos de la compra en la URL van aparecienshydo variables que tienen que ver con los distintos menuacutes que existen en la Web

El siguiente ejemplo muestra una pequentildea revista digital escrita en pocas liacuteneas y en una sola paacutegina Web que cambia sus noticias eligiendo las disshytintas opciones del menuacute

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitIacuteonalEN

httpwwww3orgTRhtml4loosedtdgt lthtmlgt ltbodygt ltphp $menu = array (1 =gt Editorial 2 =gt Opinioacuten 3 =gt Regional 4 =gt Nacional) echo (--Revista Digital --ltbrxbrgt) echo (--MENU--ltbrgt ) foreach ($menu as $indice =gt $valor)

echo (lta href = Iacutendexphpmenu=$indicegt$valorltaxbrgt)

156 Capiacutetulo 8

j

echo ( ltbrgt--NOTICIAS--ltbrgt) switch ($_GET[menuacute])

case 1 echo (Editorial) break

case 2 echo (Opinioacuten) break

case 3 echo (Regional) break

case 4 echo (Nacional) break

default echo (Noticias de Portada) break

gt ltbodygt lthtmlgt

El array $menu se carga de los distintos valores que podemos ir seleccioshynando

En la actualidad estos valores se suelen extraer de una base de datos

Para mostrar el menuacute se hace un bucle donde se extraen todos los valores e iacutendices del array y se ponen como valores en los enlaces

echo (lta href=Iacutendexphpmenu=$indicegt$valorltaxbrgt)

Los enlaces siempre se dirigen a la paacutegina principal pero con un valor distinto en la variable menuacute

La segunda parte de la Web es una eleccioacuten muacuteltiple mediante la estrucshytura s w i t c h donde en funcioacuten del valor de la variable menuacute pasada por GET se eligen unas noticias vi otras

Puede ver el resultado en la figura 84

echo (lta href=Iacutendexphpmenu=$indicegt$valorltaxbrgt)

Los enlaces siempre se dirigen a la paacutegina principal pero con un valor distinto en la variable menuacute

La segunda parte de la Web es una eleccioacuten muacuteltiple mediante la estrucshytura s w i t c h donde en funcioacuten del valor de la variable menuacute pasada por GET se eligen unas noticias u otras

Puede ver el resultado en la figura 84

Argumentos POST

La utilizacioacuten del meacutetodo GET es totalmente inseguro porque no hay forshyma de ocultar datos privados en la direccioacuten Web tales como la contraseshyntildea de entrada o el nuacutemero de cuenta bancaria

El meacutetodo POST arregla estos problemas siendo el preferido de los desa-rrolladores Este meacutetodo es tan sencillo como cambiar en el formulario el meacutetodo de enviacuteo de datos

ltpgtIntroduzca sus datos personalesltpgt ltform name=formulario method=POST action=formulario2 php gt

lttable width=50 border=0 cellspacing=0 cellpadding=0gt

En cuanto a la recuperacioacuten de los datos tambieacuten debe cambiar el nombre de la variable suacuteper-global $_GET por $_POST de esta manera

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidosltpgt ltphp foreach ($_POST as $indice =gt $valor)

echo $indice $valorltbrgt

e c h o ltbrgtGUSTOSltbrgt $ g u s t o s = $ _ P O S T [ g u s t o s ]

158 Capiacutetulo 8

foreach ($gustos as $indice =gt $valor) echo $indice $valorltbrgt

gt ltbodygt lthtmlgt

Variables suacuteper-globales

Desde PHP 4 se vienen utilizando los arrays suacuteper-globales para almaceshynar los valores que pasan de unas paacuteginas a otras se almacenan en el orshydenador del usuario o en el servidor En PHP 5 el uso de estas variables se hace obligatorio para recuperar todos los valores Las variables a utilizar son

bull $_GET Almacena las variables que se pasan desde un formulario meshydiante el meacutetodo GET

bull $_POST Almacena las variables pasadas por POST

bull $_COOKIE Guarda los valores que estaacuten almacenados en cookies Ya veremos en capiacutetulos sucesivos coacutemo utilizarlo

bull $_SESSlON bull Guarda las variables que se pasan entre sesiones

bull $_SERVER Contiene numerosos valores relativos al servidor

bull $_FILES Los archivos que enviemos a traveacutes de un formulario seshyraacuten recogidos en este array

Una equivocacioacuten en el nombre de una variable puede llevarle a dar vuelshytas sobre el coacutedigo hasta encontrar el error Por eso es necesario conocer el contenido de las variables suacuteper-globales asiacute podraacute averiguar si estaacute pasando los datos correctamente La funcioacuten siguiente se puede utilizar cada vez que le surja un error de este tipo La funcioacuten muestra todos los valores de los arrays suacuteper-globales

ltphp function depuracioacuten() echo --Variables GET--ltbrgt foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

echo --Variables POST--ltbrgt foreach ($_POST as $indice =gt $valor)

echo $indice $valorltbrgt

echo --Variables COOKIES--ltbrgt

Paso de informacioacuten entre formularios 159

foreach ($_COOKIE as $indice =gt $valor) echo $iacutendiacutece $valorltbrgt

echo --Variables SESSION--ltbrgt foreach ($_SESSION as $indice =gt $valor)

echo $iacutendiacutece $valorltbrgt

echo --Variables SERVER-~ltbrgt foreach ($_SERVER as $indice =gt $valor)

echo $indice $valorltbrgt

depuracioacuten () gt

La figura 85 muestra los valores de todas las variables suacuteper-globales

Resumen

Hasta ahora soacutelo habiacuteamos tenido la oportunidad de crear programas en PHP que realizaran tareas en una uacutenica paacutegina Web

Este capiacutetulo ha dado una visioacuten praacutectica de coacutemo utilizar los conceptos aprendidos para escribir programas distribuidos en varias paacuteginas

160 Capiacutetulo 8

Aunque no ha aprendido ninguna funcioacuten nueva ha descubierto el vershydadero secreto del disentildeo de una Web dinaacutemica el paso de variables

Si viene de otras versiones de PHP tendraacute que tener en cuenta que la forshyma de recuperar las variables es a partir de la versioacuten 43 a traveacutes de las variables suacuteper-globales

En este capiacutetulo aprenderaacute a

bull Diferenciar entre clase y objeto bull Crear clases que hereden de otras clases bull Utilizar los modificadores pr iacutevate protected ypubl ic

bull Crear meacutetodos estaacuteticos y finales bull Guardar el estado de un objeto mediante la sentildealizacioacuten bull Recuperar informacioacuten referente a las clases meacutetodos y propiedades

162 Capiacutetulo 9

Introduccioacuten

PHP comenzoacute su andadura como un simple lenguaje de scripts A medishyda que las versiones avanzaban se fueron incluyendo algunas caracteshyriacutesticas que permitiacutean programar con orientacioacuten a objetos Con la aparicioacuten de PHP 5 los desabolladores tenemos una verdadera platashyforma de programacioacuten orientada a objetos gracias a la potencia del nuevo engine Zend 20 que permite ejecutar maacutes raacutepido y eficientemenshyte este tipo de programas

La programacioacuten orientada a objetos utiliza los elementos c l a s e y o b shyj e t o con punto de inicio Actualmente en las carreras teacutecnicas es posishyble encontrar ensentildeanzas sobre lenguajes orientados a objetos como Java o C++

Nota

En realidad Java y C++ son considerados como seudo lenguajes orientados a objetos Un ejemplo de lenguaje puro es SmallTalk o su versioacuten graacutefica Squeak (httpsqueaklinexorg) con muchos antildeos de antiguumledad

La programacioacuten orientada a objetos en PHP 5 no necesita una sintaxis muy diferente sino que es una aproximacioacuten a la realidad en otro camino diferente al acostumbrado Por ejemplo si piensa en un programa que tenga que averiguar la letra del DNI de un cliente lo normal es que cree una funcioacuten con un paraacutemetro al que le pase el nuacutemero de DNI y le deshyvuelva la letra buscada

Un desarrollo orientado a objetos pensariacutea en cada problema como una idenshytidad uacutenica como un objeto Puesto que el DNI siempre va asociado a una persona puede crear un objeto que identifique a personas y dentro de ese objeto programar una funcioacuten (meacutetodo en este caso) que calcule la letra La aproximacioacuten procedural (crear una funcioacuten) no asocia esa funcioacuten a persoshynas directamente y le podriacutea pasar cualquier nuacutemero entero recibiendo una respuesta vaacutelida En cambio la aproximacioacuten de objetos crea la funcioacuten dentro del objeto c l i e n t e y soacutelo permite mediante teacutecnicas que veremos maacutes adelante recuperar la letra del DNI de una persona

La programacioacuten orientada a objetos desarrolla nuevos conceptos y termishynologiacuteas que deben aprenderse correctamente para generar buen coacutedigo

Programacioacuten orientada a objetos 163

Definicioacuten de clases

Una clase es un tipo de dato que contiene en una misma estructura vashyriables y funciones Una clase es una especie de plantilla desde la que los objetos son instanciados y toman su valor Desde una clase se pueden consshytruir varios objetos del mismo tipo La definicioacuten es la siguiente

class pagina_Web

var $titulo function getTitulo()

return $this-gttitulo

Mediante la palabra reservada c l a s s definimos una clase completa Utishylizando va r podemos definir las variables que utilizaremos en el desarroshyllo del programa La palabra reservada va r desapareceraacute en versiones siguientes de PHP a favor de las palabras publ ic p r iacute v a t e y p r o t e c -ted Las funciones se definen como en el capiacutetulo 5 siempre que esteacuten dentro de la construccioacuten de la clase En este capiacutetulo vamos a definir una clase completa cuya misioacuten seraacute mostrar una paacutegina Web Podemos seshyguir con el ejemplo ampliando las funciones

ltphp class pagina_Web

var $titulo function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

function getTitulo() return $this-gttitulo

function cabecera() echo (lthtmlxheadxtitlegt) echo $this-gttitulo echo ( lttitlexheadxbodygt) bull

function cuerpo() echo(Este es el cuerpo de la paacutegina Web)

164 Capiacutetulo 9

function pie ( )

echo (ltbodyxhtmlgt)

function mostrar_pagina()

echo $thiacutes-gtcabecera () echo $this-gtcuerpo()

echo $this-gtpie()

Como puede ver la clase se divide en varias funciones y en una sola vashyriable La variable $ ti t u l o guardaraacute el tiacutetulo deacute la paacutegina Web Las funshyciones c a b e c e r a ( ) c u e r p o () y p i e () son las encargadas de mostrar las distintas partes de una Web

Estas funciones se llaman desde la f u n c i oacute n m o s t r a r _ p a g i n a ( ) Es inteshyresante observar que en unas pocas liacuteneas de coacutedigo hemos definido un objeto que podriacutea utilizarse como base de muchas aplicaciones El operador $ t h i s es una variable que contiene el objeto actual desde el que la invocamos Para acceder dentro de un objeto a funciones o variashybles propias debe anteponerse al nombre de eacutestas la expresioacuten $ t h i s - gt Para acceder desde la funcioacuten m o s t r a r _ p a g i n a () a cualquiera de las funciones de la clase tendraacute que escribir

$this-gtcabecera () $this-gtcuerpo ( ) $this-gtpie ()

Instancia de clase

Para que el coacutedigo funcione necesita crear el objeto Esto se hace utilizanshydo el operador new seguido del nombre de la clase

$ p a g i n a = new p a g i n a _ W e b ( )

Con el coacutedigo anterior hemos creado un objeto que contiene todas las vashyriables y funciones de la clase pag ina_Web ( ) La variable que contiene ese objeto es $pag ina

Para acceder a las funciones desde el nuevo objeto creado tenemos que utilizar la variable que contiene al objeto en este caso $ p a g i n a seguido del operador - gt y el nombre de la funcioacuten Para mostrar la Web tenemos que seguir estos sencillos pasos

$ p a g i n a = new p a g i n a _ W e b ( )

Programacioacuten orientada a objetos 165

$pagina-gtsetTitulo(Paacutegina Web nueva) $pagina- gtmostrar__pagina ( )

Funcioacuten constructor

Existen algunas funciones especiales en la definicioacuten de una clase La maacutes importante es el constructor Esta se ejecuta cada vez que se crea un nueshyvo objeto y permite crear las variables iniciales que se necesitan como el tiacutetulo de la Web o el autor El nombre de la funcioacuten debe ser c o n s -t r u c t () Nuestro constructor se encargaraacute de crear el tiacutetulo de la paacutegina Web que estamos creando

funct ion c o n s t r u c t ( $ t i t u l o )

$this-gtsetTitulo($titulo)

Herencia

La programacioacuten orientada a objetos permite heredar de otras clases Con esta teacutecnica puede ahorrar mucho tiempo de trabajo La clase hija (clase que hereda de otra) adquiere estas propiedades

bull Automaacuteticamente obtiene todas las variables miembro de la clase padre

bull Tambieacuten obtiene todas las funciones miembro de la clase padre que funcionaraacuten exactamente de la misma forma

bull La clase hija puede a su vez definir nuevas variables y funciones

La sintaxis es la siguiente

class pagina_Web_formulario extends pagina_Web

function formulario_inicio() Escribir el coacutedigo necesario

La palabra reservada e x t e n d s indica que la nueva clase creada seraacute una extensioacuten (heredaraacute) de la clase que se escribe justo a la derecha de la deshyfinicioacuten Puede crear un objeto formulario a partir de la clase pagina_Web de la siguiente forma

class pagina_Web_formulario extends pagina_Web

166 Capiacutetulo 9

function formulariacuteo_inicio($accion)

echo (ltform action=$acciongt)

function formulario_fin() echo (ltformgt)

function formulario_caj a_texto($nombre) echo ($nombre ltinput type=text name=$nombregt)

function formulario_boton() echo (ltinput type=submit name=Submit

valuacutee = Enviargt )

function mostrar_pagina () $this-gtcabecera () $this- gtf ormulario__inicio ( Iacutendex php) $this- gtf ormulario__caj a_texto (Nombre) $this-gtformulario_boton() $this-gtformulario_fin()

$this- gtpie ()

Si ahora ejecuta el coacutedigo instanciando la clase que hemos creado puede ver que las funciones c a b e c e r a () p i e ( ) incluso el constructor pueshyden ser utilizadas auacuten no perteneciendo a la clase p a g i n a _ W e b _ f o r -m u l a r i o

$formulario = new pagina_Web_formularioPagina con f o r m u l a r i o ) $formular io-gtmostrar_pagina ( )

La figura 91 muestra la ejecucioacuten del objeto anterior

Meacutetodos o funciones de objeto

Cuando definimos una clase hija las funciones de la clase padre son autoshymaacuteticamente heredadas Se llama redefinicioacuten de meacutetodos a la creacioacuten de funciones en la clase hija con el mismo nombre que en la clase padre En el ejemplo anterior la funcioacuten m o s t r a r _ p a g i n a ( ) de la clase pag ina_Web_f o r m u l a r i o estaacute redefinida ya que existe una funcioacuten con

Programacioacuten orientada a objetos 167

el mismo nombre en la clase pag ina_Web Al instanciar el objeto y ejecushytar el meacutetodo m o s t r a r _ p a g i n a ( ) el meacutetodo que se ha definido es la clase hija

PHP 5 con su nuevo motor Zend Engine 2 introduce la palabra reservashyda f i n a l

Si en la clase padre ponemos delante de cualquier funcioacuten la palabra f i n a l eacutesta funcioacuten no podraacute ser sobrecargada en las clases que la heshyreden

Tambieacuten podemos declarar clases completas como f i n a l lo que signifishycaraacute que no podraacuten ser heredadas

final function mostrar_pagina()

echo $this-gtcabecera() echo $this-gtcuerpo()

echo $this-gtpie()

Si definimos la funcioacuten anterior como f i n a l en la clase pag ina_Web la clase p a g i n a _ W e b _ f o r m u l a r i o no podraacute tener una funcioacuten con este mismo nombre y mostraraacute un error en pantalla La figura 92 muestra el error que se produce al intentar sobrecargar un meacutetodo que estaacute marcado como f i n a l

Herencia encadenada

Algunos lenguajes de programacioacuten permiten heredar de varias clases a la vez esto es conocido como herencia muacuteltiple PHP 5 no permite herenshycia muacuteltiple pero siacute herencia encadenada es decir permite heredar de varias clases padres correlativamente Un ejemplo es

class A

class B extends A

class C extends B

class D extends C

Valores y alcance de variables

En versiones anteriores de PHP los objetos eran pasados por valor a otras funciones por lo tanto el estado de los objetos no se conservaba En PHP 5 los objetos son pasados por defecto por referencia gracias al Zend Engine 2

ltphp

Programacioacuten orientada a objetos 169

class Nombre

i var $nombre function setNombre($nombre)

$this-gtnombre = $nombre

function getNombre() return $this-gtnombre

function cambiaNombre($obj eto$nombre)

$objeto-gtsetNombre($nombre)

$luis = new Nombre $luis-gtsetNombre(Luis Miguel) echo El nombre del objeto es $luis-gtgetNombre() ltbrgt cambiaNombre($luisPedro) eche El nombre del objeto es $luis-gtgetNombre() ltbrgt gt

El coacutedigo muestra coacutemo cambiar las propiedades de un objeto desde una funcioacuten con PHP 5 El resultado en el navegador puede comprobarlo en la figura 93

170 Capiacutetulo 9

Dentro de los objetos debe tener tambieacuten cuidado con el alcance de las variables Las variables definidas fuera del entorno del objeto no son acshycesibles desde los meacutetodos de las clases a menos que anteponga la palashybra g l o b a l

Miembros puacuteblicos privados y protegidos

Mientras no se especifique otra cosa los meacutetodos y propiedades de una clase son siempre puacuteblicos es decir son accesibles desde fuera del objeto de la forma o b j e t o - gtf u n c i oacute n Pero existe un camino para que las vashyriables y los meacutetodos no puedan ser accedidos desde fuera del objeto Eche un vistazo ahora al objetopagina_Web Su variable $ t i t u l o es puacuteblico porque no lo hemos definido de alguna forma especial Para cambiar el valor de esta variable podriacutea utilizar la funcioacuten asociada o directamente haciendo $ o b j e t o - gt t i t u l o = nuevo v a l o r Esta forma de actuar rompe con la filosofiacutea de la programacioacuten orientada a objetos Como norshyma general las propiedades de los objetos deben estar ocultas al entorno exterior y tomar sus valores desde funciones definidas dentro del objeto

Meacutetodos privados

Si declaramos un meacutetodo o propiedad como privada soacutelo se podraacute acceshyder a eacutel desde la clase que lo define Las clases que hereden de una clase con meacutetodos privados no tendraacuten acceso a eacutestos meacutetodos y tampoco seraacute posible desde fuera del objeto hacer llamadas Para hacer un meacutetodo o propiedad privado soacutelo hay que anteponer la palabra p r iacute v a t e delante de la declaracioacuten

class pagina_Web

priacutevate $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

priacutevate function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

De esta manera la clase p a g i n a _ W e b _ f o r m u l a r i o que hereda de pagina_Web no puede acceder directamente a la funcioacuten s e t T i t u l o ()

Programacioacuten orientada a objetos 171

de la siguiente forma $ t h i s - gt s e t T i t u l o ( T i t u l o n u e v o ) porque obtenemos un error de acceso ilegal Despueacutes de esta modificacioacuten soacutelo es posible dar un tiacutetulo a la paacutegina Web a traveacutes del constructor que como siacute estaacute dentro de la clase tiene potestad para utilizarla

Meacutetodos protegidos

Los meacutetodos protegidos son menos restrictivos que los privados Cuando declaramos un meacutetodo como protegido su visibilidad es en la clase que lo declara y en todas las clases que lo heredan El ejemplo anterior puede modificarse de la siguiente forma

c l a s s pagina_Web

protected $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

protected function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

Meacutetodos puacuteblicos Por defecto todos los meacutetodos y propiedades que se declaren en un objeshyto son puacuteblicos a menos que lleven asociados la palabra p r o t e c t e d o p r iacute v a t e Como buena praacutectica de programacioacuten las variables deben deshyfinirse como privadas o protegidas para que no puedan modificarse desshyde fuera del objeto Ademaacutes deben llevar dos meacutetodos puacuteblicos asociados s e t V a r i a b l e () para dar un nuevo valor a la variable y g e t V a r i a b l e () para recibir el valor actual de la propiedad Veamos el ejemplo

class pagina_Web

private $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

public function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

172 Capiacutetulo 9

public function getTitulo()

return $this-gttitulo

Interfaces

En proyectos profesionales a veces es necesario que un equipo de varias personas trabajen juntas En este caso se hace imprescindible definir unas pautas generales de trabajo para que el resultado final sea el esperado Si el desarrollo consiste en programar varios objetos el analista de la aplicashycioacuten puede definir la estructura baacutesica en papel o crear una pequentildea planshytilla con meacutetodos que el objeto final deberiacutea tener obligatoriamente Esta plantilla es un i n t e r f a c e y permite definir una clase con funciones deshyfinidas pero sin desarrollar que obliga a todas las clases que lo imple-menten a declarar estos meacutetodos como miacutenimo

i n t e r f a c e Web

public function setTitulo($titulo = Titulo por defecto)

public function getTitulo()

La interface anterior define la estructura baacutesica que queremos para el obshyjeto declarando las funciones setTitulo y getTitulo Para que una clase haga uso de la i n t e r f a c e se declara de la siguiente forma

class pagina_Web implements Web

Clases abstractas

Un i n t e r f a c e no permite crear el cuerpo de ninguna funcioacuten dejando esta tarea a las clases que la implementen Las clases abstractas permiten definir funciones que deben implementarse obligatoriamente en los objetos que hereden y ademaacutes permiten definir funciones completas que pueden heredarse Las clases abstractas deben llevar la palabra rese rvadaabs t rac t en la declaracioacuten de la clase y en todos los meacutetodos que soacutelo definan su nombre

abstract class Web

protected $titulo

Programacioacuten orientada a objetos 173

public function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

a b s t r a c t pub l i c funct ion g e t T i t u l o ( )

En lugar de un i n t e r f a c e hemos optado por utilizar una clase abstracshyta porque tenemos claro que el meacutetodo s e t T i t u l o () tiene que funcioshynar asiacute Tambieacuten se define el meacutetodo abstracto g e t T i t u l o () que obligatoriamente debe ser declarado en la clase que herede de eacutesta En realidad un i n t e r f a c e es una clase que tiene todos sus meacutetodos absshytractos

Clases con meacutetodos estaacuteticos

En PHP 5 puede declarar funciones dentro de una clase que no utilicen propiedades o meacutetodos de la misma Estos meacutetodos pueden calcular valoshyres numeacutericos hacer una conexioacuten a una base de datos o comprobar que un correo electroacutenico esteacute bien definido Aunque no existe ninguna palashybra reservada para definirlo son conocidos como meacutetodos estaacuteticos y pueshyden ser utilizados sin necesidad de instanciar un objeto

ltphp class Nombre

protected $nombre public function getNombre(

return $this-gtnombre

public function setNombre($nombre)

$this-gtnombre = $nombre

public function NombreDefecto()

return Luis Miguelltbrgt

$luis = new Nombre echo $luis-gtNombreDefecto() Tambieacuten se puede acceder al nombre por defecto echo NombreNombreDefecto() gt

174 Capiacutetulo 9

Para acceder a un meacutetodo estaacutetico desde el cuerpo del programa se escrishybe el nombre de la clase que lo implementa seguido del operador ( ) y el nombre del meacutetodo En el ejemplo vemos que se puede acceder al meacutetoshydo NombreDef e c t o () creando un objeto o mediante la construccioacuten Nombre NombreDef e c t o Si intenta llamar a un meacutetodo que no es estaacutetico de esta forma se imprimiraacute un error en pantalla La figura 94 muestra el error que recibe si intenta llamar a un meacutetodo no estaacutetico desshyde fuera de un objeto

Llamadas a funciones padre

El operador ( ) se puede utilizar tambieacuten dentro de una clase para hacer llamadas a funciones de la clase padre que esteacuten sobrecargadas Si define un constructor para la clase padre y otro para la clase hijo cuando cree el objeto el constructor que se ejecuta es el de nivel infeshyrior el constructor hijo Para llamar al constructor padre debe utilizarshyse la nomenclatura N o m b r e _ c l a s e _ p a d r e c o n s t r u c t ()

ltphp class Nombre

protected $nombre

Programacioacuten orientada a objetos 175

f unet ion construct ( $nombre)

$this-gtnombre = $nombre

publie function getNombre() return $this-gtnombre

publie function setNombre($nombre) $this-gtnombre = $nombre

publie function NombreDefecto() return Luis Miguelltbrgt

class Apellido extends Nombre

protected $apellidos function construct($nombre$apellidos)

$this-gtapellidos = $apellidos Nombre construct(Snombre)

publie function getApellidos () return $this-gtapellidos

$luis = new Apellido(Luis MiguelCabezas Granado) echo $luis-gtgetNombre() ltbrgt echo $luis-gtgetApellidos() gt

Puede ver que el constructor de la clase Ape l l ido inicializa la variable $ape-11 idos y seguidamente llama al constructor de la clase padre Nombre Esta forma de actuar puede resultar complicada si no conoce el nombre de la clase padre La solucioacuten a este pequentildeo inconveniente la tenemos en la palabra parent que hace alusioacuten a la clase de la que heredamos El coacutedigo anterior puede quedar de esta forma

class Apellido extends Nombre

protected $apellidos function construct($nombre$apellidos)

$this-gtapellidos = $apellidos

176 Capiacutetulo 9

p a r e n t cons t ruc t ($nombre) public function getApellidos()

return $this-gtapellidos

Sobrecarga de meacutetodos

Algunos lenguajes de programacioacuten orientados a objetos permiten declashyrar maacutes de un meacutetodo con el mismo nombre La definicioacuten de estos meacutetoshydos variacutea en el nuacutemero de paraacutemetros o en los tipos de datos de los argumentos PHP 5 no permite sobrecarga de meacutetodos pero puede simushylar esta actuacioacuten empleando la teacutecnica de las funciones con un nuacutemero variable de paraacutemetros El constructor de la clase A p e l l i d o puede queshydar de la siguiente forma

class Apellido extends Nombre

protected $apellidos function construct($nombre)

if (func_num_args()= = 2 ) $apellidos = func_get_arg(1) $this-gtnombre = $nombre $this-gtapellidos = $apellidos parent construct($nombre)

else $this-gtnombre = $nombre $this-gtapellidos = $apellidos parent construct($nombre)

public function getApellidos()

return $this-gtapellidos

Sentildealizacioacuten

Los objetos son en realidad un conjunto de datos y funciones que guarshydan una serie de estados de ejecucioacuten Este conjunto de bits se pueden al-

Programacioacuten orientada a objetos 177

macenar en un momento dado y recuperar justo en el mismo estado en el que se encontraba cuando lo guardamos Esta teacutecnica se llama sentildealizashycioacuten y permite almacenar y recuperar el conjunto de bits que forman un objeto

PHP 5 ofrece dos funciones s e r i a l i ze () y u n s e r i a l i z e ( ) que toshyman como paraacutemetro un objeto y devuelven una cadena de caracteres Los objetos serializados los podemos almacenar en base de datos ficheros etshyceacutetera

$luis = new Apellido(Luis Miguel) echo $luis-gtgetNombre() ltbrgt echo $luis- gtgetApellidos () -$manuel = serialize($luis) $pedro = unserialize($manuel) echo $pedro-gtgetNombre ()

El coacutedigo anterior crea el objeto $ l u i s y utiliza los meacutetodos propios de la clase y los heredados Despueacutes utilizamos la funcioacuten s e r i a l i z e () para grabar el estado del objeto como un conjunto de caracteres en la variable $manuel La variable $pedro contiene el resultado de aplicar u n s e r i a shyl i z e () a $manuel

De esta forma conseguimos recuperar el objeto $ l u i s con los datos que ya habiacuteamos almacenado

Funciones de manejo de clases

Las funciones siguientes son uacutetiles para recuperar informacioacuten sobre la herencia de las clases sobre meacutetodos o variables miembro o llamadas a las funciones

Tabla 91 Funciones de clases

Funcioacuten Descricioacuten

ge t c l a s s () Devuelve el nombre de la clase que iexclmplementa el objeto pasado como paraacutemetro

g e t _ p a r e n t _ c l a s s 0 Devuelve el nombre de la clase padre

c l a s s _ e x iacute s t ( ) Si el paraacutemetro es el nombre de una clase devuelve un true

g e t _ d e c l a r e d _ c l a s s () Devuelve un array con el nombre de todas las clases definidas en el coacutedigo actual

178 Capiacutetulo 9

Funcioacuten Descricioacuten

i s _ s u b c l a s s _ o f () Toma dos paraacutemetros Si el primer paraacutemetro es una subclase del segundo paraacutemetro la funcioacuten devuelve un true

i s _ a ( ) g e t _ c l a s s _ v a r s ( ) Devuelve un array con parejas variable valor de una clase que tengan valores por

defecto

g e t _ o b j e c t _ v a r s () Devuelve un array con parejas variable valor de un objeto que tengan valores por defecto

method_ex is ts () Toma dos paraacutemetros Si el objeto pasado tiene un meacutetodo con el nombre del segundo paraacutemetro la funcioacuten devuelve true

ge t_c lass_method () Devuelve un array de meacutetodos definidos en una clase

Puede ver el funcionamiento de la funcioacuten g e t _ c l a s s () en el ejemplo siguiente y el resultado en la figura 95

$luis = new Nombre echo $luis-gtNombreDefecto() echo La variable $luis es un objeto del tipo get_class($luis)

Programacioacuten orientada a objetos 179

Resumen

Existe en el mundo de los desabolladores de PHP una antigua disputa sobre la mejor forma de afrontar un proyecto Web Unos opinan que la forma maacutes raacutepida de crear una Web es realizar funciones separadas en ficheros y desde las paacuteginas del proyecto hacer las llamadas necesarias

La otra vertiente opina que merece la pena dedicar un poco maacutes de tiemshypo al desarrollo de objetos porque despueacutes redundaraacute en un gran benefishycio en futuros programas En realidad depende del proyecto Si soacutelo necesita crear un formulario para recibir datos de un usuario quizaacute no merezca la pena crear un objeto y siacute algunas funciones de control Si su proyecto va a ser muy extenso la recomendacioacuten es que prepare un comshypendio de objetos que se interrelacionen para llevar a buen teacutermino el programa

Puesto que el libro versa sobre PHP 5 y sus mejoras con respecto a las vershysiones anteriores intentaremos en los capiacutetulos siguientes realizar la mashyyoriacutea de los ejemplos en metodologiacutea orientada a objetos

En este capiacutetulo aprenderaacute a

bull Abrir y cerrar ficheros de lectura y escritura

bull Utilizar funciones para leer el contenido de un fichero

bull Realizar programas para la escritura de informacioacuten en un fichero

bull Gestionar los ficheros y directorios de un sistema operativo

bull Crear ficheros de configuracioacuten

bull Generar cabeceras para la descarga de archivos

182 Capiacutetulo 10

Introduccioacuten

Antes de que la proliferacioacuten de los gestores de bases de datos se hiciera efectiva los lenguajes de programacioacuten utilizaban el acceso a ficheros para almacenar sus datos Asiacute los lenguajes COBOL Pascal o incluso C comenshyzaron a utilizar el manejo de archivos en aquellos programas que necesishytaban guardar datos para recuperarlos posteriormente

Actualmente la informacioacuten puede almacenarse en ficheros o en bases de datos Los ficheros pueden almacenar textos que pueden ser leiacutedos faacutecilshymente por nosotros y por un ordenador Ademaacutes existe una serie de utishyl idades que permiten al sistema operat ivo (gnuLinux o MacOSX) interactuar con ellos hacer buacutesquedas etceacutetera

Nota

El sistema operativo Windows tiene algunas restricciones con resshypecto al manejo de ficheros y no se recomienda para gestionar los archivos

Funciones de lectura y escritura de ficheros

Existen en PHP 5 un conjunto muy numeroso de funciones que permishyten manejar ficheros de diferentes formas La idea baacutesica para trabajar con ficheros es la siguiente

bull Abrir el fichero para su lectura escritura

bull Leer el fichero

bull Cerrar el fichero (puede hacerse maacutes tarde)

bull Realizar las operaciones necesarias en el contenido

bull Escribir los datos

Abrir el fichero

La funcioacuten f open () asigna a una variable un puntero (un descriptor) al fichero que quiera abrir La variable puede utilizarse despueacutes para hacer cualquier tipo de operacioacuten Si el fichero que intenta abrir no existe o no puede utilizarse en ese momento f open () devolveraacute un valor false

Ficheros y almacenamiento de datos 183

Los ficheros pueden abrirse en varios modos tal y como indica la tabla 101

Tabla 101 Modos de apertura de los ficheros

Modo Explicacioacuten

Soacutelo lectura (r) Soacutelo permite leer el fichero Si intenta hacer otra cosa le saldraacute un error

Lectura y escritura si existe el Permite leer y escribir un fichero que exis-fichero (r+) ta El contenido del fichero no se borra

sino que se escribe a continuacioacuten Soacutelo escritura (w) Soacutelo se puede escribir Sobrescribe cualshy

quier fichero afectado Escritura y lectura (w+) Si el fichero no existe intenta crearlo Escritura al final (a) Escribe siempre al final del fichero tanto si

existe como si no Lectura y escritura al final (a+) Escribe al final del fichero y permite leer

Desde la versioacuten 4 de PHP puede abrir ficheros remotos que esteacuten almashycenados en servidores Asiacute podraacute utilizar el protocolo HTTP o FTP para recuperar datos remotamente Puede ver como ejemplo varias formas de abrir un fichero con f open ()

ltphp Los ficheros HTTP solo pueden abrirse de lectura $descriptor = fopen(httpwwwluisyfernandanet noticiastxtr) FTP permite abrir ficheros de lectura y escritura $descriptor2 = fopen(ftp usuariocontrasentildealuisyfernandanetnoticiastxtr) Apertura normal de un fichero guardado en el ordenador local $descriptor3 = fopen(noticiastxt a+) gt

Lectura de ficheros

f r e a d () tiene como paraacutemetro un descriptor de fichero devuelto por la funcioacuten f o p e n () y el tamantildeo del bloque de datos que queremos leer

$variable = fread($descriptor 4000)

Normalmente no conoceraacute el tamantildeo del fichero y por lo tanto debe utishylizar alguna teacutecnica para leerlo correctamente Lo maacutes sencillo es apoyar-

184 Capiacutetulo 10

se en la funcioacuten f i l e s i z e () que devuelve el tamantildeo en bytes del fichero que pase como argumento Asiacute la lectura anterior quedariacutea

$variable = fread($descriptor filesize(noticiastxt))

Advertencia

Tiene que notar que el lector f i l e s i z e () no toma como paraacuteshymetro el descriptor devuelto por la funcioacuten f o p e n O sino el nombre del fichero que estamos tratando

La funcioacuten anterior devuelve un bloque completo de caracteres leiacutedos desde un fichero y puede hacerse poco manejable cuando intente buscar alguacuten dato especiacutefico PHP 5 posee algunas funciones para leer liacutenea a liacuteshynea desde un fichero f r e a d () tiene como paraacutemetros el descriptor del fichero y un bloque maacuteximo de caracteres a leer La utilizacioacuten praacutectica es la siguiente

ltphp $descriptor = fopen (librotxta +) $linea_numero = 1 while (feof($descriptor))

$linea = fgets ($descriptor4096) echo liacutenea nuacutemero $numero_linea es $linea $linea_numero++

f c l o s e ($desc r ip to r ) gt

El bucle actuacutea hasta que la funcioacuten f e o f () encuentra el final del fichero apuntado por el descriptor Mientras que no sea el fin del fichero la funshycioacuten f g e t s () iraacute leyendo liacutenea a liacutenea todo el contenido e imprimieacutendoshylo en pantalla

La forma ideal de trabajar con ficheros es ir leyendo poco a poco su conshytenido para poder buscar datos que nos interesen en cada liacutenea o conshyjunto de caracteres Existe una funcioacuten que nos permite almacenar todo el contenido de un fichero en un array para su posterior proceso con las funciones propias de las colecciones de datos La funcioacuten e x p l o d e () toma como paraacutemetros un caraacutecter por donde cortar la cadena y el nomshybre de la variable que contiene los datos Podemos ver su funcionamienshyto en el ejemplo

ltphp $descriptor = fopen (librotxta+) $linea__numero = 1

Ficheros y almacenamiento de datos 185

$archivo = while ( feof($descriptor) )

$linea = fgets($descriptor4096) $archivo = $archivo liacutenea nuacutemero $numero__linea es

$linea $1inea_numero++

fclose($descriptor) $lista = explode( $archivo) gt

En este caso e x p l o d e () busca en la variable $ a r c h i v o todos los espashycios en blanco y va almacenando en el array caracteres que esteacuten entre dos ocurrencias (entre dos espacios) Asiacute obtenemos una gran lista de palashybras almacenadas por separado que hacen muy faacutecil buscar ordenar o borrar cualquier contenido

Por uacuteltimo la funcioacuten f ge te () permite leer un fichero caraacutecter a caraacutecshyter Esto es muy uacutetil cuando construimos un parse (un programa que inshyterpreta el contenido de un fichero) y debemos ir evaluando las palabras letra por letra para actuar en consecuencia

Escritura de ficheros

Las funciones para escribir ficheros son tan sencillas de utilizar como las de lectura La funcioacuten principal f w r i t e () escribe en un fichero apuntashydo por un descriptor una cadena de caracteres Es imprescindible que el fichero esteacute abierto en uno de los modos de escritura para que no deacute error

Veamos ahora un ejemplo completo El coacutedigo siguiente es un pequentildeo libro de visitas donde todo aquel que navegue por nuestra Web puede dejar mensajes de agradecimiento y aacutenimo Aunque no es el mejor libro de visitas escrito nunca siacute es un buen ejemplo de coacutemo utilizar la lectura v escritura de archivos dentro de un entorno orientado a objetos

ltphp class libro_visitas

priacutevate $tamano priacutevate $nombre priacutevate $descriptor priacutevate $contenido function construct($nombre)

$this-gtnombre = $nombre

i

186 Capiacutetulo 10

public function leer_libro)

$this-gtdescriptor = fopen ($this-gtnombrea+) $this-gttamano=filesize($this-gtnombre) if ($this-gttamano gt 0)

$this-gtcontenido = fread($this-gtdescriptor $this-gttamano)

fclose ($this-gtdescriptor) return $this-gtcontenido

pub l i c funct ion esc r ib i r__ l ib ro ($riombre $texto)

$ t h i s - gt d e s c r i p t o r = fopen ($this-gtnombrea+) $nombre = lt t r x t d bgcolor=CCCCCCgt$nombrelttdgtlttrgt $texto = lt t r x t d bgcolor=FFFFFFgt$textolt tdx t rgt f w r i t e ( $ t h i s - gt d e s c r i p t o r $ n o m b r e ) f w r i t e ( $ t h i s - gt d e s c r i p t o r $ t e x t o ) f c l o s e ($ th i s -gtdesc r ip to r )

gt ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtralgt ltheadgt lttitlegtLibro de visitaslttitlegt ltmeta http-eguiv=Content-Type content=texthtml charset=iso-8859-lgt ltheadgt ltbodygt ltp align=centerxstronggtLibro de visitas ltstrongxpgt lttable width=100 border=0 cellspacing=0 cellpadding=0gt

ltphp if (isset ($_POST[nombre ] ) |] isset($_POST[texto]))

$libro = new libro_visitas(librotxt) $librogtescribir_libro($_POST[nombre]$_POST[texto])

$libro_ver = new libro__visitas(librotxt) echo $libro_ver-gtleer_libro() gt lttablegt ltform action=librophp raethod=POST gt Nombre ltinput name=nombre tYpe=text id=nombregt

ltpgt ltpgtTexto

Ficheros y almacenamiento de datos 187

lttextarea name=texto id= tex togtlt tex ta reagt ltpgt ltpgt

ltinput type=submit name=Submit value=Enviar gt ltpgt ltformgt ltbodygt lthtmlgt

La figura 101 muestra el resultado del libro de visitas Como puede ver el coacutedigo tiene dos partes diferenciadas La primera es la definicioacuten de una clase con tres meacutetodos que es la encargada de almacenar y recuperar los datos La segunda parte es el coacutedigo HTML que nos permite visualizar los comentarios de las personas que nos visitan Lo maacutes recomendable es seshyparar ambas partes en dos ficheros distintos y hacer uso de la funcioacuten r e q u i r e _ o n c e () para utilizar el coacutedigo PHP

Si se fija en el coacutedigo HTML hay una parte central escrita en PHP que comprueba si existen datos pasados mediante el meacutetodo POST es decir si existen datos para escribir en el fichero Si es asiacute creamos el objeto $1 lishyb r o y llamamos al m eacute t o d o e s c r i b i r _ l i b r o ( ) que se encarga de guarshydar los datos correctamente Si no hay datos que guardar simplemente se crea un objeto y se lee el archivo donde estaacuten los comentarios

188 Capiacutetulo 10

La clase l i b r o _ v i s i t a s escribe en el fichero filas de una tabla que desshypueacutes se interpretan en el HTML colocando todo correctamente

Sistema de ficheros y directorios

Existe un conjunto de funciones que permiten manejar ficheros y directoshyrios del sistema Estas funciones son muy parecidas a comandos de Unix gnuLinux y seguramente le resulten familiar al lector

Copiar borrar y renombrar

Las operaciones baacutesicas de manejo de ficheros y que se aprenden cuando comenzamos a utilizar un sistema operativo concreto son las de copia borrado y modificacioacuten

Para copiar un fichero se utiliza la funcioacuten copy ( ) que toma como paraacuteshymetros el fichero que quiere copiar y el destino donde quiere guardar la copia

Puede antildeadir un meacutetodo nuevo a la clase l i b r o _ v i s i t a s para que reashylice funciones de copia de seguridad

public function copia_seguridad()

c o p y ( $ t h i s - gt n o m b r e c o p i a t x t )

La siguiente funcioacuten u n l i n k ( ) toma como paraacutemetro el nombre de un fichero y lo borra Puede hacer uso de esta funcioacuten para ampliar su clase y permitir que se puedan borrar los ficheros que almacenan los libros de visitas

public function borrar_libro()

unlink($this-gtnombre)

Como el meacutetodo c o p i a _ s e g u r i d a d () soacutelo permite almacenar un fichero puede ampliar su gama de meacutetodos y antildeadir uno que le deacute la posibilidad de renombrar el fichero c o p i a t x t a otro nombre

public function renombrar_copia($nuevo_nombre)

rename ($this- gtnombre $nuevo__nombre)

Ficheros y almacenamiento de datos 189

Funciones de comprobacioacuten

Es necesario antes de borrar copiar o renombrar un fichero hacer una comprobacioacuten miacutenima para saber si el fichero existe

De esta forma evitaraacute errores innecesarios y tendraacute maacutes control en el flujo de su programa

La funcioacuten f i l e _ e x i s t s () comprueba si un fichero existe dando el valor tnte en caso afirmativo yfalse en caso contrario

El meacutetodo b o r r a r _ l i b r o () puede quedar de la siguiente forma

public function borrar_libro()

if (file_exists($this-gtnombre))

unlink($this-gtnombre)

En los sistemas operativos UNIX gnuLinux todos los recursos hardware se corresponden con un fichero Puede que alguna vez necesite saber el tipo de fichero con el que va a tratar (fichero directorio recurso) La funshycioacuten f i l e t y p e () devuelve un valor que indica el tipo de fichero que coshyrresponde al valor pasado como paraacutemetro

Tabla 102 Tipos de ficheros

Valor Descripcioacuten

fifo Es de tipo FIFO

char Dispositivo de caraacutecter

dir Directorio

block Dispositivo especial de bloques

link Enlace

file Fichero

unknown Tipo desconocido

Ademaacutes de la funcioacuten anterior existe un conjunto de funciones que preshyguntan directamente al archivo por su tipo y el resultado es true ofalse en funcioacuten de la veracidad de la pregunta Las funciones i s _ d i r ( ) i s__execu tab le () i s _ f i l e () y i s _ l i n k ( ) preguntan a su argumento si es del tipo directorio ejecutable fichero o enlace respectivamente

190 Capiacutetulo 10

Directorios

Es muy uacutetil disponer de un gestor de ficheros Web que nos permita naveshygar entre los archivos y directorios Para hacer esto en PHP existen dos meacutetodos El primero utiliza las funciones o p e n d i r ( ) r e a d d i r () y c l o -s e d i r ( ) muy parecidas en su funcionamiento a f open () f r e a d () y f c i oacute s e ( ) Lo mejor es ver coacutemo trabajan juntas con un ejemplo

ltphp $directorio = $descriptor = opendir($directorio) while ($entrada = readdir($descriptor) )

if (is_dir($directorio$entrada) ) echo [Directorio] $entrada ltbrgtbull

elseif ( is__f ile ($directorio $entrada) ) echo [Fichero] $entrada ltbrgt

closedir($descr iptor) gt

Como puede intuir no existe ninguna diferencia significativa entre abrir un fichero o abrir un directorio Lo primero es crear un puntero hacia el directorio que quiera observar y guardarlo en $ d e s c r i p t o r El bucle va leyendo entrada por entrada con la funcioacuten r e a d d i r () y dependiendo

Ficheros y almacenamiento de datos 191

del resultado de las funciones i s _ d i r () o i s _ f i l e () se imprimiraacute el directorio o el fichero pertinente

Existe una segunda forma de visualizar lo mismo pero utilizando proshygramacioacuten orientada a objetos PHP 5 provee un objeto que implementa toda la loacutegica vista anteriormente La funcioacuten d i r () devuelve un objeto que permite examinar el directorio pasado como paraacutemetro El objeto poshysee un meacutetodo llamado r e a d () que va leyendo todas las entradas y un meacutetodo c i oacute s e ( ) que cierra el objeto El ejemplo anterior puede verse asiacute

ltphp $directorio = $fichero = dir(directorio) while ($entrada = $fichero-gtread())

if (is_dir(directorioentrada)) echo [Directorio] $entrada ltbrgt

elseif (is_file($directorio$entrada)) echo [Fichero] $entrada ltbrgt

$ f i c h e r o - gt c l o s e ( ) gt

Ficheros de configuracioacuten

Cuando sea un excelente programador en PHP 5 necesitaraacute conocer teacutecshynicas para almacenar datos de configuracioacuten en un fichero Una teacutecnica habitual es crear un fichero con variables de PHP que toman los valores adecuados y en el transcurso del programa utilizar una llamada a la funshycioacuten r e q u i r e j o n e e () para poder utilizarlas De esta forma podriacuteamos utilizar el siguiente ejemplo como configuracioacuten para conectar a una base de datos

ltphp servidor = localhost usuario = luis $password = secreta $base_datos = anaya gt

Otra alternativa es utilizar un tipo de fichero de configuracioacuten que utiliza la misma estructura que el fichero php i n i La estructura es la siguiente

Los comentarios van despueacutes de un punto y coma

192 Capiacutetulo 10

[Base__datos] servidor=localhost usuario=luis password=secreta base_datos=anaya Creamos un nuevo apartado [Preferencias] color=rojo tamanio=medio fuente=verdana

Este archivo almacena las variables que necesite en el transcurso del proshygrama

Para leerlo existe una sentencia especial que almacena el resultado en un array Para acceder a cada uno de los campos hay que utilizar la notacioacuten de un array de dos dimensiones como muestra el ejemplo La figura 103 muestra el resultado de leer un archivo de configuracioacuten

ltphp $configuracion = parse_ini_file(configuracioacuteniniTRUE) Ejemplos de variables echo $configuracion[Base__datos] [servidor] echo $configuracion[Preferencias] [fuente] gt

Ficheros y almacenamiento de datos 193

Manejo de ficheros en el servidor

Conociendo todas las posibilidades que ofrece PHP 5 a la hora de controshylar archivos llega la hora de aplicar a la praacutectica casos reales de funcionashymiento Los dos usos maacutes comunes de manejo de ficheros en la Web tienen que ver con la subida de los mismos a un servidor o con la descarga desshyde una paacutegina Web

Subida de ficheros

Cuando utilice un formulario Web puede introducir los datos solicitados a traveacutes de cajas de texto listas desplegables o botones de seleccioacuten Adeshymaacutes existe una etiqueta HTML que permite elegir un fichero de nuestro ordenador local y subirlo al servidor Puede crear un formulario miacutenimo que contenga la etiqueta en el siguiente ejemplo

ltHTMLgt ltBODYgt ltform action=subirphp method=POST enctype=multipartform-datagt Introduce el fichero ltinput type=file name=fichero gtltbrgt ltinput type=hidden ntildeameTAMANIO valueacute = 1000gt ltinput type=subraitgt ltformgt ltBODYgt ltHTMLgt

Como puede ver el atributo e n c t y p e debe tener el valor m u l t i p a r t = f o r m - d a t a para que el formulario trabaje correctamente Ademaacutes heshymos antildeadido una etiqueta llamada TAMANIO que guarda el valor maacutexishymo en bytes que nuestro script va a permitir subir Esto debe controlarse en la Web que reciba los datos mediante PHP Puede ver el aspecto graacutefishyco en la figura 104

Cuando el formulario se enviacutea PHP detecta automaacuteticamente que hemos enviado un fichero y lo almacena en un directorio temporal del servidor La Web que recibe los datos introduce dentro de la variable suacuteper-global 3_FILES [ nombre_f i c h e r o ] un conjunto de propiedades tales como el nombre del fichero subido el nombre temporal del recurso el tamantildeo o si ha tenido alguacuten error la subida Vamos a ampliar el formulario con coacuteshydigo para el manejo de ficheros

ltHTMLgt ltBODYgt ltform action=subirphp method=POST enctype=multipartform-datagt

194 Capiacutetulo 10

Introduce el fichero ltinput type=file name=ficherogtltbrgt ltinput type=submit gt ltformgt ltPHP

$fichero = $_FILES[fichero] foreach ($_FILES[fichero] as $indice =gt $valor)

echo $indice $valorltbrgt if ($_POST[TAMANIO]lt$_FILES[fichero] [size])

echo ltbrgtEl fichero tiene un tamantildeo adecuado copy ($_FILES[fichero] [tmp_name]archivotxt)

else echo ltbrgtEl fichero es demasiado grande

gt

ltBODYgt ltHTMLgt

i n L )T^ M ^ ir 7~n l a

L- I r

1 1 1 4 t r 1 c c - 1 r

f - 1 tlf 1 4 4

1 l 1 1 4 4 1

directorios ocultos Cenes ar

Terminado

f f t Eacute f l U B M I - B [luis] v Moziacutella Firefc V E l GIMP bull $ ^ C 7

Figura 104 Formulario de entrada de ficheros

El resultado muestra un formulario donde debe introducir un fichero que puede ver en la figura 105

Cuando activa el botoacuten de subida la paacutegina vuelve a cargar pero esta vez muestra informacioacuten sobre el fichero y si el tamantildeo es adecuado o no para su almacenamiento Nos hemos apoyado en la construccioacuten foreach para averiguar las proshypiedades del fichero subido

Ficheros y almacenamiento de datos 195

Si el tamantildeo en bytes que tenemos puesto como liacutemite en el formulario es menor que el tamantildeo del archivo se utiliza la funcioacuten c o p y () para coshypiar el fichero y guardarlo en el servidor

Descarga de ficheros

Normalmente dejamos al lenguaje HTML el trabajo de enlazar los archishyvos que deseamos que los usuarios de nuestra Web puedan descargar Esto se puede hacer simplemente con un enlace del tipo

lthtmlgt ltBODYgt lta href=ejemplozipgtPincha aquiacute para descargarltagt ltBODYgt ltHTMLgt

Cuando hacemos clic en el enlace normalmente el navegador averigua el tipo de fichero que vamos a descargar (ZIP PDF imagen) y nos muestra una pequentildea ventana con informacioacuten sobre el fichero

Imagine ahora que los ficheros que queremos poner en descarga se geneshyran en ese mismo instante como los archivos PDF Tenemos que seguir una pauta distinta para permitir la descarga desde el sitio Web utilizanshydo cabeceras HTTP La figura 106 muestra la ventana del navegador que recibe la cabecera MIME

196 Capiacutetulo 10

ltphp $fichero = ejemplozip $mimeType = appliacutecationzip Si el navegador es Explorer u Opera cambiamos el tipo de cabecera if (strpos($_SERVER[HTTP_USER_AGENT]MSIE 5) |[

strpos($_SERVER[HTTP_USER_AGENT]Opera 7)) $mimeType = applicationx-download

Se genera la cabecera header(content-disposition attachment f ilename = ej emplo__personal zip) header(content-type $mimeType) header(content-length filesize($fichero)) Se enviacutea el archivo al navegador readfile($fichero) gt

Los tipo MIME identifican el tipo de fichero y lo asocian a una aplicacioacuten determinada en un sistema operativo determinado Si utiliza el tipo MIME de PDF en un sistema Windows la aplicacioacuten asociada puede ser Acrobat Reader de Adobe Casi todos los archivos llevan asociado un tipo MIME y sirve entre otras cosas para que el navegador reconozca el tipo de archishyvo que estaacute descargando y optar por mostrarlo directamente en pantalla o guardarlo en alguna ubicacioacuten del disco duro Si comprueba antes el nomshybre del navegador que ha solicitado la descarga puede cambiar el tipo para que sea compatible con distintas versiones Las cabeceras HTTP deshyben generarse con la funcioacuten h e a d e r () y debe ser lo primero que se enshyviacutea al navegador Si enviacutea alguacuten dato o etiqueta antes que la cabecera obtendraacute un error

Ficheros y almacenamiento de datos 197

La cabecera que utilizamos en este caso es la de enviacuteo de un fichero del tipo MIME indicado y tamantildeo calculado con la funcioacuten f i l e s i z e ( ) No es necesario que el archivo que vaya a enviar tenga el mismo nombre en la descripcioacuten de la cabecera que en el servidor

Finalmente la funcioacuten r e a d f i l e () lee el fichero completamente y lo enviacutea al navegador

Resumen

Situados ya en el ecuador del libro podemos asegurar que estaacute preparado para enfrentarse a programas serios Los conceptos baacutesicos los aprendioacute en los capiacutetulos 1 2 3 4 5 6 y 7 El capiacutetulo 8 le mostroacute la forma de utilishyzar las variables entre varias paacuteginas Web y el 9 la verdadera potencia de uso de PHP 5

Este capiacutetulo le ha mostrado la forma de guardar datos para que permashynezcan almacenados indefinidamente y meacutetodos para abrir cerrar copiar o borrar los ficheros que utilice Aunque no es el mejor meacutetodo para guarshydar los datos muchas aplicaciones existentes se sirven de las funciones de archivos en vez de la utilizacioacuten de bases de datos

Los dos capiacutetulos siguientes le guiaraacuten por el apasionante mundo de los gestores de bases de datos La potencia de estos gestores le permitiraacute errashydicar de sus scripts la gestioacuten de datos mediante ficheros A partir de enshytonces la gestioacuten de archivos quedaraacute relegada al manejo de ficheros graacuteficos copias o gestioacuten de la configuracioacuten

En este capiacutetulo aprenderaacute a

bull Crear sus propias bases de datos con el lenguaje SQL bull Realizar consultas con SQL para insertar modificar o borrar registros

bull Conocer las funciones baacutesicas de SQLite

bull Recuperar los datos de una tabla y el nuacutemero de registros bull Moverse entre los registros de una base de datos

200 Capiacutetulo 11

Introduccioacuten

Este capiacutetulo pretende ser una introduccioacuten al lenguaje estructurado de consulta (SQL) que es primordial conocer a la hora de utilizar alguna base de datos relacional Puesto que no es un libro dedicado a SQL soacutelo vereshymos las estructuras baacutesicas del lenguaje para poder realizar nuestros ejemshyplos por eso recomiendo leer alguacuten libro deciicado a consultas SQL para sacar el maacuteximo partido a las bases de datos

Tambieacuten conoceremos la nueva implementacioacuten de PHP 5 para bases de datos SQLite Lejos de ser un gestor de bases de datos es sencillamente una libreriacutea que nos permite tratar un fichero de iexcla misma forma que utishylizamos una base de datos SQLite viene instalado en los binarios de PHP 5 y no utiliza ninguacuten puerto de conexioacuten externo tan soacutelo funciona cuanshydo se hace una llamada a las funciones de SQLite

SQL

La estructura baacutesica de una base de datos SQL es muy sencilla Los datos de una base de datos se almacenan en tablas donde cada fila identifica uniacutevocamente a un elemento distinto Por ejemplo la tabla de usuarios tendraacute tantas filas como usuarios tenga la paacutegina Web Cada tabla puede definir varias columnas Las columnas hacen referencia a las propiedades de cada fila Por ejemplo la tabla de usuarios podriacutea tener como columshynas el coacutedigo de usuario el nombre los apellidos y la direccioacuten postal

Nota

Hoy en diacutea tedas las aplicaciones profesionales escritas en PHP se basan en la interaccioacuten entre el coacutedigo y los datos almacenados en alguna base de datos Recomiendo al lector que no escatime esfuerzos en aprender el lenguaje SQL pues le seraacute muy uacutetil para realizar despueacutes aplicaciones basadas en cualquier base de datos MySQL SQLite SQL Server o incluso Oracle

El lenguaje SQL nos permite elegir varias filas atendiendo a un criterio insertar nuevas filas actualizar los datos o borrarlas con las sentencias SELECT INSERT UPDATE y DELETE respectivamente Este lenguaje per-

Bases de datos con SQL y SQLite 201

mite soacutelo manipular los datos contenidos en las tablas Si quiere modificar la estructura tiene que apoyarse en el lenguaje de definicioacuten de datos que le permite crear nuevas tablas o bases de datos insertar nuevas propiedashydes en forma de columnas o borrar tablas con las sentencias CREacuteATE ALTER v DROP respectivamente Para seguir los ejemplos vamos a basarshynos en una pequentildea base de datos con tres tablas

Tabla 1 1 1 Usuario

id_usuario nombre cuenta

1 Luis Miguel 7011

2 Mariacutea Fernanda 3454

3 Pedro 3445

4 Javier 1123

La tabla de U s u a r i o s tiene 4 filas Cada una de ellas es diferente a las demaacutes y el paraacutemetro que las identifica uniacutevocamente es i d _ u s u a r i o En Espantildea todas las personas tienen un coacutedigo numeacuterico el DNI que las identifica y las hace distintas frente a otras personas que tengan el mismo nombre y apellidos En las tablas ocurre lo mismo Necesitamos un coacutedigo numeacuterico que nos identifique personas distintas Las dos propiedades sishyguientes son el nombre y la c u e n t a del banco para hacer los pagos

Tabla 112 Producto

id_producto nombre precio

1 ratoacuten 6

2 portaacutetil 1000

3 libro PHP5 20

La tabla de P r o d u c t o s es muy similar a la de U s u a r i o s e identifica toshydos los productos que se pueden encontrar en nuestra Web de venta

Tabla 113 Carrito

id_compra id_usuario Jd_producto

1 1 1

202 Capiacutetulo 11

idcompra iexcldusuario id_producto

2 1 2

3 2 1

4 3 3

La tabla C a r r i t o de la compra mantiene un listado que relaciona los usuashyrios con los productos que han comprado Si se fija en la primera fila el i d_compra es el nuacutemero de factura que debe ser distinto siempre en el antildeo actual el i d _ u s u a r i o es 1 lo que quiere decir que el usuario 1 Luis Miguel ha comprado el producto 1 un ratoacuten de PC Si ha entendido esto ya podemos empezar a ver las sentencias SQL para manejar los datos

SELECT

Este es el comando principal que usaraacute en todas sus aplicaciones de bases de datos La sintaxis baacutesica es la siguiente

SELECT campol campo2 campo3 FROM tabla WHERE condicioacuten

La sentencia SELECT permite escoger los campos que especifiquemos de un conjunto de filas que cumplan una condicioacuten escrita despueacutes de la claacuteushysula WHERE Por ejemplo para recuperar todos los nombres de los usuashyrios almacenados en la tabla U s u a r i o tendriacuteamos que hacer

SELECT nombre FROM Usuario

El resultado es una columna con todos los nombres

Luis Miguel Maria Fernanda Pedro Javier

Advertencia

Si se fija iexcla claacuteusula WHERE no aparece porque estamos seleccioshynando todas iexclas filas Si quisieacuteramos seleccionar todas las filas cuyo i d _ u s u a r i o sea mayor que 2 tendriacuteamos que antildeadir WHERE i d_usua r io gt 2

Bases de datos con SQL y SQLite 203

Si necesita utilizar todos los campos de una tabla puede utilizar el siacutemboshylo para seleccionar todos

SELECT FROM U s u a r i o

Un uacuteltimo truco permite conocer el nuacutemero de filas que cumplen la conshydicioacuten Si despueacutes de la sentencia SELECT escribimos c o u n t ( ) el gesshytor de bases de datos nos contaraacute el nuacutemero de filas implicadas en la seleccioacuten

SELECT c o u n t ) ) FROM U s u a r i o

El resultado devuelto es 4 el nuacutemero de usuarios dados de alta

Uniones

Imagine ahora que queremos conocer el nombre de los usuarios que han comprado un producto determinado Si nos fijamos en la tabla C a r r i t o soacutelo podemos sacar el i d _ u s u a r i o con lo aprendido hasta ahora

Existe la posibilidad de cruzar varias tablas Cuando unimos dos tablas lo que realmente pasa es que obtenemos como resultado una tabla mayor con la suma del nuacutemero de columnas de las tablas y tantas filas como inshydique la multiplicacioacuten de las filas de las tablas implicadas

Si hacemos algo asiacute

SELECT FROM Usuario Carrito

El resultado es la unioacuten de las tablas Usuario y Carrito cuyo resultado tiene la suma de las columnas (3 + 3) y la multiplicacioacuten de las filas (4 x 4)

Tabla 114 UsuarioxCarrito

idusuario nombre cuenta id_carrito id_usuario idproducto

1 Luis Miguel 7011 1 1 1

1 Luis Miguel 7011 2 1 2

1 Luis Miguel 7011 3 2 1

1 Luis Miguel 7011 4 3 3

2 Ma Fernanda 3454 1 1 1

2 Ma Fernanda 3454 2 1 2

2 Ma Fernanda 3454 3 2 1

2 Ma Fernanda 3454 4 3 3

204 Capiacutetulo 11

idusuario nombre cuenta id_carrito id_usuario id_producto

3 Pedro 3445 1 1 1

3 Pedro 3445 2 1 2

3 Pedro 3445 3 2 1

3 Pedro 3445 4 3 3

4 Javier 1123 1 1 1

4 Javier 1123 2 1 2

4 Javier 1123 3 2 1

4 Javier 1123 4 3 3

Aquiacute es donde realmente se necesita utilizar la claacuteusula WHERE Lo que queshyremos conocer es el nombre de los usuarios que han comprado el producto nuacutemero 1 Al hacer una unioacuten lo primero que tenemos que hacer es eliminar las filas repetidas mediante una sentencia que relacione las dos tablas Si se fija bien puede ver que la columna i d _ u s u a r i o aparece en las dos tablas por lo tanto es una buena referencia Observe la siguiente sentencia SQL

SELECT FROM Usuario Carrito WHERE Usuario id_usuario = Carrito id__usuario

Lo que hemos hecho es crear una unioacuten de dos tablas donde cada fila debe tener las dos columnas i d _ u s u a r i o iguales

Como las dos tablas tienen el mismo nombre para la columna i d _ u s u a r i o es necesario anteponer la tabla a la propiedad para que la consulta funshycione de la siguiente forma U s u a r i o i d _ u s u a r i o o C a r r i t o i d _ u s u a r i o

El resultado de la sentencia anterior es

Tabla 115 UsuarioxCarrito

idusuario nombre cuenta id_carrito idusuario id_producto

1 Luis Miguel 7011 1 1 1

1 Luis Miguel 7011 2 1 2

2 Ma Fernanda 3454 3 2 1

3 Pedro 3445 4 3 3

Bien ahora tenemos un conjunto de datos que nos da el nombre de los usuarios que han comprado algo en nuestra tienda Si queremos averi-

Bases de datos con SQL y SQLite 205

guar quieacuten ha comprado el producto nuacutemero 1 tendremos que modificar la sentencia

SELECT FROM Usuario Carrito WHERE Usuarioid_usuario - Carritoid_usuario AND id_producto = 1

El resultado ahora se acerca maacutes a la realidad de lo que necesitamos

Tabla 116 UsuarioxCarrito

id_usuario nombre cuenta id_carrito id_usuario id_producto

1 Luis Miguel 7011 1 1 1

2 Ma Fernanda 3454 3 2 1

Acotando un poquito maacutes la sentencia

SELECT nombre FROM Usuario Carrito WHERE Usuarioid_usuario = Carritoid_usuario AND id_producto = 1

Ahora el resultado siacute es el esperado

Tabla 117 Nombre de los usuarios que han comprado el producto 1

nombre

Luis Miguel

Ma Fernanda

Dominar la sentencia SELECT con todas sus variaciones es un trabajo duro de varios meses o antildeos pero la recompensa se recoge en los primeros pashysos cuando comenzamos a ver la potencia del lenguaje y el uso en los disshytintos gestores de bases de datos

INSERT

Para poder seleccionar los datos primero hay que poder insertarlos en las tablas La sentencia necesaria para introducir nuevos datos es

INSERT INTO tabla (columnal columna2 columna3) VALUacuteES (valorl valor2 valor3)

206 Capiacutetulo 11

El resultado de esta operacioacuten es la inclusioacuten de un registro nuevo en la tabla en las columnas indicadas y con los valores dados Aquellas columshynas que no aparezcan no tomaraacuten valor en ese registro o tomaraacuten el vashylor NULL Para insertar un nuevo cliente en la tabla de U s u a r i o puede utilizar la sentencia

INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (5 Feo Joseacute 78 98)

La tabla resultante quedaraacute de esta forma

Tabla 118 Usuario

idusuario nombre cuenta

1 Luis Miguel 7011

2 Ma Fernanda 3454

3 Pedro 3445

4 Javier 1123

5 Feo Joseacute 7898

UPDATE

Se utiliza para editar informacioacuten que ya estaacute almacenada en la base de datos En otras palabras podemos cambiar selectivamente cierta informashycioacuten sin tener que borrar un registro e insertarlo de nuevo

La sintaxis baacutesica es

UPDATE tabla SET carapol = valorl campo2 = valor2 campo3 = valor3 WHERE condicioacuten

La condicioacuten se utiliza para seleccionar el nuacutemero de filas a las que afectashyraacute el cambio Si no ponemos nada se supone que la actualizacioacuten de datos se hace sobre todas las filas de una tabla por eso es necesario poner algushyna condicioacuten

Podemos utilizar UPDATE para cambiar el nuacutemero de cuenta de uno de los usuarios

UPDATE Usuario SET cuenta = 4455 WHERE id_usuario = 2

Lo que hemos hecho es cambiar el nuacutemero de cuenta de Mariacutea Fernanda de 3454 a 4455

Bases de datos con SQL y SQLite 207

DELETE

Eacutes la sentencia maacutes peligrosa de las vistas Permite borrar de uno a varios registros de una tabla La sintaxis es

DELETE FROM tabla WHERE condicioacuten

Si se omite la claacuteusula WHERE se borran todas las filas de una tabla Es aconsejable no precipitarse en el uso de esta opcioacuten y detenerse antes un momento a recapacitar si se necesita realmente dejar la tabla vaciacutea La fila que contiene al usuario Javier puede borrarse de la siguiente forshyma

DELETE FROM Usuario WHERE nombre=Javier

Definicioacuten de tablas

El primer paso para poder interactuar con los datos de una tabla es su creacioacuten Para este fin se utiliza la sentencia CREacuteATE que define los campos y el tipo de datos que se va a almacenar en cada columna

Ll formato simplificado es CREacuteATE TABLE tabla (columnal tipo_dato columna2 tipo_dato columna3 tipo_dato)

Los tipos de datos de SQL estaacutendar pueden variar dependiendo del gesshytor de bases de datos que utilice pero baacutesicamente pueden ser

Tabla 119 Tipos de datos en SQL 92

Especificacioacuten Tipo de dato

INT INTEGER Entero grande

SMALLINT Entero pequentildeo

REAL FLOAT Coma flotante

DEC DECIMAL Decimal

CHAR(n) CHARACTER(n) Alfanumeacuterico de longitud fija n

208 Capiacutetulo 11

Especificacioacuten Tipo de dato

VARCHAR(n) Alfanumeacuterico de longitud variable como maacutexishy

mo n caracteres

DATE Fecha

TIME Hora

TIMESTAMP Instante Conjunto de Fecha y Hora de un momento determinado

Con estos datos podemos ver la definicioacuten de la tabla de U s u a r i o

CREacuteATE TABLE Usuario (id_usuario INTEGER nombre CHAR(255)

cuenta INTEGER)

Si alguno de los campos es obligatorio es decir si siempre que realice una insercioacuten de nuevos datos necesita que ciertos campos sean introducidos obligatoriamente puede utilizar la sentencia NOT NULL despueacutes de la deshyfinicioacuten del campo

El campo nombre es obligatorio en la tabla U s u a r i o ya que un registro de usuarios sin almacenar su nombre no tiene sentido

CREacuteATE TABLE Usuario (id_usuario INTEGER nombre CHAR(255) NOT

NULL cuenta INTEGER NOT NULL)

El i d _ u s u a r i o identifica un registro y soacutelo uno No puede haber en la misma tabla dos nuacutemeros iguales en esta columna La forma de encontrar raacutepidamente una fila determinada es preguntar por este dato

La clave primaria de una tabla es un identificador uacutenico en cada tabla y que puede utilizarse para relacionar una tabla con otra En nuestro ejemshyplo podemos ver claramente que i d _ u s u a r i o es la clave primaria de la tabla U s u a r i o

CREacuteATE TABLE Usuario (id_usuario INTEGER PRIMARY KEY nombre

CHAR(255) NOT NULL cuenta INTEGER NOT NULL)

SQLite

SQLite es una libreriacutea que implementa un conjunto de sentencias bastanshyte amplio de SQL 92 estaacutendar La libreriacutea es muy pequentildea y 2 oacute 3 veces maacutes raacutepida que los gestores de bases de datos MySQL o PostgreSQL Neshycesita muy poco tiempo de ejecucioacuten y muy poca memoria para el proceshyso No se necesita administrar la base de datos fuera del entorno de

Bases de datos con SQL y SQLite 209

programacioacuten ya que no es un servidor Existe un problema derivado de esto

SQLite se basa en el almacenamiento de datos en un fichero por lo tanto cada vez que se almacenan datos el fichero que contiene los registros se bloquea durante el tiempo de la actualizacioacuten y no permite a otros usuashyrios interactuar Si la base de datos se utiliza solamente para leer la veloshycidad seraacute muy elevada pero si la utilizamos para actualizar constanteshymente los datos SQLite perderaacute maacutes tiempo negociando los bloqueos del fichero que dando servicio

Entre las caracteriacutesticas de SQLite tenemos

bull Implementa muchas funcionalidades de SQL 92 incluido disparadoshyres y transacciones

bull Proteccioacuten de integridad de datos con cominit y r o l l b a c k

bull Los ficheros de datos pueden moverse de servidor y seguiraacuten funcioshynando

bull Soporta bases de datos de 2 Terabytcs

bull El coacutedigo fuente es de dominio puacuteblico

Creacioacuten de bases de datos

La interfnce de programacioacuten de la extensioacuten SQLite es muy similar al gesshytor de bases de datos MySQL y PostgeSQL La diferencia principal es que SQLite aunque acepta la definicioacuten de datos con la sentencia CREacuteATE internamente soacutelo diferencia entre valores alfanumeacutericos o valores numeacuteshyricos es decir que podemos omitir el tipo de los campos en la definicioacuten de las tablas

La funcioacuten s q l i t e _ o p e n () recibe como paraacutemetro el nombre de una base datos Si la base de datos no existe la crea Ademaacutes de esta funcioacuten neceshysitaremos otra para poder enviar consultas a la base de datos La funcioacuten s q l i t e _ s i n g l e _ q u e r y () toma como paraacutemetros la base de datos creada con s q l i t e _ o p e n () y un literal con la sentencia SQL que queremos ejeshycutar

El ejemplo siguiente crea la base de datos de usuario e inserta las filas que estamos utilizando para aprender el lenguaje SQL

ltphp

$base_datos = sqlite_single_open(Usuariodb) $consulta = CREacuteATE TABLE Usuario

(id_usuario PRIMARY KEY

210 Capiacutetulo 11

nombre CHARIacute2 55) NOT NULL

cuenta INTEGER NOT NULL)

sqlite__query ( $base_datos $ consulta)

$consultal = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (1 Luis Miguel7011)

$consulta2 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (2 Mariacutea Fernanda3454 )

$consulta3 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (3 Pedro3445)

$consulta4 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (4 Javier1123)

sqlite_single_query($base_datos$consultal)

sqlite_ single_query($base_datos$consulta2 )

sqlite_ single_query($base_datos$consulta3)

sqlite_ single_query($base_datos$consulta4)

gt

De esta forma se ha creado la tabla U s u a r i o pero hemos necesitado hashycer 4 consultas adicionales para antildeadir los datos Esto se puede simplifishycar utilizando la funcioacuten s q l i t e _ q u e r y ( ) que acepta maacutes de una liacutenea de SQL Vamos a crear de esta forma la tabla P r o d u c t o y C a r r i t o

ltphp

$consulta = CREacuteATE TABLE Producto

(Iacuted_producto INTEGER PRIMARY KEY

nombre CHAR(255) NOT NULL

precio INTEGER NOT NULL)

INSERT INTO Producto (id_producto nombre precio)

VALUacuteES (1 Ratoacuten 6)

INSERT INTO Producto (idjroducto nombre precio)

VALUacuteES (2 Portaacutetil1000)

INSERT INTO Producto (id_producto nombre precio)

VALUacuteES (3 Libro PHP520)

sqlite_query($base_datos$consulta)

consulta = CREacuteATE TABLE Carrito

(id^compra INTEGER PRIMARY KEY

id^usuario INTEGER NOT NULL

id^producto INTEGER NOT NULL)

INSERT INTO Carrito (id^compra id_usuario id_producto)

VALUacuteES (1 1 1)

INSERT INTO Carrito (id^compra id_usuario id_producto)

VALUacuteES (2 1 2)

INSERT INTO Carrito (id_compra id_usuario id_producto)

VALUacuteES (3 2 1)

INSERT INTO Carrito (id_compra id_usuario idjroducto)

VALUacuteES (4 3 3)

sqlite_query($base_datos$consulta)

gt

Bases de datos con SQL y SQLite 211

Algunos gestores de bases de datos necesitan antildeadir una sentencia espeshyciacutefica para que uno de los campos sea auto incremental es decir que su valor aumente poco a poco sin necesidad de antildeadirlo nosotros en realishydad es gestionado por la propia base de datos

Los campos enteros que llevan asociada la sentencia PRIMARY KEY autoshymaacuteticamente son tratados como campos auto incremeacutentales y en las oacutershydenes INSERT se puede omitir la inclusioacuten del valor porque SQLite le daraacute el valor correlativo de la fila que le corresponda

Uacuteltimos cambios en una tabla

Hay veces que necesitamos saber el uacuteltimo valor auto incremental que SQLite ha generado para asociar una imagen o un archivo a un registro de una tabla Para aver iguar este dato p o d e m o s usar la funcioacuten sqlite_last_insert_rowid()

ltphp $base_datos = sqlite_open(Usuariodb) sqlite_single_query($base_datosINSERT INTO Usuario (nombre cuenta) VALUacuteES (Joseacute A2677)) $ultimo_usuario = sqlite_last_insert_rowid($base_datos) sqlite_single_query($base_datosINSERT INTO Producto (nombre precio) VALUacuteES (Ibook1200)) $ultimo_producto = sqlite_last_insert__rowid($base_datos) sqlite_single_query($base_datosINSERT INTO Carrito (id_usuario id_producto) VALUacuteES ($id_usuario$id_producto)) gt

En el ejemplo puede ver la posible utilizacioacuten de la funcioacuten Con ella exshytraeraacute el uacuteltimo usuario y el uacuteltimo producto introducido y aprovecharaacute para insertarlos en la tabla de compras

Otra funcioacuten muy uacutetil es s q l i t e _ _ c h a n g e s ( ) que devuelve el nuacutemero de filas afectadas por una consulta anterior

Si borra varias filas esta funcioacuten le devolveraacute el nuacutemero de filas que han sido borradas como puede ver en la figura 1 1 1

lt php $base_datos = sqlite_open(Usuariodb)

sqlite_single_query($base_datosUPDATE Usuario set cuenta =

2 2 2 2) echo Nuacutemero de filas afectadas

sqlite_changes($base_datos) gt

Seleccioacuten de datos

Como hemos visto antes la funcioacuten s q l i t e _ q u e r y () da la posibilidad de hacer cualquier tipo de consulta vista al principio del capiacutetulo

Las sentencias CREacuteATE INSERT DELETE o UPDATE no necesitan devolshyver ninguacuten dato pero la sentencia SELECT tiene que devolver los datos requeridos

La variable que obtiene los datos se considera como un recurso y debe aplicarse una funcioacuten para recuperar las filas una a una

Lo podemos comprobar con un ejemplo cuyo resultado se muestra en la figura 112

lt php $base_datos = sqlite_open(Usuariodb) ^resultado = sqlite_query($base_datosSELECT FROM Usuario) if ( $resultado)

echo Parece que hay un error else

while ($fila = sqlite_fe tch__array ($resu l taaacuteo) ) foreach ($fila as $indice =gt $valor)

echo $indice $valorltbrgt

gt

Despueacutes de hacer una consulta con la funcioacuten s q l i t e _ q u e r y ( ) la vashyriable $ r e s u l t a d o recibe un tipo de dato que no es manejable La funshycioacuten s q l i t e _ f e t c h _ a r r a y () extrae de la variable $ r e s u l t a d o todas las filas devueltas en forma de array Para ello hemos construido un bucle w h i l e donde la variable $f i l a va recibiendo los registros

Para acceder a cada columna de un registro simplemente tenemos que hacer uso de la variable como si fuera un array y como iacutendice el nombre de la columna o el nuacutemero de registro de esta forma $f i l a [nombre] $ f i l a [ c u e n t a ] $ f i l a [ 0 ] $ f i l a [ l ]

Dentro del bucle hemos utilizado otro bucle f o r e a c h para mostrar por pantalla todos los valores del array

SQLite orientado a objetos

Puesto que la potencia de PHP 5 radica en la fuerte orientacioacuten a objetos es de agradecer que SQLite provea alguacuten objeto para la interaccioacuten con bases de datos SQLite tiene una potente interface orientada a objetos que puede ser usado para un eficaz manejo de los datos librando al progra-mador de crear su propio objeto con las funciones procedurales El objeto se llama S Q L i t e D a t a b a s e () y el constructor recibe como paraacutemetro la base de datos

214 Capiacutetulo 11

El ejemplo muestra coacutemo utilizarlo aunque el lector ya conoceraacute el funshycionamiento baacutesico de los objetos

lt php $base_datos = new SQLiteDatabase(Usuariodb) $consulta = CREacuteATE TABLE Usuario

(id^usuario INTEGER PRIMARY KEY nombre CHAR(2 55) NOT NULL cuenta INTEGER NOT NULL) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (1 VLuis Miguel7 011) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (2 VMariacutea Fernanda3454) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (3 Pedro3445) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (4 Javier1123)

$base_datos-gtquery($consulta) gt

El meacutetodo q u e r y ( ) funciona exactamente igua l que la funcioacuten s q l i t e _ q u e r y ( ) pero soacutelo recibe como paraacutemetro la consulta ya que la base de datos va impliacutecita en el objeto

Seleccioacuten de registros

Las consultas SELECT se tratan de manera parecida a lo visto anteriorshymente Puesto que estamos utilizando un objeto para recibir el resultado de una consulta tendremos que utilizar meacutetodos que nos permitan maneshyjarlos En la figura 113 puede ver el resultado

ltphp

$base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtquery($consulta) while ($resultado-gtvalid() )

$fila = $resultado-gtcurrent() echo $fila[0] ltbrgt echo $fila[l] ltbrgt echo $fila[2] ltbrgt $ resultado- gtnext () bull

gt

El meacutetodo v a l id () da un resultado true si existen valores que no se han mostrado si devuelve false es que ya hemos extraiacutedo todas las filas El meacutetodo c u r r e n t () nos da la fila actual deacutela consulta La variable $f i l a

Bases de datos con SQL y SQLite 215

obtiene un array con los datos del registro actual Para avanzar de registro en la consulta se utiliza el meacutetodo n e x t ( )

Funciones de Array para recuperar datos

SQLite ofrece tambieacuten un nuacutemero de nuevas funciones que simplifican y aceleran la recogida de informacioacuten de la base de datos Por ejemplo el meacutetodo A r r a y Q u e r y () devuelve un array de dos dimensiones donde la primera dimensioacuten indica el nuacutemero de la fila y la segunda dimensioacuten el nuacutemero de columna de esa fila Si la variable $ r e s u l t a d o recoge el resultado de A r r a y Q u e r y ( ) puede acceder a los registros de la siguienshyt e forma $ r e s u l t a d o [ 0 ] [ 0 ] $ r e s u l t a d o [ l ] [ 0 ] $ r e s u l t a -do [2] [3] Puede utilizar alguacuten bucle foreach para sacar todos los datos

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtArrayQuery($consulta) $filas = 0 while (isset ($resultado [$filas] ) )

foreach ($resultado[$filas] as $indice =gt $valor) echo $indice $valorltbrgt

$filas++

216 Capiacutetulo 11

gt

Ademaacutes de esta forma de trabajar puede hacer que el resultado de la consulshyta se devuelva en forma de objeto PHP 5 permite utilizar la construccioacuten fo-reach para interactuar con objetos v recuperar los datos de la siguiente forma

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario bullresultado = $base_datos-gtunbufferedQuerv($consulta) foreach ($resultado as $valor)

echo Svalor[0]ltbrgt echo $vaior[1]ltbrgt echo $valor[2]ltbrgt

gt

La construccioacuten unbuf f e r edQuery () devuelve las filas en forma de objeshyto y ademaacutes no almacena el resultado en buffer por lo que es muy raacutepida

Nuacutemero de filas

La extensioacuten SQLite posee un meacutetodo para determinar el nuacutemero de camshypos devueltos en una consulta en un resultado El meacutetodo n u m F i e l d s () se encarga de devolver este resultado Para poder utilizarlo debe recupeshyrar los datos con la funcioacuten unbuf f e r e d Q u e r y () y el objeto devuelto seraacute el que le indique el nuacutemero de campos que almacena

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtunbufferedQuery($consulta) $numero_filas = $resultado-gtnumFields() echo El nuacutemero de filas es $numero_filas foreach ($resultado as $valor)

echo $valorf0]ltbrgt echo $valor[1]ltbrgt echo $valor[2]ltbrgt

gt

Moverse entre registros

En muchos casos querraacute utilizar la menor memoria posible y se haraacute inshydispensable utilizar el meacutetodo unbuf f e r e d Q u e r y ( ) aunque esto hace perder funcionalidad y puede no resultar la mejor eleccioacuten

Bases de datos con SQL y SQLite 217

Por ejemplo imagine que quiere saber cuaacutentas filas devuelve un resulshytado

Usando unbuf f e r e d Q u e r y () tenemos que hacer un bucle para contar una a una las filas del resultado Con la funcioacuten q u e r y () tan soacutelo hay que llamar al meacutetodo numRows () para conocer el nuacutemero de registros implicados en la consulta

Las consultas con q u e r y () permiten ademaacutes recuperar la informacioacuten en el orden que queramos y no secuencialmente

El ejemplo siguiente muestra coacutemo utilizar una consulta para ver los reshygistros empezando desde el uacuteltimo hasta el primero

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtquery($consulta) $numero_filas = $resultado-gtnumRows() $resultado-gtseek($numero_filas-1) do

$fila = $resultado-gtcurrent () foreach ($fila as $valor)

echo $valorltbrgt

while ($resultado-gthasPrev() ampamp $resultado-gtprev()) gt

218 Capiacutetulo 11

El meacutetodo s e e k () se mueve a traveacutes del resultado y permite posicionar-nos en el registro que pasemos como paraacutemetro El meacutetodo h a s P r e v () es true si existe un registro previo y p r e v () es true si ha sido posible moshyverse a un registro anterior La figura 114 es un fiel reflejo del funcionashymiento

Resumen

SQLite es una de las caracteriacutesticas estrella de PHP 5 Se ha incluido para que no necesite instalar un gestor de bases de datos para sus proyectos Esto hace maacutes sencillo distribuir aplicaciones porque no dependen de un software adicional tan soacutelo de PHP 5

SQLite es a la vez un servidor de bases de datos y un cliente La libreriacutea permite operar con la mayor parte de las instrucciones de SQL posee un mayor juego de instrucciones que MySQL 4

Pero como todo lo bueno tiene una pequentildea pega Como SQLite trata las bases de datos como ficheros del sistema operativo cuando un usuario hace una conexioacuten para escribir datos el fichero queda bloqueado para inclusiones de otros usuarios Cuando termina la insercioacuten del primer usuario el segundo tendraacute acceso a escribir los datos Por lo tanto SQLite es muy recomendable cuando realice proyectos donde la mayor parte de las veces se hacen lecturas de la base de datos como un perioacutedico digital o un WebLog En otro caso es mejor utilizar un gestor de bases de datos como MySQL que veraacute en el siguiente capiacutetulo

En este capiacutetulo aprenderaacute a

bull Conocer la forma de conectarse a un servidor de bases de datos bull Realizar consultas y recuperar los datos de distintas formas bull Recuperar el nuacutemero de filas que intervienen en una consulta

bull Crear nuevas bases de datos y tablas

220 Capiacutetulo 12

Introduccioacuten

PHP 5 soporta muchos de los gestores de bases de datos relacioacutenales exisshytentes en el mercado Las dos alternativas maacutes comunes son ProstgreSQL y MySQL

Aunque PostgreSQL es mucho mejor en cuanto a caracteriacutesticas y funcioshynes soportadas del SQL 92 estaacutendar MySQL se ha hecho maacutes popular en el ambiente de los servidores Web Cuando los servidores Web ofrecen su sershyvicio como LAMP se refieren a Linux + Apache + MySQL + PHP

Este capiacutetulo cubre las operaciones maacutes comunes que los desarrolladores de PHP pueden hacer con MySQL desde recuperar o modificar datos buscar textos o hacer una copia de seguridad de la base de datos

Administracioacuten de usuarios

Una gran parte del uso de la seguridad y efectividad de MySQL tiene que ver con comprender el sistema de privilegios MySQL permite dar permishysos al detalle basaacutendose en grupos usuarios conexiones y comandos a utilizar En teoriacutea se puede dar privilegios a ciertos usuarios para que soacutelo puedan escribir en algunas columnas de varias tablas Es una buena idea dar a cada usuario los permisos miacutenimos necesarios para que pueda inte-ractuar con su base de datos En realidad en un mundo ideal no deberiacutea preocuparse por dar permisos a los usuarios o crear bases de datos Si su trabajo profesional se basa en el desarrollo de aplicaciones su adminisshytrador de bases de datos deberiacutea poner a punto el servidor de MySQL para facilitar su trabajo Si se estaacute interesado en conocer los entresijos del servishydor de bases de datos recomiendo al lector que lea la documentacioacuten o-line de la Web wwwmysql com o consiga uno de los muchos libros que tratan el tema

En el Apeacutendice A puede ver coacutemo instalar MySQL y dar los permisos neshycesarios para que pueda probar los ejemplos

Conexioacuten a MySQL

La conexioacuten no puede ser maacutes sencilla Es un proceso de dos pasos

bull Se conecta con el servidor de MySQL

PHP 5 y MySQL 221

bull Se solicita la conexioacuten a una base de datos especiacutefica Es importante recordar que MySQL es un servidor que puede estar alojashydo en el mismo ordenador que PHP 5 o en otro diferente Por eso la coshynexioacuten se hace de forma distinta a SQLite

Para conectar a MySQL es necesario enviar como paraacutemetros la direccioacuten del servidor el usuario y la contrasentildea

ltphp $servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras Conexioacuten al servidor de bases de datos $descriptor = mysql_connect($servidor$usuario $pass) Se selecciona la base de datos mysql_select_db($base_datos$descriptor) Se cierra la conexioacuten cuando terminemos mysql__close ( $descriptor) gt

La funcioacuten m y s q l _ c o n n e c t () permite conectar a un servidor En este caso hemos puesto como servidor a l o c a l h o s t porque estamos utilizanshydo nuestro ordenador local para hacer las pruebas

Otra cuestioacuten importante es que el servidor MySQL puede almacenar varias bases de datos de un mismo usuario por eso tenemos que utilizar la f u n c i oacute n m y s q l _ s e l e c t _ d b ( ) para seleccionar la que queremos utishylizar

Por uacuteltimo tenemos la funcioacuten m y s q l _ c l o s e () que se encarga de ceshyrrar una conexioacuten con el servidor

El ejemplo siguiente muestra coacutemo se puede crear una clase reutilizable en todos los proyectos que sirva para conectarse a una base de datos

ltphp class Servidor_Base_Datos

private $servidor private $usuario private $pass private $base_datos private $descriptor function construct($servidor$usuario$pass$base_datos)

$this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtpass = $pass

222 Capiacutetulo 12

$this-gtbase_datos = $base_datos $this-gtconectar_base_datos()

priacutevate function conectar_base_datos()

$this-gtdescriptor = mysql__connect($this-gtservidor$this-gtusuario$this-gtpass) mysql_select_db($this-gtbase_datos$this-gtdescriptor)

$servidor = localhost $usuario = luis $pass = secreto $base_datos = Usuario $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) gt

Nota

No he antildeadido al objeto ninguacuten tipo de control de errores ya que veremos ese tema con profundidad en el capiacutetulo 17

Seleccionar datos

Existen diferentes formas de recuperar datos desde MySQL pero los maacutes usados son seguramente m y s q l _ f e t c h _ q u e r y () y m y s q l _ q u e r y () Si leyoacute el capiacutetulo anterior sobre S Q L i t e no tendraacute ninguacuten problema para asimilar el funcionamiento de estas funciones

Vamos a antildeadir dos meacutetodos nuevos a la definicioacuten de la clase anterior para que nos pueda servir en otras aplicaciones

public function consulta($consulta)

$this-gtresultado = mysql_query($consulta$this-gtdescriptor)

public function extraer_registro ()

if ($fila = mysql_fetch_array($this-gtresultadoMYSQL_ASSOC)) bull return $fila

else return false

PHP 5 y MySQL 223

El meacutetodo c o n s u l t a () recibe una sentencia SQL que debe ejecutarse en la base de datos apuntada por el descriptor $ t h iacute s- gt d e s c r i p t o r

El meacutetodo e x t r ae r _ r eg i s t r o ( ) comprueba con la funcioacuten m y s q l _ f e t c h _ a r r a y () si existen ficheros en el resultado de la conshysulta

En caso afirmativo devuelve un arraxj con los datos de ese registro En el capiacutetulo anterior vimos que un registro pasado comoarray permitiacutea acceder a las columnas mediante un iacutendice numeacuterico ($f i la [0] ) o meshydiante el nombre de la columna (($f i l a [ i d _ u s u a r i o ]))

La directiva MYSQL_ASSOc elimina la posibilidad de extraer los datos con un Iacutendice numeacuterico mejorando la recuperacioacuten en Jos bucles del foreach El ejemplo siguiente muestra coacutemo utilizar los nuevos meacutetodos

ltphp Primero se antildeade el fichero que contiene la clase require_once(MySQLphp) $servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $usuario-gtconsulta (seslect from Usuario) while ($fila = $usuario-gtextraer_registro() )

foreach ($fila as $indice =gt $valor) echo $indice $valorltbrgt

gt

El coacutedigo anterior recupera la clase del fichero MySQL php e inicializa las variables necesarias para conectar con la base de datos

Tambieacuten podemos utilizar un fichero de configuracioacuten como el que vishymos en el capiacutetulo 10 para almacenar los datos de la conexioacuten

La variable $ u s u a r i o recoge la creacioacuten del objeto de conexioacuten y utiliza el meacutetodo c o n s u l t a () para recuperar el nombre de los usuarios de nuesshytra Web

Para extraer todos los datos nos encontramos con un bucle que va recupeshyrando un arraxj por registro almacenaacutendolo en $f i l a

Utilizando f o r e a c h podemos extraer todas las columnas de la fila indishycada

La figura 121 presenta el resultado del script

Manipulacioacuten de datos

Seleccionar datos de una base de datos es soacutelo el principio la potencia de SQL nos permite tambieacuten insertar actualizar y borrar filas de una tabla Con el objeto que hemos creado es muy sencillo hacer consultas del tipo INSERT UPDATE o DELETE llamando al meacutetodo c o n s u l t a ()

Insertar una fila

Para insertar una fila con nuestro objeto tendremos que definir la consulshyta y ejecutar el meacutetodo c o n s u l t a ()

ltphp require_once(MySQLphp) $servidor = localhost -$usuario = root $pass = $base_datos = Compras $insertar = INSERT INTO Usuario (nombrecuenta) VALUacuteES (Cristina2119) $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) ^usuario-gtconsuIta($insertar) gt

PHP 5 y MySQL 225

Actualizar una fila

Antes de actualizar una fila necesita identificar la fila o filas de la tabla que quiere cambiar En este ejemplo se ha utilizado una sentencia SE-LECT para averiguar primero el valor id_usuar io de Luis Miguel y desshypueacutes proceder a cambiar su cuenta bancaria

ltphp require_once(MySQLphp) $serviacutedor = localhost $usuario = root $pass = $base_datos = Compras $consulta = SELECT id_usuario FROM Usuario WHERE nombre=Luis Miguel $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $id_usuario = $fila[id_usuario] $actualizar = UPDATE Usuario SET cuenta=9999 WHERE id_usuario=$id_usuario $usuario-gtconsulta($actualizar) gt

En un caso praacutectico UPDATE puede utilizarse para modificar los datos introducidos en un formulario Web

Borrar una fila

Para borrar una fila puede seguir el mismo camino que se ha utilizado antes para actualizar Primero averiguumle el registro que quiere eliminar y despueacutes ejecute la consulta con la sentencia DELETE

ltphp require_once(MySQLphp) $servidor = localhost usuario = luis $pass = secreto $base_datos = Compras $consulta = SELECT id_usuario FROM Usuario WHERE nombre=Luis Miguel $usuario = new Servidor_Base_Datos$servidor$usuario$pass$base_datos) $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $id_usuario = $fila[id_usuario ]

226 Capiacutetulo 12

$borrar = DELETE FROM Usuario WHERE id_usuario = 1$id_usuario $usuario-gtconsulta($borrar) gt

Errores con las comillas

Examinemos ahora el coacutedigo siguiente ltPHP require_once(MySQLphp) if (isset ($_POST[nombre] ) ]| isset ($_POST[cuenta ]) )

$servidor = localhost $usuario = root $pass = $base_datos = Compras $nombre = $_POST[nombre ] $cuenta = $_POST[cuenta] $usuario = new Servidor_Base_Datos($servidor$usuario $pass$base_datos) $insertar = INSERT INTO Usuario(nombrecuenta) VALUacuteES ($nombre$cuenta) $usuario-gtconsulta ($insertar)

gt ltHTMLgt ltBODYgt ltform action=formulario_Usuario php method=POSTgt Nombre ltINPUT type=text name=nombregtltbrgt Cuenta ltINPUT type=text name=cuentagtltbrgt ltinput type=submit name=Enviar gt ltformgt ltBODYgt ltHTMLgt

El pequentildeo formulario que muestra la figura 122 permite insertar en la tabla Usuario nuevos clientes Los campos de texto que recogen el nombre y la cuenta pueden recibir cualquier tipo de caraacutecter hay ciertos siacutembolos que pueden provocar que un programa falle y son utilizados malintencionadamente por hackers para corromper el sistema Si en la casilla destinada a escribir el nombre escribe un nombre y en medio una comilla simple y otra doble tal y como muestra el ejemplo

Luis Migue1 Cabezas Granado

PHP 5 y MySQL 227

El meacutetodo c o n s u l t a () intentaraacute ejecutar

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Migue1 Cabezas Granado))

iquestPuede ver el problema Cuando MySQL lee la sentencia cree que es

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Migue

El resto de la sentencia causaraacute un error y fallaraacute la consulta La solucioacuten es antildeadir el siacutembolo de escape delante de la comilla simple para que MySQL tome el siacutembolo como un simple caraacutecter

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Miguel Cabezas Granado))

Existen tres soluciones para antildeadir el siacutembolo de escape a todas las comishyllas que aparezcan en campo de texto

bull Lo primero que puede hacer es configurar el archivo phpini activanshydo la opcioacuten m a g i c _ q u o t e s _ g p c Con esta opcioacuten a todos los datos pasados entre paacuteginas Web por los meacutetodos GET y POST se les inserta automaacuteticamente siacutembolos de escape en las comillas que aparezcan

bull Si m a g i c _ q u o t e s no estaacute activo en su servidor PHP 5 tiene la funshycioacuten a d d s l a s h e s ( ) que tiene el mismo cometido que la opcioacuten anshyterior Si m a g i c _ q u o t e s estaacute activo no podraacute utilizar esta funcioacuten porque se antildeadiriacutean dos siacutembolos de escape

228 Capiacutetulo 12

bull El tercer camino muy similar a a d d s l a s h e s usa la funcioacuten m y s q l _ e s c a p e _ s t r i n g Esta funcioacuten antildeade siacutembolo de escape a las comillas simples comillas dobles caracteres de final de fichero y reshytorno de carro Es un meacutetodo implementado por MySQL por eso es maacutes recomendable utilizar a d d s l a s h e s

Para saber si el fichero phpini tiene activado m a g i c _ q u o t e s existe la funcioacuten g e t _ m a g i c _ q u o t e s _ g p c ( ) Puede antildeadir algunas liacuteneas de coacutedigo a su formulario para que controle este tipo de error de la siguiente forma

ltphp require_once(MySQLphp) if (isset($_POST[nombre]) || isset($_POST[cuenta ]))

$servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras if (get_magic_quotes_gpc())

$nombre = $_POST[nombre] $cuenta = $__POST [cuenta ]

else $nombre = addslashes($_POST[nombre]) $cuenta = addslashes($_POST[cuenta])

$usuario = new Servidor_Base_Datos($servidor$usuario $pass$base_datos) $insertar = INSERT INTO Usuario(nombrecuenta) VALUacuteES ($nombre$cuenta ) $usuario-gtconsulta($insertar)

gt

Contando filas

A menudo es uacutetil conocer el nuacutemero de filas devueltas por una consulta antes de hacer cualquier cosa con el resultado Puede averiguar el nuacutemeshyro de filas mediante el uso de alguna funcioacuten de PHP o la utilizacioacuten de MySQL para obtener el nuacutemero de registros

Contar filas con PHP

La funcioacuten mysql_num_rows () devuelve el nuacutemero de filas seleccioshynadas

PHP 5 y MySQL 229

Su uso puede ampliar el objeto de bases de datos

public function numero_filas()

return mysql_num_rows($this-gtresultado)

Ademaacutes de esta funcioacuten tenemos mysql_num_f i e l d s ( ) que devuelve el nuacutemero de campos del una tabla es necesaria cuando hacemos una conshysulta de datos y no sabemos cuaacutentas columnas hemos seleccionado

Contar filas con MySQL

La alternativa es utilizar una consulta de SQL con la sentencia c o u n t ( ) Esto requiere hacer dos consultas una para obtener el nuacutemero de filas y otra para obtener el resultado

Utilicemos el objeto para realizar la operacioacuten

ltphp

require_once(MySQLphp) $servidor = localhost $usuario = root $pass = $base_datos = Compras $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $consulta = select count() as numero_filas from Usuario $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $numero_filas = $fila[numero_filas] $consulta = select from Usuario $usuario-gtconsulta($consulta) echo El nuacutemero de filas es $numero__f ilasltbrgt while ($fila = $usuario-gtextraer_registro())

foreach ($fila as $indice =gt $valor) echo $indice $valorltbrgt

gt

La primera sentencia SELECT cuenta el nuacutemero de filas y al resultado le da el nombre numero__f i l a s

Para acceder al nuacutemero se hace como siempre leyendo el resultado del irray $f i l a [ numero_f i l a s ]

La figura 123 muestra el resultado

Contar filas afectadas

Es posible que sea necesario saber cuaacutentas filas han sido afectadas desshypueacutes de antildeadir actualizar o borrar algunas filas

La funcioacuten m y s q l _ a f f e c t e d _ r o w s () devuelve el nuacutemero de registros afectados despueacutes de un cambio en las filas de una tabla Actualizando nuestra clase tenemos

public function filas_afectadas()

return mysql_affected_rows($this-gtdescriptor)

Uacuteltimo nuacutemero insertado

Cuando utilice campos auto numeacutericos en una tabla e inserte un nuevo registro seraacute uacutetil conocer el nuacutemero de la uacuteltima fila insertada

Para obtener este nuacutemero tan solo t iene que u t i l izar la funcioacuten m y s q l _ i n s e r t _ i d ( ) Se puede utilizar de la siguiente forma

public function ultima_fila()

PHP 5 y MySQL 231

return mysql_insert_id($this-gtdescriptor)

Buacutesquedas dentro de una tabla

La forma de buscar ocurrencias en una columna es utilizar la sentencia LIKE de SQL

SELECT FROM Usuario WHERE nombre LIKE Luis

El siacutembolo es un comodiacuten es decir puede sustituir a cualquier caraacutecter dentro de la columna donde busque

Definicioacuten de bases de datos

Como indicamos antes lo ideal es que un administrador de MySQL le genere las bases de datos y las tablas Despueacutes de esto con su usuario y contrasentildea podraacute hacer las consultas que tenga autorizadas

En muchos casos la figura del administrador de bases de datos no existe y es el desarrollador el que asume este papel En este caso le interesaraacute conocer la forma de crear desde un script sus bases de datos

Creacioacuten de bases de datos

Para crear una base de datos tiene que utilizar la funcioacuten m y s q l _ c r e a t e _ db () Recibe dos paraacutemetros el primero es el nombre de la base de datos que quiere crear y el segundo el descriptor devuelto por la funcioacuten m y s q _ c o n n e c t () La funcioacuten m y s q l _ d r o p _ d b () borra la base de dashytos del gestor de MySQL

ltphp $descriptor = mysq_connect($servidor $usuario $clave) mysql_create_db(Nueva_Base $descriptor) gt

Creacioacuten de tablas

La creacioacuten de tablas debe hacerse a traveacutes del lenguaje de consultas SQL como vimos en el capiacutetulo anterior Como ya sabe la funcioacuten m y s q l _

232 Capiacutetulo 12

q u e r y () acepta consultas de distintos tipos Aprovechando esto puede incluir una consulta para crear una tabla nueva

SQLite es una base de datos poco tipada es decir que soacutelo es capaz de almacenar dos tipos de datos nuacutemeros o caracteres En cambio MySQL es fuertemente tipada porque tiene un elevado conjunto de tipos para aplicar a sus columnas La tabla 121 muestra algunos tipos de datos que puede aplicar en la sentencia CREacuteATE

Tabla 121 Tipos de datos de MySQL

Nombre Tamantildeo Uso

BIT BOOLEAN 1 byte Almacena valores desde 0 a 255 sin

signo o -128 a 127 con signo SMALLINT 2 bytes De 0 a 65535 sin signo y de -32768 a

32767 con signo

MEDIUMINT 3 bytes De 0 a 16777215 sin signo o-8388608 a 8388607

INT INTEGER 4 bytes De0a4294967295ode-2147483648a 2147483647

BIGINT 8 bytes De 0 a 18446744073709551615 o -9223372036854775808a 9223372036854775807

FLOAT(precisioacuten) De 4 a Nuacutemero de coma flotante con precisioacuten

8 bytes

DATE 3 bytes Almacena una fecha

DATETIME 8 bytes Almacena una fecha con la hora y minutos

VARCHAR(nuacutemero) Nuacutemero Almacena tantos caracteres como indi-bytes ca el nuacutemero El tamantildeo es menor que

255 caracteres

TINYBLOB TINYTEXT Mayor que Almacena caracteres 255 bytes

BLOB TEXT Maacutes de Almacena un nuacutemero elevado de carac-64 kb teres

Como ejemplo puede ver el siguiente coacutedigo

lt $descriptor = mysq_connect($servidor $usuario $clave) mysql_create_db(Concesionario $descriptor) mysql_ select_db ( Concesionario) -

PHP 5 y MySQL 233

$consulta = CREacuteATE TAELE vehiacuteculos ( Iacuted_vehicul0 INT NOT NULL AUTO_INCREMENT PRIMARY KEY color VARCHAR(25) fecha_compra DATETIME)

$resultado = mysql_query($consulta) $mensaje = mysql_drop_db(Concesionario) gt

La columna i d _ v e h i c u l o identifica a un uacutenico vehiacuteculo de la tabla Como puede ver en MySQL tiene que antildeadir algunos modificadores a la columshyna para identificar sus caracteriacutesticas Estos modificadores son obligatoshyrios en MySQL Por ejemplo en SQLite no hace falta antildeadir ninguna propiedad para que el valor se incremente automaacuteticamente En MySQL es necesario especificar la propiedad AUTO_lNCREMENT Es obligatorio ademaacutes que todas las columnas tengan un tipo de dato definido

Resumen

MySQL es sin duda el sistema maacutes utilizado a escala mundial La mayor parte de las aplicaciones en PHP estaacuten escritas para MySQL porque da una fiabilidad y velocidad absolutas Hay que decir tambieacuten que la vershysioacuten 4 tiene bastantes restricciones con respecto a otros gestores de bases de datos como PostgreSQL pero se iraacuten solventando en las futuras vershysiones

Si terminoacute el capiacutetulo con eacutexito todaviacutea le queda un paso por andar La extensioacuten de MySQL que hemos utilizado es la que viene por defecto funshycionando con PHP 5 Recientemente se ha creado desde cero una nueva forma de interactuar con MySQL que permite hacer transacciones o conshysultas almacenadas (de la forma que lo hace Oracle) La extensioacuten se llashyma MySQLi y por su leve dificultad se escapa del objetivo de este libro

En este capiacutetulo aprenderaacute a

bull Diferenciar entre sesiones cookies y cabeceras HTTP bull Utilizar sesiones para ocultar variables entre usuarios y paacuteginas Web bull Almacenar la configuracioacuten de un usuario con cookies

bull Enviar informacioacuten de cabecera viacutea Web

236 Capiacutetulo 13

Introduccioacuten

Una sesioacuten es un periacuteodo de tiempo durante el cuaacutel una persona detershyminada ve un nuacutemero de diferentes paacuteginas Web de un determinado doshyminio

El protocolo HTTP no tiene forma alguna de distinguir un usuario que se conecte desde Espantildea de otro que se conecte desde Japoacuten PHP 5 proshyvee un mecanismo que permite antildeadir cierto nivel de diferenciacioacuten enshytre usuarios

Miremos un ejemplo

ltHTMLgt ltBODYgt ltphp switch ($_GET[opcioacuten ] )

case 1 echo La opcioacuten es 1 break

case 2 echo La opcioacuten es 2 break

case 3 echo La opcioacuten es 3 break

gt ltBODYgt ltHTMLgt

Esta paacutegina elige una de las opciones en funcioacuten del paraacutemetro GET que obtenga Como ya sabe GET pasa todos los valores junto a la direccioacuten Web y es visible para nosotros

El meacutetodo GET no es muy funcional cuando necesite pasar datos comproshymetidos a traveacutes de varias paacuteginas Web POST resuelve en parte este proshyblema

Este meacutetodo permite pasar entre paacuteginas las variables que quiera queshydando ocultas para el usuario A priori parece una buena forma de oculshytar datos pero nos encontramos que es necesario un formulario en cada paacutegina para utilizarla

Las sesiones y las variables de sesioacuten permiten pasar datos entre paacuteginas sin necesidad de utilizar formularios y es la mejor forma para ocultar dashytos comprometidos

Sesiones y Cookies 237

Sesiones en PHP 5

Las sesiones deben soportar

bull Detectar que durante el transcurso de la navegacioacuten por varias paacutegishynas Web la sesioacuten permanece invariable

bull Almacenar informacioacuten que formaraacute parte de una sesioacuten en concreto

PHP trabaja con una combinacioacuten de meacutetodos que son capaces de ocultar variables y cookies de las que hablaremos en un apartado posterior

Instanciando sesiones

El primer paso que nuestro script debe realizar es la llamada a la funcioacuten s e s s i o n _ s t a r t () Esta funcioacuten registra una sesioacuten en el servidor y la identifica con una cadena de 32 caracteres Cada persona que entre en ese mismo instante en la Web desde un ordenador diferente obtendraacute un iden-tificador distinto

La funcioacuten s e s s i o n _ s t a r t () debe incluirse en todas las paacuteginas Web que formen parte de la aplicacioacuten porque no soacutelo se encarga de iniciali-zar la sesioacuten sino que tambieacuten se encarga de mantener la misma sesioacuten durante el proceso La funcioacuten actuacutea de la siguiente forma

bull Si no existe una sesioacuten activa crea una nueva con un identificador

bull Si existe una sesioacuten que puede ser recuperada se extrae la sesioacuten y las variables asociadas ltphp session_start() gt ltHTMLgt ltBODYgt ltphp echo La variable de sesioacuten es SID gt ltBODYgt ltHTMLgt

La figura 131 muestra la variable de sesioacuten En el momento en que elscript escribe cualquier cosa el servidor termina de enviar las cabeceras HTTP y empieza a enviar el contenido No se puede enviar una nueva cabecera cuando ya estamos enviando el cuerpo de la Web Puesto que la funcioacuten s e s s i o n _ s t a r t () utiliza cabeceras para pasar la informacioacuten de sesioacuten

Sesiones y Cookies 239

La primera vez que instanciamos una sesioacuten seacute crea una constante llamashyda S ID que contiene el identificador de 32 caracteres que nos identifica

Variables de sesioacuten

Existe una variable suacuteper-global que se encarga de almacenar las variashybles que quiere pasar entre paacuteginas de una sesioacuten El array $_SESSION permite almacenar datos de cualquier tipo para recuperarlos en otras paacuteshyginas que tengan la misma sesioacuten El coacutedigo para propagar variables de sesioacuten puede ser tan sencillo como la paacutegina s e s i o n l php

ltphp session_start () gt ltHTMLgt ltBODYgt ltphp $_SESSION[nombre] = Luis Miguel Caberas $_SESSION[edad] = 29 echo lta href = sesion2phpgtPasar variablesltagt gt ltBODYgt ltHTMLgt

La vatvabie suacutepex-^toacutebal almacena valores de d-feteate tupo y creamas UTJ enlace a la paacutegina s e s i o n 2 php para poder recuperarlos

ltphp session_start () gt ltHTMLgt ltBODYgt ltphp echo Mostrar las variables de sesioacutenltbiacutegt foreach ($_SESSION as $indice =gt $valor)

echo $indice $valorltbrgt

echo Mostrar las COOKIESltbrgt foreach ($_COOKIE as $indice =gt $valor)

echo $indice $valorltbrgt gt ltBODYgt ltHTMLgt

Si se apoya en el bucle foreach podraacute extraer todos los valores pasados desde la Web s e s i o n l php Como curiosidad hemos introducido un bucle que extrae las variables almacenadas en c o o k i e s y puede ver en

Nota

Como veremos maacutes adelante iexclas cookies son pequentildeos contenishydos que se almacenan en el ordenador local Las cookies son muy utilizadas por los servidores Web para guardar las preferencias de un usuario o alguacuten dato interesante En realidad son variables que se guardan en el ordenador local del usuario y pueden ser resshycatadas por PHP en alguna otra ocasioacuten en la que se necesite

Problemas con los navegadores

Un problema muy comuacuten es que el usuario tenga por razones de segurishydad desactivada la opcioacuten de permitir c o o k i e s en su navegador El proshyb lema es que el o rdenador local no va a aceptar nuestra variable PHPSESSID y todas las paacuteginas creeraacuten que no existe sesioacuten activa y no podraacuten recuperar las variables Se puede resolver con unas pocas liacuteneas de coacutedigo para la paacutegina s e s i o n l php

ltphp

Sesiones y Cookies 241

session_start() gt ltHTMLgt ltBODYgt ltphp $_SESSION[nombre] = Luis Miguel Cabezas $_SESSION[edad] = 29 $id_sesion = SID echo lta href=sesion2php$id_sesiongtPasar variablesltagt gt ltBODYgt ltHTMLgt

Esta forma de trabajar implica tener que pasar en todos los enlaces el iden-tificador de sesioacuten La forma correcta de hacerlo es la que muestra el ejemshyplo ya que produce una URL de este tipo s e s i o n 2 phpPHPSESSID = 9 0 9 7 c 4 3 a a 8 6 d 3 4 5 9 b l 6 6 d 7 1 c 4 e a 4 c 9 3 0

Nota

Si quiere que PHP sea transparente manejando el paso de variashybles a traveacutes de c o o k i e s o viacutea el meacutetodo GET necesita tener configurado PHP 5 con las directivas - e n a b l e - t r a n s - s i d y - e n a b l e - t r a c k - v a r s Si estas opciones no estaacuten activashydas el uacutenico traacutemite para utilizar variables es pasar mediante GET o POST el identificado de sesioacuten corno en el ejemplo anterior

Funciones para el manejo de sesiones

La tabla 131 muestra algunas funciones interesantes con la descripcioacuten de uso

Tabla 131 Funciones relacionadas con las sesiones

Funcioacuten Descripcioacuten

session_start() Inicia una sesioacuten y permite almacenar variables en la

estructura $ _ S E S S I O N

session_destroy() Elimina todas las variables de sesioacuten

session_name() Devuelve el nombre de la sesioacuten normalmente PHPSES-SID

session_id() Devuelve los 32 caracteres que forman el identificador de sesioacuten

242 Capiacutetulo 13

Con las funciones relacionadas en la tabla anterior podemos construir un objeto que nos facilite el manejo de sesiones en nuestras aplicaciones

ltphp class sesioacuten

function constructor()

session_start() public function set($nombre$valor)

$_SESSION[$nombre] = $valor public function get($nombre)

if (isset ($_SESSION[$nombre] ) ) return $_SESSION[$nombre]

else return false

public function borrar_variable($nombre)

unset ($_SESSION[$nombre] ) public function borrarsesiacuteon()

$_SESSION = a r r a y O s e s s i o n _ d e s t r o y ( )

gt

Las paacuteginas s e s i o n l php y s e s i o n 2 php pueden manejarse ahora con la clase que hemos creado de la siguiente forma

ltphp require_once (clase__sesion php) $sesioacuten = new sesioacuten() gt ltHTMLgt ltBODYgt ltphp $sesioacuten-gtset(nombreLuis Miguel Cabezas) $sesioacuten-gtset(edad29) $id_sesion = SID echo lta href=sesion2php$id_sesiongtPasar variablesltagt gt ltBODYgt ltHTMLgt

Sesiones y Cookies 243

Cookies

Una cookie es una pequentildea parte de informacioacuten que queda almacenashyda en el ordenador local de los usuarios de una paacutegina Web Debe conteshyner siempre un nombre y un valor Es muy usual utilizar cookies para guardar preferencias de cada usuario en el uso de una Web pero hay que tener cuidado con el nuacutemero de variables que se pueden almacenar pues norshymalmente hay un maacuteximo de 20 por dominio seguacuten el navegador

En PHP 5 la funcioacuten s e t c o o k i e () se encarga de registrar las cookies durante el enviacuteo de las cabeceras Para recuperar el valor tiene que utilizar la variable suacuteper-global $_COOKIE

setcookie()

La funcioacuten s e t c o o k i e () normalmente tiene 2 argumentos el nombre de la variable y el valor Ademaacutes podemos pasar varios paraacutemetros que permiten dar un tiempo de vida a las variables asociar un dominio o aseshygurar el enviacuteo mediante HTTPS

La tabla 132 muestra en orden todos los argumentos que puede recibir una cookie

Tabla 132 Argumentos de la funcioacuten setcookie()

Argumento Tipo Descripcioacuten -

nombre caraacutecter El nombre de la variable cookie valor caraacutecter El valor que debe almacenar la variable Si este

valor no se indica la cookie seraacute automaacuteticashymente borrada

tiempo de vida entero Indica el tiempo de vida de unacookie Si el valor es 0 la variable nunca expiraraacute Si indica un nuacutemero entero tendraacute el tiempo que la variable permaneceraacute activa El valor hay que asignarlo en tiempo absoluto (como el devuelto por la funcioacuten mkt ime ())

ruta entero Permite distinguir entre dos variables con el mismo nombre pero llamadas desde distinta ruta en el servidor La cookie nombre llamada desde la ruta fo ro seraacute distinta a la cookie nombre llamada desde la ruta usuario

244 Capiacutetulo 13

Argumento Tipo Descripcioacuten

dominio caraacutecter Asegura el dominio de servidor que puede leerla cookie

Secure entero (0 Si el argumento es 1 la cookie soacutelo seraacute enviada oacute 1) a traveacutes de una conexioacuten segura HTTPS

Borrar una cookie

Borrar una cookie es faacutecil Si llama a la funcioacuten s e t c o o k i e () con los misshymos argumentos que para habilitarla excepto el valor la variable se elimishynaraacute del sistema local del usuario Si usa los paraacutemetros r u t a y dominio deben aparecer tambieacuten y con los mismos valores

Como de costumbre vamos a implementar una pequentildea clase para maneshyjar las cookies

ltphp

class Cookie

function constructor()

El constructor no hace nada

public function set($nombre$valor$expire=0$ruta= $dominio=$seguro=0)

setcookie($nombre$valor$expire$ruta$dominio$seguro)

public function get($nombre)

if (isset ($_COOKIE [$nombre] )) return $_COOKIE[$nombre] else return false

public function borrar_cookie($nombre)

setcookie($nombre$valor$expire$ruta$dominio$seguro

gt

El argumento tiempo de vida debe proporcionarse en valor de tiempo absoluto Esto a veces puede resultar incoacutemodo y seriacutea maacutes sencillo pro-

Sesiones y Cookies 245

porcionar el tiempo de vida de la variable en minutos o segundos La clase anterior solicita el tiempo en segundos y se encarga de antildeadir esos segundos al valor absoluto haciendo maacutes simple la asignacioacuten

Para ver coacutemo funciona podemos utilizar la Web c o o k i e l php

ltphp require_once(clase_cookiephp) $cookie = new CookieO $cookie-gtset(nombreLuis Miguel10) gt ltHTMLgt ltBODYgt ltphp echo La COOKIE es $cookie-gtget(nombre) echo lta href = cookie2phpgtPasar variablesltagt gt ltBODYgt ltHTMLgt

Como puede ver es muy sencilla la asignacioacuten de cookies y su recupeshyracioacuten

Cabeceras HTTP

Las funciones s e t c o o k iacute e () o s e s s i o n _ s t a r t () introducen su conteshynido en una cabecera HTTP sin necesidad de especificacioacuten por el usuashyrio Es posible enviar cabeceras desde PHP con la utilizacioacuten de la funcioacuten h e a d e r () La funcioacuten h e a d e r () es muy simple tan soacutelo toma como arshygumento un conjunto de caracteres que seraacute la cabecera a enviar Por ejemshyplo una forma muy uacutetil de redirigir una paacutegina a otra es utilizando la cabecera Location

lt php if (isset($_GET[usuario] ) ampamp $_GET[usuario] == Luis)

header(Location httpwwwluisyfernandanet)

gt lthtmlgt ltbodygt Si ve esta paacutegina su nombre no es Luis ltbodygt lthtmlgt

Este script evaluacutea si en la variable suacuteper-global $_GET existe un identifi-cador llamado u s u a r i o y si su valor es L u i s En caso afirmativo se enviacutea

246 Capiacutetulo 13

la cabecera al navegador que invita a cargar la Web especificada En caso negativo se enviacutea la paacutegina Web que hay despueacutes de la estructura if

Este tipo de uso de las cabeceras puede servir para redireccionar a una paacutegina de error cuando un usuario intente entrar sin permiso o cometa un fallo en la entrada de un nombre o correo electroacutenico

Resumen

Las sesiones resuelven los problemas muy comunes de seguridad El uso conjunto de sesiones cookies y cabeceras HTTP permiten un control absoshyluto sobre las variables de la aplicacioacuten Casi todos los programas que necesitan autentificar un usuario (como una tienda on-line) se sirven de estas teacutecnicas Pero el lector no debe quedarse aquiacute hay muchas cabeceras distintas que pueden ser uacutetiles en diferentes momentos como la autenticacioacuten viacutea HTTP

248 Capiacutetulo 14

Introduccioacuten

XML (Lenguaje de Marcas eXtensible) forma parte de SGML (Lenguaje de Marcas Generalizado eStandar) Auacuten asiacute no es necesario saber nada de SGML para utilizar XML El lenguaje XML define una estructura de documentos que pueden ser leiacutedos por personas y por ordenadores

El camino maacutes sencillo para comprender XML es pensar en coacutemo se utilishyzan los documentos HTML Estos documentos estaacuten estructurados y funshycionan con etiquetas y atributos Las etiquetas van encerradas entre siacutembolos de mayor y menor (ltbgt) y deben cerrarse de la misma forma antildeadiendo un siacutembolo de barra invertida (ltbgt) Los documentos HTML tienen una ortografiacutea especiacutefica es decir unas reglas que definen la forshyma correcta de estructurar un documento por ejemplo la etiqueta ltBODYgt debe ir siempre despueacutes de ltHEADgt o s ino existe eacutesta de ltHTMLgt Adeshymaacutes HTML contiene un diccionario cerrado de etiquetas que definen el lenguaje y no podemos utilizar otras que no esteacuten especificadas

En cambio XML no tiene un diccionario de etiquetas Las etiquetas que aparecen son las que nosotros mismos creamos La uacutenica norma que teneshymos que seguir es que toda etiqueta de inicio (ltcoche gt) debe tener una etiqueta de fin ( lt c o c h e gt )

El documento siguiente muestra un archivo XML bien formado

ltxml version=10 gt ltbibliotecagt lttema id=informaacuteticagt

ltlibrogt lttitulogtManual Imprescindible de PHP 5lttitulogt ltautorgtLuis Miguel Cabezas Granadoltautorgt

ltlibrogt ltlibrogt

lttitulogtDelphi 7lttitulogt ltautorgtMarco Cantultautorgt

ltlibrogt ltlibrogt

lttitulogtDelphi 6 y Kylixlttitulogt ltautorgtFrancisco Charte Ojedaltautorgt

ltlibrogt lttemagt

ltbibliotecagt

Como puede ver la estructura del documento es muy similar a la de una paacutegina Web Estaacute formado por etiquetas y atributos cuya definicioacuten pueshyde inventarse sobre la marcha es decir las etiquetas lt l i b r o gt lt t i t u -

Lectura y escritura de archivos XML 249

l o gt o lt s e c c i o n gt podriacutean tener un nombre totalmente diferente pero no asiacute en HTML que estaacute obligado a mantener el lenguaje definido Algushynos navegadores como Mozilla interpretan los ficheros XML como en la figura 141

Un documento XML estaacute obligado a cumplir ciertas normas que permishyten definir un texto bien formado

bull Debe tener un uacutenico elemento raiacutez Soacutelo puede haber un par de etishyquetas que diferencien el inicio y el final del documento como en HTML donde se utiliza ltHTMLgt y lt HTMLgt

bull Los elementos deben ser hereditarios La estructura lt A x B x B gt lt Agt se permite pero no la siguiente lt A x B x A x B gt En la primera forma la etiqueta ltAgt envuelve a la etiqueta ltBgt que es la forma coshyrrecta de escribir un documento XML HTML sin embargo permite la segunda forma de componer un documento ltA HREF=indexphpgt ltBxAx Bgt

bull Todos los elementos tienen que tener una etiqueta de cierre La pareja ltt i tulogtltt i tulo es correcta HTML permite etiquetas sin cerrar como ltBgt o ltLIgt

bull Los elementos pueden tener entre las dos etiquetas cualquier tipo de contenido como lttitulogtManual imprescindible de PHP 5lttitulogt

250 Capiacutetulo 14

bull Los caracteres amp lt gt las comillas simples y las comillas dobles estaacuten prohibidas como contenido y deben utilizarse siacutembolos de escape para utilizarlas

SAX DOM y SimpleXML

Lo primero que tenemos que hacer antes de leer archivos XML es conocer las tres formas existentes con sus ventajas e inconvenientes

bull SAX Es maacutes ligero y faacutecil de aprender trata los archivos XML como un flujo de datos que se leen poco a poco

bull DOM Lee el fichero completo y crea un objeto en memoria Permite crear archivos desde cero

bull SimpleXML Es el maacutes sencillo de utilizar Los elementos se pueden leer con un simple f o r e a c h

SAX

Se utiliza para parsear elementos XML Estaacute basado en eventos lo que sigshynifica que el parse hace llamadas a determinadas funciones dependiendo de los elementos que examina

Los eventos de SAX son proporcionados por PHP en forma de funcioacuten Al parsear se reconocen piezas de XML como etiquetas de inicio o fin datos o entidades externas y cada una de estas piezas hace una llamada a un evento El procedimiento para parsear un archivo XML con SAX debe seshyguir los siguientes pasos

bull Determinar queacute clase de eventos queremos manejar

bull Escribir una funcioacuten que maneje cada evento Es muy comuacuten escribir una funcioacuten para manejar los datos y las etiquetas de inicio y de fin

bull Crear el parse usando la funcioacuten x m l _ p a r s e r _ c r e a t e () y hacer la llamada con x m l _ p a r s e ()

bull Liberar la memoria usada con la funcioacuten x m l _ p a r s e r _ f r e e ( )

Hemos creado un objeto para leer archivos XML En principio no hace gran cosa tan solo examina las etiquetas de inicio y fin y las imprime en pantalla pero con esto bastaraacute para aprender la peculiar estructura de un parse SAX

ltphp

Lectura y escritura de archivos XML 251

class xml

function construct($fichero_xml)

$this-gtfichero_xml = $fichero_xml $this-gtxml_parser=xml_parser_create()

Puesto que el parse lo creamos desde un objeto debemos registrar la incidencia con xml_set_object

xml_set_obj ect($this~ gtxml_parser$this) Funciones de callback para manejar XML mediante SAX

xml_set_element_handler($this-gtxml_parserelemento_ inicioelemento_fin) if (($fp = fopen($this-gtfichero_xmlr)))

die (Error de Entrada y Salida)

while ($datos = fread($fpfilesize($this-gtfichero_xml)))

if (xml_parse($this-gtxml_parser$datos feof($fp)))

die (Fallo en el XML) xml_error_string(xml_get_error_ code($this-gtxml_parser))

xml_parser_free($this-gtxml_parser)

function elemento_inicio ($parser$nombre$atributos)

echo $nombreltbrgt

function elemento_fin ( $parser$nombre)

echo $nombreltbrgt

$biblioteca = new xml(bibliotecaxml) gt

Si guarda la clase en un archivo llamado c l a s e _ x m l php podraacute usarla en sus proyectos tan soacutelo con instanciar el objeto Si comienza por el consshytructor veraacute que el paraacutemetro que recibe es el archivo que quiere par-sear Debe crear el parse con la f u n c i oacute n x m l _ p a r s e _ c r e a t e () y despueacutes registrarlo en PHP como un objeto mediante la funcioacuten x m l _ s e t _ o b -j e c t () Si crea un parse fuera de la estructura de un objeto no haraacute falta hacer la llamada a la funcioacuten anterior

252 Capiacutetulo 14

La funcioacuten x m l _ s e t _ h a n d l e r () indica al parse que los eventos encarshygados de encontrar las etiquetas de inicio y de fin seraacuten manejadas con las funciones que se pasan como paraacutemetro En este c a s o e l e m e n t o _ i n i c i o ( ) se ejecutaraacute cada vez que se encuentre una etiqueta de inicio y e l e m e n t o _ f in ) cuando se encuentre la etiqueta de cierre

La uacuteltima parte del constructor lee el archivo pasado como argumento y analiza los datos a traveacutes de la funcioacuten x m l _ p a r s e ( ) que inicia la seshycuencia de anaacutelisis Si ejecuta una instancia de la clase comprobaraacute que el navegador muestra todas las etiquetas de inicio y de fin con una rigurosa herencia La figura 142 muestra las etiquetas leiacutedas del archivo XML

Para poder ver los datos tiene que antildeadir una nueva funcioacuten que maneje ese evento La f u n c i oacute n x m l _ s e t _ c h a r a c t e r _ d a t a _ _ h a n d l e r () permite manejar el evento que se dispara cada vez que se encuentra un dato entre dos etiquetas Esta funcioacuten tendraacute que antildeadirla al constructor despueacutes del meacutetodo que maneja los eventos de etiquetas

xml_set_character_data_handler($this-gtxml_parserdatos)

Ademaacutes de esto tendraacute que incluir una nueva funcioacuten que se encargaraacute de mostrar los datos

function datos($parser$valor)

Lectura y escritura de archivos XML 253

echo $v9lorltbrgt

Nota

Los eventos antildeadidos deben iexcllevar Jos argumentos necesarios para recuperar los datos Cada vez que cree un par se del tipo SAX las funciones tienen que tener los paraacutemetros que indicamos en nuesshytra clase de ejemplo

Despueacutes de comprobar el funcionamiento de la clase puede modificarla para que haga algo realmente uacutetil como mostrar ordenadamente los dashytos del fichero Las funciones de la clase pueden quedar de esta forma

function elemento_inicio ($parser$nombre$atributos)

switch($nombre) case TEMA

$tema = $atributos [ ID ] bull echo Tema $temaltbrgt break

case TITULO echo ltbgt break

case AUTOR echo - break

function elemento_fin ($parser$nombre)

switch($nombre) case TITULO

echo ltbgt break

case AUTOR echo ltbrgt break

function datos($parser$valor)

echo $valor

En este caso el parser iraacute analizando las etiquetas que nos interesan y reashylizaraacute una accioacuten determinada Por ejemplo cuando se comprueba la exis-

254 Capiacutetulo 14

tencia de una etiqueta TITULO escribimos en HTML la etiqueta de negrishyta ltBgt para resaltar este dato como muestra la figura 143

Elaborando un poco maacutes la clase obtendraacute un objeto de gran utilidad que podraacute recuperar informacioacuten de bases de datos o archivos de configurashycioacuten

DOM

Esta API define un completo camino para crear definir y parsear archivos XML D O M es una recomendacioacuten del consorcio World Wide Web

La idea baacutesica consiste en que todos los archivos XML pueden verse como un conjunto de nodos que forman parte de un aacuterbol Empezando desde el elemento raiacutez del que todos los elementos nacen como hijos cualquier programa deberiacutea ser capaz de crear una estructura loacutegica del documento

La API puede utilizarse para leer archivos en memoria modificarlos y volver a escribir el archivo con los nuevos datos

DOM estaacute escrito en metodologiacutea orientada a objetos y todos los nodos son instancias de diferentes objetos

Lectura y escritura de archivos XML 255

Usar DOM para leer archivos

El siguiente coacutedigo muestra un archivo XML muy simple

ltxml version=l0 gt lttema id=informaacuteticagt

lttitulogtManual Imprescindible de PHP 5lttitulogt lttemagt

Si parseamos este documento con DOM la etiqueta t i t u l o seraacute consideshyrada un nodo y ademaacutes un hijo del nodo raiacutez que en este caso es tema Esta parte queda maacutes o menos clara debido a la jerarquiacutea de etiquetas que tiene XML La controversia llega con el texto que hay en el nodo tema que no se considera como una parte sino como un nodo independiente cuyo valor es el texto Manual I m p r e s c i n d i b l e de PHP 5 Este nodo permite recuperar el valor con el meacutetodo n o d e V a l u e

Vamos a ver los pasos necesarios para leer el archivo b i b l i o t e c a xml ya que difiere bastante la metodologiacutea con respecto a SAX

Todo es un objeto

PHP 5 implementa una clase DOM para representar los archivos XML llashymada domDocument Como ya sabe para instanciar la clase soacutelo tiene que hacer uso del operador de objetos

$biblioteca = new domDocument

La extensioacuten D O M sigue las especificaciones de XML y trata los espacios en blanco como contenido Esto significa que si entre dos etiquetas existe un espacio el contenido seraacute tratado como un objeto de texto Para evitar fallos de este tipo puede ejecutar el siguiente meacutetodo

preserveWhiteSpace = f a l s e

Lo siguiente que tendraacute que hacer es leer el archivo b i b l i o t e c a xml con el meacutetodo l o a d () del objeto $ b i b l i o t e c a Si el contenido XML se almacena en una variable puede utilizar el meacutetodo loadXML ()

$biblioteca-gtload(bibliotecaxml)

A partir de aquiacute ya puede recuperar el contenido del fichero atendienshydo a sus preferencias En SAX teniacutea que leer el documento completo e ir preguntando etiqueta por etiqueta para averiguar todos los autores que estaban dados de alta en el archivo XML En D O M puede recupeshyrar esta informacioacuten usando g e t E l e m e n t s B y T a g n a m e () que devuelshyve un conjunto de objetos que coinciden con la etiqueta que pase como paraacutemetro

256 Capiacutetulo 14

ltphp Instanciamos el objeto $biblioteca = new domdocument Anulamos la posibilidad de que un espacio en blanco sea un obj eto $biblioteca-gtpreserveWhiteSpace = false Leemos el archivo XML $biblioteca-gtload(bibliotecaxml) Buscamos todas las etiquetas libro $libros = $biblioteca-gtgetElementsByTagname(libro) Imprimimos todos los libros foreach ($libros as $libro)

echo $libro-gtfirstChild-gtnodeVaiue ltbrgt

gt

La variable $ l i b r o s es en realidad un objeto de la clase d o m n o d e l i s t y guarda una relacioacuten de nodos cuya etiqueta es l i b r o es decir hemos seleccionado todos los libros del archivo Con un bucle f o r e a c h podeshymos sacar todos los valores Antes vimos que el texto asociado a un nodo es un nodo hijo con un valor determinado por eso debe llamar al meacutetodo f i r s t C h i l d

El hijo de la etiqueta l i b r o es el texto asociado y su valor lo podemos recibir llamando a n o d e V a l u e

El resultado es la lista de libros

Manual Imprescindible de PHP 5 Delphi 7 Delphi 6 y K y l i x

Atributos

Para recuperar los atributos de los nodos estaacute el meacutetodo g e t A t t r i b u -te ( ) al que tiene que pasar como argumento el nombre del atributo El archivo b i b l i o t e c a xml tiene una uacutenica etiqueta con el atributo id pero nos sirve para mostrar coacutemo funciona el meacutetodo

ltphp $biblioteca = new domdocument -$biblioteca-gtpreserveWhiteSpace = false $biblioteca-gtload(bibliotecaxml) $temas = $biblioteca-gtgetElementsByTagname(tema) foreach ($temas as $tema)

echo $tema-gtgetAttribute(id)

gt

El resultado es el nombre del tema o temas que esteacuten almacenados

Lectura y escritura de archivos XML 257

Buacutesquedas muacuteltiples

Nuestro objetivo final es mostrar todos los tiacutetulos con sus autores ordeshynados por temaacutetica Conociendo ya los meacutetodos principales para recorrer los objetos DOM es sencillo pensar en un coacutedigo que implemente lo que pedimos

ltphp $biblioteca = new domdocument Sbiblioteca-gtpreserveWhiteSpace = false $biblioteca-gtload(bibliotecaxml) $biblioteca-gtdocumentElement $temas = $biblioteca-gtgetElementsByTagname(tema)bull foreach ($temas as $tema)

echo Tema $tema-gtgetAttribute(id) ltbrgt $libros = $tema-gtgetElementsByTagname(libro) foreach ($libros as $libro)

echo ltbgt $libro-gtfirstChild-gtnodeValue ltbgt - $autores = $libro-gtgetElementsByTagname(autor) foreach ($autores as $autor)

echo $autor-gtfirstChild-gtnodeValue ltbrgt

gt

Aunque es un poco maacutes complejo el fundamento baacutesico es ir utilizando bucles para leer los hijos de un nodo determinado hasta recuperar todos los datos necesarios

Escribir archivos XML con DOM

D O M permite hacer maacutes cosas que la simple impresioacuten de los datos en pantalla Se puede utilizar para crear nuevos documentos con el nivel de jerarquiacutea que quiera Para hacer esto debe apoyarse en la creacioacuten de obshyjetos de la clase domElement ()

Vamos a crear un script para crear el siguiente archivo XML ltxml ve r s ion=1 0gt lt b i b l i o t e c a gt

lttemagtTextolttemagt lt b i b l i o t e c a gt

Para crearlo necesita instanciar una serie de objetos que empieza por la creacioacuten de un documento DOM mediante la utilizacioacuten del objeto d o shymdocument ()

ltphp

258 Capiacutetulo 14

$biblioteca = new doradocument(10) $raiz = new domelement(biblioteca) $raiz = $biblioteca-gtappendChild($raiz) $tema = new domelement(temaTexto) $tema = $raiz-gtappendChild($tema) $biblioteca-gtsave(bibliotecaxml) gt

La variable $ r a i z es el objeto que contendraacute todo el documento Para crear las etiquetas tiene que utilizar el meacutetodo a p p e n d C h i l d ( ) El objeto que llama al meacutetodo contendraacute como hijo al elemento que se pasa como paraacuteshymetro

Si se fija en el ejemplo $tema es un nuevo elemento que tendraacute la etiqueshyta tema

Para que $tema sea un hijo de la raiacutez debe hacer que el objeto padre $ r a i z llame al meacutetodo a p p e n d C h i l d () con el paraacutemetro $tema

Para grabar el resultado final el objeto D O M tiene que llamar al meacutetodo s a v e ( ) El fichero b i b l i o t e c a xml lo puede crear con el coacutedigo sishyguiente

ltphp $biblioteca = new domdocument(10) $raiz = new domelement(biblioteca) $raiz = $biblioteca-gtappendChild($raiz) $tema = new domelement(tema) $tema = $raiz-gtappendChild($tema) $tema-gtsetAttribute(idinformaacutetica) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloManual Imprescindible de PHP 5 bull $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autor Luis Miguel Cabezas Granado) $autor = $libro-gtappendChild($autor) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloDelphi 7 ) $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autorMarco Cantu) $autor = $libro-gtappendChild($autor) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloDelphi 6 y Kylix) $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autor Francisco Charte Ojeda) $autor = $libro-gtappendChild($autor) $biblioteca-gtsave(bibliotecaxml) gt

Lectura y escritura de archivos XML 259

El conjunto de liacuteneas de coacutedigo anterior crea un archivo completo XML Quizaacute sea mejor dividir el texto en funciones recursivas que permitan teshyclear menos a la hora de crear los documentos pero eso ya es trabajo para el lector El meacutetodo s e t A t t r i b u t e () antildeade un atributo al objeto que hace la llamada el primer argumento seraacute el nombre del atributo y el segundo su valor La llamada a domelement () puede tener uno o dos valores Si lleva un atributo significaraacute que el nombre de la etiqueta seraacute ese paraacutemeshytro Si se llama con dos paraacutemetros el primero seraacute el nombre de la etiqueta y el segundo un objeto de texto que se antildeadiraacute como texto hijo del nodo

Modificar archivos XML

La verdadera potencia de D O M reside en el poder de gestionar los archishyvos para antildeadir modificar o eliminar nodos La mayoriacutea de los algoritmos que realizan alguna de estas operaciones se basan en la buacutesqueda de los nodos para posteriormente antildeadir hijos nuevos o eliminar los encontrashydos Para antildeadir nuevos elementos se hace como cuando creamos el ficheshyro b i b l i o t e c a xml con el meacutetodo a p p e n d C h i I d ( ) Antes de antildeadir nuevos nodos tiene que localizar el lugar exacto donde quiere antildeadir las etiquetas El ejemplo siguiente muestra coacutemo antildeadir un nuevo nodo tema

ltphp $biblioteca = new domdocument(10) $biblioteca-gtload(bibliotecaxml) $raiz = $biblioteca-gtdocumentElement $tema_nuevo = new domelement(tema) $tema_nuevo = $raiz-gtappendChild($tema_nuevo) $tema_nuevo-gtsetAttribute (id ficcioacuten ) $biblioteca-gtsave(biblioteca2xml) gt

Los pasos son los que ya ha aprendido Cargue el documento y cree un objeto llamado $ r a i z que se convierta en la etiqueta raiacutez mediante el meacutetodo documentElement Cree un nuevo elemento del tipo tema y antildeaacuteshydalo para despueacutes insertar el atributo que se necesita Por uacuteltimo guarde el archivo en el fichero b i b l i o t e c a 2 xml

SimpleXML

Probablemente el punto maacutes fuerte de PHP 4 fue la incorporacioacuten de heshyrramientas para el soporte de XML PHP 5 le da una vuelta maacutes a la tuerca

260 Capiacutetulo 14

implementando nuevas herramientas de lectura elaboracioacuten y modificashycioacuten de archivos XML basado en la libreriacutea l i b x m l 2 y una nueva API llamada SimpleXML

Si XML es un lenguaje bien construido y legible por personas y ordenadoshyres los programas para manipular estos archivos deberiacutean ser tambieacuten sencillos de utilizar SimpleXML nace con esta premisa permitiendo leer un fichero completo con una sola instruccioacuten e inmediatamente despueacutes poder leer los datos como conjunto de variables PHP

El conjunto de funciones que pertenece a la API SimpleXML es nuevo en PHP 5 Mantiene una absoluta flexibilidad a favor de la simplicidad y bajo nivel de memoria usado SimpleXML utiliza el menor nuacutemero de liacuteneas de coacutedigo para leer o escribir datos en un fichero XML El e jemplo s iguiente muestra coacutemo p o d e m o s parsear el a rch ivo b i b l i o t e c a xml

ltphp $biblioteca = simplexTnl_load_fiie(bibliotecaxml) foreach ($biblioteca-gttema as $tema)

echo Tema es $tema[id] ltbrgt foreach ($tema-libro as $libro)

echo ltbgt $libro-gttitulo ltbgt -

echo $libro-gtautor ltbrgt

gt

Lo primero que llama la atencioacuten es que en apenas 10 liacuteneas de coacutedigo se ha conseguido extraer todos los datos necesarios a diferencia de SAX o DOM

La funcioacuten s implexml__load_f i le () crea un objeto con el archivo XML que pase como argumento

A partir de aquiacute puede acceder a todos los datos asiacute como acceder a las variables de los objetos

echo $biblioteca-gttema-gtlibro [0] -gttitulo echo $biblioteca-gttema-gtlibro[1]-gttitulo

Para extraer el contenido que necesita lo maacutes sencillo es crear una estrucshytura de bucles f o r e a c h para ir sacando los datos ordenados

El nombre SimpleXML es totalmente descriptivo aunque no hay que conshyfundir la palabra simple con baacutesico La prueba de su potencia estaacute en que los desarrolladores de PEAR van a utilizar SimpleXML para desarrollar su libreriacutea de SOAP

Lectura y escritura de archivos XML 261

Resumen

XML se ha convertido en un estaacutendar para el intercambio de informacioacuten en Internet Numerosas aplicaciones estaacuten construidas con alguacuten tipo de tecnologiacutea que implementa XML como XML-RPC RSS o SOAP

En este capiacutetulo ha aprendido a leer y escribir documentos de tres formas posibles La maacutes completa sin duda es DOM que permite ademaacutes de leer archivos escribir y modificarlos a nuestro antojo El problema es que pueshyde resultar algo complicado de entender al principio y quizaacute no merezca la pena en aplicaciones sencillas

En el capiacutetulo siguiente conoceraacute la verdadera aplicacioacuten praacutectica Basaacutenshydonos en SimpleXML y en DOM crearemos algunas clases para leer archishyvos de noticias o ejecutar funciones definidas en un ordenador remoto

264 Capiacutetulo 15

Introduccioacuten

Existen en el mercado muchas publicaciones que hablan sobre XML y sus tecnologiacuteas derivadas En estos libros que suelen ser de unas 1000 paacuteginas se hace un recorrido por todos los rincones de XML DTD XLST etceacutetera Si lee alguna publicacioacuten de este tipo puede quedar desencanshytado porque entre tantos conceptos no se ve una aplicacioacuten real de la tecnologiacutea

Como este libro es eminentemente praacutectico me gustariacutea que el lector aprenshydiera dos metodologiacuteas que se utilizan actualmente en la Web RSS y XML-RPC La primera describe una forma de exportar informacioacuten noticias o datos al exterior para que desde cualquier paacutegina Web puedan leerse La segunda es una forma de trabajar que permite ejecutar funciones que esshytaacuten almacenadas en un ordenador remoto

Compartir informacioacuten con RSS

RSS es un mecanismo para publicar informacioacuten sobre el contenido de un sitio Web y es muy comuacuten utilizarlo para dar las uacuteltimas noticias Esto permite introducir en su sitio Web un documento XML con noticias de otras paacuteginas

La versioacuten original de RSS la 090 fue creada por Netscape con el objetishyvo de crear portales servidores de noticias de distinta categoriacutea pero reshysultoacute algo complejo de utilizar La versioacuten 091 mucho maacutes simple la desarrolloacute la empresa UserLand Software quien lo comercializoacute como parte de sus productos basados en paacutegina Web como los Weblogs

Un tercer grupo de desabolladores independientes basaacutendose en los coshymienzos de RSS la versioacuten 090 escribioacute una nueva revisioacuten basada en RDF esta versioacuten recibe el nombre de RSS 10 Desde la aparicioacuten de la versioacuten 01 UserLand Software ha seguido desarrollando las versiones 092 093 094 y la 20

Distintos formatos

Existen 7 formatos distintos y como programador deberiacutea ser lo suficienshyte habilidoso como para manejar cualquiera de ellos Pero como el conteacute-

Aplicaciones praacutecticas de XML 265

nido lo produce la Web que desea exportar su informacioacuten tendraacute que tener en cuenta las caracteriacutesticas de cada formato

Tabla 151 versiones de RSS

Versioacuten Desarrollo Descripcioacuten Status Recomendacioacuten

090 Netscape Obsoleta No usar por la apashyricioacuten de 10

091 UserLand Simple Muy popular Sencilla y faacutecil de pero obsoleta migrar a la versioacuten por la aparicioacuten 20 de 20

092 UserLand Permite texto Obsoleto por Mejor usar la 20 093 enriquecido y la 20 094 metadatos

10 Grupo de Basado en Muy estable Usar si necesitamos desarrollo RDF y exten- especificaciones RSS-DEV sible con avanzadas

moacutedulos

20 UserLand Exter=Aacuteble corraquo EsteWe y ef Uso de caraacutecter moacutedulos Faacutecil continuo general con meta-de migrar desarrollo datos y texto enri-desde cualquier quecido versioacuten 09

Como ejemplo vamos a leer el RSS 10 de la Web del autor wwwluisy fernandanet que contiene esta informacioacuten

ltxml version=10 encoding=iso-8859-1 gt ltrdfRDF xmlnsrdf=httpwwww3org19990222 -rdf-syntax-ns xmlns=httpmynetscapecomrdfsimple09gt

ltchannelgt lttitlegtwwwluiacutesyfernandanetlttitlegt ltlinkgthttpwwwluisyfernandanetiacutendexphp

blogId=2ltlinkgt ltdescriptionxdescriptiongt

ltchannelgt ltitemgt

lttitlegtPHP 5 en la liacutenea de salidalttitlegt ltdescriptiorvgtiacuteuumladi Gutwampias dice que en 24 horas estaraacute lista la nueva versioacuten de PHP5 bull que nervios ampltbr

266 Capiacutetulo 15

ampgtPara el que no pueda esperar la Releacutease Candidate 4 estaacute en amplta href =ampquothttp snapsphpnet~andiampquotampgthttpsnapsphpnet ~andiampltaampgtampltbrampgt ampltbrampgtampltbrampgtlt descriptiongt

ltlinkgthttpwwwluisyfernandanetiacutendexphpop=View ArticleampamparticleId=41ampampblogId=2ltlinkgt ltitemgt

lt itemgt lttitlegtGalopiacuten 10lttitlegt ltdescriptiongt amplt a

href=ampquothttpwwwluisyfernandanetresserverphp blogId=2amp amp resource=DSCN0840 JPG ampquot ampgt amplt img align=ampquot rightampquot style=ampquotmargin 5pxampquot border=ampquotOampquot alt=ampquotRueda de prensaampquot src=ampquothttpwwwluisyfernandanetresserver phpblogId=2ampampresource=DSCN0 840JPGampampmode=previewampquot ampgtampltaampgt

Hoy se ha presentado en la AAVV de La Antigua en Meacuterida la versioacuten 10 de Galopiacuten una herramienta escrita en PHP por dos desarrolladores extrementildeos Tras los forcejeos con la prensa y las salidas con quite de los implicados nos quedamos con la miel en los labios deseando probar la aplicacioacuten y porqueacute no destriparla para ver como funciona el chismeampltbr ampgtEl que quiera descargarla puede hacerlo desde la Web de sinuh en amplta href=ampquothttp galopinsinuhorgampquotampgtgalopinsinuhorgampltaampgtampltbr

ampgtScltbxSiacutegpound ampltbr ampgtltdescriptiongt ltlinkgthttpwwwluisyfernandanet

indexphpop=ViewArticleampamparticleld=4 0ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtEL TIEMPO DE MERIDAlttIacutetlegt ltdescriptiongt Hace unos diacuteas empeceacute escribir alguna cosilla para averiguar

la temperatura que hay en Meacuterida Los datos los recojo de la Web del Instituto Nacional de Meteorologiacutea y los plasmo en una tabla Si quieres puedes utilizar los datos llamando a la Web amplt a href = ampquothttpwwwluisyfernandanet clase_tiempophpLOCALIDAD=MERIDAampquotampgthttp wwwluisyfernandanetclase_tiempophpLOCALIDAD=MERIDAamplt aampgtampltbr ampgtDonde pone LOCALIDAD se puede poner alguna poblacioacuten distinta como CORIA CACERES BADAJOZUNIVERSIDAD etcampltbr ampgtEl moacutedulo estaacute en fase alfa y el dibujito que aparece puede que no corresponda con la realidad pero es un avance )ampltbr ampgtEn unas semanas implementareacute el servicio en SOAP como lo hace weathercomampltbr ampgtSaludosampltbr ampgtampltbr ampgtampltbr ampgtampltbrampgt

Aplicaciones praacutecticas de XML 267

ampltbr ampgtltdescriptiongt ltlinkgthttpwwwluisyfernandanet

indexphpop=ViacuteewArticleampamparticleld=3 6ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtPHP 5 a punto de caramelolttitlegt ltdescriptiongtHace un par de diacuteas en la lista interna de

desarrolladores de PHP Andi Gutmans ha escrito que PHP5 ya estaacute horneado y le falta un poquito de chocolate para salir al mercado Estaacuten teniendo alguacuten problemilla con libreriacuteas que controlan el acceso a memoria pero se preveacute que la primera versioacuten estable salga esta semana ampltbr ampgtamplta href=ampquothttpwwwzendcomlistsphp-dev2004 07 msg00059htmlampquot ampgtNotica de Zend ampltaampgtampltbr ampgtampltbr ampgtltdescriptiongt

ltlinkgthttpwwwluisyfernandanet indexphpop=ViewArticleampamparticleld=3 3ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtOpenOffice2htm en Sourceforgelttitlegt ltdescriptiongt Acaban de aceptar el Proyecto OpenOffice2htm

en sourceforge ellos sabraacuten lo que hacen Lo que pasa es que tengo un pequentildeo problema entre tanto menuacute de administracioacuten de ficheros documentos etc me pierdo y por ahora no he podido subir ninguacuten fichero de la clase Espero aclararme estos diacuteas y tener listo la primera Releacutease en amplta href=ampquothttpwwwluisyfernandanet wwwsourceforgecomampquotampgtwwwsourceforgecomamplt aampgtampltbr ampgtampltbrampgtampltbr ampgtltdescriptiongt

ltlinkgthttpwwwluisyfernandanet indexphpop=ViewArticleampamparticleld=17ampampblogId=2ltlinkgt ltitemgt ltrdfRDFgt

El archivo anterior muestra las uacuteltimas noticias de la Web www lu i sy fernadanet sobre PHP y proyectos en los que el autor estaacute involucrado

Si se fija no es maacutes que un archivo XML con un formato determinado

Puede verlo en la figura 151

Tiene dos partes diferenciadas

bull Una parte de descripcioacuten del documento entre las etiquetas ltchan-n e l gt En esta zona puede encontrar el tiacutetulo de Web donde estaacuten las noticias la URL del archivo RSS y una descripcioacuten de la temaacutetica que aborda

bull Otra zona entre los nodos lt i t emgt que contiene todas las noticias que quiere exportar

Leer un archivo RSS

En el capiacutetulo anterior vimos coacutemo parsear un archivo XML creado por nosotros mismos Esta vez tenemos que extraer el contenido que nos inshyteresa de un archivo con un formato determinado Vamos a crear un peshyquentildeo objeto que sea capaz de insertar en nuestra Web las noticias de la paacutegina wwwluisyfernandanet Por supuesto vamos a utilizar SimpleXML por ser una de las herramientas estrella de PHP 5

ltphp class SimpleRSS

priacutevate $RSS function construct($fichero)

$this-gtRSS = simplexml_load_file($fichero)

public function parsea_item() foreach ($this-gtRSS-gtitem as $item)

$this-gtparsea_titulo($item) $this-gtparsea_descripcion($item) $this-gtparsea_enlace($item)

private function parsea_titulo($item)

Aplicaciones praacutecticas de XML 269

echo $item-gttitle bull ltbrgt echo lthrgt

priacutevate function parsea_descripcion ($item)

echo $item-gtdescription ltbrgt

priacutevate function prsea_enlace($item)

echo $item-gtlink bull ltbrgt

public function paiacutesea_cabecera()

ampc^o Titilo- laquo St^va-^SSS-gtet^trade^l-gttltLe -JaxV- echo Web $this-gtRSS-gtchannel-gtlink ltbrgt echo lthrgt

$RSS = new SimpleRSS(httpwwwluisyfernandanet rssphpcategoryId = 3ampblogId=2 ) $RSS-gtparsea_cabecera () $RSS-gtparsea_item() gt

Si ejecuta el programa tendraacute como resultado las uacuteltimas noticias sobre PHP del portal wwwluisyfernandanet separadas por liacuteneas horizontashyles El meacutetodo puacuteblico p a r s e a _ i t e m () es el encargado de extraer notishycia a noticia y mandarlas al navegador Este meacutetodo hace 3 llamadas a 3 meacutetodos distintos que se encargan de recuperar el tiacutetulo el enlace a la noticia y la descripcioacuten Hemos separado los meacutetodos para que cada lector personalice la forma de visualizar los distintos datos Mi forma particular puede verla en la fishygura 152 Por ejemplo el tiacutetulo podriacutea mostrarlo en azul y el texto en gris todo metido en una tabla-

Escribir archivos RSS

Los archivos XML y en particular los archivos RSS pueden generarse de la misma forma que creamos un fichero de texto antildeadiendo etiquetas con cierto criterio a un archivo de texto pero la opcioacuten maacutes correcta es utilizar DOM para generar nuestros propios documentos de noticias Como ya sabe la extensioacuten DOM permite antildeadir borrar y modificar eleshymentos a lo largo de un documento en cualquier orden

Para este cometido tenemos la siguiente clase que nos va a generar docushymentos RSS a partir de cualquier fuente de datos

ltphp class GeneraRSS

priacutevate documento private $raiz priacutevate $channel private $titulo private $enlace private descripcioacuten private $item function construct() $this-gtdocumento = new domdocument(1bull0 ) $this-gtinicio ( )

private function inicio() $this-gtraiz = $this-gtdocumento-gtcreateElement(rdfRDF ) $this-gtraiz-gtsetAttribute(xmlnsrdfhttpwwww3org1999 0222-rdf-syntax-ns) $this-gtraiz-gtsetAttribute(xmlnshttppurlorgrss10) $this-gtraiz = $this-gtdocumento-gtappendChild($this-gtraiz)

Aplicaciones praacutecticas de XML 271

pub l i c funct ion c a n a l ( $ t i t u l o $ e n l a c e $ d e s c r i p c i o n $ s o b r e )

$this-gtchannel = $this-gtdocumento-gtcreateacuteElement(channel) $this-gtchannel = $ th i s -gtra iz -gtappendChi ld ($ th i s -gtchanne l ) $ th i s -gt t i tu lo=$th i s -gtdocumento-gtcrea teElement ( t i t l e ) $ th i s -gt tex to t i t u lo=$ th i s -gtdocumen to -gtc rea t eTex tNode($ t i tu lo ) $ t h i s - gt t i t u l o - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o t i t u l o ) $ t h i s - gt c h a n n e l - gt a p p e n d C h i l d ( $ t h i s - gt t i t u l o ) $ t h i s - gt e n l a c e = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l s m e n t ( l i n k ) $ th i s -gt tex toen lace=$th i s -gtdocumento-gtcrea teTextNode($en lace) $ t h i s - gt e n l a c e - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o e n l a c e ) $ th i s -gtchanne l -gtappendChi ld ($ th i s -gten lace ) $ t h i s - gt d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( d e s c r i p t i o n ) $ t h i s - gt t e x t o d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e T e x t N o d e ( $ d e s c r i p c i o n ) $ t h i s - gt d e s c r i p c i o n - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o d e s c r i p c i o n $ th i s -gtchanne l -gtappendCh i ld ($ th i s -gtdesc r ipc ion )

pub l i c funct ion i t em_nuevo($ t i tu lo $en lace $descr ipcion)

$this-gti tem = $this-gtdocumento-gtcreateElltment( i tem) $ this-gti tem = $ th i s -gtra iz -gtappendChi ld ($ th i s -gt i t em) $ t h i s - gt t i t u l o = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( t i t l e ) $ th i s -gt t ex to t i t u lo=$ th i s -gtdocumen to -gtc rea t eTex tNode ($ t i t u lo ) $ t h i s - gt t i t u l o - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o t i t u l o )

$ t h i s - gt i t e m - gt a p p e n d C h i l d ( $ t h i s - gt t i t u l o ) $ t h i s - gt e n l a c e = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( l i n k ) $ th i s -gt tex toen lace=$th i s -gtdocumento-gtcrea teTextNode($en lace) $ t h i s - gt e n l a c e - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o e n l a c e ) $ t h i s - gt i t e m - gt a p p e n d c h i l d ( $ t h i s - gt e n l a c e ) $ t h i s - gt d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( d e s c r i p t i o n ) $ t h i s - gt t e x t o d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e T e x t N o d e ( $ d e s c r i p c i o n ) $ t h i s - gt d e s c r i p c i o n - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o d e s c r i p c i o n ) $ t h i s - gt i t e m - gt a p p e n d C h i l d ( $ t h i s - gt d e s c r i p c i oacute n ) $ th i s -gt i t ems [ ]=$ th i s -gt i t em

public function grabar($fichero) $this-gtdocumento-gtsave($fichero)

^documento = new GeneraRSS () ^documento-gtcanal (wwwluisyfernandanet httpwwwluisy fernandanet La Web del auto) $docimeito-gtitev1_YYievo VMaiwial Imprescindible de PHP 5 http- v iwwluisyfernandanet Ya a la v e n t a )

272 Capiacutetulo 15

$documento-gtitem_nuevo(Nueva releacutease de PHP 5http wwwiuisyfernandanetLa nueva releacutease corrige algunos fallos) Sdocumento-gtgrabar(miRSSxml) gt

La clase anterior se puede guardar en un archivo independiente y utilizar cuando sea necesario en el transcurso de un proyecto

Aunque no implementa todas las especificaciones de RSS 10 puede utilishyzarse para generar noticias de nuestra base de datos

Nota

Si desea modificar ia ciase para que contemple todas las opciones de Ja especificacioacuten RSS 10 puede visitar ia Web httpllpurtorgl rss10

En el capiacutetulo anterior vimos coacutemo se puede generar un archivo XML con una sucesioacuten de llamadas a meacutetodos Esta vez hemos encapsulado todas las llamadas en varios meacutetodos que se encargan de generar la parte de descripcioacuten del RSS y por otro lado las noticias

El meacutetodo c r e a t e E l e m e n t () se encarga de crear nuevos nodos para desshypueacutes encadenarlos c o n a p p e n d C h i l d () a los nodos padre Para crear un nodo de texto sin embargo tenemos que utilizar el meacutetodo c r e a t e T e x t -Node () una vez creado el nodo de texto tenemos que asociarlo a un nodo-elemento (una etiqueta)

El uacuteltimo paso es hacer una llamada al meacutetodo s a v e () con el nombre del fichero como paraacutemetro para guardar el archivo RSS

Servicios Web XML-RPC

El trabajo como programador puede llevarle a desarrollar aplicaciones para distintos Sistemas Operativos y en distintos lenguajes de prograshymacioacuten

Si en alguacuten momento necesita comunicar dos programas que estaacuten funshycionando en maacutequinas distintas (un servidor Windows y otro gnuLinux) y escritos con lenguajes diferentes puede que XML-RPC sea la solucioacuten perfecta

El mecanismo permite que el ordenador cliente pueda acceder a los meacutetoshydos del ordenador servidor y ejecutar rutinas almacenadas remotamente

Aplicaciones praacutecticas de XML 273

Este apartado muestra alguacuten ejemplo de coacutemo implementar y explotar un servicio Web con la libreriacutea de clase IXR creada por Simoacuten Willison bajo el auspicio de Open Source

Una llamada XML-RPC consiste en dos partes una pregunta y una resshypuesta

Cada una de las partes es un archivo XML que contiene los paraacutemetros solicitados al servidor o los datos devueltos

Una pregunta al servidor puede ser como la que sigue

ltmethodCalIgt ltmethodNamegtconteritgetNotiacuteciasltmethodNamegt ltparamsgt

ltparamgt ltvaluexintgt23ltiacutent gtltvaluegt

ltparamgt ltparams gt

ltmethodCallgt

Como puede ver es un archivo XML con una definicioacuten determinada La etiqueta ltmethodNamegt contiene el nombre del meacutetodo que debe llamarse en el servidor y ltparamgt contiene un paraacutemetro que se le pasaraacute al meacutetoshydo de la llamada

El documento anterior seraacute transmitido viacutea HTTP mediante POST al sershyvidor de XML-RPC que parsearaacute el documento ejecutaraacute la funcioacuten y devolveraacute un documento similar con los datos de la respuesta

Clase IXR

IXR es un conjunto de clases que implementa un servidor y un cliente de XML-RPC

Nota

Puede encontrar la libreriacutea en la Web httpscriptsiricutiocom xmlrpc o en la paacutegina del libro en httpunuzunnaiamulti-mediacom

Lo mejor de la programacioacuten orientada a objetos es que no necesita saber coacutemo funcionan las clases que utilice soacutelo conocer el uso correcto de los meacutetodos Asiacute puede utilizar la clase IXR de la manera que vamos a ver sin conocer siquiera el formato de los archivos XML-RPC

274 Capiacutetulo 15

Cliente XML-RPC

Los servicios XML-RPC tienen una direccioacuten Web con una paacutegina Web escrita en PHP Si escribe la direccioacuten completa en el navegador se proshyduciraacute un error porque la Web esperaraacute que mande mediante POST un archivo XML Para utilizar sus servicios Web o los servicios Web de alshyguna empresa como UserLand tiene que utilizar un cliente XML-RPC escrito en este caso en PHP 5 En este caso vamos a utilizar la clase IXR__Client de la libreriacutea IXR El ejemplo muestra coacutemo utilizar el cliente en varios pasos

bull Crear un objeto cliente con la URL pasada como paraacutemetro

bull Usar el meacutetodo q u e r y () para hacer la consulta al servicio Web

bull Extrae el resultado con el meacutetodo g e t R e s p o n s e ()

Lo primero que vamos a hacer es implementar un pequentildeo objeto para recuperar la fecha de un servidor remoto

ltphp require_once(IXR_Libraryincphp) class XMLRPCFechacliente

private $cliente function construct($url$debug=false) $this-gtcliente= new IXR__Client ($url) $this-gtcliacuteente-gtdebug=$debug

function getFecha($argumentol) if ($this-gtcliente-gtquery(fechagetFecha$argumentol)) trigger_error($this-gtcliente-gtgetErrorCode () $this-gtcliente-gtgetErrorMessage()) return false

return $this-gtcliente-gtgetResponse ()

gt

La clase X M L R P C F e c h a c l i e n t e implementa dos meacutetodos El construcshytor crea un objeto cliente IXR que recibe el servidor de servicios Web El meacutetodo g e t F e c h a () tramita la peticioacuten de la fecha con el servidor y obshytiene una respuesta que devuelve a la paacutegina Web Si todo va bien el sershyvidor enviaraacute la fecha del lugar donde esteacute

La llamada a q u e r y () tiene como paraacutemetro primero el nombre del meacuteshytodo que debe ejecutar el servidor y como segundo paraacutemetro un argu-

Aplicaciones praacutecticas de XML 275

mentoacute que puede pasarse La Web que quiera mostrar esta informacioacuten debe crear el objeto anterior maacutes o menos como se muestra en el siguiente ejemplo

ltphp require_once(XMLRPCFechaclientephp) $servidor=httpwwwluisyfernandanetFechaphp $fechaRemota= new XMLRPCFechacliente($servidor) echo $fechaRemota-gtgetFecha(Hoy) gt

Si evaluacutea el coacutedigo en tan soacutelo 4 liacuteneas puede recibir cualquier tipo de informacioacuten que el servidor tenga Para ello debe crear una variable que contenga el nombre del servidor y la paacutegina PHP que contiene el prograshyma de respuesta La instanciacioacuten del objeto X M L R P C F e c h a c l i e n t e y la llamada al meacutetodo g e t F e c h a () es suficiente para desencadenar la coshynexioacuten con el servidor

Servidor XML-RPC

En el apartado anterior ha visto que puede utilizar servicios Web ofrecishydos por otras empresas para averiguar la hora de un Paiacutes remoto el camshybio de moneda el tiempo o incluso el cataacutelogo de libros de una conocida tienda on-line Pero lo realmente interesante es poder crear sus propios servicios Web

La clase IXR_Server hace la mayoriacutea del trabajo por usted que puede emplear el tiempo en inventar nuevos servicios Web

Hemos creado una clase que implementa el servicio g e t F e c h a ( ) que el objeto cliente utiliza

ltphp require_once(IXR_Libraryincphp) class XMLRPCFechaservidor extends IXR_Server

function construct()

$this-gtIXR_Server(array(fechagetFecha =gt thisgetFecha)) function getFecha($argumentol)

if ($argumentol==Hoy) $fecha = La fecha remota es date(d-m-Y)

else

$fecha = Especifique un dia

2 7 6 Capiacutetulo 15

re turn $fecha

gt

La clave para entender el funcionamiento del servidor estaacute en el construcshytor Aquiacute se crea un array con el nombre de los meacutetodos que se pueden utilizar desde fuera

El primer valor f e c h a g e t F e c h a es el nombre que el cliente debe emshyplear para recuperar la Fecha del Servidor y el segundo valor t h i s g e t Fecha es el meacutetodo perteneciente al servidor que se ejecutaraacute cuando reciba una pregunta a esa funcioacuten

La figura 153 muestra el dato que obtiene el cliente

La definicioacuten del meacutetodo que enviacutea la fecha se hace como ya estamos acosshytumbrados

Lo que hemos visto es soacutelo la definicioacuten de la clase pero necesitamos una paacutegina Web de apoyo que instancie el objeto y lo ejecute Puede ser tan sencillo como

ltphp require_once(XMLRPCFechaservidorphp) $servidor= new XMLRPCFechaservidor() gt

Aplicaciones praacutecticas de XML 277

Usos de XML-RPC

Los ejemplos que hemos visto no son especialmente excitantes pero dan una idea de lo sencillo que es exportar cualquier tipo de informacioacuten La verdadera potencia de los servicios Web es que permiten disfrutar de nueshyvas funcionalidades de las que no disponemos Podriacuteamos crear un servishycio Web que permitiera a usuarios de PHP 4 utilizar nuestro objeto de SimpleXML pero esto lo dejo en manos del lector

Resumen

XML se ha convertido en los uacuteltimos antildeos en un estaacutendar libre para el inshytercambio de informacioacuten Incluso Microsoft poco amiga de los archivos abiertos estaacute implementando servicios en XML con su plataforma NET

Despueacutes de leer este capiacutetulo podraacute crear elegantes paacuteginas que contenshygan noticias relevantes sobre cualquier tema y exportarlas a otras paacuteginas amigas gracias a la tecnologiacutea RSS

En cuanto a la creacioacuten de servicios Web existe una controversia entre dos desarrollos principales XML-RPC y SOAP de Microsoft SOAP (Simshyple Object Access Protocol) es una implementacioacuten muy extensa de Microshysoft para la creacioacuten de servicios Web Pese a que su definicioacuten aboga por la simpleza (Protocolo Simple) la paradoja es que es mucho maacutes complishycada de utilizar que XML-RPC y por eso se escapa de los objetivos de este libro

Una de las nuevas caracteriacutesticas de PHP 5 es la inclusioacuten de una extenshysioacuten para la generacioacuten de servidores y clientes SOAP pero todaviacutea estaacute en fase experimental

El futuro cercano puede estar en SOAP asiacute que recomiendo al lector visishytar algunas paacuteginas Web sobre el tema para comenzar a entender su funshycionamiento

280 Capiacutetulo 16

Introduccioacuten

La construccioacuten de un sitio Web no soacutelo debe contar con textos bases de datos y funciones escritas en PHP para manejar los datos Existe un gran abanico de posibilidades que pueden dotar a la paacutegina de contenido multishymedia (imaacutegenes v sonidos) y que ademaacutes pueden ser procesados de alshyguna forma por PHP

Entre las funciones maacutes baacutesicas de interactuacioacuten con las imaacutegenes PHP puede realizar graacuteficos de barras para mostrar resultados estadiacutesticos antildeadir una marca de agua a todas nuestras fotografiacuteas o mostrar una reacuteshyplica de las imaacutegenes en un formato maacutes reducido para poder seleccionar entre un conjunto de ellas

La mayoriacutea de los ejemplos utilizan la libreriacutea graacutefica GD para PHP que puede instalarse faacutecilmente en los tres Sistemas Operativos maacutes comunes (gnuLinux MacOSX y Windows)

Graacuteficos HTML

Antes de entrar de lleno en las maravillas que ofrece la libreriacutea graacutefica GD vamos a realizar un pequentildeo ejemplo para aprovechar las posibilidades del lenguaje HTML para la creacioacuten de estadiacutesticas graacuteficas Esta posibilishydad nos permite realizar estudios graacuteficos baacutesicos sin tener que instalar ninguacuten paquete adicional a PHP

Puede decantarse por este meacutetodo o por utilizar la libreriacutea dependiendo de la complejidad de su proyecto

Vamos a crear como ejemplo un sistema de votacioacuten electroacutenico que cuente los votos de cada participante y los almacene en una base de datos Vashymos a utilizar el gestor SQLite visto en el capiacutetulo 11 Para tal fin hemos creado una clase de conexioacuten a SQLite muy parecida a la clase de conexioacuten de MySQL

ltphp

class Servidor_Base_Datos

priacutevate $base_datos priacutevate $descriacuteptor priacutevate ^resultado function construct($base_datos)

Generacioacuten de graacuteficos con PHP 5 281

$this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtpass = $pass $this-gtbase_datos = $base_datos $this-gtconectar_base_datos()

priacutevate function conectar_base_datos( )

$thiacutes-gtdescriptor = sqlite_open($this-gtbase_datos)

i public function consulta($consulta)

$this-gtresultado = sqlite_query($consulta $this-

gtdescriptor) public function extraer__registro ()

if ($fila = sqlite_fetch_array($this-

gtresultadoSQLITE_ASSOC)) return $fila

else return false

gt

Los meacutetodos son praacutecticamente iguales y la forma de utilizar el objeto es exactamente igual que en los ejemplos del capiacutetulo 12

Los datos que vamos a manejar en la encuesta son parte de una pequentildea tabla que almacenaraacute el nombre del Lenguaje de Programacioacuten que prefeshyrimos y el nuacutemero de votos que le hemos dado Podemos inicializar la base de datos con el siguiente script

ltphp requirejonee(clase_SQLitephp) $base_datos = new Servidor_Base_Datos(votacionesdb) $base_datos-gtconsulta(creacuteate table lenguaje (id_lenguaje INT PRIMARY KEY lenguaje CHAR(255) votos INT))

$base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees ( PHP 0) ) $base_datos-gtcoacutensulta(insert into lenguaj e (lenguaj evotos) valuacutees (JSPeuro)) $base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees (ASP 0) )

282 Capiacutetulo 16

$base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees (COLD FUSIOacuteN0)) $base_datos-gtconsulta(select from lenguaje)

while ($fila = $base_datos-gtextraer_registro ()) echo $fila [lenguaje] $fila[votos] ltbrgt

gt

Todo deberiacutea serle familiar Lo que hacemos es crear una tabla nueva en la base de datos e insertar los lenguajes objetivo de la encuesta Por uacuteltishymo hacemos una comprobacioacuten para ver si los datos estaacuten almacenados en la base de datos Lo siguiente que vamos a ver es una Web con un formulario para elegir el lenguaje que maacutes nos agrada En la zona inferior de la paacutegina tenemos un contador que nos indica el nuacutemero de votos

ltphp

Primero comprobamos si tenemos un voto

$base_datos = new Servidor_Base_Datos(votaciones2db)

Si hemos votado sumamos el valor al nuacutemero de votos almacenado

if (isset($_POST[voto] ) )

$voto = $_POST[voto] $base_datos-gtconsulta(select votos from lenguaje where id_lenguaj e=$voto) $numero_votos = $base_datos-gtextraer_registro() $numero_votos = $numero_votos[votos] $numero_votos + + $base_datos-gtconsulta(update lenguaje set votos= $numero_votos where id_lenguaje = $voto)

gt lthtmlgt ltbodygt iquestQueacute lenguaje de programacioacuten prefieres

Formulario que permite votar

ltform action=votophp method=post gt ltselect name=votogt ltphp $base_datos-gtconsulta (select from lenguaje) while ($fila = $base_datos-gtextraer_registro () )

$id_lenguaje = $fila[id_lenguaje] $lenguaje = $fila [lenguaje]

Generacioacuten de graacuteficos con PHP 5 283

echo ltoption value=$id_lenguajegt$lenguajeltoptiongt

gt ltselectgt ltinput type=submit name=Enviar value=Enviar gt ltformgt lttablegt ltphp $base_datos-gtconsulta(select from lenguaje) while ($fila = $base_datos-gtextraer_registro () )

$lenguaje = $fila [lenguaje] $votos = $fila [ votos] echo lt t rx tdgt$ lengua j e lt t d x t d gt $votos vo toslt tdgtlt

t r gt

gt lt t ab l egt ltbodygt lthtmlgt

Como puede ver es un mecanismo muy sencillo de entender La parte principal es el formulario que permite elegir entre los 4 lenguajes de script Si enviamos un voto la misma paacutegina recibiraacute el dato y actualizaraacute la base de datos mostrando posteriormente los votos que tienen los lenguajes En la figura 161 puede ver el resultado

284 Capitulo 16

Graacuteficos de barras

Despueacutes de todo este coacutedigo estaraacute preguntaacutendose por las imaacutegenes geshyneradas automaacuteticamente Todaviacutea no hemos hecho nada de eso pero en el coacutedigo siguiente tiene la clave de este apartado Baacutesicamente jugamos con 4 imaacutegenes r o j o png v e r d e p n g a z u l png y a m a r i l l o png Cada imagen tiene un tamantildeo de 1 piacutexel de ancho y alto El truco estaacute en hacer un caacutelculo porcentuado de los valores de votos con respecto al que mayor votos tiene

De ahiacute sacamos el ancho de la imagen Una vez encontrado este ancho se le pasa a la propiedad w i d t h de la etiqueta lt imggt y obtenemos un graacutefishyco con imaacutegenes de distintos anchos es decir obtenemos un graacutefico de barras estadiacutestico

El coacutedigo puede ser como el siguiente

ltphp $imagenes = array(rojopngazulpngverdepngamarillopng) $base_datos-gtconsulta(select from lenguaje) while ($fila = $base_datos-gtextraer_registro() )

$id_lenguaje = $fila [ id_lenguaje ] $lenguaje = $fila [lenguaje] $votos = $fila[votos] $ancho = dame_ancho($votos$id_lenguaje) $imagen = $ imagenes[$ id_ lengua je -1] echo lt t r x t d gt $ l e n g u a j e - $votos v o t o s lt t d x t d x i m g src=$imagen width=$ancho h e i g h t = 2 0 gt lt t d x t r gt

function dame_ancho($votos)

$base_datos2 = new Servidor_Base_Datos(votaciones2db) $base_datos2-gtconsulta(select max(votos) as maacuteximo from lenguaje) $numero_votos = $base_datos2-gtextraer_registro() $maximo_votos = $numero_votos[maacuteximo] return (intval($votos)300)intval($maximo_votos)

gt lttablegt

Antes generaacutebamos una tabla con los lenguajes y el nuacutemero de votos Ahora generamos los lenguajes y calculamos con la funcioacuten dame_an-cho () el porcentaje con respecto al mayor valor de cada uno de los votos de los lenguajes La figura 162 muestra los graacuteficos de barras de la votacioacuten electroacutenica

Libreriacutea GD

La libreriacutea graacutefica GD estaacute escrita en lenguaje C y permite crear y manipushylar graacuteficos faacutecilmente Permite importar y exportar graacuteficos de distinto tipo (GIF JPG y PNG) La filosofiacutea de los archivos GIF y PNG es casi la misma Estos dos archivos guardan en memoria el conjunto completo de piacutexeles con su color concreto y comprimen el resultado para que el archishyvo final no sea muy pesado Los archivos JPG tambieacuten estaacuten comprimishydos pero se basan en algoritmos complejos que permiten un mayor rendimiento y la hacen muy propicia para usarse con fotografiacuteas

Tipos MIME

El estaacutendar MIME se concibioacute originariamente para identificar los difeshyrentes contenidos que podemos enviar por correo electroacutenico Actualmente se utiliza para describir el tipo de archivo que enviamos a traveacutes de Intershynet Es importante conocer los tipos MIME para trabajar con las libreriacuteas GD

En general antes de recibir la respuesta del servidor eacuteste debe enviarnos una cabecera anunciando el tipo de contenido que vamos a recibir usando una cabecera especial C o n t e n t - T y p e PHP por defecto enviacutea el tipo

286 Capiacutetulo 16

MIME t e x t h t m l (documento HTML) Cuando utilice la libreriacutea GD necesitaraacute enviar una cabecera con el tipo de la imagen

ltphp header(Content-Type imagepng) gt

Tabla 161 Tipos MIME

Formato de imagen MIMEacute

JPG iexclmagejpeg

PNG imagepng

GIF imagegif

BMP imagebmp

SVG imagexml+svg

Mostrar una imagen en pantalla

Normalmente utilizamos la etiqueta ltimggt de HTML para mostrar una imagen en un lugar determinado de nuestra paacutegina Web La propiedad s r c debe indicar una imagen determinada con formato coshynocido La liacutenea siguiente mostraraacute en pantalla el logotipo de php

ltimg src=phppnggt

La libreriacutea graacutefica GD tambieacuten permite enviar imaacutegenes con el uso de unas funciones determinadas Como ejemplo vamos a ver coacutemo mostrar el misshymo logotipo esta vez utilizando GD

ltphp $imagen = imagecreatefrompng(phppng) header(Content-Type imagepng) imagepng($imagen) gt

Advertencia

La etiquete ltimggt de nuestra paacutegina Web debe apuntar ahora al

archivo PHP que genera la imagen ltimg s r c = imagen php gt

La funcioacuten i m a g e c r e a t e f rompng () recupera una imagen de un archishyvo y crea un descriptor en la variable $ imagen Para mostrar la imagen

Generacioacuten de graacuteficos con PHP 5 287

tiene que enviar la cabecera del tipo de archivo graacutefico que quiere mosshytrar y despueacutes enviar la imagen con imagepng ()

A simple vista parece demasiado esfuerzo para algo que resuelve perfecshytamente la etiqueta ltimggt pero examine el siguiente coacutedigo

ltphp

$imagenes = array(phppngzendpngparispng) Semilla aleatoria srand( (double)microtime 01000000) $aleatorio = rand(02) $fichero = $imagenes[$aleatorio] $imagen = imagecreatef rompng ($f ichero) header(Content-Type imagepng) imagepng($imagen) gt

El array $ i m aacute g e n e s contiene varios archivos graacuteficos en PNG Generashymos un nuacutemero aleatorio y recuperamos la imagen que ocupa la posicioacuten del nuacutemero

Los siguientes pasos son exactamente iguales a los vistos anteriormente El script muestra una imagen distinta cada vez que lo ejecutamos y puede servir para crear una Web con distintos banners aleatorios Puede ver el resultado en la figura 163

288 Capiacutetulo 16

Crear imaacutegenes en miniatura

Si su paacutegina Web permite enviar fotografiacuteas quizaacute necesite mostrar un gran nuacutemero de ellas en una sola paacutegina HTML permite poner un ancho determinado a la imagen aunque el tamantildeo permaneceraacute invariable Lo ideal es crear dos versiones de cada fotografiacutea Una en miniatura con poco peso en bites y otra la original que puede ser mostrada cuando se haga clic en la imagen pequentildea

Gracias a la libreriacutea GD podraacute modificar el tamantildeo de las fotografiacuteas que quiera Vamos a crear una clase para generar fotografiacuteas con la mitad de tamantildeo

ltphp class imagen

priacutevate $archivo priacutevate $ imagen priacutevate $dimensiones function construct($archivo)

$this-gtarchivo = $archivo $this-gtimagen = imagecreatefromjpeg($archivo) $this-gtdimensiones = getimagesize ($archivo)

i

public function imagen_original()

header(Content-Type imagejpeg) imagejpeg$this-gtimagen)

public function imagen_miniacuteatura()

$dimensionx = $thiacutes-gtdimensiones[0] 2 $dimensiony = $this-gtdimensiones[1] 2 $this-gtminiatura = imagecreatetruecolor($dimensionx $dimensiony) imagecopyresampled($this-gtminiatura $this-gtimagen 0 0 0 0 $dimensionx $dimensiony $this-gtdimensiones[0] $this-gtdimensiones[1])header (Content-Type imagejpeg) imagejpeg($tnis-gtminiatura)

$fotografia = new imagen($_GET[fotografiacutea])

if ($_GET[modo]==original)

$fotografia-gtimagen_original()

Generacioacuten de graacuteficos con PHP 5 289

else $fotografia-gtimagen_miniatura()

gt

La clase estaacute especializada en construir imaacutegenes con la mitad de tamantildeo Para que funcione tiene que hacer una l lamada a la url c l a s e _ imagen php pasando como paraacutemetros GET el nombre de la fotografiacutea y el modo (tamantildeo original o miniatura)

El constructor de la clase rescata el archivo graacutefico y averigua las dimenshysiones X e Y con la funcioacuten g e t i m a g e s i z e ()

El meacutetodo i m a g e n _ o r i g i n a l () funciona exactamente igual que el ejemshyplo anterior El meacutetodo i m a g e n _ m i n u a t u r a () divide entre 2 las dimenshysiones capturadas de la imagen y crea un entorno de trabajo con esas dimensiones con la funcioacuten i m a g e c r e a t e t r u e c o l o r ( ) En este momenshyto la variable $ m i n i a t u r a del objeto tiene un espacio de memoria asigshynado para almacenar un graacutefico pero estaacute vaciacuteo Lo que hacen las liacuteneas siguientes es redimensionar y copiar la imagen original a nuestro entorno de trabajo La funcioacuten i m a g e c o p y r e s a m p l e d () copia la imagen guarshydada en el segundo paraacutemetro en el espacio de trabajo del primer paraacuteshymetro

Los argumentos 3 y 4 son las coordenadas X e Y donde empezaraacute a pegarshyse la imagen copiada y el 5 y 6 las coordenadas desde las que se empezaraacute a copiar la imagen original Los siguientes paraacutemetros son el ancho y alto de las imaacutegenes destino y origen

Una vez copiada la imagen al espacio de trabajo ya podemos mostrarla enviando la cabecera y la imagen con la funcioacuten image j pg ( )

Vamos a crear una Web que haga uso de esta clase

lthtmlgt ltbodygt ltform action=imagenphp method=POST enctype=multipart form-datagt Elige un archivo de imagen jpg ltinput type=file name=ficherogt ltinput type=submit name=Enviar value=Enviargt ltformgt ltphp if (isset($_FILES[fichero] ) )

echo Imagen Originalltbrgt $fotografia = $_FILES[fichero][tmp_name] copy($fotografia$_FILES[fichero] [ntildeame]) $foto_copia = $_FILES[fichero] [ntildeame] ampmodo= original

290 Capiacutetulo 16

$url = clase_imagenphpfotografia=$foto_copia echo ltimg src=$urlgt echo Imagen Miniaturaltbrgt $foto_copia = $_FILES[fichero ] [ntildeame] ampmodo= miniatura $url = clase_imagenphpfotografia=$foto_copia echo ltimg src=$urlgt

gt ltbodygt lthtmlgt

La paacutegina Web muestra un formulario que nos da la posibilidad de enviar al servidor una fotografiacutea de nuestro ordenador

Si le damos a enviar la paacutegina nos mostraraacute la fotografiacutea en su versioacuten original y en su versioacuten reducida como puede comprobar en la figura 164

Generar una marca de agua

Otro problema comuacuten sencillo de resolver es la creacioacuten de marcas de agua sobre las fotografiacuteas que ofrecemos en nuestra Web La marca de agua puede ser un graacutefico o un texto que insertamos encima de la fotografiacutea original

Generacioacuten de graacuteficos con PHP 5 291

Una forma sencilla de implementar marcas de agua es antildeadiendo un meacuteshytodo nuevo a la clase

priacutevate function marca_agua()

$this-gtmarca_agua = imagecreatefrompngphppng) $dimensiones = getimagesize(phppng) $posicionx = $this-gtdimensiones [0] - $dimensiones [0] $posiciony = $this-gtdimensiones [1] - $dimensiones [1] imagecopy($this-gtimagen $this-gtmarca_agua $posicionx $posiciony 0 0 $dimensiones [0] $dimensiones[1] )

Podemos llamar al meacutetodo desde el constructor para que la imagen guarshyde la informacioacuten de la fotografiacutea grabada e inserte la marca en alguna parte de la misma Tambieacuten podemos generar un texto como marca de agua

Vamos a antildeadir un nuevo meacutetodo a la clase para poder marcar las fotoshygrafiacuteas

priacutevate function marca_texto()

$color = imagecolorallocate($this-gtiraagen 25500) iacutemagestriacuteng($thiacutes-gtimagen 4 0 0 Hecho con PHP5

$color)

La figura 165 muestra la inclusioacuten de una marca de agua graacutefica y otra marca de agua de texto

292 Capiacutetulo 16

La funcioacuten i m a g e a l l oacute c a t e () crea un color con los componentes RGB como paraacutemetros La funcioacuten devuelve un nuacutemero que identifica al color creado en la imagen La funcioacuten i m a g e s t r i n g () imprime un texto de color determinado en la imagen El segundo paraacutemetro es el tipo de fuenshyte que queremos introducir

Graacuteficos estadiacutesticos profesionales con JpGraph

JpGraph es una libreriacutea escrita en PHP que permite crear todo tipo de graacuteshyficos estadiacutesticos en dos y tres dimensiones Hace uso de la libreriacutea graacutefica GD en su versioacuten 2 Se puede descargar de la paacutegina wwwjpgraphorg

JpGraph tiene dos licencias de uso Una gratuita para proyectos no coshymerciales y con caraacutecter educativo y otra de caraacutecter comercial de pago Le recomiendo leer ambas licencias para comprobar que puede utilizarshylas

Para instalar la libreriacutea tiene que copiar el directorio con las clases en la ruta donde guarde su aplicacioacuten o en la ruta de buacutesqueda de PHP 5

Graacuteficos de barras

El ejemplo maacutes sencillo es la creacioacuten de un graacutefico con varios valores en el que podemos ver todos los valores interconectados entre siacute por unas liacuteneas

ltphp require_once (jpgraphjpgraphphp) require_once (jpgraph jpgraph_linephp) $datosy = array(11O81251913157) Creamos el graacutefico $grafico = new Graph(350250) $grafico-gtSetScale (textlin) Creamos una nueva linea de puntos $puntos =new LinePlot($datosy) $puntos-gtSetColor(blue) Antildeadimos los puntos al graacutefico $grafico-gtAdd($puntos) Se muestra el graacutefico $grafico-gtStroke ()

bull gt

Suponiendo que la libreriacutea esteacute guardada en la carpeta j p g r a p h haceshymos u n r e q u i r e _ o n c e () de la clase principal j p g r a p h php y de la clase que utilizaremos para graacuteficos de liacutenea j p g r a p h _ l i n e php La variable $ d a t o s y guarda diez valores que pueden identificar el nuacutemero de visishytas a nuestra Web o el nuacutemero de ventas por meses de un artiacuteculo Para crear un graacutefico tiene que crear el objeto Graph con el ancho y alto que quiere que tenga en la Web Lo siguiente es configurar la escala en la que apareceraacute el graacutefico Lo mejor es echar un vistazo al manual para eleshygir el que maacutes le convenga en cada momento

Seguidamente cree un conjunto de puntos con el meacutetodo L i n e p l o t () con los valores del array $ d a t o s y Puede elegir tambieacuten el color de la liacuteshynea resultado con el meacutetodo S e t C o l o r ()

Para finalizar antildeada los valores al graacutefico y mueacutestrelo con S t r o k e ()

Con estas liacuteneas hemos conseguido crear el graacutefico de la figura 166

Puede antildeadir algunas caracteriacutesticas maacutes a sus graacuteficos como tiacutetulos en

los ejes colores o varias liacuteneas de valores para comparar datos

Para antildeadir tiacutetulos a los graacuteficos le pueden servir las liacuteneas siguientes

$graf ico-gttitle-gtset (Graacutefico JpGraph) -

294 Capiacutetulo 16

$grafico-gtxaxis-gttitle-gtset(dia) $grafico-gtyaxis-gttitle-gtset(visitas)

El meacutetodo t i t l e genera un tiacutetulo asociado al objeto inmediatamente anshyterior Si el objeto es $ g r a f i c o el tiacutetulo seraacute el de la imagen completa Si el objeto anterior es el eje x o el eje y ( x a x i s o y a x i s ) el tiacutetulo corresshyponderaacute con cada uno de los ejes Puede ver el resultado en la figura 167

Ademaacutes puede antildeadir tantos datos como quiera para hacer un estudio comparativo de varios datos Para hacer esto debe repetir algunos pasos pero con distintos valores

$datosy2 = array(12378543127) $puntos2 = new LinePlot($datosy2) $puntos2-gtSetColor(red) $grafico-gtAdd($puntos2) $puntos-gtSetLegend(Europa) Spuntos2-gtSetLegend(America) $grafico-gtlegend-gtPos(00505rightcenter)

Como vimos en el ejemplo anterior podemos antildeadir otro array lleno de valores crear una nueva liacutenea de puntos con un color determinado y asoshyciarlo finalmente con el graacutefico que estamos creando como puede ver en

Graacuteficos en 3D

JpGraph realiza casi cualquier tipo de graacutefico estadiacutestico Uno de los maacutes utilizados es el graacutefico de quesito donde podemos evaluar por porcioshynes el dato de mayor amplitud soacutelo con un vistazo El ejemplo siguiente muestra coacutemo hacer un graacutefico de este tipo

ltphp include (jpgraph jpgraphphp) include (jpgraph jpgraph_piephp) include (jpgraph jpgraph_pie3dphp)

$datos = array(4 0So21 33)

$grafico = new PieGraph(300200) $grafico-gtSetShadow()bull

$grafico-gttitle-gtSet(Graacutefico de quesito) $pl = new PiePlot30($datos) $pl-gtSetAngle(20)

Generacioacuten de graacuteficos con PHP 5 295

la figura 168 Las uacuteltimas 3 liacuteneas antildeaden una leyenda en la parte derecha del graacutefico es decir un pequentildeo graacutefico explicativo de las liacuteneas de datos

296 Capiacutetulo 16

$pl-gtSetSize (05) $pl-gtSetCenter (045) $pl-gtSetLegends($gDateLocale-gtGetShortMonth())

$grafic0-gtAdd($pl) $grafic0-gtStroke ()

Para crearlo primero tiene que incluir los archivos j p g r a p h _ p i e php y j p g r a p h ^ p i e 3 d php que permitiraacuten instanciar el tipo de graacutefico P i e P l o t 3 D El meacutetodo SetShadowC) crea una sombra en eiacute contorno exterior del graacutefico La instanciacioacuten del graacutefico circular se hace sobre la variable $pi que empieza a tomar forma con las propiedades S e t A n -g l e () y S e t C e n t e r () que permiten definir el aacutengulo del graacutefico con respecto a la vista frontal y el centrado del graacutefico con respecto a la caja que lo contiene La fase final es antildeadir el quesito al graacutefico creado y mostrarlo en pantalla Una mejora del graacutefico anterior puede ser resaltar la porcioacuten del graacutefico que tiene mayor valor y separarlo notablemente Esto puede hacerse antildeadiendo la liacutenea siguiente

$ p l - gt E x p l o d e S l i c e ( 1 )

El graacutefico de quesito se muestra en la figura 169

Generacioacuten de graacuteficos con PHP 5 297

Resumen

El tratamiento de imaacutegenes desde PHP 5 nos da la posibilidad de crear proyectos muy profesionales Tanto la posibilidad de crear graacuteficos mas pequentildeos marcas de agua o texto sobreimpresos como la de generar esshytadiacutesticas en tiempo real crean un potencial que no todas las paacuteginas Web saben aprovechar

Existen algunos proyectos como K++ que permiten crear imaacutegenes del tipo Flash y que merece la pena indagar en la buacutesqueda de contenido orishyginales para nuestro portal

300 Capitulo 17

Introduccioacuten

Si estaacute familiarizado con otros lenguajes de programacioacuten como C o Java ya conoceraacute algunos mecanismos que permiten manejar errores y excepshyciones Una de las nuevas caracteriacutesticas que PHP 5 incluye es un objeto de manejo de excepciones con una sintaxis muy similar a Java El manejo de excepciones es una herramienta muy potente que podraacute apreciar una vez que comprenda el concepto y haga buen uso del objeto en su coacutedigo Estas funciones permiten depuiacutear condiciones de error reshycuperar situaciones inesperadas y presentar interfaces limpias de errores

Errores y Excepciones

Lo primero que tenemos que hacer es no pensar en una excepcioacuten como si fuera un error Una excepcioacuten es una condicioacuten que se experimenta en un programa inesperadamente y no puede ser manejada por el coacutedigo que hemos escrito Generalmente no causan la parada del programa pero siacute es posible detectarla para que continuacutee normalmente Las excepciones si son tratadas correctamente pueden dar maacutes fiabilidad a su aplicacioacuten y librarle de muchos dolores de cabeza Aunque si no son correctamente utilizadas pueden crear maacutes problemas que resolverlos Debe tomar un tiempo para determinar si necesita crear sus propios meacuteshytodos de manejo de errores y si es asiacute veraacute que a la larga resulta maacutes grashytificante Como ejemplo vamos a ver una pieza de coacutedigo que simula la recepcioacuten de un identificador de usuario y su posible comprobacioacuten en una base de datos Tal y como puede ver se comprueba que los tres prishymeros caracteres sean usr que el tamantildeo en caracteres sea al menos de 9 y que exista en una base de datos

ltphp extraemos el usuario por GET $usuario_id = $_GET[usuario_id ] Si existe el usuario escribimos el mensaje CORRECTO if (usuario_valido($usuario_id))

echo ERROR El usuario $usuario_id no existe else

echo CORRECTO El usuario $usuario_id existe

function usuario_valido($usuario_id)

Gestioacuten de errores en PHP 5 301

$cadena = usr Comprobaciones de usuario if ( (strstr ($usuario_id$cadena) == false) [[

(strpos($usuario_id$cadena) = 0)) return false

if (strlen ($usuario__id) lt 9) return false

if (existe__base_datos ($usuario_id) )

return true else

return false

gt

Como puede ver cualquier condicioacuten que estaacute dentro de la funcioacuten que valida los usuarios puede dar un resultado negativo y soacutelo uno de ellos daraacute un resultado positivo si el usuario existe en la base de datos

Las excepciones permiten distinguir entre distintos tipos de errores y manejarlos dependiendo de su naturaleza

La clase Exception

La clase Except ion se ha creado en PHP 5 para manejar las anomaliacuteas producidas En vez de utilizar comprobaciones que evaluacutean si es falso o verdadero una determinada condicioacuten se utiliza una instancia de la clase Except ion que captura los errores y permite mostrar un mensaje de error personalizado

ltphp extraemos el usuario por GET $usuario__id = $_GET [ usuario_id] Si existe el usuario escribimos el mensaje CORRECTO try

if ( lusuario_valido($usuario_id)) echo ERROR El usuario $usuario_id no existe

else echo CORRECTO El usuario $usuario_id existe

catch(Exception $ex)

Devuelve el mensaje de error $mensaje = ($ex-gtqetMessage() ) echo $mensaje

302 Capiacutetulo 17

function usuario_valido($usuario_id) $cadena = usr Comprobaciones de usuario if ( (strstr ($usuario_id$cadena) == false) |

(strpos($usuario_id $cadena) = 0)) throw new Exception ($usuario_id no contiene el

prefijo)

if (strlen($usuario_id) lt 9)

throw new Exception (El tamantildeo de $usuario_id es menor de 9 caracteres)

if (existe_base_datos($usuario_id) )

return false else

return false

Gestioacuten de errores en PHP 5 303

Como puede ver las excepciones se crean de una manera algo diferente En el momento en el que se escribe th row new E x c e p t i o n los errores que no se controlen con el flujo normal del programa son utilizados como excepciones separadas del resto de la aplicacioacuten

Bloque Try Catch

Las excepciones son controladas por el bloque t r y c a t c h Todo el coacutedishygo que escriba y que pueda generar un error se incluiraacute dentro de una estructura t r y Si dentro del bloque t r y se encuentra un error la ejecushycioacuten del coacutedigo se para y se pasa el control al bloque c a t c h Este bloque se consuita para encontrar la excepcioacuten que ha producido el error de acuershydo con el coacutedigo que hemos escrito

Una de las cosas maacutes convenientes de utilizar excepciones es que puede mostrar tanta informacioacuten o tan poca como quiera El objeto E x c e p t i o n tiene varios meacutetodos para manejar sus propios errores El coacutedigo siguiente muestra coacutemo utilizar t h row e inmediatamente capshyturar la excepcioacuten Podemos capturar tambieacuten algunos paraacutemetros uacutetiles

ltphp try

throw new Exception(Error de sintaxis) catch (Exception $ex)

Mensaje de error $mensaje = ($ex-gtgetMessage ()) Coacutedigo de error configurable $codigo = ($ex-igetCode()) Fichero del error $fichero = ($ex-gtgetFile ( ) ) Linea donde se ha producido el error $linea = ($ex-gtgetLine())

echo Error nuacutemero $codigo $mensaje en el fichero $fichero en la linea $linea

gt

El mensaje de error que se muestra es muy tiacutepico en PHP Como es totalshymente configurable puede generar su propio formato de Mensaje de Error que puede ver en la figura 172

Aunque en este ejemplo el coacutedigo que captura la excepcioacuten soacutelo tiene una liacutenea podraacute incluir dentro del bloque varias liacuteneas o funciones dentro que actuaraacuten de la misma forma

Heredar de (a clase Exception

PHP 5 permite definir sus propias clases qulta heredan de la clase E x c e p shyt i o n Puede hacerlo de la siguiente forma

ltphp class Excepcioacuten extends Exception

function construct($mensaje)

parent Exception($mensaj e)

gt

El siguiente ejemplo muestra coacutemo crear clases propias que manejan erroshyres a partir de la clase E x c e p t i o n

ltphp $usuario_id = $_GET[usuario_id] try

if f J usuario_valido ($usuario__id) ) [ echo ERROR El usuario $usuario id no existe

Gestioacuten de errores en PHP 5 305

else echo CORRECTO El usuario $usuario_id existe

catch(MiExcepcion $ex)

$cadena = usr if ((strpos($usuario_id$cadena) == false) |]

(strpos($usuario_id$cadena) = 0)) $mensaje = $ex-gtgetMessage()

catch(OtraExcepcion $ex)

if (strlen($usuario_id) lt 9) $mensaje = $ex-gtgetMessage()

Definicioacuten de las clases que heredan de Exception class MiExcepcion extends Excepcioacuten

function construct($mensaje)

parentException($mensaje)

class OtraExcepcion extends Excepcioacuten

function construct($mensaje)

parent Exception($mensaj e)

echo $mensaje function usuario_valido($usuario_id)

$cadena = usr if ((strpos($usuario_id$cadena) == false) ||

(strpos($usuario_id$cadena) = 0)) throw new MiExcepcion(Usuario $usuario_id no

contiene el prefijo )

if (strlen($usuario_id) lt 9) throw new OtraExcepcion(Usuario tiene menos de 9

caracteres)

gt

Limitaciones de PHP 5

El objeto de excepciones es totalmente nuevo en PHP 5 Debido a esto algunas funcionalidades creadas en otros lenguajes de programacioacuten como

306 Capiacutetulo 17

Java no han sido todaviacutea implementadas por ejemplo el uso de los meacutetoshydos f i n a l ly () y t h r o w s () Los errores comunes de PHP que se muesshytran en el navegador no son mapeados a excepciones automaacuteticamente Esta funcionalidad seraacute implementada en versiones posteriores de PHP Los errores que no pueden ser controlados por E x c e p t i o n pueden mashynejarse con otras teacutecnicas de programacioacuten

Control de errores sin excepciones

Si ya conoce algunas versiones de PHP sabraacute que hay multitud de funcioshynes capaces de controlar errores incluidos los errores nativos de PHP controladores personalizados de error y los errores de usuario

Errores nativos de PHP

PHP genera 3 tipos de error dependiendo de su seriedad

bull Notice No son errores severos y no crean problemas complejos Por defecto no se muestran en pantalla cuando suceden a menos que dishygamos lo contrario en el archivo de configuracioacuten php i n i

bull Warning Alguna parte del coacutedigo ha causado un error pero la ejecushycioacuten continuacutea

bull Fatal error Un problema serio que hace abortar la ejecucioacuten del proshygrama

Cada tipo de error es representado por una constante diferente E_USER_NOTICE E_USER_WARNING y E_USER_ERROR Puede elegir el nivel de error que quiere mostrar en pantalla con la funcioacuten e r r o r _ r e p o r t i n g ( )

ltphp Mostrar errores fatales error_reporting(E_USER_ERROR) Mostrar advertencias y notificaciones error_reporting(E_USER_WARNING | E_USER_NOTICE) Mostrar todos los errores error_reporting (E__USER__ALL) gt

El manejo de errores queda limitado la mayoriacutea de veces a los del tipo warn ing Los errores fatales se consideran tan criacuteticos que no pueden conshytrolarse y la ejecucioacuten del programa queda suspendida

Gestioacuten de errores en PHP 5 307

Controladores de error

Cuando suceda un error que no tenga contemplado en su aplicacioacuten pueshyden aparecer mensajes en la pantalla que no interesa mostrar La solucioacuten es crear su propia funcioacuten para controlar y mostrar errores

ltphp function errores($errormensaje$fichero$linea)

echo ltbgt ERROR ltbxbrgt echo Sentimos comunicarle que se ha producido un error echo Tipo de error $error $mensaje en $fichero en la linea $linea

gt

Con estas liacuteneas hemos creado una funcioacuten que muestra el error producishydo pero con un disentildeo acorde a nuestra paacutegina Web Puede mostrar tanta informacioacuten como quiera El siguiente paso es llamar a la funcioacuten s e t _ e r r o r _ h a n d l e r () para que PHP sepa que nuestra funcioacuten e r r o shyr e s () se va a encargar a partir de ahora de gestionar los posibles fallos en el flujo del programa

ltphp set_error_handler(errores) gt

308 Capiacutetulo 17

Con el coacutedigo anterior todos los errores producidos del nivel que tenga permitido ( f a t a l e r r o r w a r n i n g o n o t i c e ) seraacuten enviados a la funshycioacuten e r r o r e s () para mostrar su mensaje particular

Errores de usuario con trigger_error()

Desde PHP 4 puede usarse una funcioacuten para identificar los errores proshyducidos por los usuarios muy parecida a la funcioacuten de PHP 5 th row () La funcioacuten t r i g g e r _ e r r o r () genera un error del tipo que quiera ( f a shyt a l e r r o r warn ing o n o t i c e ) y seraacute gestionado por PHP o por su propio gestor de errores

ltphp error_reporting(E_ALL) function errores($error$mensaje$fichero$linea)

echo ltbgt ERROR ltbxbrgt

echo Sentimos comunicarle que se ha producido un error echo Tipo de error $error $mensaje en $fichero en la liacutenea $ linea

set_error_handler(errores)

if (1 = 0 ) trigger_error( Esto es falso E_USER_NOTICE)

gt

Es mejor u t i l izar s iempre la funcioacuten t r i gg e r _ e r r o r ( ) con s e t _ e r r o r _ h a n d l e r () El error que creemos puede ser de cualquiera de los 3 tipos existentes en PHP En este caso generamos un error no t i -ce para indicar que la condicioacuten es falsa

Depuracioacuten de errores

El manejo de errores puede ahorrar esfuerzos a la hora de depurar el funshycionamiento oacuteptimo de su coacutedigo pero tambieacuten puede crear algunos doshylores de cabeza si empieza a suprimir algunos fallos

La f u n c i oacute n e r r o r _ l o g () crea un archivo donde se iraacuten almacenando las ocurrencias de su coacutedigo Con el siguiente ejemplo podraacute capturar todos los errores producidos en el programa para despueacutes hacer un estudio de lo que ha pasado

ltphp

Gestioacuten de errores en PHP 5 309

try if ($usuario = Luis)

throw new Exception(El usuario no existe)

catch (Exception $ex)

$mensaje = ($ex-gtgetMessage() ) $codigo = ($ex-gtgetCode() ) $fichero = ($ex-gtgetFile()) $linea = ($ex-gtgetLine()) $log_mensaje =date(Hi d-m-Y) Error $codigo en

$fichero en la liacutenea $linea Error $mensaje error_log($log_mensaj e3 UsersluisSiteserrorlog) echo $log_mensaje

gt

Nota

Los ficheros l o g son muy utilizados en los Sistemas Operativos para mantener un registro de incidencias Los ficheros l o g guarshydan desde el nuacutemero de veces que ha entrado un usuario hasta los errores que se han producido en el inicio del sistema

La funcioacuten e r r o r _ l o g () puede pasar como segundo paraacutemetro un nuacuteshymero entero que identifica el tipo de error y queacute hacer con eacutel

bull 0 Se utiliza el mecanismo del sistema operativo bull 1 Enviacutea el error a una direccioacuten de correo especificada como cuarto

paraacutemetro (Debe formar parte de una cabecera) bull 2 Enviacutea el error a traveacutes de una sesioacuten de depuracioacuten de PHP (Debe

estar habilitado el modo depuracioacuten)

bull 3 Enviacutea el error a un fichero

Resumen

Como puede darse cuenta la mayoriacutea de los programas incluidos en el libro no tienen ninguacuten tipo de control de errores He preferido evitarlos para ganar en claridad y no tener que empezar explicando los bloques Try Catch desde el principio A partir de ahora sieacutentase libre para modifishycar todos los scripts a su antojo para que sean maacutes fiables y seguros

310 Capiacutetulo 17

El desarrollo de las posteriores versiones de PHP permitiraacute manejar los errores maacutes faacutecilmente El futuro de las excepciones no ha hecho maacutes que empezar con la versioacuten 5 de PHP y se esperan mejoras suculentas con respecto a las anteriores Pese a esto muchas libreriacuteas ya incluyen sus proshypios controles de error como la de MySQL o PEAR

312 Capiacutetulo 18

Introduccioacuten

Transferir ficheros de un ordenador a otro es una tarea que sucede milloshynes de veces a lo largo del diacutea en Internet Ya no es un problema comparshytir un fichero entre dos ordenadores ubicados entre distintos puntos del mundo Los dos meacutetodos maacutes utilizados son el protocolo FTP y el correo electroacutenico

Los ficheros pueden ser transferidos simplemente dejaacutendolos en alguacuten lugar puacuteblico de nuestro servidor Web o utilizando alguacuten programa para enviarlos El protocolo FTP y el correo electroacutenico son programas indeshypendientes que deben estar instalados en el servidor para poder usarse Son dos programas del tipo cliente servidor Para poder utilizar cualshyquiera de los dos servicios anteriores debe conectarse a un servidor en un ordenador remoto y enviar los datos

FTP

Para utilizar el protocolo FTP tiene que tener habilitada la opcioacuten cuando instale PHP Puede utilizar FTP para enviar ficheros en un script escrito en PHP desde alguna paacutegina Web Para conectar a un servidor tendraacute que utilizar la siguiente funcioacuten

$conexioacuten = f tp__connect ( www l u i s y f ernanda net)

Tambieacuten puede utilizar una direccioacuten IP para la conexioacuten $conexioacuten = f tp_connect (12 7 0 0 1)

Nota

La direccioacuten IP identifica un uacutenico ordenador dentro de Internet

La IP 127001 apunta a nuestro propio ordenador

El servidor FTP contiene un listado de usuarios a los que les permite la conexioacuten Dependiendo del usuario que se conecte el servidor le permitishyraacute descargar unos archivos u otros

El siguiente paso es autentificarse como usuario del servidor de FTP con la funcioacuten

ftp_login($conexioacuten $usuario $clave)

Conexiones desde PHP 5 313

Como paraacutemetros tiene que pasar la conexioacuten establecida anteriormente el usuario y la contrasentildea

Advertencia

El protocolo FTP no es seguro El usuario y la contrasentildea se enshyviacutean en formato de texto y podriacutean ser capturados por alguacuten proshygrama sniffer que se encuentre entre su ordenador y el servidor de destino

Como de costumbre puede encapsular todas las funciones para hacer una clase que permita conectar a un servidor

ltphp class ftp

priacutevate $serviacutedor priacutevate $usuario priacutevate $clave priacutevate $conexion priacutevate $login function construct($servidor$usuario $clave)

set_time_limit(0) $this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtclave = $clave $thiacutes-gtconectar($this-gtservidor)

priacutevate function conectar($servidor)

$this-gtconexion = ftp_connect($servidor21 30) priacutevate function loginFtp($usuario$clave)

$this-gtlogin = ftp_login($this-gtconexion usuario $clave)

$ftp = new ftp(127001luissecreto) gt

Como puede ver el meacutetodo constructor utiliza la funcioacuten set__t ime_ l i m i t () Normalmente los script de PHP tienen un tiempo de vida deshyterminado en el fichero de configuracioacuten php i n i Este tiempo suele ser de 30 segundos y es una proteccioacuten para que si un programa se queda

314 Capiacutetulo 18

bloqueado y su ejecucioacuten lleva maacutes de ese tiempo automaacuteticamente queshyde cancelada su ejecucioacuten

La funcioacuten s e t _ t i m e _ l i m i t () le da la posibilidad de ampliar el tiemshypo de ejecucioacuten al nuacutemero de segundos que indique como paraacutemetro Si el argumento es un 0 el tiempo de ejecucioacuten seraacute infinito

La funcioacuten f t p _ c o n n e c t () tambieacuten puede llevar como paraacutemetros el puerto de conexioacuten (por defecto es el 21) y el nuacutemero de segundos que tardaraacute PHP en volver a intentar la conexioacuten si el intento anterior ha sido fallido

Mostrar los archivos remotos

Despueacutes de conectar con el servidor de FTP lo maacutes usual es recuperar un listado de ficheros que estaacuten en el servidor La funcioacuten f t p _ n l i s t () extrae el nombre de los archivos del directorio que pasemos como paraacuteshymetro

El resultado es un array

public function ver($directoriacuteo = )

$this-gtarchivos = ftp_nlist($this-gtconexion$directorio) foreach ($this-gtarchiacutevos as $archivo)

echo $archivoltbrgt

Puede antildeadir el meacutetodo anterior a la clase f t p La funcioacuten f t p _ n l iacute s t () utiliza la conexioacuten almacenada en el constructor de la clase y recibe un listado de ficheros que guarda como array en la variable $this-gtarchivos

Maacutes adelante utilizando un bucle f o r e a c h podraacute extraer todos los nombres e imprimirlos en pantalla como puede comprobar en la figushyra 181

Si no es la primera vez que utiliza el protocolo FTP sabraacute que al conecshytar con un servidor lo maacutes comuacuten es que conecte en el sistema raiacutez donshyde encontraraacute los archivos y directorios que puede utilizar La funcioacuten f t p _ c h d i r () permite cambiar de directorio dentro del sistema de fishycheros

Si en alguacuten momento no sabe en queacute directorio se encuentra puede hashycer uso de la funcioacuten f tp_pwd ( ) que le daraacute la ruta completa de su situacioacuten

Descargar y Enviar ficheros

Puede descargar ficheros con la funcioacuten f tp_ge t () El siguiente ejemshyplo descarga un fichero despueacutes de hacer la conexioacuten

ftp_get($conexioacuten nuevoFicherotxtFicherotxtFTP_ASCII)

El nombre nuevoFichero t x t se corresponde con el nombre del ficheshyro que tendraacute el archivo despueacutes de ser descargado y F iche ro t x t es el archivo remoto que queremos descargar El uacuteltimo paraacutemetro FTP_ASCI I le dice al FTP el tipo de archivo que va a ser descargado Los modos que puede elegir son FTP_ASCI I o FTP_BINARY Los ficheros binarios son archivos escritos en el lenguaje maacutequina como los archivos graacuteficos Ademaacutes puede enviar archivos al servidor con la funcioacuten f tp_put () El siguiente ejemplo muestra coacutemo subir un archivo al servidor

ftp_put($conexion nuevoFicherotxtFicherotxtFTP_ASCII)

Como en el ejemplo anterior n u e v o F i c h e r o t x t seraacute el nombre del archivo en el servidor remoto y F i c h e r o t x t el archivo que vamos a enviar El ejemplo siguiente descarga todos los archivos con extensioacuten PHP en nuestro ordenador local

public function descargaPHP($directorio = )

316 Capiacutetulo 18

$this-gtarchivos = ftp_nlist($this-gtconexion$directorio) foreach ($this-gtarchivos as $archivo)

if (ereg(php$archivo)) if ( f ile__exists ($archivo) )

ftp_get($this-gtconexion$archivo$directorio $archivoFTP_ASCII)

else

echo Fichero $archivo ya existeltbrgt

else

echo El archivo $archivo no es de PHPltbrgt

Otras funciones de FTP

Ademaacutes de las funciones descritas en este capiacutetulo existen otras muchas para el manejo del protocolo FTP

Tabla 181 Funciones comunes al manejo de FTP

Funciones Descripcioacuten

ftp_cdup($conexion) Cambia al directorio inmediatamente

superior al directorio actual ftp_chdir($conexioacuten Cambia al directorio que pasemos como

nombre directorio) paraacutemetro

ftp_close($conexion) Cierra una conexioacuten FTP

ftpconnect(servidor) Establece una conexioacuten con el servidor

ftp_delete($conexioacuten ruta) Borra un fichero del servidor

ftp_exec($conexioacuten comando) Ejecuta un comando del sistema remoto

ftp_fget($conexioacuten $descriptor Descarga un fichero y vuelca los datos Ficherotxt FTP_ASCII) en un fichero abierto en el ordenador

local

ftp_fput($conexioacuten $descriptor Enviacutea un archivo a un fichero abierto Ficherotxt FTP_ASCII)

ftp_get($conexioacuten nuevoFicherotxt Recupera un fichero de un servidor Ficherotxt FTP_ASCII)

ftp_put($conexioacuten nuevoFicherotxt Enviacutea un fichero al servidor

Ficherotxt FTP_ASCII)

Conexiones desde PHP 5 317

Funciones Descripcioacuten

ftp_login($conexiexcloacuten $usuario $clave) Autentifica al usuario en el servidor ftp_mdtm($conexioacutenFicherotxt) Recupera la fecha de la uacuteltima actualishy

zacioacuten del fichero ftp_mkdir($conexioacuten directorio) Crea un directorio

ftp_nlist($conexioacuten directorio) Recupera la lista de archivos de un directorio

ftp_pwd($conexion) Obtiene el nombre del directorio actual ftp_rename($conexioacuten Cambia de nombre un archivo remoto ArchivoAntiguoArchivoNuevo) ftp_size($conexionFicherotxt) Devuelve el tamantildeo de un fichero ftp_systype($conexion) Permite obtener el tipo de sistema

Correo electroacutenico

La aplicacioacuten maacutes utilizada sin duda en Internet es el correo electroacutenico La explosioacuten de Internet y la expansioacuten de servidores gratuitos que ceden cuentas de correo a todos los usuarios ha permitido que el crecimiento de los e-tnail se dispare en estos uacuteltimos antildeos

Para lograr la comunicacioacuten a traveacutes del correo electroacutenico han de intershyvenir numerosas piezas de un puzzle

La mayor parte del modelo utiliza

bull Servidor TCP IP Se encarga de mantener activos para la conexioacuten diversos servicios como FTP SMTP o POP

bull MTA (Mail Transfer Agent) Acepta correo de otros servidores SMTP y busca una ruta para que los correos lleguen a su destino

bull Cola de correo Recipiente donde se almacenan todos los correos enshytrantes dirigidos a una persona

bull MUA (Mail User Agent) Programa muy liviano para leer el correo elecshytroacutenico normalmente desde el servidor

bull Servidor POP IMAP Recibe peticiones de lecturas de correo El sershyvidor chequea si hay correos nuevos y los enviacutea al cliente

bull MLM (Mailing List Manager) Este software ayuda a enviar grandes cantidades de correo

318 Capiacutetulo 18

Enviar correo desde PHP

Soacutelo existe una funcioacuten para enviar correo electroacutenico desde PHP 5 La funcioacuten mail () devolveraacute un valor true si los datos son enviados correcshytamente La forma maacutes sencilla de utilizar esta funcioacuten la puede ver en el ejemplo siguiente

ltphp $resultado = mail ( luisaacutenccextremadura org Ejemplo de Asunto Cuerpo del mensaje) if ($resultado)

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt

El primer paraacutemetro recibe el correo de la persona a la que quiere enviar el mensaje El segundo es un resumen del contenido de su carta electroacutenishyca y por uacuteltimo el tercer paraacutemetro es el mensaje que quiere transmitir Puede dividir la funcioacuten en variables para que sea maacutes sencillo de utishylizar

ltphp $correo = luisnccextremaduraorg $asunto = Ejemplo de Asunto $cuerpo = Cuerpo del mensaje $resultado = mail($correo $asunto $cuerpo) if ($resultado)

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt

Hay veces que necesitaraacute algo maacutes de control sobre lo que quiera enviar o necesite enviar un correo a varias personas a la vez Esto es posible antildeashydiendo cabeceras adicionales a la funcioacuten mail

ltphp $correo = luisnccextremaduraorg $asunto = Ejemplo de Asunto $cuerpo = Cuerpo del mensaje $cabecera = From fernandarnbccpedronccextremaduraorgrnContent-type textplainrnX-mailer PHP phpversion () $resultado = mail($correo $asunto $cuerpo $cabecera) if ($resultado)

Conexiones desde PHP 5 319

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

La cabecera muestra coacutemo enviar junto al correo la direccioacuten de la persoshyna que lo enviacutea y una copia del mismo mensaje al correo pedroncc extremaduraorg Es necesario antildeadir los separadores r y n para indishycar un salto de liacutenea entre los paraacutemetros de la cabecera

Las cabeceras adicionales pueden antildeadir muchos tipos de informacioacuten entre los que se encuentran

bull El nombre del emisor

bull Correo del emisor

bull Correo de respuesta

bull X-mailer y nuacutemero de versioacuten

bull versioacuten MIME

bull Content-type

bull Codificacioacuten

bull Campo de copia y copia oculta

La funcioacuten m a i l () estaacute preparada para emitir mensajes sencillos pero hay muchas caracteriacutesticas que debe implementar con cabeceras Por eso han nacido una serie de libreriacuteas escritas en PHP que facilitan el enviacuteo de correos

La libreriacutea PHPMailer antildeade a la funcioacuten m a i l () muchas funcionalidashydes como ficheros adjuntos o correos HTML

PHPMailer

PHPMailer estaacute basado en programacioacuten orientada a objetos Contiene varios ficheros que deben guardarse en el directorio de PHP dedicado a libreriacuteas o en nuestro espacio de trabajo

La construccioacuten maacutes baacutesica es la siguiente

ltphp require_once(phpmailerclassphpmailerphp) $correo = new phpmailer() Datos personales del emisor $mail-gtFrom = luisnccextremaduraorg

320 Capitulo 18

$mail-gtFromName = Luis Miguel Cabezas

$mail-gtSubject = Mensaje de prueba

$mail-gtBody = Cuerpo del mensaje Direccioacuten de destino $mail-gtAddAddress(zeevSphpzendcomZeev Suraski)

if ( l$mail-gtSend()) echo Correo enviado correctamente

else echo El correo no ha podido enviarse

gt

Como puede ver las propiedades de la clase p h p m a i l e r son auto explishycativas El ejemplo va asociando cada propiedad a un dato necesario para el enviacuteo El meacutetodo A d d A d d r e s s () antildeade una direccioacuten de correo a la que enviar el mensaje y Send () lo enviacutea a traveacutes de Internet

Antildeadir un fichero adjunto

Existen tres meacutetodos para antildeadir un fichero adjunto a un mensaje dos para archivos y otro maacutes especiacutefico para imaacutegenes

bull AddAttachment(ruta nombre) Antildeade un fichero localizado en el servidor Este archivo se puede subir antes al servidor mediante un formulario

bull AddStringAttachment(caracteres fichero) Se puede utilizar para enviar ficheros almacenados en variables

bull AddEmbeddedImage(ruta cid nombre) Antildeade una imagen y pershymite antildeadirla al cuerpo de un correo HTML

Las liacuteneas siguientes se pueden antildeadir al ejemplo anterior para enviar un fotografiacutea almacenada en el servidor

if ($mail-gtAddAttachment(abuelojpgabuelojpg))

echo Falloacute al antildeadir un fichero adjunto

Para demostrar la teoriacutea anterior vamos a crear un pequentildeo formulario que permita enviar correo Es un coacutedigo muy sencillo pero permite enshyviar mensajes escritos en HTML e incluir imaacutegenes

ltphp if (isset($_POST[nombre]))

require_once(phpmailerclassphpmailerphp)

Conexiones desde PHP 5 321

$correo = new phpmailer() Datos personales del emisor $mail-gtFrom = luisnccextremaduraorg $mail-gtFxowpoundawgte = Luis Miguel Cabezas $mail-gtSubject = $_POST [ asunte ] $mail-gtBody = $_POST[mensaje] Direccioacuten de destino $mail-gtAddAddress($_POST[nombre]$_POST[correo]) if ($mail-gtAddEmbeddedImage($_FILES[imagen] [tmp_name 12 34 5 imagen))

echo Falloacute al antildeadir un fichero adjunto

if ( $mail-gtSend() )

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt lthtmlgt ltbodygt ltform action=mailphp method=post enctype=multipartform-data name=formlgt lttable width=50 border=0 cellspacing=0

cellpadding=Ogt lttrgt

lttd width=28gtNombrelttdgt lttd width=72xinput name=nombre type=text

id=nombregtlttdgt lttrgt lttrgt lttdgtCorreolttdgt lttdxinput name=correo type=text id=correogtlttdgt

lttrgt lttrgt lttdgtAsuntolttdgt lttdxinput name=asunto type=text id= asuntogtlttdgt

lttrgt lttrgt lttdgtMensajelttdgt lttdxtextarea name= mensa j e rowS=5 id= mensa j e gtlt textareaxtdgt

lttrgt lttrgt lttdgtSelecciona imagen lttdgt lttdxinput name=imagen type=file id= imagen xtdgt

lttrgt lttablegt ltpgt

322 Capiacutetulo 18

ltinput type=submit name=Submit value=Enviargt ltPgt

lt formgt ltbodygt lthtmlgt

La figura 182 muestra un formulario capaz de enviar contenido HTML e imaacutegenes adjuntas

Resumen

PHP se ha promovido tanto debido a las numerosas extensiones que pershymiten hacer casi cualquier cosa En concreto las dos formas vistas para conectarse con un servidor le seraacuten muy uacutetiles para ofrecer servicios inshynovadores a sus usiiarios

La mayoriacutea de los portales Web que necesitan el registro de sus usuarios enviacutean por correo electroacutenico las contrasentildeas y los datos de inscripcioacuten La funcioacuten mail () le puede servir para hacer sus pequentildeos controles de usuarios

Conexiones desde PHP 5 323

Si se siente maacutes ambicioso tambieacuten puede utilizar PHPMailer para consshytruir una paacutegina Web que permita enviar o recibir correo electroacutenico La recomendacioacuten es que continuacutee investigando en la clase PHPMailer y en todo lo que ofrece que no hemos podido ver en este capiacutetulo

326 Capiacutetulo 19

Introduccioacuten

Como probablemente ya sabe el HTML no es el uacutenico formato para mosshytrar contenido en Internet Ademaacutes de los distintos tipos de imaacutegenes teshynemos varios formatos capaces de contener textos como Adobe PDF Macromedia Flash o algunos documentos alternativos escritos en XML como los archivos graacuteficos SVG (Graacuteficos Vectoriales Escalables) WML (Lenguaje de Marcas Inalaacutembrico) o XUL (Lenguaje de interfaz de Usuashyrio en XML con Mozilla) Cada uno de estos tipos de documentos tiene su propio terreno y de nosotros depende elegir cuaacutel o cuaacuteles utilizar para dotar a nuestra Web de mayores posibilidades

Los archivos Adobe PDF se han establecido como un estaacutendar en los doshycumentos de texto para la Web

Existen dos extensiones escritas para PHP PDFLib y C l ibPDF capaces de generar archivos PDF Desgraciadamente estas libreriacuteas son de uso coshymercial y requieren el pago de alguacuten tipo de licencia Ademaacutes de las extensiones anteriores tenemos una serie de aplicaciones escritas completamente en PHP que permiten llegar al mismo resultado como RampOS PDF o FPDF No son tan raacutepidas como las extensiones pero cumplen perfectamente nuestras expectativas

Libreriacutea FPDF

La libreriacutea FPDF creada en septiembre de 2001 no necesita licencia de uso ni tampoco alguna configuracioacuten especial de PHP Lo uacutenico que neshycesita es la libreriacutea que la puede descargar del sitio Web h t t p wwwfpdforg

La libreriacutea principal contiene la definicioacuten de una clase que debe instan-ciar para poder generar sus documentos Nuestro coacutedigo inicial deberiacutea ser algo parecido a

ltphp require__once ( f pdf fpdf php) $pdf = new FPDF() gt

El constructor se utiliza de esta forma con los valores por defecto que son paacutegina A4 con orientacioacuten vertical y el tamantildeo medido en miliacutemetros El primer paraacutemetro del constructor permite elegir entre orientacioacuten verti-

Creacioacuten de archivos PDF 327

cal (L) u horizontal (P) El segundo paraacutemetro sirve para que las medidas de referencia se hagan en base a puntos (pt) miliacutemetros (mm) centiacutemetro (cm) o pulgadas (in) El uacuteltimo paraacutemetro nos ofrece la oportunidad de elegir entre los diferentes formatos de paacutegina que existen A3 A4 A5 Let-ter y Legal

Nota

Hay que recordar que un punto es 172 pulgadas

$pdf = new FPDF( P cm A 4 )

Nuestro primer documento

El siguiente ejemplo muestra la creacioacuten baacutesica de un documento PDF de forma lineal

ltphp define(FPDF_FONTPATHfpdffont) require_once ( fpdffpdfphp) $pdf = new FPDF() $pdpound-gtAddPageU bull $pdf-gtSetFont(Arial 15) $pdf-gtWrite(155 Mi primer documento) $pdf-gtOutput() gt

La primera liacutenea define una constante que contiene la ruta donde estaacuten almacenadas las fuentes Despueacutes de las funciones que incluyen la clase y la instancia del objeto tenemos una serie de llamadas a meacutetodos que nos permiten manipular el documento a nuestro antojo

Advertencia

FPDF mantiene la posicioacuten de un cursor Las funciones que geneshyran texto imprimiraacuten los datos de acuerdo con la posicioacuten del curshysor en ese momento Es posible de todas formas cambiar de sitio el cursor con algunas funciones que veremos en este capiacutetulo

El meacutetodo AddPage () antildeade una paacutegina al documento con la orientashycioacuten que Le pida En este caso hemos antildeadido una con orientacioacuten vertical que es la elegida por defecto S e t F o n t () selecciona una fuente tomando

Funciones de texto

Meacutetodo Write()

Imprime el texto pasado como paraacutemetro en la posicioacuten que indica el curshysor La construccioacuten es

W r i t e ( a l t u r a t e x t o e n l a c e )

Los paraacutemetros son los siguientes

bull altura Altura de la celda bull texto Texto a imprimir bull enlace Podemos considerar el texto como un enlace a una paacutegina o a

una Web

Como ejemplo puede ver el primer coacutedigo que hemos realizado

328 Capiacutetulo 19

como paraacutemetro el tipo la propiedad (negrita cursiva) y el tamantildeo Por uacuteltimo tenemos una llamada a los meacutetodos Write () y Output () que escriben el texto en una posicioacuten determinada del documento y lo muesshytran en pantalla respectivamente como puede ver en la figura 191

Creacioacuten de archivos PDF 329

Meacutetodo Cell()

El meacutetodo c e l l () puede tomar hasta 8 paraacutemetros y es el encargado de imprimir en el documento PDF un cuadro de texto en la posicioacuten indicashyda El cuadro de texto puede tener un borde alrededor o en alguno de los lados

La construccioacuten es como sigue

cell(ancho altura texto borde liacutenea alineacioacuten relleno enlace)

Los dos primeros paraacutemetros son obligatorios los demaacutes opcionales A continuacioacuten vemos para queacute sirve cada paraacutemetro

bull ancho Ancho de la celda Si es 0 se considera el ancho total del folio

bull altura Altura de la celda

bull texto Texto a imprimir

bull borde Un 1 significa que llevaraacute borde Tambieacuten se pueden incluir algunos caracteres para indicar en cuaacutel de las partes de la celda debe llevar borde L R T y B significan Izquierda Derecha Arriba y Abajo respectivamente

bull liacutenea Cuando termine la llamada a la creacioacuten de la celda indica al generador de PDF doacutende debe colocar el cursor para continuar Un 0 indica a la derecha de la tabla un 1 en la siguiente liacutenea y un 2 seguido

bull alineacioacuten Acepta 3 caracteres L para alinear a la izquierda R a la derecha y C para texto centrado

bull relleno Indica con un 1 si la celda debe tener un relleno para diferenshyciarla del resto del folio

bull enlace Enlace devuelto por la funcioacuten A d d l i n k ()

Como ejemplo puede ver la forma de introducir un tiacutetulo en una paacutegina

lt php define(FPDF_FONTPATHfpdffont) require__once ( fpdffpdf php i $pdf = new FPDF()

$pdf-gtAddPage() $pdf-gtSetFont(Courier 1 0 ) $pdf-gtCell(80) $pdf-gtCell (2010 Titulo 11C) $pdf-gtOutput() gt

Una celda soacutelo puede contener el nuacutemero de caracteres que quepa en una liacutenea Si necesita mostrar maacutes liacuteneas de texto puede utilizar el meacutetodo

330 Capiacutetulo 19

Muiacute ti Ce 11 () que toma los mismo paraacutemetros que Ce 11 ( ) pero cuanshydo el texto llegue al final de la liacutenea se antildeade automaacuteticamente un salto a la liacutenea siguiente

Truco

Puede utilizar Ce 11 () para desplazar el cursor hacia la derecha antildeadiendo como paraacutemetro un ancho de 8 centiacutemetros (80 miliacuteshymetros) Despueacutes para imprimir el texto antildeada otra celda que inshycluya el literal Tiacutetulo centrado dentro de una celda con borde

Desplazamiento de los cursores

Existen varias funciones para colocar el cursor en distintas partes del doshycumento Se tX () y S e t Y () colocan el texto en el punto indicado en la medida seleccionada (centiacutemetros miliacutemetros etc)

Se tX () desplaza el cursor de izquierda a derecha tantas unidades como indique el paraacutemetro y S e t Y () de arriba hacia abajo Si se les pasa un nuacutemero negativo el origen se tomaraacute desde la derecha o desde abajo resshypectivamente

SetXY () toma dos valores y permite realizar las dos operaciones con una sola instruccioacuten

$pdf-gtSetXY(100100) $pdf-gtwrite(2Este texto se mostraraacute a 10 cm del margen)

Salto de paacutegina automaacutetico

El meacutetodo S e t A u t o P a g e B r e a k () activa o desactiva el salto de paacutegina automaacutetico

Esto quiere decir que si estaacute activado cuando el texto llegue al final de la paacutegina se crearaacute una paacutegina nueva para poder contener el resto El primer paraacutemetro debe ser true ofalse para activa o desactivar la proshypiedad

El segundo paraacutemetro indica la distancia desde la parte inferior que desshyencadena la llamada a una nueva paacutegina

Se tAutoPageBreak( t rue 20 )

El coacutedigo anterior activa el salto de paacutegina automaacutetico cuando el texto lleshygue a 2 centiacutemetros del margen inferior

Creacioacuten de archivos PDF 331

Sobrescribir los meacutetodos

La clase FPDF contiene algunos meacutetodos vaciacuteos que debe escribir usted si quiere que sus documentos queden profesionales Puede crear un objeto propio que herede del objeto FPDF e implementar algunas caracteriacutesticas avanzadas

Cabecera

La cabecera de un documento es un conjunto de texto escrito en la parte superior del folio y que debe aparecer en todas las paacuteginas La clase FPDF implementa el meacutetodo header () que se llama cada vez que existe un salto de paacutegina

Puesto que el meacutetodo estaacute vaciacuteo en FPDF tendraacute que crear un objeto nueshyvo que herede todos sus meacutetodos e implemente la cabecera

ltphp define ( FPDF_FONTPATH fpdffont ) requireonce(fpdffpdfphp) class PDF extends FPDF

function Header()

$this-gtSetFont(ArialB15) $this-gtSetX(70) $this-gtCell(100 10 Manual Imprescindible de PHP 510C) $this-gtLn(20)

$pdf = new PDF () for($i=l$ilt=200$i++) $pdf-gtCell(010Imprimiendo liacutenea nuacutemero $i0l)

$pdf-gtOutput () gt

El meacutetodo header () configura un tipo de letra determinado en negrita avanza el cursor 8 centiacutemetros hacia la derecha e imprime una celda con el tiacutetulo El meacutetodo Ln (2 0 ) inserta un salto de liacutenea cuya altura es determinada por el argumento

Para probar el objeto hemos hecho un bucle que imprime 100 liacuteneas y asiacute comprobar que la cabecera aparece invariable El resultado se puede obshyservar en la figura 192

Imagen de cabecera

Tambieacuten es posible antildeadir una imagen a la cabecera con el meacutetodo Ima-ge ( ) La construccioacuten es la siguiente

Image(fichero x y ancho alto tipo enlace)

Los paraacutemetros necesarios son fichero x e y La descripcioacuten de todos los argumentos es

bull fichero Indica la ruta hacia el fichero que va a insertar

bull x Posicioacuten en el eje x de la imagen

bull y Posicioacuten en el eje y de la imagen

bull ancho Ancho de la imagen

bull alto Alto de la imagen Si no se indica y el paraacutemetro ancho estaacute defishynido el alto se escala en funcioacuten del ancho

bull tipo El tipo de imagen Por ahora soacutelo se aceptan imaacutegenes JPG JPEG y PNG

bull enlace La imagen puede ser un enlace

Ahora que sabe coacutemo insertar imaacutegenes puede incluir en la cabecera el logotipo de su empresa o asociacioacuten

funct ion Header()

Creacioacuten de archivos PDF 333

$this-gtSetFontArialB15) $this-gtSetX(70) $this-gtCell(10010Manual Imprescindible de PHP 510C) $this-gtSetX(-20) $this-gtImage(phppng1705) $this-gtLn (20)

La figura 193 muestra una cabecera con una imagen insertada

Pie de paacutegina

De la misma forma puede sobrescribir el meacutetodo que imprime el pie de paacutegina de la clase FPDF

Este meacutetodo recibe el nombre de F o o t e r () y tiene el mismo tratamiento que la cabecera cada vez que existe un salto de paacutegina se hace una llamashyda al mismo Nuestro pie de paacutegina puede quedar de la siguiente forma

funct ion Footer()

$this-gtSetY (-15) $this-gtSetFont(Arial I 10) $this-gtCell (010 Paacutegina $this-gtPageNo() 00 C )

334 Capiacutetulo 19

S e t Y () nos coloca el cursor a 15 miliacutemetros del borde derecho Seguidashymente escoja el tipo de fuente Aria e imprima el nuacutemero de la paacutegina acshytual con el meacutetodo PageNo ()

Muchos documentos informan ademaacutes del nuacutemero de paacuteginas que tiene el texto Esto es complicado a primera vista porque a priori no podraacute saber cuaacutentas paacuteginas ocuparaacute su texto Existe un meacutetodo que se ejecuta cuando el documento es cerrado y sustituye una marca por el nuacutemero de folios con los que cuenta nuestro proyecto

function FooterO

$this-gtSetY(-15) $this-gtSetFont ( Anal I 10) $this-gtAliasNbPages() $this-gtCell(0 10 Paacutegina $this-gtPageNo()

nb 00 C)

El meacutetodo A l i a s N b P a g e s () cuenta el nuacutemero de paacuteginas cuando el doshycumento estaacute cerrado y sustituye la marca nb por este nuacutemero

Tablas

Una tabla no es maacutes que un conjunto de celdas colocadas en un orden determinado Podemos diferenciar entre la cabecera de la tabla que conshytendraacute las propiedades y los datos Si realiza una clase para escribir tashyblas puede hacer tambieacuten esa diferenciacioacuten cambiando el tipo de letra el tamantildeo o el color El coacutedigo siguiente muestra coacutemo se puede instaurar una clase para la creacioacuten de tablas faacutecilmente

ltphp define(FPDF_FONTPATHfpdffont) require_once(fpdffpdfphp) class PDF extends FPDF function tabla($cabecera$datos)

$this-gtcabecera ($cabecera) $this-gtdatos($datos)

function cabecera($cabecera) Cabecera

$this-gtSetFont(ArialB15)

Creacioacuten de archivos PDF 335

foreach($cabecera as $columna) $this-gtCell(407$columna1 0 C )

$this-gtLn()

function datos($datos) Datos

$this-gtSetFont(Arial12) foreach ($datos as $dato)

foreach ($dato as $columna) $this-gtCell(407$columna10 C )

$this-gtLn ()

$pdf = new PDF () $pdf-gtAddPage ()

$cabecera = array(UsuariosVisitasLocalidadTeleacutefono) $datos = array(array(Luis Miguel 12Badajoz555345678)

array(Mariacutea Fernanda 45 Meacuterida 234234654) array(Pedro Casas3Caacuteceres342123 890))

$pdf-gttabla($cabecera$datos) $pdf-gtOutput () gt

En este caso los datos se sacan de un array de dos dimensiones pero pueshyde utilizar la libreriacutea de bases de datos o la de XML creadas en los capiacutetushylos anteriores para extraerlos

Los datos los recibe el meacutetodo T a b l a ( ) que los enviacutea a sus corresponshydientes meacutetodos para ser tratados El funcionamiento baacutesico consiste en la creacioacuten repetitiva de celdas cuyo nuacutemero coincidiraacute con el nuacutemero de datos existentes en el array Todas las celdas se muestran seguidas dando sensacioacuten de ser una tabla como puede ver en la figura 194 Ahora que es casi un experto en la creacioacuten de tablas para facturas o alba-ranes en PDF puede dar un toque de color al relleno texto o liacuteneas de las celdas

Puede comprobar que con tan soacutelo tres liacuteneas de coacutedigo maacutes el aspecto visual del documento mejora considerablemente

function cabecera($cabecera)

Cabecera $this-gtSetFillColor (25500)

336 Capiacutetulo 19

$this-gtSetTextColor(255) $this-gtSetDrawColor(12 800) $this-gtSetFont(ArialB15) foreach($cabecera as $columna)

$this-gtCell(407$columna10C1)

$this-gtLn()

function datos($datos)

D a t o s $this-gtSetTextColor (1) $thiacutes-gtSetDrawColor (12 800) $this-gtSetFont ( Arial 12) foreach ($datos as $dato)

foreach ($dato as $columna) $this-gtCell(407$columna10C)

$this-gtLn ()

El resultado es mucho maacutes llamativo gracias a los meacutetodos que antildeaden color El meacutetodo S e t F i l l C o l o r () define el color de fondo de las celdas

Creacioacuten de archivos PDF 337

y los rectaacutengulos que no sean transparentes Puede ser expresado con un componente RGB o en escala de grises El valor se mantiene durante todo el documento hasta que se vuelva a invocar el meacutetodo

S e t T e x t C o l o r () y S e t D r a w C o l o r () funcionan de la misma forma actuando esta vez sobre el color del texto o el color de las liacuteneas y bordes de celda La figura 194 muestra los colores (tonos de grises en este caso) distintos que pueden tomar un archivo PDF

Enlaces

Una de las ventajas del formato PDF es que permite hacer enlaces intershynos es decir que si tiene un documento de 500 folios podraacute acceder a cada uno de los capiacutetulos haciendo clic en el iacutendice tal y como funcionan los enlaces en las paacuteginas Web

Un enlace externo es muy faacutecil de crear

$pdf-gtWrite(5wwwluisyfernandanethttpwwwluisyfernandanet)

Los meacutetodos dedicados a texto tienen un argumento para antildeadir un enlashyce que si es externo debe llevar la direccioacuten URL completa

338 Capiacutetulo 19

Crear un enlace interno es algo maacutes complicado Tiene que hacer uso del meacutetodo A d d l i n k ( ) que genera una referencia que debe ponerse en el lugar hacia donde quiere que se produzca el salto En ese lugar utilice el meacutetodo S e t L i n k () para cerrar el enlace

El coacutedigo de ejemplo puede aclarar el concepto

ltphp define(FPDF_FONTPATHfpdffont) require_once(fpdffpdfphp) $pdf = new FPDF() $pdf-gtAddPage () $pdf-gtSetFont(Arial 15) $enLace = $pdf-gtAddLink() $pdf-gtWrite(5Este texto contiene un enlace$enlace) $pdf-gtAddPage) $pdf-gtSetLink($enlace) $pdf-gtWrite (5 Enlace Interno) $pdf-gtOutput () gt

Lo uacutenico a destacar es la creacioacuten del enlace con AddLink ( ) La variable $ e n l a c e recoge el valor de referencia y se antildeade al texto de la liacutenea sishyguiente En este momento el texto contiene un enlace pero no sabemos hacia doacutende La solucioacuten estaacute en llamar al meacutetodo S e t L i n k () en la paacutegishyna de destino con la referencia de paraacutemetro

Resumen

Los archivos PDF se consideran desde hace unos antildeos ideales para la geshyneracioacuten de contenidos on-line As iacute revistas digitales como w w w phparchcom o wwwphpmagnet utilizan este sistema para vender su publicacioacuten

Ademaacutes de revistas digitales podemos encontrar empresas que hacen lleshygar las instrucciones de sus productos en PDF o realizan las facturas de los clientes on-line como el programa de facturacioacuten extrementildeo Galopiacuten (httpgalopinsinuhorg)

La generacioacuten de sus propios archivos ya no es un misterio y puede im-plementar clases muchos maacutes potentes que las mostradas en el libro para sus propios proyectos La inclusioacuten de colores imaacutegenes y tablas de disshytintos tipos haraacuten del lector un profesional de la edicioacuten Web

En este capiacutetulo aprenderaacute a

bull Conocer queacute es un sistema de plantillas con Smarty

bull Independizar el coacutedigo HTML de PHP bull Crear plantillas con variables y bucles bull Crear plugins propios y modificar los ya existentes bull Crear filtros para mejorar el proceso

340 Capiacutetulo 20

Introduccioacuten

Cuando PHP nacioacute fue considerado como un sencillo lenguaje para geneshyrar dinaacutemicamente etiquetas de HTML Tras la versioacuten 3 de PHP se antildeashydioacute un compendio de funciones complejas para el manejo de cadenas arrays y bases de datos lo suficientemente completas como para crear sishytios Web muy extensos

Despueacutes de la creacioacuten de entornos completos en PHP los desarrollado-res comenzaron a pensar que no era muy uacutetil mezclar coacutedigo PHP con coacutedigo HTML e inventaron una forma de independizar los dos lenguajes mediante el uso de plantillas El primer entorno de plantillas que apareshycioacute fue FastTemplate escrito originariamente en Perl

En un periacuteodo corto de tiempo aparecieron muchos programas que facilishytaban el uso de plantillas como vTemplate Xtemplate TemplatePower o SmartTemplate Todos permiten sustitucioacuten de variables bloques repetishytivos inclusioacuten de muacuteltiples plantillas y bloques opcionales con estructushyras del tipo i f La diferencia estaacute en que muchos de estos sistemas utilizan expresiones regulares y hace muy complicado su uso Ademaacutes la velocishydad con la que se generan las plantillas es una propiedad a tener en cuenshyta en un entorno de trabajo en produccioacuten

SmartTemplate aparecioacute en 1999 y es el predecesor de lo que hoy conoceshymos como Smarty Es un entorno muy similar a otros pero incluye caracshyteriacutesticas muy avanzadas que lo hacen uacutenico la compilacioacuten de plantillas Esto significa que Smarty lee la plantilla y crea un script escrito en PHP Una vez creado este script se ejecuta y muestra el resultado en pantalla Lo bueno es que la compilacioacuten soacutelo se hace la primera vez las veces sishyguientes Smarty comprueba si hay nuevos datos que mostrar y si no los hay se utiliza la plantilla escrita en PHP por lo que la ejecucioacuten se hace muy raacutepida Algunas de las caracteriacutesticas generales de Smarty son

bull Extremadamente raacutepido

bull Muy eficiente porque el parse de PHP hace todo el trabajo

bull Soacutelo se compilan las plantillas que cambien los datos

bull Podemos realizar funciones propias y modificadores de variables Esto hace que Smarty sea extensible por el usuario

bull Se pueden utilizar varios delimitadores como j ltmdashmdashgt

bull Las estructuras de control son manejadas directamente por el parse de PHP por lo tanto pueden ser tan complejas como quiera

Plantillas con Smarty 341

bull Se puede incluir coacutedigo PHP dentro de nuestras plantillas

bull Funciones configurables para el manejo de la cacheacute

bull Arquitectura de plugins ampliable

Instalacioacuten de Smarty

La instalacioacuten del entorno de Smarty es muy sencillo y pasa por descargar de la Web httpsmartyphpnet la uacuteltima actualizacioacuten del sistema El archivo comprimido consta de varias carpetas que deberiacutean estar dentro del directorio de libreriacuteas de PHP Tambieacuten es posible guardar la carpeta de Smarty junto con nuestros programas pero no es recomendable

Las libreriacuteas del sistema de plantillas incluidas dentro del directorio l i b s son

Smartyclassphp Smarty_Compilerclassphp Config_Fileclassphp debugtpl

Ademaacutes de estos archivos existen las carpetas c o r e y p l u g i n s que se encargan de controlar el flujo de los objetos de Smarty

Las plantillas que creemos las vamos a guardar en un directorio llamado t e m p l a t e s y las plantillas compiladas deberaacuten estar en t e m p l a t e s _ c

Advertencia

La carpeta t e m p l a t e s _ c debe permitir la escritura porque aquiacute se iraacuten guardando las plantillas compiladas

Utilizacioacuten baacutesica de Smarty

Durante el desarrollo del libro hemos visto algunas teacutecnicas para escribir limpiamente nuestro coacutedigo PHP mezclado con HTML Vamos a ver una clase implementada por nosotros que genera una Web desde PHP y desshypueacutes vamos a ver coacutemo hacer lo mismo desde Smarty

ltphp c l a s s PaginaWeb

342 Capiacutetulo 20

priacutevate $titulo function construct($titulo)

$this-gttitulo = $titulo

priacutevate function cabecera($titulo)

echo lthtmlgt echo ltheadgt -echo lttitlegt$tituloltheadgt echo ltheadgt echo ltbodygt

priacutevate function cuerpo()

echo Este es el cuerpo de nuestra Webltbrgt priacutevate function pie()

echo Pie creado con PaginaWeb class echo ltbodygt echo lthtmlgt

public function creaWeb()

$this-gtcabecera($this-gttitulo) $this-gtcuerpo () $this-gtpie ()

$pagina = new PaginaWeb(Pagina Web generada con PHP) $pagina-gtcreaWeb () gt

Lo que hace cada meacutetodo es generar las etiquetas necesarias para crear una paacutegina Web Imagine ahora un gran sitio Web con cientos de paacuteginas Web con distinto tipo de informacioacuten Cambiar el aspecto visual de esa Web seriacutea un trabajo muy laborioso de varios meses primero buscando doacutende se encuentran las etiquetas junto al coacutedigo PHP y segundo modishyficando todo el coacutedigo HTML para que cambie el aspecto visual Las planshytillas solucionan este problema en muy poco tiempo separando el coacutedigo de la presentacioacuten

El resultado se puede ver en la figura 201

La paacutegina Web siguiente p l a n t i l l a r t p l es la misma que genera la clase anterior pero esta vez creada como plantilla

plantillaltpl

Plantillas con Smarty 343

lthtmlgt ltheadgt lttitlegt$titulolttitlegt ltheadgt ltbodygt $cuerpo $pie ltbodygt lthtmlgt

Todas las etiquetas conservan el estilo de HTML antildeadiendo siacutembolos de llave donde debe aparecer contenido dinaacutemico $ t i t u l o $cuerpo y $pie son variables que reciben su valor desde el programa escrito en PHP

Nota

Todo lo que estaacute entre se considera un comentario

344 Capiacutetulo 20

Para poder asignar valores a la plantilla tiene que hacer una instancia de la clase Smar ty

Puede modificar el objeto anterior para que haga uso de plantillas

ltphp class PaginaWeb

priacutevate $titulo priacutevate $Web function construct($titulo)

$this-gttitulo = $titulo requiacutere_once(Smarty1 ibsSmartyclassphp) $this-gtWeb = new Smarty

priacutevate function cabecera($titulo)

$this-gtWeb-gtassign(titulo$this-gttitulo) priacutevate function cuerpo()

$this-gtWeb-gtassign(cuerpoEste es el cuerpo de nuestra Web)

priacutevate function pie ( )

$this-gtWeb-gtassiacutegn(pie Pie creado con PaginaWeb) public function creaWeb()

$this~gtcabecera($this-gttitulo) $this-gtcuerpo () $this-gtpie()

$this-gtWeb-gtdisplay(plantilla1tpl)

$pagina = new PaginaWeb(Pagina Web generada con PHP) $pagina-gtcreaWeb() gt

La clase es exactamente igual (con los mismos meacutetodos) pero ahora se encuentra libre de etiquetas HTML En su lugar aparecen asignaciones a variables de Smarty El constructor instancia un objeto desde la clase Smarshyty y lo guarda en $ t h i s - gtWeb Las asignaciones de variables se hacen con el meacutetodo a s s i g n () que tiene que recibir como primer paraacutemetro el nombre de la variable escrita en la plantilla y como segundo argumento el texto que debe aparecer en lugar de la variable

Plantillas con Smarty 345

Despueacutes de asignar todos los valores tendremos que llamar al meacutetodo d i s -p l a y () con la plantilla como argumento para que la Web aparezca en el navegador

Si se fija ahora en el directorio de las plantillas compiladas t e m p l a t e s _ c veraacute que ha aparecido un archivo que contiene el siguiente coacutedigo

ltphp Smarty versioacuten 263 created on 2004-08-15 130335

compiled from plantillaltpl gt lthtmlgt ltheadgt lttitlexphp echo $this-gt_tpl_vars [ titulo ] bull gt lttitlegt ltheadgt ltbodygt ltphp echo $this-gt_tpl_vars[cuerpo] gt

ltbrxbrgt ltphp echo $this-gt_tpl_vars[pie] gt

ltbodygt lthtmlgt

Como puede apreciar la compilacioacuten de una plantilla de Smarty consiste en cambiar los valores entre llaves por coacutedigo PHP que hace llamadas a las variables Esto lo convierte en un meacutetodo muy raacutepido porque es el mismo PHP el que se encarga de mostrar la plantilla ya compilada

Cuidado con los estilos CSS

Es muy uacutetil utilizar estilos CSS para definir los colores tipos de letra y demaacutes objetos de presentacioacuten que vamos a utilizar en nuestras paacuteginas Web

El problema surge porque su construccioacuten es de la siguiente forma

lts ty l e t y p e = t e x t c s s gt lt - -P colorgreen - - gt ltstylegt

Este estilo sirve para que los paacuterrafos sean por defecto de color verde El problema es que Smarty parsea todo lo que estaacute entre siacutembolos de llave como c o l o r g r e e n En este caso se produciriacutea un error porque el parse no identificariacutea ninguna funcioacuten estructura o variable de plantilla Para solucionar esto se pueden antildeadir las etiquetas l i t e r a l y l i t e -

346 Capiacutetulo 20

r a l que al ser parseadas su contenido se identifica como un comentashyrio y se salta hasta el siguiente juego de llaves

literal ltstyle type=textcssgt lt --P colorgreen mdash gt ltstylegt literal

Llamada a varias plantillas

Casi todas las paacuteginas Web pueden dividirse en varias partes bien difeshyrenciadas cabecera menuacute cuerpo pie

Con Smarty podraacute crear una Web simple que incluya todas las partes de la Web como un uacutenico archivo HTML o crear 4 plantillas distintas y 1 que las unifique por lo que seriacutea maacutes sencillo cambiar el aspecto de cada una de las partes

La funcioacuten i n c l u d e f i l e de Smarty permite antildeadir plantillas a un fishychero La plantilla principal puede ser de la siguiente forma

lthtmlgt ltheadgt lttitlegt$titulolttitlegt ltheadgt ltbodygt include file=cabeceratpl include file=cuerpotpl include file=$pie ltbodygt lthtmlgt

De esta forma podemos modificar alguna de las plantillas y automaacuteticashymente todas las Web que hagan referencia a la misma cambiaraacuten su asshypecto

Como puede ver la plantilla que genera el pie de paacutegina es una variashyble por lo tanto podemos pasar desde PHP el nombre de cualquier planshytilla en funcioacuten de alguacuten caacutelculo interno o de alguacuten dato de MySQL etceacutetera

Variables

Smarty acepta muchos tipos de variables diferentes

Plantillas con Smarty 347

Pueden ser utilizadas para mostrarse directamente o como paraacutemetro de alguna funcioacuten o modificador dentro de alguna estructura de control etshyceacutetera

$nombre $contactonombre $contacto [0] $persona-gtnombre config_load_file=configuracioacutenconf lttitlegttitulolttitlegt

El coacutedigo anterior contiene diferentes tipos de variables y la forma de imshyprimir el dato que nos interesa Para una variable del tipo array puede utilizar la forma asociativa $ c o n t a c t o nombre o la forma indicativa $ c o n t a c t o [0] Tambieacuten es posible mostrar las propiedades de un objeshyto haciendo referencia asiacute $ p e r s o n a - gtnombre

Por uacuteltimo Smarty posee una funcioacuten que permite cargar una configurashycioacuten de un fichero Con la instruccioacuten c o n f iacute g _ l o a d _ f iacute l e cargaraacute en memoria la configuracioacuten del fichero que deacute como argumento El fichero debe estar escrito de esta forma

titulo = Pagina Web con PHP nombre = Luis Miguel color = FFFFFF

Modificadores

Los modificadores se pueden aplicar a las variables funciones o cadenas de caracteres Eacutestos permiten embellecer el texto recortarlo o adecuarlo a un formato determinado Para utilizar un modificador tiene que especifishycar la variable seguido de un siacutembolo de tuberiacutea ( I ) y el nombre del modificador

lthtmlgt ltheadgt cambia el texto a mayuacutesculas lttitlegt$titulo|upperlttitlegt ltheadgt ltbodygt Recorta el texto a 10 caracteres y le suma tren puntos suspensivos $cuerpoiexcltruacutencate10 ltbrxbrgt $pie ltbodygt lthtmlgt

348 Capiacutetulo 20

La plantilla anterior contiene el modificador upper que convierte todos los caracteres que recibe en mayuacutesculas El modificador t r uacute n c a t e recorshyta el texto dejaacutendolo en 10 caracteres y le antildeade puntos suspensivos como puede apreciar en la figura 202 La tabla 201 contiene un conjunto de modificadores que pueden utilizarse en las plantillas

Tabla 201 Modificadores de Smarty

Modificador Descripcioacuten Paraacutemetros

capitalize Convierte la primera letra Ninguno de cada palabra a mayuacutescula

count_characters Se usa para contar los Ninguno caracteres de una variable

cat Concatena el paraacutemetro 1 El texto a concatenar pasado a la variable

count_paragraphs Cuenta el nuacutemero de paacuterrafos Ninguno que contiene una variable

count_words Cuenta el nuacutemero de palabras Ninguno

Plantillas con Smarty 349

Modificador Descripcioacuten Paraacutemetros

date_format Imprime en un formato 1 Formato de salida 2 Si determinado la fecha y hora la entrada estaacute vaciacutea acep-del sistema este paraacutemetro por defecto

default Valor por defecto de la 1 El valor por defecto variable Si no se asigna ninguacuten valor la variable tendraacute el valor por defecto

escape Antildeade caracteres de escape 1 html htmlall url quo-a la variable tes hex hexentity javas-

cript

indent Antildeade varios caracteres a 1 Nuacutemero de caracteres a la izquierda de la variable indentar 2 Caraacutecter elegishy

do para indentar

lower Convierte a minuacutescula todos Ninguno los caracteres

nl2br Convierte los saltos de liacutenea a ltbrgt

regexreplace Busca y reemplaza una 1 Expresioacuten regular 2 Ca-expresioacuten regular dena de texto a reemplazar

replace Reemplaza una cadena de 1 Cadena a reemplazar caracteres por otra 2 Cadena de texto que susshy

tituiraacute al paraacutemetro 1

spacify Inserta un caraacutecter determinado 1 Caraacutecter entre los caracteres de la variable Por defecto un espacio en blanco

string_format Formatea un texto 1 Formato del texto como lo usa s p r i n t f

strip Reemplaza todos los espacios Ninguno saltos de liacuteneas y fabuladores por un espacio en blanco

strip_tags Elimina todas las etiquetas Ninguno

truacutencate Recorta una variable el nuacutemero 1 Nuacutemero de caracteres a de caracteres que indiquen los recortar 2 Texto que debe paraacutemetros aparecer si se recorta 3

True permite recortar en mitad de una palabra

upper Convierte a mayuacutesculas todos los caracteres de una variable

350 Capiacutetulo 20

Es bueno saber que podraacute aplicar varios modificadores a una misma vashyriable Tiene que antildeadirlos en el orden en el que quiera que se ejecuten de izquierda a derecha

$cuerpo[upper|spacify j truacutencate20

Nota

Si la variable es un array se aplicaraacute el modificador a todos ss valores

Funciones

El gestor Smarty tiene varias funciones que se pueden utilizar dentro del aacutembito de las plantillas Ademaacutes puede crear sus propias funciones o modificar las que ya estaacuten construidas

foreach

El bucle foreach se utiliza para mostrar un array simple La sintaxis es algo distinta al bucle de PHP

lttablegt foreach from=$art is tas i tem=valor lt t r x t d gt $ v a l o r lt t d x t r gt foreach lt t ab legt

Lo puede utilizar para antildeadir los valores de un array a una tabla como en el coacutedigo anterior La construccioacuten maacutes baacutesica de fo reach recibe en el atributo f rom el array que contiene los valores El atributo item crea una variable de Smarty que recoge los valores del array y se puede utilizar para mostrar el valor unas liacuteneas maacutes abajo

Otra construccioacuten un poco maacutes compleja es lttablegt foreach name=buclel from=$artistas key=indice item=valor lttrxtdgt $indice $valor lttdxtrgt foreach lttablegt

Funciona exactamente igual que el anterior El atributo key recoge el vashylor del iacutendice del array y ntildeame da un nombre al bucle para poder acceder a eacutel desde las variables propias de Smarty

Plantillas con Smarty 351

Truco

Se puede acceder al bucle mediante la variable global de Smarty Esta variable es $ smar ty Para acceder al bucle puede hacerlo de la siguiente forma $ s m a r t y f o r e a c h b u c l e 1

El resultado de la ejecucioacuten de la plantilla es

0 Paquito DRivera 1 Michel Camilo 2 Jerry Gonzaacutelez

if elseif else

La construccioacuten i f es tan flexible como la sentencia de PHP Cada i f debe tener una pareja del tipo i f

if $artistas[0] = Michel Camilo El primer artista toca el saxofoacuten alto

else El primer a r t i s t a toca e l piano

i f

Ademaacutes de los operadores baacutesicos de PHP tambieacuten puede utilizar mushychos otros como eq ne neq g t l t l t e l e g t e g e i s even i s odd i s n o t odd no t mod d i v by e v e n by o odd by El coacutedigo siguiente es similar al anterior

if $artistas[0] ne Michel Camilo El primer artista toca el saxofoacuten alto

else

El primer artista toca el piano

if

php incluido en plantillas

Puede antildeadir a una plantilla coacutedigo PHP encerrado entre las etiquetas de Smarty php y phpiexcl Si recuerda la filosofiacutea de las plantillas separar el coacutedigo de la presentacioacuten no se me ocurre ninguna excusa para utilizar esta habilidad en alguacuten proyecto por si acaso alguien le encuentra alguacuten sentido su uso es muy sencillo

php Incluir aquiacute alguacuten coacutedigo escrito en PHP include_once(logotiposphp) Php

352 Capiacutetulo 20

assign

Crea una variable y le asigna un valor determinado

assign var=variable value=Michel Camilo El valor de $variable es $variable

Se utiliza en tiempo de ejecucioacuten de la plantilla

counter

Se utiliza para imprimir un contador en pantalla

counter start=0 skip=3 print=falseltbrgt counterltbrgt counterltbrgt counterltbrgt

El atributo s t a r t indica el nuacutemero desde el que va a empezar el contashydor y s k i p el nuacutemero que debe sumarse al contador cada vez que exista una ocurrencia Cada vez que el parse encuentre c o u n t e r se incremenshytaraacute el contador y el navegador mostraraacute el resultado Para el ejemplo anterior podemos obtener

3

6

9

cycle

Una funcioacuten interesante que permite alternar entre varios valores pasashydos Cada vez que se ejecuta se recupera un valor distinto hasta el final de los valores Cuando se llega al final de la lista se vuelve a empezar Es muy uacutetil cuando queremos mostrar valores en una tabla y que cada liacutenea de detalle muestre un color diferente

lttablegt foreach name=buclel from=$artistas key=indice item=valor lttr bgcolor=cycle valueacutes=EEEEEEd0d0d0gtlttdgt$indice $valorlttdxtrgt foreach lttablegt

En este caso el bucle genera nombres de artistas del Jazz Latino y los inshytroduce en una tabla Gracias a la funcioacuten c y c l e se pueden diferenciar unos de otros por tener los colores de fondo de cada liacutenea distintos

Plantillas con Smarty 353

Opciones avanzadas de Smarty

Existen muchos tutoriales en Internet sobre el sistema de plantillas Toshydos abarcan la forma de utilizar las funciones y variables del entorno pero pocos se ocupan de las caracteriacutesticas que lo hacen uacutenico

La arquitectura de Smarty estaacute escrita en PHP Los ficheros que contienen las funciones baacutesicas para que el parse pueda realizar su trabajo estaacuten dentro de c o r e Pero la mayoriacutea de las funciones de presentacioacuten estaacuten incluidas dentro de la carpeta de p l u g i n s

Plugins

Un plugin dentro de la estructura de Smarty es un pequentildeo programa que realiza una tarea determinada Por ejemplo todos los modificadores son plugins y cada uno se encarga de hacer algo con el texto Veamos la estructura del plugin c a p i t a l i z e que recordemos modifica la primera letra de cada palabra y la convierte a mayuacutescula

ltphp function smarty_modifiacuteer_capitalize($string)

return ucwords($string)

gt

El funcionamiento del plugin es obvio Tan soacutelo hace uso de una funcioacuten existente en PHP para mostrar el resultado Puesto que es tan sencillo vamos a crear un plugin que serviraacute para enfatizar nuestro texto en detershyminadas ocasiones

ltphp function smarty_modifier_enfatizar($string)

re turn ltbgt $ s t r ing ltbgt

gt

Para crear un plugin modi f icador cree un fichero con el nombre modif i e r nombre php y guaacuterdelo en el directorio d e p l u g i n s En este caso tendraacute que crear un archivo con el nombre modi f i e r e n f a t i z a r php El nombre de la funcioacuten tambieacuten debe llevar un nombre estructurado Nuestro modificador se llamaraacute s m a r t y _ m o d i f i e r _ e n f a t i z a r y reci-

354 Capiacutetulo 20

biraacute como paraacutemetro la cadena de caracteres que lo utilice Dentro de la funcioacuten puede antildeadir el coacutedigo que sea necesario para cumplir su propoacuteshysito y despueacutes devolver el valor con la funcioacuten re turn

En nuestro caso devolvemos la misma cadena pero antildeadiendo la etiqueta de HTML para mostrar el texto en negrita por lo que quedaraacute enfatizado Tambieacuten podemos antildeadir alguacuten paraacutemetro para elegir entre distintos tishypos de eacutenfasis

ltphp funetion smarty_modifier_enfatizar($string $parametrol)

switch ($parametrol)

case 1 return ltbgt $striacuteng ltbgt break-

case 2 return ltemgt $string ltemgt break

case 3 return i i iexcl $string break

default return ltbgt $string ltbgt

gt

Ahora tenemos tres formas distintas de mostrar un texto que llame la atenshycioacuten Para invocar desde la plantilla cualquiera de los tipos de eacutenfasis hashybraacute que separar el modificador con un siacutembolo de dos puntos ( )

$valor|enfatizar3

Filtros

Los filtros son funciones que realizan una tarea determinada en nuestra plantilla justo antes o despueacutes de que sea compilada Se pueden consideshyrar los pre-filtros y los post-filtros respectivamente Existe un tercer tipo de filtro que se ejecuta en el momento de la llamada al meacutetododisplay ()

Crear un filtro para Smarty es tan sencillo como crear un plugin Hay que seguir estrictamente la nomenclatura del archivo y del nombre de la funshycioacuten para que funcione correctamente

ltphp function smarty_jostfilter_HechoCon($compiled amp$smarty)

Plantillas con Smarty 355

return $compiled ltbgtHecho con Smartyltbgt

gt

El filtro HechoCon () es una funcioacuten que recibe como paraacutemetros la fuente de la paacutegina Web ya compilada y el objeto Smarty que estamos utilizanshydo Nuestro filtro HechoCon devuelve la Web y antildeade un pequentildeo texto que indica que ha sido creado con Smarty

Para poder utilizar el filtro tenemos que cargarlo antes de utilizar el meacuteshytodo d i s p l a y ( ) en nuestro coacutedigo Esto se hace con la funcioacuten l o a d _ f i l t e r ( )

$this-gtWeb- gtload__f ilter (pre trim) $this-gtWeb-gtload_filter(postHechoCon) $this-gtWeb-gtload_filter(outputcompress)

El primer paraacutemetro del meacutetodo l o a d _ f i l t e r () indica el tipo de filtro que vamos a cargar y el segundo el nombre que recibe

Resumen

Alguacuten lector se preguntaraacute despueacutes de entender correctamente lo bueno que es separar el coacutedigo de la presentacioacuten por queacute he esperado tanto tiempo en contar el secreto de Smarty La verdad es que es mejor aprenshyder PHP paso a paso haciendo pequentildeos programas con HTML embebishydo para despueacutes ir concibiendo la mejor forma de atajar los diferentes proyectos que nos propongan

Con Smarty tiene una viacutea libre de exploracioacuten maacutes porque muchas de sus caracteriacutesticas no han podido ser tratadas en este capiacutetulo Le queda aveshyriguar coacutemo utilizar la cacheacute los recursos (habilidad para leer de una base de datos una plantilla) y las numerosas funciones que hemos dejado en el tintero Una vez que conozca la potencia de Smarty no querraacute mezclar nunca maacutes su coacutedigo con HTML

358 Apeacutendice A

Antes de comenzar

El primer paso para desarrollar programas en PHP 5 es encontrar un sershyvidor donde hacer las pruebas del programa y posteriormente dejarlo almacenado para que los usuarios puedan utilizarlo Este servidor debeshyriacutea estar disponible las 24 horas del diacutea con una conexioacuten fija a Internet

Como esto puede ser algo complicado al principio vamos a ver los pasos necesarios para instalar un servidor de pruebas donde escribir nuestros primeros scripts

PHP 5 se distribuye como coacutedigo fuente listo para compilar en el sistema operativo que quiera El problema es que es algo complicado si nunca ha compilado un programa Por eso he elegido paquetes ya compilados que soacutelo necesitan ser instalados para comenzar a funcionar

Vamos a instalar los siguientes programas

bull Servidor Web Apache

bull PHP 5

bull MySQL 4

Instalacioacuten en MacOSX

Uno de los maacutes excitantes desarrollos Open Source ha sido la apertura parshycial del coacutedigo de la plataforma Macintosh Gracias a esto muchos usuashyrios estaacuten contribuyendo con la creacioacuten de paquetes de instalacioacuten como el de PHP 5

Apache

El servidor Web Apache es necesario para enviar las peticiones HTTP de los clientes

Afortunadamente Apache viene ya instalado en MacOSX Para ponerlo en funcionamiento tendraacute que seguir los siguientes pasos

bull Abra una Terminal

bull Entre como suacuteper usuario con el comando su

bull Introduzca la passzvord de suacuteper usuario

bull Escriba a p a c h e c t l s t a r t

La figura A l muestra los pasos realizados en el terminal para iniciar el servidor Web A partir de ahora puede probar si funciona Apache escribiendo en el nashyvegador la direccioacuten l o c a l h o s t como muestra la figura A2

360 Apeacutendice A

PHP5

Existe una Web dedicada al mundo de MacOSX que se actualiza todos los diacuteas

Su administrador L i y a n a g e es el encargado de crear paquetes con toshydas las versiones de PHP 5 que ven la luz que en el momento de redactar el libro es la 501

Para instalar PHP 5 tendraacute que descargar el paquete de

ht tp www2entropychdownloadEntropy-PHP-5-01-1dmg

Una vez copiado el archivo en su sistema soacutelo tiene que hacer doble clic en eacutel y seguir los pasos de instalacioacuten del sistema operativo como puede ver en la figura A3

MySQL 4

Los pasos son exactamente igual que en la instalacioacuten de PHP 5

El primer paso es descargar el paquete para MacOSXmysql - s t a n d a r d -4 0 2 0 - a p p l e - d a r w i n 7 3 0 -powerpc dmg que se encuentra en la seccioacuten de descargas de la Web wwwmysql com

El paquete se instala como cualquier paquete de MacOSX simplemente haciendo doble clic

Instalacioacuten de PHP 5 y MySQL 361

Comprobacioacuten final

Para comprobar que todo funciona correctamente tendraacute que seguir los pasos siguientes

bull Abra una Terminal

bull Entre como suacuteper usuario con el comando su

bull Introduzca la password de suacuteper usuario

bull Reinicie la ejecucioacuten de Apache para que acepte la nueva configurashycioacuten de PHP 5 con el comando a p a c h e c t l r e s t a r t

bull Inicie MySQL con el comando u s r l o c a l m y s q l - s t a n d a r d -4 0 2 0 - a p p l e - d a r w i n 7 3 O - p o w e r p c b i n m y s q l d - u r o o t

bull Cree una Web de prueba y guaacuterdela en la ruta del usuario para paacutegishynas Web Normalmente es U s e r s u s u a r i o S i t e s

bull Abra el navegador y escriba la direccioacuten del servidor junto con el nomshybre de la Web La direccioacuten seraacute parecida a esta l o c a l h o s t - u s u a shyr i o i n f o r m a c i oacute n php

El programa que hemos escrito para comprobar que todo funciona correcshytamente y muestra el contenido de la figura A4 es

ltphp

362 Apeacutendice A

p h p i n f o ( ) gt

En la figura A4 puede ver el funcionamiento de todo el sistema instalado

Instalacioacuten en Windows

Instalar un sistema completamente funcional en un sistema operativo Windows puede ser tan sencillo o tan complicado como quiera Existe un paquete de aplicaciones llamado XAMPP que contiene todo lo necesario para funcionar con Apache PHP 5 y MySQL

En la Web wwwapachefriendsorg puede encontrar un archivo de instashylacioacuten de Windows

Despueacutes de descargar el archivo tiene que hacer doble clic y seguir las instrucciones impresas en pantalla como muestra la figura A5

Una vez instalado en la ruta lniciogtProgramasgtapachefriendsgtxampp veraacute tres apartados importantes

bull xampp basic start Se encarga de iniciar Apache PHP 5 y MySQL

bull xampp basic stop Para la ejecucioacuten de los servidores

bull xampp httpdoc folder Carpeta donde tiene que guardar todos sus programas escritos en PHP 5

Para probar que todo funciona puede ejecutar el programa xampp bashys i c s t a r t abrir un navegador y escribir como direccioacuten l o c a l h o s t Si

Instalacioacuten en gnuuumlnux

Existen en el mercado varias versiones de gnuLinux como gnuLinEx 2004 SuSe RedHat Gentoo Cada una de ellas posee un sistema de paquetes distinto Puesto que no tenemos espacio para describir 3 formas diferenshytes de instalar PHP 5 nos conformaremos con describir un tema general que sirve para todos los sistemas gnuLinux

Como ya puede imaginar nos vamos a apoyar en X A M P P para gnushyLinux

Una vez descargada la versioacuten para gnuLinux en el disco duro tendraacute que descomprimirla en un directorio El archivo comprimido deberiacutea llamarse x a m p p - l i n u x - 1 4 7 t a r g z Para instalarlo debe seguir los pasos sishyguientes

bull Descomprima con el comando g z i p -d x a m p p - l i n u x - 1 4 7 t a r g z

bull Vuelva a descomprimir el archivo esta vez con t a r x v f x a m p p - l i -n u x - 1 4 7 t a r

Instalacioacuten de PHP 5 y MySQL 363

todo se instaloacute correctamente podraacute ver una Web parecida a la de la figushyra A6

364 Apeacutendice A

bull Se crearaacute una carpeta llamada lampp

bull Copie la carpeta al directorio op t con el comando cp -r lampp opt

bull Ya lo tiene instalado Para ejecutarlo debe ser suacuteper usuario e invocar el comando opt lampp lampp s t a r t

La figura A7 muestra un terminal con el comando de inicio

En la figura A8 puede ver la paacutegina de inicio de XAMPP tras poner en el navegador l o c a l h o s t como direccioacuten Web Todas las paacuteginas Web que genere tendraacute que guardarlas en el directorio op t l ampp h tdocs para poder verlas a traveacutes del navegador

Recomendacioacuten final

La forma maacutes raacutepida y sencilla de hacer funcionar PHP 5 en su sistema es la que hemos visto pero no es la mejor La forma maacutes recomendable que se escapa del enfoque de este libro es compilar su PHP 5 De esta manera tendraacute la posibilidad de antildeadir los

Instalacioacuten de PHP 5 y MySQL 365

moacutedulos y extensiones que realmente vaya a utilizar La recomendacioacuten es que navegue por la Web wwwphpnet e investigue la forma de compishylar su sistema

368 Apeacutendice B

Introduccioacuten

El archivophp i n i contiene informacioacuten de configuracioacuten que puede moshydificar a su antojo Es un fichero de texto que se lee cada vez que se inicia el servidor Web Apache Para averiguar la ruta del disco duro donde se almacena el archivo php i n i soacutelo tiene que fijarse en el apartado Conf i g u r a t i o n F i l e (php i n i ) Path de la Web que recibioacute al ejecutar phpinf o () La configuracioacuten contiene parejas de variables valores separadas por puntos y comas Los valores que tenemos que asignar suelen ser rutas del disco duro 10 Yes No On Off o True False Cada vez que cambie alguna parte de la configuracioacuten tendraacute que reini-ciar Apache para que los cambios surtan efecto

short_open_tag

Permite la forma corta de antildeadir scripts de PHP de la forma lt gt Si quiere utilizar funciones XML es mejor dejarlo a Off

disable_functions

Desactiva funciones que nos resulten peligrosas como el enviacuteo de correos funciones de red etceacutetera

max_execution_time

Tiempo maacuteximo de ejecucioacuten de un script PHP en el servidor

error_reporting

Muestra el nivel de error que configure cuando un script falla Los tipos de errores los puede ver en el capiacutetulo 17

register_globals

Esta configuracioacuten ya no se utiliza a partir de la versioacuten PHP 42 y estaacute destinada a desaparecer

Configuracioacuten de phpini 369

Si la activa todas las variables seraacuten pasadas como globales y no dentro de las variables suacuteper globales

magic_quotes_runtime

Antildeade el siacutembolo de escape cuando se pasan variables con los siacutembolos de comillas simples o dobles

include_path

Antildeade rutas donde puede almacenar libreriacuteas que pueda utilizar sus proshygramas

Resumen

Hemos visto las principales opciones de configuracioacuten del archivo php i n i La configuracioacuten es mucho maacutes extensa pero no merece la pena indagar en otras opciones a menos que vaya a dedicarse a la administrashycioacuten del Sistema

372 Apeacutendice C

Bibliografiacutea

El desarrollo del libro ha sido posible gracias a la consulta de numerosas publicaciones escritas paacuteginas Web y revistas profesionales que han dado una visioacuten actual de la programacioacuten en PHP 5 La bibliografiacutea presente en este libro muestra un compendio de libros revistas y paacuteginas Web que pueden ser uacutetiles al lector si decide ampliar sus conocimientos una vez terminado este libro

Libros de PHP 5

bull PHP5 and MySQL Bible Tim Converse y Joyce Park Completo libro que abarca numerosos temas Especializado en generar bases de datos con MySQL y PHP 5

bull The PHP Anthology Harry Fuecks El mejor libro sobre PHP esshycrito nunca Abarca casi todos los temas importantes a la hora de crear un sitio Web profesional Todos los scripts estaacuten cuidadosashymente pensados y orientados a objetos El autor es uno de los proshypulsores de los patrones de disentildeo

bull Learning PHP5 David Sklar Contenido muy sencillo pero direcshyto Para aprender PHP 5 desde 0

bull PHP5 for Dummies Janet Valade Un buen libro para aprender y profundizar en varias aacutereas Desde luego el teacutermino Dummies no le hace justicia porque a veces se hace algo complicado de seguir

bull Proyectos Profesionales PHP Ashish Wilfred Meeta Gupta Kartik Bhatnagar Proyectos orientados a PHP 4 pero muy bien construidos

bull PHP 4 Esteban Trigos Libro muy sencillo para iniciarse en PHP 4 bull PHP 5 Power Programming Andi Gutmans De uno de los creashy

dores de PHP Muy bien enfocado y con muacuteltiples temas bull Beginning PHP 5 Equipo Wrox Libro extenso sobre PHP 5 Cubre

todo lo que se puede conocer sobre PHP 5 En Octubre saldraacute la seshygunda parte llamada Proffesional PHP 5

Revistas profesionales

bull PHP Solutions Revista polaca traducida al espantildeol Contiene muy buenos artiacuteculos sobre desarrollo actual con PHP

Bibliografiacutea 373

bull PHP Magazine Revista alemana de gran alcance bull PHP Architect Revista canadiense donde habitualmente escriben

desabolladores como Harry Fuecks Marco Tabini o Andi Gutmans La misma editora de esta revista ha sacado el libro de estudio para preshysentarse al examen de Certificacioacuten de PHP

Paacuteginas Web

bull wwwphpsolmagorg Web de la revista PHP Solutions bull wwwphpmagnet Web de la revista PHP Magazine bull wwwphparchcom Web de la revista PHP Architect bull wwwsinuhorg Comunidad GnuLinux de Extremadura

bull wwwphpbuildercom Comunidad de usuarios con mucho coacutedishygo libre

bull wwwluisyfernandanet Web del autor bull wwwphppatternscom La Web de Harry Fuecks bull wwwphpnet Web oficial de PHP

bull wwwzendcom La empresa que hay detraacutes de PHP Ofrece curshysos y seminarios on-line

bull wwwcodewalkerscom Web con mucho coacutedigo libre

Page 5: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo

Agradecimientos

Finalizar este libro ha sido una odisea donde han intervenido muchas personas y factores mudanza incluida Para empezar me gustariacutea agradecer a Marta Camarero y a Eugenio Tuya su fe en miacute como escritor Me dieron aacutenimos desde el principio y un poquito de prisa A Zeev Suraski y Andi Gutmans creadores de PHP 5 por crear el lenguashyje y tratarme como a uno de los suyos en los iquestseminar de wwwzendcom Ademaacutes tengo que agradecerles la rapidez con la que escribieron el proacuteshylogo del libro A Marco Tabini director de la revista canadiense PHParchitect por enshyviarme el manual de Certificacioacuten PHP en papel y no en PDF A Tim Converse y Joyce Park por escribir PHP5 and MySQL Bible cuyos conocimientos me bebiacute en apenas 3 diacuteas A Harry Fuecks por escribir el mejor libro de PHP de todos los tiempos The PHP Anthology que me hizo reorientar todos los esfuerzos a la innoshyvacioacuten

A la Asociacioacuten Regional de Universidades Populares de Extremadura (AUPEX) por probar todos mis programas escritos en PHP (libros de visita foros nccproject newton etceacutetera) Espero dar alguacuten diacutea con la tecla A mis compantildeeros de trabajo Pako Palomo Javi y Pedro por las largas horas de discusioacuten en torno a Delphi Java C y por supuesto PHP A Justo Cabezas porque todo lo que me regaloacute fueron libros de informaacuteshytica y encima escritos por eacutel Sigo tus pasos A los grupos de usuario de gnuLinux de Extremadura wwwsinuhorg y wwwgulexorg por ser una fuente inagotable de conocimientos Por uacuteltimo A mi padre Ramoacuten que ya no estaacute a mi madre Felisa y a mi hermano Felipe porque nunca entendieron nada de informaacutetica pero me animashyron a seguir adelante con todo lo que me propuse Al resto de la familia porque cada uno de ellos ha tenido algo que ver en miacute vida y forman parte de lo que soy

iacutendice

Coacutemo usar este libro 19 Destinatarios de este libro 20 Organizacioacuten del libro 20 Convenios que emplea este libro 25 Los ejemplos en la Web de Anaya 26

Proacutelogo 27

Introduccioacuten 29 Historia de PHP 30 Nuevas Caracteriacutesticas de PHP 5 31

Faacutecil de usar 31 Embebido en HTML 32 Multiplataforma 33 Licencia Open Source 34 Multitud de Extensiones 34 Velocidad e incorporacioacuten de objetos 34 Popularidad 35 Gran Comunidad de apoyo 35

Objetivos del libro 36

1 Introduccioacuten a PHP 5 39 Introduccioacuten 40

8 iacutendice

HTML estaacutetico 40 Tecnologiacuteas del lado del cliente 42 Tecnologiacuteas del lado del servidor 43 Etiquetas de PHP 45 Nuestro primer programa en PHP 5 46 Repaso de HTML 47

Cabecera y cuerpo de una paacutegina Web 47 Cabecera 48 Cuerpo del documento 48 Paacuterrafos y saltos de liacuteneas 49 Estilo de texto 49 Enlaces de texto 51 Listas 51 Imaacutegenes 52 Tablas 53

Resumen 54

2 Variables constantes y tipos de datos 55 Variables en PHP 5 56

Tipos de Variables 56 Asignacioacuten de variables 57

Tipos simples 57 Enteros (integer) 58 Nuacutemeros de coma flotante (double) 59 Cadena de caracteres (string) 59 Boolean 61 NULL 62

Variables de variables 62 Constantes 63

defined() 63 Constantes predefinidas 64

Funciones relacionadas con variables 65 isset() 65 unsetQ 66 gettype() 66 settype() 67 empty() 67 is_integer() is_double() is_string() 67 intvalQ doublevalQ strvalQ 68

Resumen 68

iacutendice 9

3 Operadores 69

Introduccioacuten 70 Operador de asignacioacuten 70 Operador Unario 71 Operadores Aritmeacuteticos 71 Operadores de comparacioacuten 71 Operadores Loacutegicos 73 Operador Ternario 74 Operadores bit a bit 74 Operadores de asignacioacuten combinados 75 Operador de ejecucioacuten 76 Operador de supresioacuten de errores 77 Precedencia de Operadores 78 Resumen 80

4 Estructuras de control 81

Introduccioacuten 82 Estructuras de eleccioacuten 82

if-else 82 elseif 83 switch 84

Bucles 86 while 86 do-while 89 for 89

break y continueacute 92 Finalizar la ejecucioacuten de un programa 93 Sintaxis alternativa 93 Resumen 94

5 Funciones 95 Introduccioacuten 96 Valores de las funciones 96 Funcioacuten de ejemplo Obtencioacuten de la fecha actual 97 Documentacioacuten sobre funciones 98 Funciones de usuario 99

Definicioacuten de funciones 99 Paraacutemetros insuficientes 101 Paraacutemetros en exceso 102

10 iacutendice

Aacutembito de las variables 102 Variables estaacuteticas 104

Include() y require() 105 Recursividad 105 Funciones con nuacutemero de argumentos variables 106

Argumentos por defecto 106 Argumentos mediante un array 107 Muacuteltiples argumentos con func_num_args() 109

Llamadas por valor 110 Llamadas por referencia 111

Referencia a variables 112 Funciones variables 113 Resumen 114

6 Cadenas de caracteres y expresiones regulares 115 Introduccioacuten 116 Propiedades de las cadenas 116

iacutendices de string 116 Operadores 118 Sintaxis para muacuteltiples liacuteneas 118

Funciones de string 119 Tamantildeo de la cadena 120 Posicioacuten de los caracteres 120 Comparacioacuten 121 Buacutesqueda de caracteres 122 Seleccioacuten de subcadenas 122 Funciones de limpieza de cadenas 124 Sustitucioacuten de cadenas 126 Funciones de mayuacutescula y minuacutescula 126

Expresiones regulares 127 Comprobar expresiones regulares 129 Reemplazar patrones 131

Resumen 131

7 Conjuntos de datos del tipo array 133

Introduccioacuten 134 Creacioacuten de arrays 134

Asignacioacuten directa 134 array() 135 Funciones que devuelven arrays 136

iacutendice 11

Arrays multidimensionales 136 Propiedades de arrays 137

count() 1 3 7

in_array() 137 Borrar ocurrencias 138 Interactuar con arrays 138

Funciones para avanzar en un array 140 Funciones para retroceder en un array 142 Intercambio de valores 143 Inversioacuten del contenido 144 Mezcla de los valores 145

Pilas 145 Ordenacioacuten de los valores 146 Resumen 148

amp Paso de informacioacuten entre formularios 149

Introduccioacuten 150 Argumentos GET 150

Formularios con GET 151 Paso de informacioacuten con GET 155

Argumentos POST 157 Variables suacuteper-globales 158 Resumen 159

9 Programacioacuten orientada a objetos bull bull 1 6 1

Introduccioacuten 162 Definicioacuten de clases 163

Instancia de clase 164 Funcioacuten constructor 165

Herencia 165 Meacutetodos o funciones de objeto 166 Herencia encadenada 168 Valores y alcance de variables 168

Miembros puacuteblicos privados y protegidos 170 Meacutetodos privados 170 Meacutetodos protegidos 171 Meacutetodos puacuteblicos 171

Interfaces 172 Clases abstractas 172 Clases con meacutetodos estaacuteticos 173

12 iacutendice

Llamadas a funciones padre 174 Sobrecarga de meacutetodos 176 Sentildealizacioacuten 176 Funciones de manejo de clases 177 Resumen 179

10 Ficheros y almacenamiento de datos 181 Introduccioacuten 182 Funciones de lectura y escritura de ficheros 182

Abrir el fichero 182 Lectura de ficheros 183 Escritura de ficheros 185

Sistema de ficheros y directorios 188 Copiar borrar y renombrar 188 Funciones de comprobacioacuten 189 Directorios 190

Ficheros de configuracioacuten 191 Manejo de ficheros en el servidor 193

Subida de ficheros 193 Descarga de ficheros 195

Resumen 197

11 Bases de datos con SQL y SQLite 199 Introduccioacuten 200 SQL 200

SELECT 202 Uniones 203

INSERT 205 UPDATE 206 DELETE 207

Definicioacuten de tablas 207 SQLite 208

Creacioacuten de bases de datos 209 Uacuteltimos cambios en una tabla 211 Seleccioacuten de datos 212

SQLite orientado a objetos 213 Seleccioacuten de registros 214 Funciones de Array para recuperar datos 215 Nuacutemero de filas 216 Moverse entre registros 216

Resumen 218

iacutendice 13

12 PHP 5 y MySQL 219 Introduccioacuten 220 Administracioacuten de usuarios 220 Conexioacuten a MySQL 220

Seleccionar datos 222 Manipulacioacuten de datos 224

Insertar una fila 224 Actualizar una fila 225 Borrar una fila 225

Errores con las comillas 226 Contando filas 228

Contar filas con PHP 228 Contar filas con MySQL 229

Contar filas afectadas 230 Uacuteltimo nuacutemero insertado 230 Buacutesquedas dentro de una tabla 231 Definicioacuten de bases de datos 231

Creacioacuten de bases de datos 231 Creacioacuten de tablas 231

Resumen 233

13 Sesiones y Cookies 235 Introduccioacuten 236 Sesiones en PHP 5 237

Instanciando sesiones 237 Variables de sesioacuten 239 Problemas con los navegadores 240 Funciones para el manejo de sesiones 241

Cookies 243 setcookie() 243 Borrar una cookie 244

Cabeceras HTTP laquo 245 Resumen 246

14 Lectura y escritura de archivos XML 247 Introduccioacuten 248 SAXDOMySimpleXML 250 SAX 250 DOM 254

14 iacutendice

Usar DOM para leer archivos 255 Todo es un objeto 255 Atributos 256 Buacutesquedas muacuteltiples 257

Escribir archivos XML con DOM 257 Modificar archivos XML 259

SimpleXML 259 Resumen 261

15 Aplicaciones praacutecticas de XML 263 Introduccioacuten 264 Compartir informacioacuten con RSS 264

Distintos formatos 264 Leer un archivo RSS 268 Escribir archivos RSS 269

Servicios Web XML-RPC 272 Clase IXR 273 Cliente XML-RPC 274 Servidor XML-RPC 275 Usos de XML-RPC 277

Resumen 277

16 Generacioacuten de graacuteficos con PHP 5 279 Introduccioacuten 280 Graacuteficos HTML 280

Graacuteficos de barras 284 Libreriacutea GD 285

Tipos MIME 285 Mostrar una imagen en pantalla 286 Crear imaacutegenes en miniatura 288 Generar una marca de agua 290

Graacuteficos estadiacutesticos profesionales con JpGraph 292 Graacuteficos de barras 292 Graacuteficos en 3D 295

Resumen 297

17 Gestioacuten de errores en PHP 5 299 Introduccioacuten 300 Errores y Excepciones 300

iacutendice 15

La clase Exception 301 Bloque Try Catch 303 Heredar de la clase Exception 304 Limitaciones de PHP 5 305

Control de errores sin excepciones 306 Errores nativos de PHP 306 Controladores de error 307 Errores de usuario con trigger_error() 308

Depuracioacuten de errores 308 Resumen 309

18 Conexiones desde PHP 5 311

Introduccioacuten 312 FTP 312

Mostrar los archivos remotos 314 Descargar y Enviar ficheros 315 Otras funciones de FTP 316

Correo electroacutenico 317 Enviar correo desde PHP 318

PHPMailer 319 Antildeadir un fichero adjunto 320

Resumen 322

19 Creacioacuten de archivos PDF 325

Introduccioacuten 326 Libreriacutea FPDF 326

Nuestro primer documento 327 Funciones de texto 328

Meacutetodo Write() 328 Meacutetodo Cell() 329

Desplazamiento de los cursores 330 Salto de paacutegina automaacutetico 330

Sobrescribir los meacutetodos 331 Cabecera 331 Imagen de cabecera 332 Pie de paacutegina 333

Tablas 334 Enlaces 337 Resumen 338

16 iacutendice

20 Plantillas con Smarty 339

Introduccioacuten 340 Instalacioacuten de Smarty 341 Utilizacioacuten baacutesica de Smarty 341

Cuidado con los estilos CSS 345 Llamada a varias plantillas 346 Variables 346 Modificadores 347

Funciones 350 foreach 350 if elseif else 351 php incluido en plantillas 351 assign 352 counter 352 cycle 352

Opciones avanzadas de Smarty 353 Plugins 353 Filtros 354

Resumen 355

Apeacutendice A Instalacioacuten de PHP 5 y MySQL 357

Antes de comenzar 358 Instalacioacuten en MacOSX 358

Apache 358 PHP 5 360 MySQL 4 360 Comprobacioacuten final 361

Instalacioacuten en Windows 362 Instalacioacuten en gnuLinux 363 Recomendacioacuten final 364

Apeacutendice B Configuracioacuten de phpini 367 Introduccioacuten 368

short_open_tag 368 disable_functions 368 max_execution_time 368 error_reporting 368 register_globals 368 magic_quotes_runtime 369

iacutendice 17

include_path 369

Resumen 369

Apeacutendice C Bibliografiacutea 371 Bibliografiacutea 372

Libros de PHP 5 372 Revistas profesionales 372 Paacuteginas Web 373

Glosario 375

iacutendice alfabeacutetico 381

Coacutemo usar este libro

20 Coacutemo usar este libro

Destinatarios de este libro

Este libro estaacute dirigido a usuarios noveles que no sepan programar en ninshyguacuten lenguaje de desarrollo y a usuarios que ya conocen PHP pero desean tener una base soacutelida sobre la nueva versioacuten

PHP 5 estaacute ligado a Internet por lo tanto todas las aplicaciones praacutecticas del lenguaje estaacuten orientadas a realizar contenidos dinaacutemicos para paacutegishynas Por eso el lector debe conocer los aspectos baacutesicos de disentildeo en HTML

El libro puede dividirse en dos partes Una primera en la que se detallan los conceptos principales del lenguaje como las variables estructuras de control manejo de cadenas de caracteres creacioacuten de objetos y conectivi-dad con bases de datos que daraacute al lector novel una visioacuten general de PHP 5 y le permitiraacute comenzar a desarrollar sus primeras aplicaciones La segundaparte algo maacutes compleja haraacute las delicias del usuario novel y del medio Esta cuenta con teacutecnicas avanzadas para la lectura escritura de archivos XML creacioacuten de imaacutegenes en tiempo de ejecucioacuten conexioshynes de FTP y correo electroacutenico o disentildeo de plantillas con Smarty

El Software Libre estaacute presente en el aacutembito de la programacioacuten Por eso podemos utilizar algunos programas libres como base para construir aplishycaciones maacutes complejas El disentildeo de plantillas o la creacioacuten de llamadas a procedimientos remotos no seriacutea posible sin las libreriacuteas Smarty o IXR para XML-RPC desarrolladas por la comunidad de PHP para su uso libre

Por tanto el libro va dirigido a usuarios noveles que no saben nada de PHP Pero tambieacuten a usuarios medios o avanzados que desean conocer las nuevas caracteriacutesticas de PHP 5 y manejar teacutecnicas avanzadas de coshymunicacioacuten y disentildeo

Organizacioacuten del libro

Este libro estaacute dividido en 20 capiacutetulos con los siguientes contenidos

bull Capiacutetulo 1 Introduccioacuten a PHP 5 La introduccioacuten a PHP hace un reshycorrido por las nociones baacutesicas de HTML Ademaacutes aprenderaacute coacutemo crear su primera paacutegina en PHP y coacutemo mezclar el coacutedigo HTML con PHP

bull Capiacutetulo 2 Variables constantes y tipos de datos Los valores que manejamos en los programas deben ser almacenados en zonas de me-

PHP 5 21

moria reservadas por PHP Estas zonas reciben el nombre de variables y pueden ser tratadas de diferentes forma dependiendo de los valores que guarden (nuacutemeros enteros cadenas de caracteres valores boolea-nos) Este capiacutetulo contiene todo lo necesario para comprender coacutemo maneja PHP 5 las variables y las constantes estableciendo una diferenshycia con otros lenguajes fuertemente tipados como Java o C

bull Capiacutetulo 3 Operadores Otro aspecto de los lenguajes de programashycioacuten tiene que ver con los siacutembolos que se utilizan para realizar operashyciones aritmeacuteticas loacutegicas o de asignacioacuten Cada uno de los siacutembolos recibe el nombre de operador Este capiacutetulo muestra por grupos todos los operadores con los que se puede encontrar en PHP 5 Asiacute podraacute ver operadores especializados en sumas restas multiplicaciones o dishyvisiones (aritmeacuteticos) operadores de igualdad desigualdad o asignashycioacuten (de comparacioacuten) incluso operadores de manejo a nivel de bits (binarios)

bull Capiacutetulo 4 Estructuras de control El flujo de los programas viene deshyterminado siempre por las estructuras de control Estas indican en cada momento el rumbo que debe llevar el coacutedigo y lo que debe mostrar nuesshytra paacutegina basaacutendose en el valor contenido en las variables Las estrucshyturas de control y los operadores estaacuten iacutentimamente relacionados y su unioacuten permite desviar a evolucioacuten del programa en uno u otro sentido Las estructuras de control que veraacute en este capiacutetulo le daraacuten la potencia suficiente para crear sus primeros programas funcionales

bull Capiacutetulo 5 Funciones Si su coacutedigo se hace muy extenso a medida que avanza en la comprensioacuten del libro en este capiacutetulo aprenderaacute a remeshydiarlo Las funciones permitiraacuten al lector agrupar fragmentos de coacutedishygo repetitivo y aislarlo en ficheros independientes Este capiacutetulo no soacutelo cubre los aspectos teoacutericos para la creacioacuten de funciones sino que adeshymaacutes es un compendio de buenas praacutecticas a tener en cuenta para que sus proyectos se desarrollen ordenadamente Los aspectos baacutesicos a trashytar son la creacioacuten de funciones propias y el paso de paraacutemetros entre funciones de varias formas diferentes

bull Capiacutetulo 6 Cadenas de caracteres y expresiones regulares La mayor parte de la informacioacuten que puede encontrar en las paacuteginas es texto Conocer todas las teacutecnicas para concatenar medir cortar y buscar texshytos es baacutesico para crear un proyecto basado en contenido dinaacutemico Un perioacutedico digital un Log o incluso su propio CMS ya no tendraacuten seshycretos despueacutes de leer este capiacutetulo Ademaacutes la gran potencia de buacutesshyqueda de patrones viene de la mano de las expresiones regulares Eacutestas

22 Coacutemo usar este libro

permiten encontrar palabras frases y patrones dentro de un texto deshyterminado para manipularlo a nuestro antojo

bull Capiacutetulo 7 Conjuntos de datos del tipo array Este capiacutetulo trata a fonshydo las colecciones de datos PHP 5 maneja los conjuntos de datos como arrays asociativos Es posible acceder a los valores de un array de forma simple utilizando un iacutendice como en C y de forma asociativa asocianshydo una palabra a un valor determinado dentro del array Los arrays tieshynen un incalculable valor en los posteriores capiacutetulos usaacutendose como valor de retorno de muchas funciones de conectividad de bases de dashytos lectura de archivos XML o creacioacuten de plantillas

bull Capiacutetulo 8 Paso de informacioacuten entre formularios Si en el capiacutetulo 1 pudo ver los conceptos baacutesicos de la creacioacuten de paacuteginas en este podraacute conocer las teacutecnicas para enviar informacioacuten a traveacutes de formularios La mayoriacutea de las paacuteginas utilizan formularios para interactuar con los usuashyrios Aprenderaacute a pasar variables y arrays entre dos paacuteginas y coacutemo recoshyger desde PHP 5 los valores que se enviacutean Ademaacutes podraacute saber la diferencia entre los meacutetodos GET y POST y las variables suacuteper-globales

bull Capiacutetulo 9 Programacioacuten orientada a objetos El gran avance queacute ha sufrido PHP 5 desde su versioacuten anterior ha sido la total incorporacioacuten de la sintaxis y teacutecnica orientada a objetos Esto permite desarrollar proshygramas reutilizables en varios proyectos Una de las ventajas de la proshygramacioacuten orientada a objetos es que nos permite utilizar software de otras personas simplemente conociendo los meacutetodos que implementa no es necesario conocer coacutemo funciona el objeto para utilizarlo En este capiacutetulo el usuario novel y medio aprenderaacute las nuevas caracteriacutesticas de la programacioacuten orientada a objetos de PHP 5 A partir del capiacutetulo 9 casi todos los ejemplos estaraacuten basados en esta metodologiacutea de trabajo

bull Capiacutetulo 10 Ficheros y almacenamiento de datos La forma maacutes natushyral de almacenar datos persistentes es guardarlos en un fichero de dashytos Es una tarea muy sencilla y no dependemos de la instalacioacuten de alguacuten programa externo como una base de datos El capiacutetulo 10 mueacutes- tra coacutemo almacenar variables y textos dentro de un archivo para desshypueacutes recuperarlo en nuestra paacutegina Ademaacutes aprenderaacute una serie de teacutecnicas para recuperar ficheros enviados a traveacutes de un formulario y para poner en descarga archivos del servidor

bull Capiacutetulo 11 Bases de datos con SQL y SQLite Sin duda la mejor forma de almacenar datos masivos es utilizar una base de datos PHP 5 incorshypora una API de gestioacuten de bases de datos SQLite que permite almaceshynar millones de registros de diferentes tipos en un archivo binario Lo

PHP 5 23

mejor de utilizar SQLite es que no necesita instalacioacuten de una base de datos ni su administracioacuten todo estaacute contenido dentro de la API Aunshyque este libro no estaacute dedicado a la programacioacuten con bases de datos se da una referencia de los usos maacutes comunes del lenguaje de consultas estructurado (SQL) para que se pueda iniciar en este complejo mundo

bull Capiacutetulo 12 PHP 5 y MySQL MySQL ha sido siempre la panacea del desarrollo en el aacutembito profesional Es una base de datos robusta que permite administracioacuten de usuarios y seguridad a nivel de tablas y celshydas Es algo compleja de administrar pero muy sencilla de manejar desde PHP 5 Su utilizacioacuten ha sido tal que en el mundo de desarrollo se habla de las paacuteginas LAMP (Linux + Apache + MySQL + PHP) En este capiacutetulo aprenderaacute a manejar las funciones maacutes caracteriacutesticas de MySQL y a utilizarlas por medio de objetos en sus aplicaciones La proacutexima aparicioacuten de MySQL 5 hace prever que la combinacioacuten con PHP seraacute perfecta (MySQL 5 + PHP 5 = 10)

bull Capiacutetulo 13 Sesiones y Cookies En este capiacutetulo se detallan las teacutecnishycas necesarias para grabar informacioacuten en el equipo de los usuarios Estas pequentildeas variables (Cookies) permiten crear un pequentildeo control de asistencia de sus usuarios o guardar configuraciones especiales En cuanto a las sesiones son muy necesarias a la hora de crear espacios de venta de productos Las sesiones identifican a un usuario en concreto dentro de una paacutegina y permiten asociar variables concretas a ese usuashyrio aunque la paacutegina esteacute siendo visitada por muchas personas a la vez

bull Capiacutetulo 14 Lectura y escritura de archivos XML Frente a una inmenshysa cantidad de tipos de archivos propietarios como los documentos DOC o XLS nos encontramos a una serie de archivos basados en el lenguaje XML Este tipo de archivos como SXW (Openoffice) o SVG (graacuteficos vectoriales) estaacuten creados para ser entendidos por las personas y por los ordenadores Por lo tanto crear programas que interpreten estos archivos no es nada complejo El capiacutetulo 14 muestra tres caminos disshytintos para leer archivos XML Dos de ellos que vienen funcionando desde versiones anteriores SAX y DOM Y uno nuevo implementado en PHP 5 para facilitar esta tarea al programados Ademaacutes se incluyen las pautas necesarias para que cree sus propios archivos XML con la metodologiacutea DOM

bull Capiacutetulo 15 Aplicaciones praacutecticas de XML Si en el capiacutetulo anterior sentaacutebamos las bases para la lectura de informacioacuten desde archivos XML en este capiacutetulo crearemos objetos que implementen aplicacioshynes reales y actuales para compartir informacioacuten Es muy habitual hoy

24 Coacutemo usar este libro

en diacutea que las paacuteginas lleven asociados un panel de noticias que se generan en portales diferentes Esta informacioacuten se puede mostrar grashycias a teacutecnicas como RSS

Ademaacutes de crear sus propios objetos de generacioacuten de contenido RSS y su lectura haremos hincapieacute en lo que actualmente se llaman servicios Los servicios son pequentildeos programas almacenados en alguacuten servidor que informan acerca de algo concreto Aquiacute aprenderaacute a crear sus sershyvicios con las teacutecnicas ya adquiridas en el capiacutetulo 14

bull Capiacutetulo 16 Generacioacuten de graacuteficos con PHP 5 La generacioacuten de graacuteshyficos desde PHP 5 es posible gracias a la utilizacioacuten de libreriacuteas extershynas como GD Esto le permite manipular archivos graacuteficos que sus usuarios puedan subir a traveacutes de un formulario Con esta libreriacutea pueshyde generar graacuteficos en miniatura para despueacutes de hacer clic en eacutel antildeashydir una marca de agua a todas las imaacutegenes antildeadiendo el logo de su empresa o asociacioacuten

Otra gran libreriacutea es JpGraph que permite crear todo tipo de graacuteficos estadiacutesticos Esto le serviraacute para conocer el nuacutemero de visitas por diacutea mes o antildeo comparativas anuales de ventas de productos y todo un abanico de posibilidades

bull Capiacutetulo 17 Gestioacuten de errores en PHP 5 Una vez terminada la aplishycacioacuten tendraacute que tener en cuenta las partes del coacutedigo donde puede tener problemas Algunos usuarios pueden introducir caracteres no permitidos o nuacutemeros donde se esperaban letras La gestioacuten de errores permite mostrar al desarrollador y al usuario doacutende aparece el error y el tipo de fallo que se ha producido Una buena gestioacuten de errores haraacute que su programa sea maacutes fiable

bull Capiacutetulo 18 Conexiones desde PHP 5 La conectividad de PHP con otras aplicaciones o servicios ha sido siempre una preocupacioacuten de sus desarrolladores Asiacute desde anteriores versiones puede encontrar coshynectividad con servicios LDAP POP3 SMTP o FTP

Este capiacutetulo trata de abarcar dos servicios muy utilizados por la coshymunidad de usuarios El FTP en primer lugar para enviar y recuperar informacioacuten de otros servidores desde un programa escrito en PHP Y en segundo lugar el manejo de las funciones necesarias para enviar informacioacuten por correo electroacutenico

bull Capiacutetulo 19 Creacioacuten de archivos PDF El formato de texto maacutes difundishydo en Internet es el PDF Tanto se ha extendido este formato que la mayoshyriacutea de las paacuteginas profesionales contienen archivos PDF con diferentes contenidos Desde paacuteginas de contenido tecnoloacutegico hasta las de cocina

PHP 5 25

exportan sus contenidos en PDF para que sus usuarios puedan disfrutar desde su ordenador del manual del video o la receta de la semana

En este capiacutetulo veraacute paso a paso coacutemo generar un archivo PDF comshypleto desde la cabecera hasta el pie de paacutegina pasando por todo tipo de textos e imaacutegenes

bull Capiacutetulo 20 Plantillas con Smarty La uacuteltima aportacioacuten de este libro tiene que ver con la tendencia de separar el coacutedigo PHP de la presentashycioacuten en HTML Smarty provee unos sencillos mecanismos desde PHP que permiten realizar sencillamente esta separacioacuten Ademaacutes de las caracteriacutesticas baacutesicas de las plantillas la potencia de Smarty reside en la compilacioacuten del disentildeo cada vez que cambian los datos hecho que otorga a Smarty el puesto nuacutemero 1 en velocidad en el ranking de sisteshymas de plantillas En este capiacutetulo aprenderaacute a crear plantillas con Smarty que permitiraacuten cambiar el aspecto graacutefico de su aplicacioacuten sin tocar el coacutedigo escrito en PHP 5

bull Apeacutendice A Instalacioacuten de Apache y PHP 5 en distintos Sistemas Opeshyrativos La instalacioacuten de PHP 5 es muy sencilla en gnuLinux MacOSX y Windows El Apeacutendice muestra los pasos necesarios para instalar un servidor Apache con el parse de PHP 5 listo para ser utilizado con los ejemplos En cada caso la instalacioacuten se hace de una forma distinta Hemos buscado para cada Sistema Operativo la opcioacuten maacutes sencilla que es utilizando alguacuten paquete compacto que se instale y deje listo el sistema Puesto que es un libro para principiantes hemos huido de crear PHP 5 desde el coacutedigo fuente compilando el programa

bull Apeacutendice B Configuracioacuten baacutesica de phpini El archivo de configurashycioacuten php i n i contiene aspectos de funcionamiento de PHP 5 que pueshyden cambiarse sin necesidad de compilar el programa Este Apeacutendice contiene algunos paraacutemetros de configuracioacuten que pueden ser uacutetiles

bull Apeacutendice C Bibliografiacutea Este libro estaacute basado en el conocimiento adquirido tras la lectura de numerosos libros sobre la temaacutetica paacutegishynas Web y revistas profesionales del sector Este Apeacutendice cubre todas las posibilidades dando al lector un camino a seguir despueacutes de termishynar el presente libro

Convenios que emplea este libro

El nombre de los comandos funciones meacutetodos u objetos aparecen resalshytados en el libro de la siguiente forma ob j e t o

26 Coacutemo usar este libro

Algunas palabras teacutecnicas que no tienen una traduccioacuten faacutecil al castellano o simplemente estaacute fuertemente asentada en el idioma teacutecnico aparecen de la siguiente forma array true ofalse

En el libro aparecen resaltados una serie de temas circunstancias o aconshytecimientos extraordinarios de la siguiente forma array true ofalse

Nota

Anotaciones sobre el texto

Advertencia

Informacioacuten importante a tener en cuenta a la hora de desarrollar un programa Explican de alguna manera posibles equivocacioshynes o ayudas para no caer en errores frecuentes

Truco

Consejo o informacioacuten importante que puede facilitar el trabajo

Los ejemplos en la Web de Anaya

La mayoriacutea de los ejemplos del libro se pueden obtener en la Web de Anashyya Multimedia en la direccioacuten siguiente

httpwwwanayamultimediaes Seleccionando los menuacutes Atencioacuten a clientegtComplementosgtManuales lmprescindiblesgtManual Imprescindible de PHP 5 Ademaacutes de los ejemplos puede encontrar las aplicaciones externas o enshylaces a las mismas que utilizamos para desarrollar algunos ejemplos como Smarty FPDF JpGraph o la libreriacutea IXR

Todos los ejemplos han sido probados en el servidor Apache para MacOSX con el paquete de PHP 501 y en un servidor Apache sobre gnuLinEx Todas las capturas de pantalla se han realizado con el navegador Grulla (Mozilla Firefox) de gnuLinEx 2004

Proacutelogo

28 Proacutelogo

Una de las preguntas maacutes interesantes que nos hacen es queacute hace que PHP tenga tanto eacutexito Distintas personas nos han dado respuesta a esta preshygunta Algunos sostienen que es su excelente conexioacuten con bases de dashytos otros que se debe al coacutedigo abierto por el contrario otros mantienen que es su funcionamiento Sin embargo nuestra opinioacuten difiere PHP pershymite que cualquier usuario obtenga raacutepidamente resultados de forma senshycilla incluso aquellos que no posean experiencia en programacioacuten Al mismo tiempo a diferencia de las herramientas RAD PHP permite el deshysarrollo de proyectos tan complejos como se desee En nuestra opinioacuten esta combinacioacuten ausente en la mayoriacutea de las plataformas Web actuales es lo que hace que PHP sea especial

Lograr el equilibrio entre estas dos liacuteneas (la potencia y la sencillez) no ha sido faacutecil pero siacute imprescindible para el eacutexito de PHP como tambieacuten lo son las nuevas caracteriacutesticas que permiten al desarrollador aprovechar la uacuteltima tecnologiacutea

PHP 5 es el producto de este importante equilibrio Aunque dotado de muchas funciones nuevas esta versioacuten es tan accesible como lo fueron PHP 3 y PHP 4 con lo que permite un raacutepido aprendizaje para aquellos que se inicien De hecho algunas de las novedades basadas en la interfaz de Zend Engine II como SimpleXML SQLite y SOAP hacen maacutes sencillo el uso de PHP al tiempo que incrementa el potencial de aquellos usuarios noveles pues les permite trabajar con XML SQL y Web Services sin esfuerzo

La nueva generacioacuten PHP tambieacuten supone una buena noticia para desashybolladores experimentados En primer lugar por simplificar todas aqueshyllas funciones que ya se han indicado (al contrario de lo que normalmente se piensa ni siquiera a los desabolladores avanzados les gusta trabajar a menos que sea imprescindible) y en segundo lugar por poner a su disposhysicioacuten funciones mejoradas Las nuevas opciones orientadas a objetos de Zend Engine II son un regalo para el desarrollo de aplicaciones de media y gran escala como la nueva extensioacuten mysqli y el nuevo moacutedulo de inteshygracioacuten NET que permite la creacioacuten de aplicaciones hiacutebridas de PHP que emplean la estructura NET

Este libro es una gran introduccioacuten a PHP en general y de PHP 5 en partishycular Si no tiene experiencia previa con PHP e incluso si no tiene ningushyna experiencia en programacioacuten en breve podraacute trabajar con eacutel

Zeev Suraski Tel A v i v

Andi Gutmans Cupertino

Introduccioacuten

30 Introduccioacuten

Historia de PHP

Rasmus Lerdorf miembro del equipo de desarrollo de Apache creoacute PHP (Personal Home Page) en 1994 Su uacutenica intencioacuten fue la de crear un pequeshyntildeo sistema de control para verificar el nuacutemero de personas que leiacutean su curriculum vitae en la Web

En los meses siguientes a su creacioacuten PHP se desarrolloacute en torno a un grushypo de programadores que comprobaban el coacutedigo y sus revisiones Para dar maacutes potencia al sistema Rasmus creoacute funciones en lenguaje C para permitir conexioacuten a bases de datos Este fue el comienzo de la potencia real del leguaje

En 1995 aparecioacute un conjunto de herramientas sobre PHP Esta biblioteca se llamoacute Herramientas para paacuteginas personales y conteniacutean un analizashydor de coacutedigo muy sencillo un libro de visitas un contador y algunas macros que facilitaban el trabajo de los disentildeadores

A mediados de 1995 aparecioacute una revisioacuten puacuteblica llamada PHPFI 20 Esta nueva versioacuten contaba con un analizador sintaacutectico reescrito desde 0 ademaacutes de unas herramientas escritas para el tratamiento de datos desshyde un formulario (de ahiacute el nombre aacuteeFI Form iacutenterpreter) y conectividad con mSQL (Gestor de bases de datos)

Hacia 1997 PHPFI se estaba usando en maacutes de 50000 paacuteginas en todo el mundo En este periacuteodo de tiempo Zeev Suraski y Andi Gutmans decishydieron crear una nueva versioacuten de PHPFI para solventar unos probleshymas con una aplicacioacuten de comercio electroacutenico que estaban desarrollando PHP 30 nacioacute con suculentas innovaciones como la conectividad con vashyrios gestores de bases de datos protocolos y una API ampliada La vershysioacuten oficial de PHP 30 vio la luz en junio de 1998 donde se contemplaba ya la programacioacuten orientada a objetos

En 1999 se realizoacute la primera revisioacuten del motor Zend (Zend Engine) que aportaba modularidad claridad y herramientas de optimizacioacuten para paacuteshyginas de gran escala Zend viene de la unioacuten de Zeev y Andi

PHP 40 vio la luz en mayo de 2000 dividida en 3 partes El motor Zend la API de servidor y los moacutedulos de funcionas El motor Zend es el responshysable de analizar el coacutedigo PHP definir la sintaxis y del lenguaje de proshygramacioacuten La API permite la comunicacioacuten con el servidor Con esta API es posible utilizar PHP desde varios servidores Los moacutedulos contienen funciones para el manejo de cadenas archivos XML o tratamiento de imaacuteshygenes

PHP 5 31

La orientacioacuten a objetos no estaacute muy lograda en PHP 40 Los objetos tieshynen un tratamiento muy pobre e iloacutegico La definicioacuten de las variables miembro (propiedades) y los meacutetodos son siempre puacuteblicos por lo que la encapsulacioacuten es nula Todos los objetos se pasan por valor por defecto cuando deberiacutean pasarse por referencia

Todas estas propuestas realizadas por el equipo de desarrollo de PHP han desembocado en la creacioacuten del motor Zend 20 y su consecuencia PHP 5

PHP 5 incorpora una verdadera orientacioacuten a objetos Antildeadiendo las pashylabras reservadas public protected y priacutevate a la definicioacuten de las propiedashydes y meacutetodos de los objetos se permite una verdadera encapsulacioacuten Ademaacutes del considerable avance con respecto a los objetos PHP 5 incorshypora un control de errores muy mejorado al estilo de los lenguajes de proshygramacioacuten maacutes avanzados

Nota

Despueacutes de una encuesta entre desarrolladores y usuarios de PHP se decidioacute cambiar el significado de PHP a PHP Hypertext Pre-processor Este cambio sigue los pasos de Richard Stallman al nombrar a su sistema operativo GNU (GNU is not Unix) doshytando a la palabra PHP de recursividad Es un juego de palabras muy utilizado en el ambiente hacker

Nuevas Caracteriacutesticas de PHP 5

Existen muchas razones para elegir PHP 5

Faacutecil de usar

PHP 5 es un lenguaje muy faacutecil de aprender con respecto a otros lenguashyjes utilizados para el mismo propoacutesito como JAVA o ASP Debido a esto no es necesario hacer un estudio muy concienzudo de sus funciones para realizar programas sencillos que nos resuelvan la mayoriacutea de los probleshymas diarios

La mayoriacutea de las funciones maacutes usuales estaacuten disponibles por defecto como la conexioacuten a bases de datos o la utilizacioacuten de servidores IMAP Existe una gran cantidad de paacuteginas con documentacioacuten y programas heshychos por desarrolladores que se pueden leer y modificar libremente

32 Introduccioacuten

Embebido en HTML

Las paacuteginas escritas en PHP son simples paacuteginas en HTML que contieshynen ademaacutes de las etiquetas normales el programa que queremos ejecushytar Por ejemplo

ltHTMLgt ltBODYgt ltHEADgt ltTITLEgtEjemplo de PHP5 embebidoltTITLEgt ltHEADgt ltBODY ltPgtEsto es HTML del buenoltPgt ltphp Aquiacute comienza el coacutedigo PHP Lo siguiente es una simple asignacioacuten de variables y su salida por pantalla $nombre=Luis Miguel $apellidos=Cabezas Granado $fecha_hoy=date(d-ra-Y1) gt ltPgtEste paacuterrafo contiene HTML y PHP El autor del script es ltphp echo ($nombre $apellidosgt gtlt Pgt ltPgtLa fecha de ejecucioacuten del script es ltphp echo($fecha_hoy)gtltPgt ltBODYgt ltHTMLgt

Cuando un cliente solicita esta paacutegina el servidor preprocesa los datos y ejecuta las instrucciones de PHP En este caso las variables (las palabras que tienen el signo $ delante) se llenan con los valores que hay a la dereshycha del signo igual Una vez resuelto todo el proceso el servidor le enviacutea al cliente una paacutegina soacutelo con etiquetas de HTML La figura 11 muestra este proceso

Si inspeccionamos ahora el coacutedigo que tenemos en el navegador nos dareshymos cuenta de que las etiquetas de PHP han desaparecido

ltHEAD ltTITLEgtEjemplo de PHP5 embebido-TITLEgt ltHEADgt ltBODYgt ltPgtEsto es HTML del buenoltPgt ltPgtEste paacuterrafo contiene HTML y PHP El autor del script es Luis Miguel Cabezas GranadoltPgt ltPgtLa fecha de ejecucioacuten del script es 05-07-2004ltPgt ltBODYgt ltHTMLgt

higura ii Kesuitaao ae ejecutar un scnpi sencillo

La consecuencia maacutes inmediata es que no es necesario compilar el prograshyma en coacutedigo binario antes de poder testar si funciona o no PHP es un lenshyguaje interpretado como otros muchos en el mercado (ASP Python o JSP)

Multiplataforma

PHP 5 se ejecuta en multitud de plataformas Sistemas Operativos y Sershyvidores existentes Es compatible con los tres servidores liacutederes del mershycado Apache Microsoft Internet Information Server y Netscape Enterprise Server

Tabla 11 Sistemas Operativos y Servidores para PHP 5

Basados en UNIX Windows

Sistema Operativo AIX AUX BSDI Digital UNIXTru64 FreeBSD HP-UX IacuteRIX MacOS X gnuLinux gnuLinEx NetBSD OpenBSD SCO UnixWare Solaris SunOS Ultrix Xenix y muchos maacutes Windows 98Me Windows NT 2000XP2003

Servidores Apache fhttpd Netscape US PWS Netscape Apashyche Omni

Puesto que PHP se ejecuta en todos los Sistemas Operativos indicados en la tabla 11 y en la mayoriacutea de las plataformas hardware existentes (Intel

PHP 5 33

34 Introduccioacuten

A M D PowerPc SPARC etceacutetera) nos seraacute muy sencillo conseguir un lashyboratorio de pruebas para nuestros script

Licencia Open Source

La licencia de Coacutedigo Abierto implica que el coacutedigo fuente de PHP 5 es libre de ser descargado e inspeccionado por nosotros La consecuencia principal es que el coste del producto en la mayoriacutea de los casos es de 0 Euros Tener el coacutedigo fuente de PHP 5 sirve entre otras cosas para poshyder hacer nuestro servidor a medida es decir podemos compilar el proshygrama con las opciones que realmente utilicemos (base de datos LDAP)

Si acompantildeamos Apache el servidor maacutes popular a la instalacioacuten de PHP 5 y antildeadimos alguna base de datos Open Source como PostgreSQL tendreshymos un sistema completo de script de servidor cuyo coste es nulo frente a otras opciones en las que es necesario el uso de licencias

Multitud de Extensiones

PHP 5 se desarrolla para dar la mayor versatilidad y flexibilidad a los usuashyrios que lo utilizan Es por esto por lo que existen muchas extensiones del lenguaje que permiten utilizar nuevas bases de datos protocolos enlaces a libreriacuteas etceacutetera

El acceso a bases de datos tiene una gran potencia implementando soporshyte nativo para 15 Sistemas Gestores de Bases de Datos muy populares En cuanto a los protocolos podemos contar con extensiones que controlan el acceso a LDAP IMAP o POP3 Tambieacuten se ha cuidado el soporte para crear imaacutegenes en tiempo de ejecucioacuten gracias a la libreriacutea GD

Dada la importancia del desarrollo del lenguaje XML en los uacuteltimos antildeos PHP 5 incorpora tres meacutetodos de acceso a este tipo de archivos SAX D O M y simpleXML Ademaacutes se incorpora a PHP 5 la gestioacuten de errores mediante el manejo de excepciones

En esta versioacuten se han antildeadido facilidades para utilizar los repositorios de coacutedigo de PEAR

Velocidad e incorporacioacuten de objetos

El nuevo motor Zend 20 acelera los procesos de ejecucioacuten del coacutedigo Ademaacutes incorpora un nuevo modelo de objetos que permite crear ciacutea-

Figura 12 Uso de PHP desde el antildeo 2000

Gran Comunidad de apoyo

PHP 5 se ha escrito bajo el auspicio del Coacutedigo Abierto Por lo tanto exisshyte una comunidad que apoya su desarrollo en colaboracioacuten La ventaja principal es que existen multitud de paacuteginas listas de correo y foros de debate cuyo tema de conversacioacuten es el manejo de este lenguaje de proshygramacioacuten

Esta comunidad sirve de apoyo para todos los que necesitamos conocer desde los aspectos maacutes baacutesicos hasta las implementaciones maacutes complishycadas Tan pronto como hagamos uso de esta ayuda nos sentiremos oblishygados a prestar la nuestra a usuarios principiantes y asiacute la Comunidad se

PHP 5 35

ses y meacutetodos privados protegidos y puacuteblicos clases abstractas e inter-faces

Popularidad

El uso de PHP se ha disparado desde el antildeo 1999 como puede verse en la figura 12

36 Introduccioacuten

iraacute ampliando Si nuestros conocimientos llegan a superar alguacuten diacutea los objetivos de este libro podemos pensar en contribuir enviando fallos en el lenguaje respondiendo a mensajes de las listas de correo participando en foros de debate o escribiendo extensiones en lenguaje C

Objetivos del libro

A la hora de seleccionar este libro o cualquier otro sobre PHP 5 creo que es esencial que conozca los objetivos que marcan sus capiacutetulos Este libro en concreto estaacute pensado para

bull Tener una visioacuten general de los lenguajes de script para desarrollo

bull Conocer las ventajas de PHP 5 frente a otros lenguajes similares Tener una visioacuten general de las nuevas caracteriacutesticas que ofrece PHP 5

bull Aprender los conceptos baacutesicos para empezar a desarrollar aplicacioshynes sencillas que muestren contenido dinaacutemico

bull Identificar claramente todas las caracteriacutesticas de la orientacioacuten a objeshytos y aprender a desarrollar aplicaciones divididas en partes con moacuteshydulos reutilizables en distintos proyectos

bull Sacar partido de la API SQLite y del gestor de bases de datos MySQL para crear aplicaciones maacutes profesionales que nutran de contenido las paacuteginas

bull Crear formularios que enviacuteen informacioacuten y ficheros entre varias paacuteshyginas de distinta forma

bull Aprender a generar archivos para Internet de distintos formatos Los archivos XML o PDF se han vuelto indispensables en esta era y muy uacutetiles para exportar informacioacuten a los usuarios

bull Conocer las funciones baacutesicas para la creacioacuten de paacuteginas que controshylen y manipulen imaacutegenes Ademaacutes conoceraacute herramientas para geshynerar en el momento graacuteficos estadiacutesticos de diferentes formas

bull Controlar todos los errores que puedan producir los programas evishytando mostrar en el navegador mensajes de error geneacutericos para mosshytrar errores controlados por nosotros

bull Generar plantillas con libreriacuteas para separar el coacutedigo escrito en PHP de la presentacioacuten creada con HTML o alguacuten programa de disentildeo

El libro crea una base muy fuerte para comenzar a realizar aplicaciones profesionales Es evidente que la creacioacuten de archivos XML PDF genera-

PHP 5 37

cioacuten de graacuteficos o plantillas Smarty necesitan un libro entero para cubrir todas las caracteriacutesticas que ofrecen Este libro da una visioacuten general a los lectores y permite conocer las herramientas que actualmente se utilizan para que cada uno pueda investigar por su cuenta las que maacutes le interese

Capiacutetulo 1

Introduccioacuten aPHP5

En este capiacutetulo aprenderaacute a

bull Diferenciar entre scripts de cliente y servidor bull Utilizar diferentes tipos de etiquetas de inicio de PHP bull Escribir su primer programa en PHP bull Conocer las etiquetas HTML

40 Capiacutetulo 1

Introduccioacuten

El mundo de los desarrolladores de paacuteginas ha cambiado de forma vertishyginosa en los uacuteltimos antildeos En poco tiempo han surgido tecnologiacuteas y reshyvisiones de esas tecnologiacuteas que hacen que los programadores tengamos que reciclarnos continuamente

Hace unos antildeos el desarrollo de grandes paacuteginas era complicado de manshytener El lenguaje existente era uacutenicamente HTML y solo permitiacutea crear las paacuteginas y subirlas a un servidor El problema de esto es que modificar alguacuten dato de una de las paacuteginas implicaba un trabajo extra que incluiacutea descargarla modificarla maquetarla de nuevo y subirla al servidor

Actualmente existe un conjunto de lenguajes que permiten desarrollar paacutegishynas Web dinaacutemicas es decir que el contenido puede variar muy raacutepidamente sin ninguacuten esfuerzo por parte de los desarrolladores Eacutestos se denominan lenguajes de script de servidor porque la ejecucioacuten del programa se realiza en el servidor Web donde se encuentra alojada la paacutegina Existe un largo compendio de lenguajes que se pueden utilizar para la creacioacuten de paacuteginas Web dinaacutemicas ASP de Microsoft Java y JSP de Sun Perl Python PHP

HTML estaacutetico

El tipo maacutes baacutesico de paacutegina Web es completamente estaacutetico basado en texto plano y completamente escrito en HTML La paacutegina siguiente es un ejemplo de Web estaacutetica

ltHTMLgt ltHEADgt

ltTITLEbLibros sobre PHP 5 y gnuLinuxltTITLEgt ltHEADgt ltBODYgt ltTABLE BORDER-lgt ltTRgt

ltTDgtTiacutetulo de libros americanos sobre PHP 5ltTDgt ltTRgt ltTABLEgt ltulgt ltlixbgt Advanced PHP Programmingltbxbrxligt ltlixbgtPHP5 and MySQL bibleltbxbrxligt ltlixbgtLearning PHP 5ltbgtltbrxligt ltlixbgtUpgrading to PHP 5ltbxbrxligt ltlixbgtBeginning PHP 5 and MySQLltbxbrxligt

Introduccioacuten a PHP 5 41

ltlixbgtPHP 5 Power Programmingltfcgtgtltbrgtltligt lt u lgt ltTABLE border=lgt ltTRgt ltTDgtTiacutetulo de libros americanos sobre gnuLinuxltTDgt ltTRgt ltTABLEgt ltulgt ltlixbgtRunning Linuxltbxbrxligt ltlixbgtLinux in a Nutshellltbxbrxligt ltlixbgtHow Linux Worksltbxbrxligt ltlixbgtLinux for Non-Geeksltbxbrxligt ltulgt ltBODYgt ltHTHLgt

Figura 11 Ejemplo de paacutegina Web estaacutetica

La figura 11 muestra el ejemplo de una Web estaacutetica El funcionamiento de Internet es algo complejo para explicarlo en este capiacutetulo pero vamos a dar vinas nociones baacutesicas sobre lo que pasa tras la peticioacuten de una paacutegina Web por un cliente Los pasos que sigue nuestro navegador de Internet son

bull Nuestro ordenador solicita al servidor una paacutegina Web a traveacutes de Inshyternet

bull El servidor enviacutea los datos solicitados en formato de texto

42 Capiacutetulo 1

bull El navegador recibe estos datos interpreta la paacutegina Web enviada y la muestra en la pantalla de acuerdo con la resolucioacuten del monitor las preferencias del usuario y alguacuten otro factor

En la figura 12 podemos ver todo el proceso

Figura 12 Esquema de peticioacuten de una Web estaacutetica

Las paacuteginas Web estaacuteticas no permiten apenas una interactividad con el usuario final Por eso han aparecido numerosas tecnologiacuteas que hacen maacutes usable las paacuteginas y eliminan algunas restricciones o limitaciones Los lenshyguajes Javascript Vbscript CSS o los ap-plet de Java ofrecen una mayor interactividad pero son dependientes del navegador que utilicemos o de programas externos

Tecnologiacuteas del lado del cliente

Muchas de las mejoras antildeadidas al lenguaje HTML pertenecen a tecnoloshygiacuteas del lado del cliente es decir que se descargan junto con la paacutegina Web solicitada al servidor y se ejecutan en nuestro ordenador local La tabla 11 todas las tecnologiacuteas aparecidas hasta ahora del lado del cliente Estas tecnologiacuteas aunque son maacutes llamativas y permiten desarrollar la imashyginacioacuten en pro del disentildeo dependen totalmente de las caracteriacutesticas del navegador Por ejemplo si tiene un ordenador ibook de Apple con un Sisshytema Operativo gnuLinux Debiacutean (como el autor) le seraacute complicado obshytener una maacutequina virtual de Java y un inteacuterprete de Flash Las tecnologiacuteas de cliente no pueden rescatar datos de servidores porque su ejecucioacuten es uacutenicamente en local Eacutesto los imposibilita para recuperar informacioacuten de bases de datos o servicios

introduccioacuten a PHP 5 43

Tabla 11 Tecnologiacuteas del lado del cliente

[Tecnologiacutea Descripcioacuten Efecto de ejemplo

CSS HTML Sirve para dar formato a las Enlaces con movi-Dinaacutemico paacuteginas color tamantildeo capas efectos miento Javascript Manejo de eventos del navegador Imaacutegenes que Vbscript cambian cuando

se aproxima el ratoacuten Applets Aplicaciones pequentildeas Puzzles conectivi-de Java dad con bases de

datos Animaciones Animaciones graacuteficas Peliacuteculas iexclnteracti-Flash vas

Tecnologiacuteas del lado del servidor

Los lenguajes del lado del servidor son invisibles para los clientes Las paacuteginas que utilicen scripts de este tipo contienen el coacutedigo entre etique-fas parecidas a las de HTML pero eacutestas desaparecen cuando el cliente reshycibe la paacutegina

Los pasos que debe seguir nuestro navegador de Internet son

bull Nuestro ordenador solicita al servidor una paacutegina Web a traveacutes de Inshyternet

bull El servidor comprueba si la paacutegina solicitada contiene scrvpt del lado del servidor (PHP ASP JSP etceacutetera)

bull Ejecuta los posibles scripiacutes y antildeade el resultado final a la paacutegina Web resultante

bull El navegador recibe estos datos interpreta la paacutegina Web enviada y la muestra en la pantalla de acuerdo con la resolucioacuten del monitor las preferencias del usuario y alguacuten otro factor

La figura 13 muestra el proceso Los lenguajes del lado del servidor necesitan un motor (un programa) que interprete el coacutedigo Este programa puede formar parte o no del servidor Web En nuestro caso utilizaremos el motor Zend Engine 20 para parsear (interpretar) los proshygramas escritos en PHP 5

Figura 14 Zend Studio 351 para MacOSX

Suponiendo que ya tiene un servidor para probar los programas o ha leiacuteshydo el Apeacutendice A para instalar su propio servidor Web con PHP 5 vamos a crear nuestro primer programa del lado del servidor Para escribir los programas puede utilizar cualquier editor de texto plano

44 Capiacutetulo 1

Introduccioacuten a PHP 5 45

En gnuLinux tiene algunos editores libres que funcionan muy bien Sus nombres son Bluefish o Anjuta En entornos propietarios como Windows o MacO^X existen editores proshyfesionales que ademaacutes de disentildear paacuteginas Web permiten antildeadir todo tipo de coacutedigo PHP eso siacute los programas no son gratuitos y hay que pagar una elevada licencia por su uso Para los tres sistemas operativos tenemos una impresionante herramienta de edicioacuten y depuracioacuten creada por los programa^ores de PHP 5 La herramienta Zend Studio tiene dos versiones una de pago bajo licenshycia con muacuteltiples opciones de depuracioacuten y otra gratuita con opciones de desarrollo tan interesantes como el auto completado de funciones y variables

Etiquetas de PHP

Lo primero que debe saber es que todo prograrr1^ escrito en PHP debe empezar por unas etiquetas determinadas

ltphp gt

Ademaacutes aacutee esta iacuteoxma oacutee iacutemciax xm programa pu^dt ^urf^cam -iquesti -hiti iquesti-vo php i n i para que sus programas puedan empezar entre

lt gt

Nota

El archivo php i n i contiene la configuracioacuten de PHP en ese moshymento Cambiando algunos paraacutemetros podraacute cambiar la forma de funcionar del parser

El paraacutemetro s h o r t - o p e n - t a g puede igualarse a off o a on Si contiene el valor on PHP permitiraacute el uso de la etiqueta cofta Otra forma posible de empezar un programa escrito en PHP es utilizando las etiquetas de ASP Mucha gente que desarrolla con programas de Microsoft como Fron-tPage para generar paacuteginas Web utiliza esta forma de empezar el coacuteshydigo

lt gt

46 Capiacutetulo 1

Nuestro primer programa en PHP 5

Despueacutes de estas pequentildeas nociones ya estaacute preparado para crear su prishymer programa Eacuteste le va a permitir tener una visioacuten de la configuracioacuten global de PHP 5

Puede escribir el programa siguiente en cualquier editor de texto como vimos anteriormente

ltHTMLgt

ltHEADgt ltTITLEgtMi primer programa en PHP 5ltTITLEgt ltHEADgt ltBODYgt ltphp echo Este es el tiacutepico Hola Mundo ltbrxbrgt phpinfo() gt ltBODYgt ltHTMLgt

Como puede ver el programa contiene la estructura normal de una paacutegishyna Web La etiqueta ltHTMLgt define el comienzo y el final de la paacutegina Esta puede dividirse en dos partes La primera estaacute separada por la etishyqueta ltHEADgt y contiene informacioacuten sobre el autor tiacutetulo y meta datos que pueden servir para antildeadir coacutedigo Javascript o CSS La segunda parte es el cuerpo de la paacutegina Web es decir contiene todos los datos que veraacute el usuario en el navegador Estaacute separada entre etiquetas ltBODYgt

Dentro del BODY puede ver que empleamos las etiquetas de inicio y fin de programa PHP Dentro de estas etiquetas hay dos funciones que hacen cosas distintas Las funciones son programas ya creados y funcionales que pueden utilizarse en el transcurso de nuestro programa Existen en PHP 5 una infinidad de funciones uacutetiles para el manejo de cadenas de caracteshyres funciones aritmeacuteticas o funciones para mostrar texto en pantalla La funcioacuten echo ) se encarga de mostrar los datos en pantalla en este caso se encargaraacute de mostrar la frase Este es el tiacutepico Hola Mundo Ademaacutes imprime dos etiquetas ltbr gt que no se muestran porque tienen sentido dentro de HTML La etiqueta ltbrgt antildeade un salto de liacutenea a la paacutegina Web

La funcioacuten phpinf o () enviacutea al navegador la configuracioacuten de PHP que estamos utilizando en el servidor Aquiacute aparece la configuracioacuten que se ha utilizado para compilar el parser las libreriacuteas auxiliares que contiene el sistema que se estaacute utilizando etceacutetera

Introduccioacuten a PHP 5 47

Nota r Durante el proceso de aprendizaje del libro conoceraacute muchas funshyciones y sus aplicaciones inmediatas En el capiacutetulo 5 del libro aprenderaacute a crear sus propias funciones

El resultado de la ejecucioacuten del programa lo muestra la figura 15

Figura 15 Resultado de nuestro primer script

Repaso de HTML

El lenguaje de marcas de hipertexto se ha convertido en el principal refeshyrente de la Web Para seguir adecuadamente los contenidos del libro neshycesitaraacute conocer el funcionamiento de HTML para insertar sus programas escritos en PHP 5

Cabecera y cuerpo de una paacutegina Web

Todo documento escrito en HTML estaacute contenido entre las etiquetas ltHTMLgt y ltHTMLgt Se pueden estructurar en

bull Cabecera Entre las etiquetas ltHEADgt y ltHEADgt Contiene informashycioacuten relativa al documento

48 Capiacutetulo 1

bull Cuerpo Entre las etiquetas ltBODYgt y ltBODYgt Debe contener la inshyformacioacuten que el usuario veraacute en el navegador

Cabecera

El tiacutetulo del documento debe ir entre las etiquetas ltTITLEgt y ltTITLEgt Este tiacutetulo se mostraraacute en la parte superior del navegador Ademaacutes se utiliza como descripcioacuten si guarda la paacutegina en el apartado de Favoritos

Para antildeadir informacioacuten sobre el autor fecha de expiracioacuten o el programa con el que hemos disentildeado la Web puede utilizar la etiqueta ltMETAgt

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODYgt ltBODYgt

ltHTMLgt

Algunas etiquetas permiten la inclusioacuten de atributos La etiqueta ltMETAgt contiene el atributo NtildeAME y CONTENT para sentildealar en el documento el autor de la paacutegina Los buscadores haraacuten buen uso del contenido de estas etishyquetas para enlazarlas en sus motores de buacutesqueda

Cuerpo del documento

La etiqueta ltBODYgt tambieacuten puede contener atributos que modifiquen el aspecto exterior de la paacutegina

Los principales atributos son

bull BGCOLOR Indica el color de fondo de la Web

bull TEXT Color general del texto

bull LINK Color del texto de los enlaces

bull VLINK Color de los enlaces que ya han sido utilizados

bull ALINK Color de activacioacuten del texto

bull BACKGROUND Imagen de fondo de un documento

En el siguiente ejemplo puede ver la utilizacioacuten de los atributos de la etishyqueta del cuerpo

ltHTMLgt ltHEADgt

introduccioacuten a PHP 5 49

ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODY BGCOLOR=FF0 0 00 LINK=000000 VLINK=FF00FFgt ltBODYgt ltHTMLgt

Nota

El color se escribe en formato RGB Esto quiere decir que un color puede dividirse en tres componentes (rojo verde y azul) y elishygiendo la intensidad de cada componente se forma el color deseashydo Cada componente tiene 2 cifras en hexadecimal Asiacute el color FF0000 tiene al nuacutemero FF hexadecimal (255 en decimal) en su componente rojo y los demaacutes a 0 por lo tanto el color resulshytante seraacute Rojo intenso

Paacuterrafos y saltos de liacuteneas

Los textos pueden escribirse dentro de la etiqueta ltBODYgt en el orden que quiera los navegadores no interpretan los saltos de liacuteneas o liacuteneas en blanshyco eliminando todos los espacios vaciacuteos Para crear un salto de liacutenea tiene que utilizar ltBRgt escrito despueacutes del texto Para crear paacuterrafos tendraacute que escribir el texto entre las etiquetas ltPgt ltpgt

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltHEADgt ltB0DYgt ltPgt Esto es paacuterrafo y tambieacuten un salto de liacuteneasbrgt ltPgt ltBODYgt ltHTMLgt

Estilo de texto

Podemos resaltar partes del texto con algunas etiquetas

bull ltBgt Bloque de texto en negrita bull ltIgt Texto en cursiva

Figura 16 Diferentes estilos de textos

Ademaacutes puede elegir el formato de las fuentes de cada bloque de texto

50 Capiacutetulo 1

bull ltUgt Bloque de texto subrayado bull ltBIGgt Texto con su mayor tamantildeo bull ltSMALLgt Texto con m tamantildeo pequentildeo bull ltCENTERgt Texto centrado

bull ltSUPgtSuperiacutendice bull ltSUBgt Subiacutendice

El ejemplo siguiente que tambieacuten se muestra en la figura 16 muestra la utilizacioacuten de alguna de las etiquetas anteriores

ltHTMLgt

ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author CONTENT=Luis Miguel Cabezas Granadogt ltHEADgt ltBODYgt ltCENTERgtTexto centrado-CENTERxBRgt ltUxIxBIGgtTexto subrayado y cursivaltBIGxIgtltUxBRgt ltBgtTexto en negritaltBxBRgt ltSUPgtTexto superiacutendiceltSUPxBRgt Este cont iene un ltSUBgtsubiacutendiceltSUBgt ltBRgt ltBODYgt ltHTMLgt

Introduccioacuten a PHP 5 51

La etiqueta ltFONTgt permite seleccionar entre varios atributos para utilishyzar distintas fuentes colores o tamantildeos Entre los atributos que podemos utilizar

bull COLOR Color de la fuente

bull SIZE Tamantildeo de la fuente

bull FACE Tipo de fuente ltFONT SIZE=1 FACE=ComicgtTexto con tamantildeo y fuente determinadosltFONTgt

Enlaces de texto

Un enlace es un mecanismo que permite dirigirse a una paacutegina determishynada despueacutes de hacer clic en el texto Si entre las etiquetas ltAgt y ltAgt aparece alguacuten contenido (texto o imagen) al hacer clic en la situacioacuten denshytro de navegador la paacutegina seraacute dirigida a la nueva direccioacuten

El atributo HREF contiene la direccioacuten del enlace

ltA HREF=pagina2htmgtenlaceltAgt

Listas

Las listas son capaces de presentar ordenadamente una serie de concepshytos Los tipos de lista son

bull ltULgt Lista desordenada

bull ltOLgt Lista ordenada

bull ltDLgt Lista de definicioacuten

La diferencia entre los tipos de lista radica en el caraacutecter que aparece en la zona izquierda de cada liacutenea de la lista Las listas desordenadas tendraacuten un graacutefico formal (una forma geomeacutetrica) las ordenadas tendraacuten un nuacuteshymero de orden y las listas de definicioacuten una letra

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltHEADgt ltBODYgt ltBgtLiacutesta desordenada-BxBRgt ltULgt

ltLIgtLiacutenea 1 laquoLis-Liacutenea 2 ltLIgtLiacutenea 3

Figura 17 Listas ordenadas y desordenadas

52 Capiacutetulo 1

ltUI-igt

ltLIgtLiacutenea 31 ltLIgtLiacutenea 32

ltULgt ltLIacutegtLiacutenea 4

ltULgt ltBgtLiacutesta ordenadaltBgtltBRgt ltOLgt

ltLIacutegtLiacutenea 1 ltLJgtLiacutenea 2 ltLlgtLiacutenea 3 ltotgt

ltLIgtLiacutenea 31 ltLIgtLiacutenea 32

ltOLgt ltLIacutegtLiacutenea 4

ltOLgt ltBODYgt ltHTMLgt

Cada liacuteitea de una lista debe estar precedida de la etiqueta ltLIgt El coacutedishygo anterior genera la Web de la figura 17

Imaacutegenes

La etiqueta lt IMGgt utiliza el atributo SRC para insertar la imagen seleccioshynada en el documento

Introduccioacuten a PHP 5 53

Ademaacutes puede utilizar ALT para antildeadir una descripcioacuten a la imagen Entre las imaacutegenes que se pueden incluir en la Web estaacuten los tipos de archishyvos GIF PNG y JPG

ltIMG SRC=fo to l jpg ALIGN=centergt

La alineacioacuten de la imagen con respecto a la pantalla se puede controlar con el atributo ALIGN

Tablas

El elemento estrella en una paacutegina Web es la tabla Actualmente las tashyblas se utilizan para colocar en lugares determinados de la pantalla texshytos imaacutegenes o el menuacute de seleccioacuten Para definir u n a tabla tiene que insertar todos los datos entre las etiquetas ltTABLEi y ltTABLEgt

A continuacioacuten antildeada las filas y las columnas de nuestras tablas Para antildeadir una fila tendraacute que utilizar la etiqueta ltT^gt y para incluir una nueva columna la etiqueta ltTDgt

Para disentildear una tabla de 3 filas y 4 columnas siga los pasos que muestra el ejemplo

ltHTMLgt ltHEADgt ltTITLEgtPaacutegina en HTMLltTITLEgt ltMETA NAME=Author COMTENT=Luis Miguel Cabltbzas Granadogt ltHEADgt ltBODYgt ltTABLE B0RDER=1gt ltTRgt ltTDgtColumna 11ltTDgt ltTDgtColumna 12ltTDgt ltTDgtColumna 13ltTDgt ltTDgtColumna 14ltTDgt ltTRgt ltTRgt ltTDgtColumna 2 1ltTDgt ltTDgtColumna 2 2ltTDgt ltTDgtColumna 2 3ltTDgt ltTDgtColumna 24ltTDgt ltTRgt ltTRgt ltTDgtColumna 31ltTDgt ltTDgtColumna 3 2ltTDgt ltTDgtColumna 33ltTDgt ltTDgtColumna 34ltTDgt ltTRgt

Figura 18 Tabla de 3 filas y 4 columnas

54 Capiacutetulo 1

ltTABLEgt ltBODYgt ltHTMLgt

Como muestra el coacutedigo la etiqueta ltTABLEgt puede contener atributos como BORDER que antildeade un borde a todas las celdas de la tabla Esta forshyma de actuar la vemos en la figura 18

Resumen

Es muy importante para la lectura de los capiacutetulos del libro que conozca el lenguaje HTML en profundidad PHP 5 se encarga de generar datos dinaacutemicamente desde una base de datos archivos o haciendo caacutelculos complejos pero al final seraacute una etiqueta HTML la que muestre esos dashytos en pantalla Puesto que el objetivo de este libro no es conocer los asshypectos de HTML invito al lector a indagar en otras publicaciones o en Internet para suplir las posibles carencias que pueda tener

Los ejemplos del libro se han escrito directamente en un editor de textos pero esta no es la uacutenica posibilidad Tambieacuten puede utilizar para realizarshylos alguacuten programa de disentildeo Web con la ventaja de que las etiquetas HTML seraacuten antildeadidas a golpe de clic

Capiacutetulo 2

Variables constantes y tipos

de datos

En este capiacutetulo aprenderaacute a

bull Almacenar informacioacuten en variables bull Manejar variables constantes y constantes predefinidas por PHP 5

bull Utilizar funciones de manejo de datos

56 Capiacutetulo 2

Variables en PHP 5

Como en todos los lenguajes de programacioacuten PHP 5 permite almacenar datos de distintos tipos en memoria Estas zonas de memoria se llaman variables Las variables comienzan por el siacutembolo de doacutelar ($) y no necesishytan ser declaradas antes de comenzar el programa como en otros lenguashyjes

Tipos de Variables

Existen varios tipos de variables

bull Entero (integer) Almacena nuacutemeros sin decimales Se puede utilizar la notacioacuten decimal (83) octal (0123) o hexadecimal (0x12)

bull Coma Flotante (double) Nuacutemeros con decimales bull Caraacutecter (string) Texto o informacioacuten numeacuterica escrita entre comillas

dobles () o simples () bull Bootean Soacutelo tiene dos posibles valores Verdadero o Falso bull Nulo NULL) Es un tipo especial que solo contiene un valor NULL bull Vectores (array) Colecciones de datos

bull Objetos (object) Conjunto de datos y funciones independientes

Los 5 primeros tipos son simples y los 2 siguientes (array y object) son comshypuestos Trataremos los tipos compuestos en capiacutetulos sucesivos

ltphp Asignacioacuten de nuacutemeros enteros de coma flotante y cadenas de caracteres $numero_entero = 12343 $numero_flotante = 12343123 $cadena_caracter = 12 34 3 Asignacioacuten de los tipos especiales boolean y NULL $verdadero = TRUE $vacio = NULL gt

Hay que tener en cuenta que el nombre de las variables no puede empeshyzar por un nuacutemero pero siacute puede contenerlos Tambieacuten pueden empezar por un guioacuten bajo (__) Puesto que PHP 5 es sensible a las mayuacutesculas y minuacutesculas las variables $numero y $NUMERO seraacuten distintas

ltphp $4numero = 23 Esta liacutenea da error

Variables constantes y tipos de datos 57

$_numero = 45 Las liacuteneas siguientes muestran que PHP 5 es sensible a mayuacutesculas $numero = 23 $NUMERO = 24 $Numero = 25 echo (numero es $numeroltbrgt) echo (NUMERO es $NUMEROltbrgt ) echo (Numero es $Numeroltbrgt) gt

Nota

Es una buena praacutectica de programacioacuten llamar a las variables de una forma descriptiva Si tenemos un formulario que intenta pashysar datos sobre el nombre y apellido de una persona lo maacutes coshyrrecto es llamar a las variables $nombre y $ ape l l i do en vez de $n y $a Hay que buscar siempre la similitud entre el dato que pasamos y el nombre de la variable para que el programa resulte legible

Asignacioacuten de variables

La asignacioacuten es simplemente dar un valor a la variable Esto se hace poshyniendo un siacutembolo = entre la variable y el dato que queremos asignar

ltphp $numero_pi = 314159 Aproximadamente gt

Si se fija en el ejemplo acabamos de asignar un nuacutemero de coma flotante a la variable $numero_pi En este momento podemos cambiar el valor de la variable asignando un nuevo valor que puede ser de un tipo difeshyrente

ltphp $numerojiacute = 314159 El tipo se convierte a cadena de caracteres gt

Tipos simples

Los tipos de variables simples (enteros coma flotante cadenas de caracteshyres boolean y NULL) deberiacutean ser familiares si conocemos alguacuten lenguaje

58 Capiacutetulo 2

de programacioacuten como C Puesto que la base de la programacioacuten consiste en almacenar datos correctamente vamos a ver las peculiaridades de los diferentes tipos

Enteros (integer)

Corresponde a un nuacutemero entero sin decimales pudiendo ser negativo o el nuacutemero cero Pueden ser almacenados en diferentes formatos corresshypondiendo con las bases decimal (base 10) octal (base 8) y hexadecimal (base 16) Por defecto se utiliza la numeracioacuten decimal Para utilizar base 8 debe ponerse un 0 delante del nuacutemero asignado y un Ox si queremos utilizar base 16 Para antildeadir un nuacutemero negativo basta con poner el signo menos (-) delante del nuacutemero

ltphp $entero_baselO = 1234 $entero_base8 = 01234 $entero_basel6 = 0x1234 $entero_negativo = -1234 echo (Decimal $entero_baselOltbrgt) echo (Octal $entero_base8ltbrgt) echo (Hexadecimal $entero_basel6ltbrgt) echo (Negativo $entero_negativoltbrgt) gt

La salida del navegador es

Figura 21 Asignacioacuten de enteros en decimal octal y hexadecimal

Variables constantes y tipos de datos 59

La salida de los nuacutemeros se hace en decimal aunque la asignacioacuten se haya hecho en hexadecimal o en octal Esto es asiacute porque PHP trabaja internashymente en binario y hace la conversioacuten a decimal de todos los nuacutemeros enteros y de coma flotante

Nuacutemeros de coma flotante (double)

Este tipo de dato contiene nuacutemeros enteros con decimales Se almacenan de forma diferente a los nuacutemeros enteros por lo que las sumas de cantishydades de coma flotante con cantidades enteras daraacuten como resultado un nuacutemero de coma flotante

ltphp Nuacutemeros de coma flotante $numero__double = 1234123 $numero_double2 = 01213 $numero_double3 = -12 3 40 echo (Salida de la funcioacuten echo() $numero_double3ltbrgt) gt

La salida en el navegador seriacutea S a l i d a de echo -1234

Como puede comprobar parece que el nuacutemero que se muestra en pantashylla es del tipo entero Esto es porque la funcioacuten echo 0 no muestra el forshymato del dato Para que esto ocurra debemos utilizar otro tipo de funcioacuten

ltphp $numero_double3 = -12340 echo (Salida de printft) ) printf(f$numero_double3) gt

El coacutedigo anterior muestra ahora una salida por pantalla maacutes coherente Salida de printf() es -1234000000

Cadena de caracteres (string)

Es un conjunto de caracteres encerrados entre comillas dobles () o sim-pies ( )bull

ltphp Definicioacuten de variables de tipo string $cadenal = Esto es una cadena de caracteres $cadena2 = Esto es una cadena entre comillas simples $cadena3 = Cadena con 0 caracteres gt

60 Capiacutetulo 2

La diferencia entre las comillas simples y las comillas dobles radica en

bull Comillas simples Permiten imprimir el contenido iacutentegro de caracteshyres que esteacute entre las dos comillas

bull Comillas dobles Permiten incluir variables para imprimirlas junto al texto ltphp $dato = IMPRIMIBLE $texto_simple = No puede imprimir la variable $dato $texto_doble = Imprime la variable dato como $dato echo ($texto_simpleltbrgt) echo ($texto_doble) gt

Existen algunos caracteres especiales que no pueden ser antildeadidos a una variable de tipo string a menos que avisemos antes a PHP para que tenga cuidado a la hora de manejar el dato Este aviso se conoce como secuenshycia de escape y no es maacutes que la inclusioacuten delante del caraacutecter especial de un siacutembolo Asiacute si quiere insertar unas comillas dobles entre un texto tendraacute que escribir para que no se produzca un error

ltphp Secuencias de escape $cadenal = Aquiacute se pueden antildeadir comillas doblesltbrgt $cadena2 = Aquiacute se pueden antildeadir comillas simplesltbrgt $cadena3 = Esta cadena da errores por las comillas doblesltbrgt $cadena4 = Esta cadena no da errores por las comillas doblesltbrgt echo $cadenal echo $cadena2 echo $cadena3 echo $cadena4 gt

El resultado muestra la impresioacuten de las cadenas excepto la cadena3 que da un error por no incluir la secuencia de escape para las comillas

Tabla 21 Secuencias de escape comunes

Secuencia Valor

$ Signo de doacutelar $

Comillas dobles

V Comillas simples

Bar ra invert ida

Variables constantes y tipos de datos 61

Secuencia Valor

n Nueva liacutenea

r Retorno de carro

t Tabulador

Boolean

Una variable de tipo boolean soacutelo puede contener dos valores Verdadero o Falso Se suelen utilizar para comprobar si se cumple una condicioacuten en el programa

ltphp $variable_booleana = TRUE if ($variable_booleana) echo (El resultado es VERDADERO)

gt

El resultado se muestra en la figura 22

Aunque todaviacutea no hemos visto las estructuras de control podemos adshyvertir que la salida del programa anterior da como resultado la impresioacuten en pantalla del texto que contiene la funcioacuten echo () Ademaacutes de las vashyriables boolean podemos tomar otros tipos de datos como Verdaderos o Falsos para hacer nuestras comprobaciones

62 Capiacutetulo 2

bull Los nuacutemeros enteros o decimales positivos o negativos son todos Verdashyderos El 0 se considera Falso En cualquier caso se recomienda no utilishyzar variables de coma flotante para comprobar si son Verdaderos o Falsos

bull Las cadenas de caracteres son Verdaderas excepto cuando no contieshynen ninguacuten dato o contienen uacutenicamente el caraacutecter 0

bull Las variables del tipo NULL son siempre Falsas

NULL

Es un tipo especial de datos que soacutelo contiene el valor NULL Aunque se suele utilizar por norma en mayuacutescula PHP 5 lo acepta escrito de divershysas formas NULL nuil NuLl

ltphp $variable_nula = NuLl if ($variable_nula) echo (La comprobacioacuten es VERDADERA)

else echo (La comprobacioacuten es FALSA) gt

Variables de variables

Las variables son en definitiva nombres descriptivos que asocian un esshypacio en memoria del servidor con una palabra entendible por nosotros En ese espacio de memoria podemos almacenar diferentes tipos de datos Podemos definir una variable de la siguiente forma

ltphp $variablel = hola gt

En este momento tenemos un espacio de memoria llamado $ v a r i a b l e l donde se aloja el dato hola iquestQueacute pasa si queremos tratar la palabra hola como una variable Podemos hacerlo antildeadiendo un signo de $ delante de $ v a r i a b l e l por lo que se reservaraacute otro espacio en memoria para aloshyjar el nuevo contenido esta vez con el nombre $hola

ltphp $variablel = hola $$variablel = mundo

Variables constantes y tipos de datos 63

Las dos liacuteneas siguientes producen la misma salida echo ($variablel $$variablelltbrgt) echo ($variablel $holaltbrgt) gt

La salida por pantalla nos da el siguiente resultado hola mundo hola mundo

Constantes

Las constantes son tipos de datos que no variacutean en el desarrollo de un programa En la vida real existen muchos tipos de constantes el nuacutemero pi la temperatura de congelacioacuten del agua el nombre de la Empresa etshyceacutetera Para crear una constante tiene que usar la funcioacuten de f ine () de la siguiente forma

ltphp define(EMPRESAZendSA) define(AutorLuis Miguel Cabezas Granado) gt

Para mostrar el valor de las constantes uacutenicamente hay que invocar su nombre esta vez sin utilizar el siacutembolo de $

ltphp Definimos primero la constante define (COLOR_ROJO FF0000) Y ahora escribimos en pantalla su resultado echo COLOR_ROJO Hay que destacar que el signo de $ no hace falta ponerlo Existe otra funcioacuten que nos permite averiguar el valor de la constante echo constant ( C0L0R_R0JO) gt

defined()

Puede utilizar def ined () para averiguar si una constante ya se ha creado

ltphp define(EditorialAnaya) if (defined(Editorial) ) echo La Editorial es Editorial

gt

64 Capiacutetulo 2

Constantes predefinidas

PHP 5 define varias constantes cada vez que se ejecuta un script y que son accesibles por nosotros

Tabla 22 Algunas constantes definidas por PHP 5

Nombre Descripcioacuten

PHP_VERSION Versioacuten del parse de PHP que estamos utilizando

PHP_OS Sistema operativo del servidor de PHP

PEAR_EXTENSION_DIR Ruta donde estaacute instalada la extensioacuten PEAR

PHP_LIBDIR Ruta donde estaacuten almacenadas las libreriacuteas de PHP 5

Finalmente tenemos 5 constantes maacutegicas tal y como las definen en el sishytio Web wwwphpnet que cambian de valor dependiendo del lugar donshyde se usen Por ejemplo el valor de la constante LINE depende de la liacutenea donde la estemos usando en nuestro programa

Tabla 23 Constantes maacutegicas

Nombre Descripcioacuten

LINE Indica el nuacutemero de liacutenea desde la que imprimimos el

valor

FILE Ruta completa al fichero

FUNCTION Nombre de la funcioacuten que la contiene

CLASS Nombre de la clase

_ M E T H O D _ Nombre del meacutetodo

Advertencia

Hay que tener cuidado con el nombre de las constantes maacutegicas Los siacutembolos que hay a la izquierda y ala derecha del nombre son dos guiones bajos seguidos (_)

ltphp echo LINE - VERSIOacuteN de PHP 5PHP_VERSION echo ltbrgt

Variables constantes y tipos de datos 65

echo LINE - SISTEMA Operativo Servidor PHP_OS echo ltbrgt echo LINE - Ruta de las extensiones PHP_EXTENSION_DIR echo ltbrgt echo LINE - API de Servidor PHPJ3API gt

Funciones relacionadas con variables

PHP 5 brinda al programador una serie de funciones para el manejo de variables

isset()

Con esta funcioacuten podemos averiguar si una funcioacuten existe dentro de nuesshytro programa Si existe devuelve true y si no existe false

ltphp $DNI = 8868543-Z if (isset($DNI)) echo (La variable DNI existe)

66 Capiacutetulo 2

gt

unset()

Libera la memoria ocupada por una variable destruyendo su nombre y su contenido Despueacutes de usar unset () la variable destruida apareceraacute comoase al utilizar la funcioacuten i s s e t ()

ltphp $Nombre = Mariacutea Fernanda if (isset($Nombre)) echo (El nombre existe)

Podemos comprobar queacute pasa si liberamos la variable $Nombre unset($Nombre)iexcl if (isset($Nombre)) echo (El nombre existe) else echo (El nombre ya no existe) gt

El resultado es el siguiente El nombre e x i s t e El nombre ya no e x i s t e

gettype()

Con esta funcioacuten podemos averiguar el tipo de dato almacenado en la variable Nos puede devolver uno de los siguientes valores

bull integer

bull double

bull string

bull array

bull object

bull class

bull unknown type ltphp $correo = luisnccextremaduraorg echo la variable correo es del tipo

Variables constantes y tipos de datos 67

echo g e t t y p e ( $ c o r r e o ) gt

settype()

Convierte el tipo de la variable al especificado en la funcioacuten El tipo debe especificarse eligiendo uno de los siguientes array double integer object o string Si la funcioacuten no es capaz de convertir el tipo de la variable devuelshyve el valor false

ltphp $correo = luisnccextremaduraorg if (settype($correointeger))

echo (Variable correo convertida a Enteroltbrgt)

else

echo (Imposible convertir al tipo Enteroltbrgt)

echo (Valor actual de correo es $correo) gt

Al tratar de convertir un tipo string (una cadena de caracteres) a un enteshyro PHP 5 comprueba si existe alguacuten nuacutemero Si no existe cambia el valor a O y la funcioacuten s e t t y p e () la evaluacutea como correcta

empty()

Comprueba si una variable estaacute vaciacutea no existe o su valor es 0 ltphp $correo = luisnccextremaduraorg if (empty($nombre))

echo (La variable nombre no existe)

$numero_entero = O if (empty($numero_entero))

echo (La variable numero_entero no existe o tiene el valor O) gt

isjntegerf) is_double() is_string()

Estas funciones devuelven true si la variable pasada coincide con el tipo que indica la funcioacuten

68 Capiacutetulo 2

Si la variable $numero_en te ro se evaluacutea con la funcioacuten i s _ i n t e g e r ( ) devolveraacute true

ltphp $numero_entero = 0 if (is_integer()($numero_entero))

echo (numero_entero es del tipo integer)

gt

intval() doublevalQ strval()

Convierte el valor de una variable al tipo indicado en la funcioacuten Esta funshycioacuten no permite la conversioacuten a tipos object o array

ltphp Conversioacuten de un tipo string a un integer $cadena = 232 echo El tipo de la variable cadena es gettype($cadena)ltbrgt $numero = intval($cadena) echo (el numero es $numero) gt

Resumen

La base de la programacioacuten reside en la creacioacuten de datos y su procesashymiento En este capiacutetulo hemos visto coacutemo declarar variables de diferenshytes tipos y coacutemo utilizar funciones para averiguar las propiedades de cada una de ellas Ademaacutes de las variables las constantes juegan un papel muy importante sobre todo las predefinidas por PHP 5 que nos dan informashycioacuten muy uacutetil con la que poder trabajar

En este capiacutetulo aprenderaacute a

bull Utilizar los diferentes tipos de operadores existentes bull Distinguir entre operadores unarios binarios y ternarios

bull Comprender la preferencia de ejecucioacuten entre operadores

70 Capiacutetulo 3

Introduccioacuten

En el capiacutetulo anterior hemos visto ejemplos de coacutedigo escrito en PHP que utilizan siacutembolos muy comunes en el ambiente matemaacutetico e inforshymaacutetico Estos siacutembolos que aparecen entre variables o dentro de funciones son conocidos como operadores Existen varios tipos de operadores

bull De asignacioacuten bull Unario bull Aritmeacuteticos bull De comparacioacuten bull Loacutegicos bull Ternario bull Bit a bit bull Asignacioacuten combinados bull De ejecucioacuten bull Supresioacuten de errores

Operador de asignacioacuten

El maacutes baacutesico es el siacutembolo de asignacioacuten (=) utilizado para dar valores a las variables que usamos en nuestro coacutedigo

ltphp $variable = 34 $variable2 = Asignacioacuten de valores gt

Las variables que estaacuten a la izquierda del operador toman el valor que se encuentra en la expresioacuten de la derecha

Advertencia

No hay que confundir el operador de asignacioacuten (=) con el operashydor de comparacioacuten (==) sobre todo en bucles de control donde seriacutea difiacutecil encontrar alguacuten fallo

Operadores 71

Operador Unario

El signo menos (-) se utiliza delante de un nuacutemero o variable numeacuterica Este operador tiene la propiedad de hacer a los nuacutemeros negativos o poshysitivos dependiendo del signo actual

ltphp $entero = 23 $entero_negativo = -$entero El valor es ahora -23 entero2 = -$entero__negativo El valor cambia ahora a 23 gt

Operadores Aritmeacuteticos

Este tipo de operadores forman parte de la aritmeacutetica baacutesica Nos resultashyraacute familiar porque son siacutembolos muy utilizados en el aprendizaje de las matemaacuteticas

Tabla 31 Operadores aritmeacuteticos

Ejemplo Nombre Resultado

$a + $b suma Suma las dos variables $a - $b resta Hace la diferencia de las dos variables Sa $b multiplicacioacuten Producto de las variables $a $b divisioacuten Cociente entre las dos variables $a $b Moacutedulo Resto de la divisioacuten de $a entre $b

Nota

-rr PHP 5 ignora los espacios en blanco entre las variables y los opeshyradores Aunque $a + $b es equivalente a $a + $b es preferible utilizar la primera forma de escribir porque se hace maacutes legible

Operadores de comparacioacuten

En algunos ejemplos del capiacutetulo anterior puede ver que se utiliza la esshytructura de control if el se Como veremos maacutes adelante esta estructu-

72 Capiacutetulo 3

ra compara dos valores y elige el camino a seguir El valor de la comparashycioacuten siempre es true ofalse

Tabla 32 Operadores de comparacioacuten

Ejemplo Nombre Resultado

$a == $b Igualdad Devuelve true si $a y $b son iguales $a === $b Identidad Verdadero si son iguales y del mismo tipo $a = $b Distinto True si son distintos $a ltgt $b Distinto True si son distintos $a lt $b Menor que Cierto si $a es menor que $b $a gt $b Mayor que Cierto si $a es mayor que $b $a lt= $b Menor o igual Correcto si $a es menor o igual que $b $a gt= $b Mayor o igual Correcto si $a es mayor o igual que $b

ltphp $a = 23 Asignacioacuten de los valores $b = 75 if ($a gt= $b) La condicioacuten no se cumple El resultado es false

echo Esta parte no se ejecuta else

echo La comparacioacuten es false porque $a es menor que $b

gt

Operadores 73

Operadores Loacutegicos

Durante el desarrollo de su proyecto puede encontrarse con situaciones en las que necesite hacer varias comparaciones seguidas para que se cumshypla una determinada condicioacuten PHP 5 permite unir todas las comparashyciones en una mediante el uso de los operadores loacutegicos

Tabla 33 Operadores loacutegicos

Ejemplo Nombre Resultado

expresionl and expresion2 Y Si las dos expresiones son vershydaderas el valor es true

expresionl or expresion2 O Si una de las expresiones es vershydadera el valor es true

expresionl xor expresion2 O exclusivo True si una expresioacuten es verdashydera y la otra falsa

expresionl Negacioacuten Verdadero si la expresioacuten no es cierta

expresionl ampamp expresion2 Y Si las dos expresiones son vershydaderas el valor es true

expresionl || expresion2 O Si una de las expresiones es vershydadera el valor es true

El listado siguiente muestra dos condiciones anidadas lt php $a = 2 3 Sb = 75 $c = true if ($a lt $b)

if ($c) echo (Se cumplen las dos condiciones)

gt gt

Egtta expresioacuten se puede hacer maacutes legible utilizando alguacuten operador loacuteshygico

ltphp $a = 23 3b = 75 $c = t rue

74 Capiacutetulo 3

i f ($a lt $b and $c) echo Se cumplen l a s dos cond ic iones

gt

Operador Ternario

Los operadores que hemos visto hasta ahora son capaces de manejar un operando (Unarios) o dos operandos (binarios) El operador ternario o de comparacioacuten evaluacutea un operando y dependiendo de si es falso o vershydadero evaluacutea el segundo operando o el tercero La expresioacuten que se quiere evaluar se escribe delante de un siacutembolo () despueacutes la expresioacuten que tiene que ejecutarse si la evaluacioacuten anterior es true seguida del siacutembolo () con la expresioacuten que debe ejecutarse si es false

ltphp $valor = false $valor == true $resultado = OK $resultado = FALLO Si $value es true $resultado seraacute OK Si es false $re sultado seraacute FALLO echo $resultado gt

Operadores bit a bit

Estos operadores son complicados de entender si no conoce la loacutegica bishynaria Afortunadamente se utilizan en muy pocas ocasiones Los operashydores de bit utilizan las variables a nivel bajo tal y como se almacenan en memoria fiacutesica y comparan bit a bit los valores Lo mejor es verlo con un ejemplo

ltphp bull$a = 4 Valor binario 100 $b = 5 Valor binario 101 $c = $a amp $b echo $c El valor de c es 100 gt

El operador binario Y (siacutembolo amp) compara bit a bit las variables $a y $b Si los bits de una misma posicioacuten son true (tienen el valor 1) el bit resultashydo es 1 En este caso soacutelo existe una pareja de bits que es igual a true (sus

Operadores 75

dos valores son 1) por lo tanto el valor de la variable $c es 4 (en binario 100)

Tabla 34 Operadores bit a bit

Ejemplo Nombre Resultado

$a amp $b Y Si las parejas de bits son verdaderas el resultado es

verdadero

$a | $b O Si alguacuten bit de la pareja es verdadero el resultado es

verdadero

$a A $b O Si un bit de la pareja es true y el otro false el resultado exclusiva es verdadero

~$a No Los bits 1 se vuelven 0 y viceversa Tambieacuten cambia el bit que se refiere al signo positivo o negativo

$a ltlt $b Desplaza- Desplaza a la izquierda los bits de la variable $a tantos miento a bits como indique la variable $b la izquierda de bits

$a gtgt $b Desplaza- Desplaza a la derecha los bits de la variable $a tantos miento a bits como indique la variable $b la derecha

Nota

Puesto que la notacioacuten binaria se escapa del enfoque de este libro le recomiendo algunas lecturas posteriores referidas a la loacutegica de bit si es que tiene curiosidad Probablemente no utilizaraacute estos operadores nunca pero eso depende de la magnitud de los proyecshytos a los que se enfrente

Operadores de asignacioacuten combinados

En numerosas ocasiones se nos presentan situaciones en las que una va-riable debe incrementar o disminuir su valor en 1

ltphp

$a =23

$a = $a +1 Incrementamos en 1 el valor de la variable gt

HP 5 provee operadores combinados que permiten asignar raacutepidamente crementos de valor concatenaciones de caracteres etceacutetera

76 Capiacutetulo 3

Tabla 35 Operadores de asignacioacuten combinados

Ejemplo Nombre Equivalencia

$a++ Incremento $a = $a +1

$a~ Decremento $a = $a -1

++$a Incremento $a = $a +1

~$a Decremento $a = $a -1

$a += $b Suma $a = $a + $b

$a -= $b Resta $a = $a - $b

$a = $b Multiplicacioacuten $a = $a $b

$a = $b Divisioacuten $a = $a $b

$a = $b Moacutedulo $a = $a $b

$a amp= $b Y $a = $a amp $b

$a |= $b O $a = $a | $b

$a A= $b O exclusiva $a = $a A $b

$a = $b Concatenacioacuten $a = $a $b

$a gtgt= $b Desplazamiento a la derecha $a = $a gtgt $b

$a ltlt= $b Desplazamiento a la izquierda $a = $a ltlt $b

Advertencia

Como vemos en la tabla 35 iexclos operadores de incremento y deshycremento pueden aparecer a la derecha o a la izquierda de un vashyriable La posicioacuten del operador influye en el orden en el que la variable se asigna o se incrementa Mejor verlo en un ejemplo ltphp $a = 23 $b = $a++ $b es igual a 23 porque $a se incrementa despueacutes de la asignacioacuten

$a = 2 3 $c = + + $a $c es igual a 24 porque $a se incrementa antes de la asignacioacuten

echo la variable b es $b y c es $c gt

Operador de ejecucioacuten

Si tiene experiencia con la programacioacuten en shell de Unix o gnuLinux sabraacute que el apostrofe invertido sirve para ejecutar comandos del sis-

Operadores 77

tema PHP 5 ha adoptado esta nomenclatura y funciona exactamente igual

ltphp $listado_archivos = Is -la~ Hacemos un listado de los ficheros del directorio actual echo $listado_archivos y lo sacamos por pantalla gt

Nota

El comando ls del ejemplo anterior es propio de sistemas Unix y gnuLinux Siacute hace pruebas sobre un sistema basado en el Sistema Operativo Windows el ejemplo anterior no funcionariacutea tendriacutea que cambiar el comando por dir

Operador de supresioacuten de errores

La mayoriacutea de las funciones que se utilizan en PHP 5 muestran errores en el navegador cuando algo falla

Si intenta abrir un fichero que no existe PHP mostraraacute un mensaje de error v continuaraacute la ejecucioacuten del programa

78 Capiacutetulo 3

El operador () colocado delante de una funcioacuten evitaraacute que se muestre el error

ltphp $fichero = fopen(pruebatxt r) Muestra un error en el navegador echo (El programa sigue ejecutaacutendose) gt

El coacutedigo siguiente oculta la salida de error por pantalla

ltphp $fichero = fopen(pruebatxtr) echo (El programa sigue ejecutaacutendose) gt

Precedencia de Operadores

Vamos a echar un vistazo al coacutedigo siguiente

ltphp $resultado = 20 + 10 10 echo $resultado gt

Aparentemente es un coacutedigo muy simple pero encierra un problema mashytemaacutetico

Existen dos resultados posibles en funcioacuten del operador que debe ejecushytarse antes

Si la suma se ejecuta antes la variable $ r e s u l t a d o tendraacute el valor 300 y si la multiplicacioacuten se ejecuta antes tendremos q u e $ r e s u l t a d o equivashyle a 120

Si comprobamos el coacutedigo el resultado que nos muestra es 120 por lo tanto el operador de multiplicacioacuten () es preferente con respecto al operador de suma (+)

Si los operadores que aparecen son ideacutenticos existe un orden de ejecushycioacuten que puede ser desde la izquierda a la derecha o derecha a izquierda

ltphp $resultado = 2 0 1 0 2 echo $resultado gt

El valor de $ r e s u l t a d o es ahora 1 porque primero se calcula 20 10 y despueacutes ese mismo resultado se divide entre 2 es decir la asociacioacuten enshytre operadores de divisioacuten es desde la izquierda

Operadores 79

Tabla 36 Orden de preferencia de los operadores

Operador Operacioacuten Asociacioacuten

() Pareacutentesis de preferencia NA

new Instancia de objeto NA

[] array Derecha

NO loacutegico Derecha

Signo menos Derecha

++ -- Incremento decremento Derecha

Supresioacuten de errores Derecha

Multiplicacioacuten divisioacuten y moacutedulo Izquierda

+ - Suma resta concatenacioacuten Izquierda

ltlt gtgt Desplazamiento izquierda y derecha Izquierda

lt lt = gt gt = Menor que menor o igual NA

mayor que mayor o igual

== = Igual no igual NA

amp Y izquierda A O exclusivo Izquierda

| O Izquierda

ampamp Y loacutegico Izquierda

|| O loacutegico Izquierda

condicional Derecha = += = = = Asignacioacuten Derecha = = amp= = -= ltlt= gtgt=

and Y loacutegico Izquierda

xor O exclusivo loacutegico Izquierda

or O loacutegico Izquierda

El operador pareacutentesis tiene la propiedad de dar preferencia en la evaluashyron a todos los operadores que contiene El siguiente ejemplo muestra oacutemo podemos utilizar correctamente el operador pareacutentesis

ltphp $resultado = 2 0 1 0 + 2 echo $resultado El resultado es 4 $resultado = 20 (10 + 2) echo $resultado El resultado es 166666667 gt

Resumen

Los operadores son responsables de todas las operaciones que realizamos en nuestros programas Por eso es importante conocer las propiedades v los casos de uso de cada uno de ellos para poder sacarles el maacuteximo partishydo Sin embargo si ya conoce alguacuten lenguaje de programacioacuten la intuishycioacuten le haraacute utilizarlos adecuadamente sin pararse a pensar en el tipo de operador

Por uacuteltimo debe prestar un especial intereacutes a la preferencia de uso ya que una mala utilizacioacuten redundaraacute en un error muy difiacutecil de controlar

En este capiacutetulo aprenderaacute a

bull Utilizar las estructuras de control de eleccioacuten simple y muacuteltiple bull Crear bucles de diferentes tipos bull Crear sus primeros programas bull Conocer las sentencias para interrumpir un bucle

82 Capiacutetulo 4

Introduccioacuten

Es difiacutecil imaginar un programa sin estructuras de control Eacutestas nos permishyten elegir diferentes caminos en funcioacuten de los datos que evaluamos en cada momento En este capiacutetulo trataremos dos tipos de estructuras de control

bull Estructuras de eleccioacuten

bull Estructuras de bucle

Las estructuras de eleccioacuten permiten evaluar una condicioacuten o varias y eleshygir el camino correcto Las de bucle repiten un nuacutemero determinado de veces un conjunto de instrucciones

Estructuras de eleccioacuten

Existen dos tipos

bull Eleccioacuten simple bull Eleccioacuten muacuteltiple

if-else

La sintaxis de esta estructura es if (condicioacuten) instruccioacuten

Si se cumple la condicioacuten se ejecuta la instruccioacuten que le sigue Si quiere que se ejecuten varias instrucciones debe utilizar el siacutembolo llave ( insshytrucciones iexcl )

if (condicioacuten) instruccionl instruccion2iexcl

instruccion3

La estructura if puede ampliarse para que se pueda elegir entre condishycioacuten verdadera y falsa

if (condicioacuten) instruccionl instruccioacuten2 instruccion3

else

Estructuras de control 83

instruccionl -instruccioacuten2 instruccion3

Si la condicioacuten es verdadera se ejecutan las instrucciones inmediatamente despueacutes del if y si la condicioacuten es falsa se ejecutan las instrucciones disshypuestas despueacutes de la palabra e l s e Puede ver un ejemplo completo

ltphp $valor = 23 $valor2 = 27 if ($valor lt $valor2)

echo La variable valor es menor que valor2 else

echo La variable valor es mayor que valor2

gt

elseif

Es muy comuacuten hacer comparaciones en cascada para comprobar varios valores

ltphp $ d i a = 4 if ($d ia == 1)

84 Capiacutetulo 4

echo El diacutea es Lunes else

if ($dia == 2) echo El diacutea es Martes

else if ($dia == 3)

echo El diacutea es Mieacutercoles else

if ($dia == 4) echo El diacutea es Jueves

gt

El patroacuten anterior es tan comuacuten que existe una estructura especial para manejarlo

Puede escribir el ejemplo anterior con la palabra reservada e l s e i f de la siguiente forma

ltphp $dia=4

if ($dia == 1) echo El diacutea es Lunes

elseif ($dia == 2) echo El diacutea es Martes

elseif ($dia == 3) echo El diacutea es Mieacutercoles

elseif ($dia == 4) echo El diacutea es Jueves

gt

El ejemplo anterior evaluacutea la variable $dia hasta que encuentra el valor correcto y ejecuta las instrucciones

switch

La construccioacuten swi t ch comprueba el valor de una expresioacuten y permite elegir entre un conjunto de instrucciones El formato es el siguiente switch (expresioacuten)

case valorl instruccionl instruccion2 instruccion3 break

Estructuras de control 85

case valor2 instruccionl instruccion2 instruccion3 break

case valor3 instruccionl instruccion2 instruccion3 break

default instruccionl instruccion2

instruccion3

La expresioacuten puede ser de cualquier tipo siempre que devuelva un valor de tipo entero de coma flotante o de cadena de caracteres Una vez evashyluada la expresioacuten se busca el valor en la instruccioacuten case y si coincide se ejecutan todas las instrucciones hasta la palabra reservada break Si no coincide ninguacuten valor se ejecutan las instrucciones por defecto Veamos un ejemplo completo

ltphp $dia = 4 switch ($dia)

case 1

echo El diacutea es Lunes break

case 2 echo El diacutea es Martes break

case 3 echo El diacutea es Mieacutercoles break

case 4 echo El diacutea es Jueves break

case 5 echo El diacutea es Viernes break

case 6 echo El diacutea es Saacutebado break

case 7 echo El diacutea es Domingo break

default

Bucles

Los bucles son estructuras de control que permiten repetir varias veces las mismas instrucciones

while

El bucle while es el maacutes baacutesico de todos La construccioacuten baacutesica es la sishyguiente

while (condicioacuten) instruccioacutenlbull instruccioacuten2 instruccioacuten3

La condicioacuten se evaluacutea al principio

Si es verdadera se ejecutan las instrucciones que estaacuten dentro del bucle y se vuelve a evaluar la condicioacuten

86 Capiacutetulo 4

echo El diacutea de la semana es incorrecto

gt

Estructuras de control 87

Si la condicioacuten es falsa no se ejecutan las instrucciones y se continuacutea con el desarrollo del programa

Puesto que la condicioacuten se evaluacutea antes de ejecutar las instrucciones es posible que algunos bucles no se ejecuten ninguna vez

El siguiente ejemplo muestra una instruccioacuten while que no se ejecuta nunshyca porque la condicioacuten es falsa

ltphp $variable = false while ($variable)

echo Esta linea no se ejecuta nunca

gt

Existe la posibilidad de que un bucle se ejecute infinitas veces si dentro de las instrucciones no existe nada que cambie la condicioacuten que se evaluacutea al principio

ltphp $variable = true while ($variable)

echo CUIDADO Esta liacutenea se ejecuta siempre

gt

88 Capiacutetulo 4

El bucle while se puede utilizar para ejecutar un nuacutemero determinado de veces las instrucciones que implica

Veacutease el ejemplo de la serie de Fibonacci

ltphp $numero_anterior = 1 $numero_posterior = 1 $serie = 1 $fin = 10000 echo Serie de Fibonacci while ($serie lt $fin) echo $serie $serie = $numero_anterior + $numero_posterior $numero_anterior = $numero_posterior $numero_posterior = $serie

gt

Cada nuacutemero de la serie de Fibonacci se forma sumando los dos nuacutemer -anteriores

En el ejemplo la condicioacuten es que el nuacutemero de la serie sea menor que t

nuacutemero que marca la variable $f i n es decir si el nuacutemero que indica iquest serie es mayor que 10000 el bucle finaliza

La variable $f in sirve de valor maacuteximo y puede cambiarlo en funcioacuten la cantidad de nuacutemeros que quiera tener en pantalla

Estructuras de control 89

do-while

Este bucle es igual que el anterior pero la condicioacuten se evaluacutea al final de las instrucciones Por lo tanto el coacutedigo que estaacute entre las llaves se ejecuta al menos una vez El formato baacutesico es el siguiente

do instruccioacutenl instruccioacuten2 instruccioacuten3

while (condicioacuten)

Puede comprobar que la diferencia es miacutenima cuando utiliza esta estrucshytura de control para la serie de Fibonacci

ltphp $numero_anterior = 1 $numero_posterior = 1 $serie = 1 $fin = 6765 echo Serie de Fibonacci do

echo $serie $serie = $numero_anterior + $numero_posterior $numero_anterior = $numero_posterior $numero_posterior = $serie

whi le ($ser ie lt $ f i n ) gt

for

La construccioacuten de bucle maacutes complicada es la del for Tiene la siguiente sintaxis

for (expresioacuten inicial condicioacuten de fin expresioacuten de fin) instruccioacutenl instruccioacuten2

instruccioacuten3

El funcionamiento es muy sencillo La expresioacuten inicial se ejecuta una sola vez al principio del bucle La condicioacuten de fin se evaluacutea cada vez que se ejecuta el bucle Si es verdashydera se continuacutea la ejecucioacuten y si es falsa se sale del bucle Al final de cada interaccioacuten se ejecuta la expresioacuten de fin

90 Capiacutetulo 4

Puede simular la instruccioacuten f or con una instruccioacuten w h i l e de esta forma

expresioacuten inicial

while (condicioacuten de fin)

instruccioacutenl

instruccioacuten2

instruccioacuten3

expresioacuten de fin

Otra forma poco corriente es eliminar alguna o todas las expresiones de bucle Si quita todas las expresiones se crea un bucle infinito

fOr ( )

instruccioacutenl

instruccioacuten2

instruccioacuten3

equivale a

while (true)

instruccioacutenl

instruccioacuten2

instruccioacuten3

El caso contrario es antildeadir maacutes de una condicioacuten en cada clase de expreshysioacuten separadas por comas En este caso la condicioacuten de fin se evaluara falso si alguna de las claacuteusulas es falsa En realidad funciona como un C loacutegico

ltphp

for ($x = 1 $y = 1 $z = 1 $y lt 10 $z lt 10 $x++ $y = $y -

2 $z = $z + 3)

echo ($x $y $zltbrgt)

gt

Un ejemplo claacutesico es la tabla de multiplicar lthtmlgt ltbodygt ltbgtTABLA DE MULTIPLICARltbgt lttable border=lgt ltphp echo (lttrgt) echo (ltthxthgt ) for ($cabecera = 1 $cabecera lt= 10 $cabecera++)

echo (ltthgt) echo $cabecera

Estructuras de control 91

echo (ltthgt)

echo (lttrgt) for ($x = l$x lt= 10 $x++ )

echo (lttrgt) echo (ltthgt) echo $x echo (ltthgt) for ($y = l$y lt= 10 $y++ )

$multiplicacion = $x $y echo (lttdgt) echo ($multiacutepliacutecaciacuteon) echo (lttdgt)

echo (lttrgt) gt gt lttablegt ltbodygt lthtmlgt

[ ejemplo se sirve de un bucle for que crea una cabecera de tabla con la queta especial ltthgt donde inserta los nuacutemeros del uno al diez Estos umeros escritos en horizontal se podraacuten cruzar con los verticales para atener asiacute el resultado de una multiplicacioacuten

92 Capiacutetulo 4

El siguiente paso es un conjunto de dos bucles anidados El primer bucle almacena en la variable $x los valores numeacutericos que apareceraacuten como cabecera de la columna uno El segundo bucle seraacute el encargado de multishyplicar el valor actual de $x por los valores del 1 al 10

Cada vez que se ejecuta el segundo f o r se obtiene una celda nueva con un valor determinado por la multiplicacioacuten y cada vez que se ejecuta el primer bucle aparece una nueva fila cuya cabecera es un nuacutemero del 1 al 10

break y continueacute

El camino ordinario para salir de un bucle es que la condicioacuten se evaluacutee a false Existe una forma especial de salir de un bucle utilizando las palashybras reservadas b r e a k y c o n t i n u eacute Su forma de actuar es la siguiente

bull break Sale del bucle actual y continuacutea el programa

bull continueacute Salta hasta el final de la interaccioacuten y continuacutea la ejecucioacuten desde el principio del bucle

El coacutedigo siguiente muestra la forma de utilizar b r e a k

ltphp for ($x = 1 $x lt 20 $x++)

if ($x == 10) break

else echo $xltbrgt

La salida por pantalla es una sucesioacuten de nuacutemeros del 1 al 9 Al llegar la variable $x al nuacutemero 10 la condicioacuten del if se cumple y se ejecuta la instruccioacuten b r e a k saliendo del bucle Veamos ahora el mismo ejemplo pero utilizando c o n t i n u eacute

ltphp for ($x = 1 $x lt 20 $x++)

if ($x == 10) continueacute

else echo $xltbrgt

gt

Estructuras de control 93

En este caso cuando $x alcanza el valor 101o que hace la instruccioacuten conshyt i n u eacute es ir hacia el final de bucle y volver al principio comprobando la condicioacuten

El resultado por pantalla es una sucesioacuten de nuacutemeros desde el 1 hasta el 19 sin incluir el nuacutemero 10

Finalizar la ejecucioacuten de un programa

Hay veces que necesitamos parar la ejecucioacuten de un programa por divershysas causas ha ocurrido un error un fallo en la entrada del nombre y la conshytrasentildea La funcioacuten para la ejecucioacuten es e x i t () o d i e () Estas dos funciones aceptan un paraacutemetro que se imprime en pantalla Por ejemplo considere el siguiente coacutedigo que asume la conexioacuten a una base de datos

ltphp $conexion = conectar_base_datos(libros) if ( $conexion)

die (Se ha producido alguacuten error en la conexioacuten)

gt

Se puede apreciar que si la variable $ c o n e x i oacute n se evaluacutea false (no se ha conseguido la conexioacuten) se detiene la ejecucioacuten del programa Una vershysioacuten maacutes compacta se consigue utilizando el operador or

ltphp $conexion = conectar_base_datos(libros) or die (Se ha producido alguacuten error en la conexioacuten) gt

Nota

e x i t () y d i e () eran iexclas uacutenicas alternativas para el control de errores criacuteticos en versiones anteriores de PHP En PHP 5 aforshytunadamente se ha incluido un potente manejo de excepciones que hace la ejecucioacuten maacutes flexible

Sintaxis alternativa

Algunas estructuras de control pueden escribirse de una forma distinta Las estructuras i f w h i l e f or y s w i t c h pueden escribirse sustituyen-

94 Capiacutetulo 4

do la llave de inicio por un siacutembolo de dos puntos () y la llave de cierre por e n d i f e n d w h i l e endf or y e n d s w i t c h respectivamente

Como ejemplo podemos ver la estructura i f

ltphp $variable = 10 if ($variable == 10)

echo Nueva estructura de control gt

El coacutedigo siguiente es equivalente al anterior

ltphp $variable = 10 if ($variable == 10)

echo Nueva estructura de control end i f

gt

Resumen

Si ha llegado hasta aquiacute ya conoceraacute los secretos baacutesicos de la programashycioacuten en PHP 5 Como puede darse cuenta lo uacutenico necesario para hacer un programa es tener claro la forma de utilizar las variables los operadoshyres y las estructuras de control Una vez dominado esto lo demaacutes es aprenshyder funciones de PHP y teacutecnicas de recuperacioacuten e insercioacuten de datos

Los capiacutetulos siguientes hacen un estudio maacutes concienzudo de las variashybles y las funciones que facilitan el proceso de interaccioacuten entre ellas

En este capiacutetulo aprenderaacute a

bull Crear sus propias funciones bull Utilizar paraacutemetros fijos y variables

bull Realizar funciones recursivas bull Separar el coacutedigo fuente en varios ficheros

96 Capiacutetulo 5

Introduccioacuten

Las funciones son grupos de instrucciones independientes que tienen un propoacutesito determinado

Asiacute tenemos funciones que calculan la raiacutez cuadrada de un nuacutemero nos dan un nuacutemero aleatorio o permiten contar los caracteres de una palabra La sintaxis baacutesica de una funcioacuten es la siguiente

nombre_funcioacuten (paraacutemetrol paraacutemetro2 paraacutemetro3paraacutemetro_n)

Las funciones pueden ser llamadas con varios paraacutemetros o con ninguno dependiendo de su definicioacuten

Cuando PHP encuentra en el coacutedigo la llamada a una funcioacuten primero evaluacutea cada argumento y los utiliza como paraacutemetro de entrada Despueacutes ejecuta la funcioacuten y devuelve el valor solicitado o realiza alguna accioacuten sin enviar ninguacuten valor de salida

El siguiente ejemplo contiene un conjunto de llamadas a funciones con 01 oacute 2 paraacutemetros de entrada

ltphp echo sqrt(9) Raiacutez cuadrada de 9 es 3 echo rand(1020) Nuacutemero aleatorio entre 10 y 20 echo pi() Nuacutemero pi gt

Valores de las funciones

Cada funcioacuten en PHP se considera como una expresioacuten Se pueden utilishyzar las funciones para lo mismo que se utilizan las expresiones como alshymacenar su resultado en una variable o formar parte de una expresioacuten maacutes compleja

ltphp $numero_aleatorio = rand (1100) Se almacena en una variable $numero_aleatorio = rand (1100) + rand (1100) sqrt(9) Expresioacuten compleja gt

No todas las funciones devuelven un valor numeacuterico Tambieacuten pueden devolver caracteres array o truefalse si la funcioacuten ha tenido eacutexito o no Este tipo de funciones se utiliza para conectar a bases de datos escribir a ficheros de texto manipular imaacutegenes etceacutetera

Funciones 97

Funcioacuten de ejemplo Obtencioacuten de la fecha actual

Existen un conjunto de funciones que permiten averiguar la fecha actual del sistema Una de estas funciones es d a t e ( ) que permite recuperar el antildeo diacutea mes etceacutetera del momento en el que se hace la consulta Para averiguar el diacutea de hoy podemos utilizar la construccioacuten

lt d a t e (d) gt

El paraacutemetro que pasamos entre pareacutentesis indica a la funcioacuten el formato de fecha que queremos obtener En este caso la d indica que queremos obtener el diacutea en formato numeacuterico La siguiente tabla relaciona los caracshyteres dentro de la funcioacuten d a t e () con su aplicacioacuten praacutectica

Tabla 51 Formato de fecha con date()

Caraacutecter Valor

a Imprime am o pm

A AM o PM

h La hora en formato (01-12)

H Hora en formato 24 (00-23)

g Hora de 1 a 12 sin un cero delante

G Hora de 1 a 23 sin cero delante

i Minutos de 00 a 59

s Segundos de 00 a 59

d Diacutea del mes (01 a 31)

j Diacutea del mes sin cero (1 a 31)

w Diacutea de la semana (0 a 6) El 0 es el domingo

m Mes actual (01 al 12)

n Mes actual sin ceros (1 a 12)

Y Antildeo con 4 diacutegitos (2004)

y Antildeo con 2 diacutegitos (04)

z Diacutea del antildeo (0 a 365)

t Nuacutemero de diacuteas que tiene el mes actual

98 Capiacutetulo 5

Se pueden utilizar varios caracteres dentro de la funcioacuten indicando el forshymato de fecha que nos interesa

ltphp $meses = array (Enero Febrero Marzo Abril Mayo

Junio Julio Agosto Septiembre Octubre Noviembre Diciembre)

echo Fecha actual date(d-m-Y) ltbrgt echo Diacutea del antildeo date(z) ltbrgt echo Estamos en el mes $meses[date(n) ] ltbrgt gt

El resultado en pantalla es el siguiente

Documentacioacuten sobre funciones

Desde sus inicios PHP se disentildeoacute para que fuera sencillo de utilizar y de extender por la comunidad de desarrolladores La potencia reside en la gran cantidad de funciones escritas de todo tipo Este libro cubre las funciones maacutes utilizadas en el desarrollo de un proshyyecto profesional pero seriacutea imposible cubrir todas las funciones existenshytes con detalle Por esta razoacuten es imprescindible tener como referencia la

Funciones 99

guiacutea on-line de PHP en wwwphpnet donde podemos encontrar clasifishycadas por temaacutetica todas las funciones existentes hasta ahora

Ademaacutes contamos con un buscador de apoyo que nos permite buscar la definicioacuten de una funcioacuten y ejemplos de uso escritas por usuarios de PHP

Para los usuarios que no conocen la forma de trabajar con el lenguaje C se hace necesario explicar coacutemo aparecen las funciones descritas en el mashynual de wwwphpnet El formato es el siguiente

tipo_devuelto nombre_funcioacuten (tipol argl tipo2 arg2) -

El t i p o - d e v u e l t o es el tipo de valor que la funcioacuten daraacute como salida Puede ser un integer double array etceacutetera El nombre de la f u n c i oacute n es la forma correcta de ejecutar el coacutedigo Los p a r aacute m e t r o s de e n t r a d a (arshygumentos) deben pertenecer al tipo que define la funcioacuten Un ejemplo de definicioacuten es

string substr (string string int start[ int length] )

Puede ver que la funcioacuten s u b s t r () devolveraacute como resultado una cadeshyna de caracteres y que tiene 2 argumentos de entrada como miacutenimo El paraacutemetro que se encuentra entre dos corchetes es opcional y puede decishydir usarlo o no

Funciones de usuario

Para realizar programas complejos en PHP 5 no es necesario escribir funshyciones Se pueden escribir programas utilizando todo lo aprendido hasta ahora

A medida que el proyecto se haga maacutes complejo el coacutedigo se haraacute maacutes extenso y menos legible En este punto deberiacutea comenzar a pensar en crear funciones que realicen determinadas tareas

Definicioacuten de funciones

El formato es el siguiente

function nombre_funcioacuten($argumentol $argumento2 )

instruccioacutenl instruccioacuten2 instruccioacuten3

100 Capiacutetulo 5

Como puede ver se comienza con la palabra reservada f u n c t i o n seguishyda del nombre de la f u n c i oacute n y el nuacutemero de p a r aacute m e t r o s n e c e s a shyr i o El bloque de coacutedigo que pertenece a nuestra funcioacuten debe introducirse entre dos siacutembolos de llave ( ) Un ejemplo claacutesico consiste en calcular el factorial de varios nuacutemeros El factorial del nuacutemero x se obtiene multishyplicando el nuacutemero x por el factorial de (x-1) teniendo en cuenta que el factorial de 1 es 1 Por ejemplo el factorial de 3 seriacutea 3 por el factorial de 2 es decir 3 2 1 El coacutedigo sin utilizar funciones es

ltphp $resultado = 1 $factorial = 3 Queremos calcular el factorial de 3 for ($x = $factorial $x gt 0 $x--)

^resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt bull

$resultado = 1 $factorial = 4 Queremos calcular el factorial de 4 for ($x = $factorial $x gt 0 $x--)

$resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt

$resultado = 1 $factorial = 5 Queremos calcular el factorial de 5 for ($x = $factorial $x gt 0 $x--)

$resultado = $resultado $x

echo El factorial de $factorial es $resultadoltbrgt

gt

Si se fija en el coacutedigo anterior podraacute comprobar que sigue un patroacuten muy evidente El caacutelculo del factorial se realiza en un bucle que va disminushyyendo el valor de una variable y multiplicando todos los valores entre siacute Aprovechando este patroacuten puede crear una funcioacuten que realice el factoshyrial del nuacutemero x ahorrando liacuteneas de coacutedigo

ltphp function factorial($numero)

$resultado = 1 for ($x = $numero $x gt 0 $x--)

$resultado = $resultado $x return $resultado

echo El factorial de 3 es factorial(3)ltbrgt

Funciones 101

echo El factorial de 4 es factorial(4)ltbrgt echo El factorial de 5 es factorial(5) ltbrgt gt

Si comparamos los dos ejemplos podemos llegar a la conclusioacuten de que el segundo es mucho maacutes legible y maacutes sencillo de realizar Como puede ver la funcioacuten f a c t o r i a l () hace uso de la palabra reservada r e t u r n que es la encargada de devolver el valor que estamos solicitando cuando se invoca la funcioacuten

Nota

Aunque en el ejemplo la funcioacuten f a c t o r i a l () recibe como pashyraacutemetro el nuacutemero 3 4 oacute 5 tambieacuten es posible llamarla con una variable del tipo integer o double

Paraacutemetros insuficientes

Si llama a una funcioacuten con menos paraacutemetros de los que debe utilizar por definicioacuten apareceraacute el siguiente error por defecto

Warning Missing argument 1 for factorial()

Este tipo de error no es criacutetico y puede controlarse con excepciones como veremos en capiacutetulos sucesivos Ademaacutes de las excepciones podemos utilishyzar el operador de supresioacuten de error delante de la funcioacuten de esta forshyma f a c t o r i a l ( )

No se recomienda eliminar los mensajes de error en este caso ya que hace complicado la correccioacuten de los posibles fallos

Paraacutemetros en exceso

Si al contrario que en el apartado anterior le pasa a una funcioacuten maacutes paraacuteshymetros que los definidos eacutestos seraacuten omitidos y la ejecucioacuten continuaraacute normalmente sin ninguacuten mensaje de error Esta propiedad de PHP 5 pershymite utilizar variables con un nuacutemero de paraacutemetros variable

Aacutembito de las variables

Las variables definidas en un archivo de PHP permanecen declaradas en todo el fichero menos en las funciones Las funciones crean un entorno de ejecucioacuten donde soacutelo pueden ver las variables que estaacuten dentro de las mismas Aunque no parece muy loacutegico esto nos permite tener variables

Funciones 103

con el mismo nombre en diferentes funciones haciendo el coacutedigo reutili-zable

Si nos fijamos en el ejemplo

ltphp $pi = 3 1 4 funct ion v a l o r _ p i ( )

if ( uuml s s e t ($pi) ) $pi = p i ()

re turn $pi

echo v a l o r _ p i ( ) gt

Se puede observar que definimos al comienzo del coacutedigo la variable $pi como un valor aproximado del nuacutemero pi (314) La funcioacuten v a l o r _ p i () comprueba si la variable $pi estaacute definida y si no lo estaacute recupera ese valor con una funcioacuten de PHP 5 Para entender el alcance de las variables vamos a ir paso a paso viendo queacute es lo que ocurre

bull Se define $pi a nivel global en el programa

bull Se define la funcioacuten v a l o r _ p i () que por ahora no se utiliza

bull Se lanza la ejecucioacuten de la funcioacuten

bull La funcioacuten evaluacutea si existe la variable $pi y da como resultado false Esto es asiacute porque la variable estaacute definida fuera de la funcioacuten y no dentro de ella por lo tanto se considera que la variable $p i dentro de la funcioacuten es distinta (entorno local) a la variable $pi definida fuera de la funcioacuten (entorno global)

bull El resultado por pantalla es 31415926535898

Esta forma de programar se considera la correcta en la comunidad de de-sarrolladores de PHP Auacuten asiacute existen mecanismos que permiten que una variable definida fuera de una funcioacuten pueda ser utilizada dentro de la misma simplemente anteponiendo la palabra reservada g l o b a l a la vashyriable definida dentro de la funcioacuten

Utilizando el ejemplo anterior tenemos

ltphp $pi = 3 1 4 funct ion v a l o r _ p i ( )

g l o b a l $pi if ( Uuml s s e t ($pi) )

$pi = pi ()

104 Capiacutetulo 5

re turn $pi

echo v a l o r _ p i ( )

gt

Si vemos paso a paso el ejemplo

bull Se define $pi a nivel global en el programa bull Se define la funcioacuten v a l o r _ p i () que por ahora no se utiliza bull Se lanza la ejecucioacuten de la funcioacuten

bull Dentro de la funcioacuten la variable $pi se define como global es decir se utiliza la variable creada al principio del coacutedigo

bull La funcioacuten evaluacutea si existe la variable $p i y da como resultado true

bull El resultado por pantalla es 314

Variables estaacuteticas

Por defecto las funciones que creamos en PHP 5 no retienen en memoria el valor de las variables que se utilizan Cada llamada a una funcioacuten imshyplica la nueva creacioacuten de las variables locales con su valor inicial La deshyclaracioacuten static antildeadida a una variable causa que la funcioacuten retenga en memoria el valor de esa variable en cada llamada Como puede ver en el ejemplo las 100 llamadas a la funcioacuten c o n t a d o r () dan siempre el misshymo resultado porque la variable $ c o n t a d o r se crea con cada llamada

ltphp function contador()

$contador = 0 $contador = $contador +1 return $contador

for ($x = 1 $X lt= 100 $x++)

echo contador() gt

Sin embargo podemos hacer que la funcioacuten recuerde los valores antildeadienshydo la palabra s t a t i c a la definicioacuten de la variable

ltphp function contador()

static $contador = 0 $contador = $contador + 1 return $contador

for ($x = 1 $x lt= 100 $x++)

Funciones 105

echo contador()

gt

iacutenclude() y require()

A medida que su proyecto se hace maacutes complejo comenzaraacute a crear funshyciones muy uacutetiles para conectar a bases de datos crear imaacutegenes al vuelo conectar por FTP etceacutetera y seguramente quiera emplear estas funcioshynes en otros proyectos distintos para ahorrar tiempo El camino para hashycer esto es muy sencillo Soacutelo tiene que guardar las funciones necesarias en un fichero con extensioacuten php htm c s s i n c etceacutetera y utilizar las directivas i n c l u d e () o r e q u i r e f ) desde la Web que vaya a utilizarlas

En PHP 5 no existen apenas diferencia entre ambas funciones salvo que la funcioacuten i n c l u d e () es maacutes tolerante a fallos que r e q u i r e () y permishyte continuar la ejecucioacuten del programa aunque se haya encontrado un fashyllo

La conclusioacuten es que debe utilizarse r e q u i r e () para aplicaciones que necesiten obligatoriamente alguacuten archivo criacutetico y no pueda continuarse la ejecucioacuten sin eacutel

Si en el desarrollo de nuestro proyecto nos encontramos con que vamos a utilizar varios archivos que hacen llamadas unos a otros podriacutea pasar que hagamos varias inclusiones del mismo archivo en distintos puntos proshyvocando alguacuten fallo difiacutecil de detectar Las funciones r e q u i r e _ o n c e () e i n c l u d e _ o n c e () solucionan eacuteste problema ya que si se intenta incluir un fichero varias veces con dichas funciones PHP 5 simplemente ignorashyraacute las llamadas El formato es el siguiente

require base_datosphp include contador_vistasphp require_once test php-include_once visitasphp

Recursividad

El paradigma de la programacioacuten nos lleva a los desarrolladores a invenshytar foacutermulas que minimicen el esfuerzo en nuestros programas pecando

106 Capiacutetulo 5

algunas veces de complejidad Las funciones recursivas son aquellas cashypaces de llamarse a siacute mismas Como uacutenico requisito es que haya una forshyma de salir en la llamada recursiva Si volvemos al ejemplo del nuacutemero factorial nos encontramos en que se puede escribir de la siguiente forma

ltphp function factorial($numero)

if ($numero == 1) return $numero

else return $numero factorial($numero-l)

echo El factorial de 7 es factorial(7) ltbrgt gt

Lo primero que llama la atencioacuten es que carece de un bucle f or para ir disminuyendo los nuacutemeros implicados en el factorial Lo que hace la funshycioacuten es multiplicar el nuacutemero que se pasa por el factorial del nuacutemero-1 Si el nuacutemero que se pasa es igual a 1 la funcioacuten deja de hacer llamadas reshycursivas y comienza a devolver los valores hasta llegar al resultado final

Funciones con nuacutemero de argumentos variables

Es habitual que el nuacutemero de paraacutemetros que se le pase a una funcioacuten dependa de la situacioacuten en la cual es llamada Hay tres formas de hacer esto en PHP

bull Definiendo la funcioacuten con argumentos por defecto Este meacutetodo pershymite hacer llamadas con menos paraacutemetros sin que aparezca un error

bull Usando un array para pasar las variables

bull Usando las funciones de argumento variable f unc_num_args () f u n c _ g e t _ a r g () y f u n c _ g e t _ a r g s () ya utilizadas en PHP 4

Argumentos por defecto

Para definir paraacutemetros de este tipo se sustituyen las variables por exshypresiones de asignacioacuten El formato es el siguiente

function nombre_funcioacuten($argumentol=valorl $argumento2=valor2 )

Funciones 107

De esta forma al llamar a la funcioacuten podemos hacerlo con varios paraacutemeshytros Si alguno de los paraacutemetros es obviado la variable tendraacute como vashylor el valor por defecto de la definicioacuten

ltphp function capitales($Pais$Capital = Madrid$habitantes = muchos)

re turn (La c a p i t a l de $Pais es $Capi ta l y t i ene $habi tantes hab i tan tes ltbrgt)

echo capitales(Espantildea) echo capitales(PortugalLisboa) echo capitales(FranciaParismuchiacutesimos) gt

La salida por pantalla es la siguiente

La capital de Espantildea es Madrid y tiene muchos habitantes La capital de Portugal es Lisboa y tiene muchos habitantes La capital de Francia es Paris y tiene muchiacutesimos habitantes

La funcioacuten c a p i t a l e s () tiene un paraacutemetro fijo y dos paraacutemetros por defecto El paraacutemetro $ P a i s es obligatorio pero los demaacutes pueden queshydarse en blanco recibiendo el valor por defecto La limitacioacuten de este meacutetodo es que los argumentos tienen un orden y no podemos saltarnos ninguno es decir no podemos dar los valores $ C a p i t a l y $ h a b i t a n -t e s porque en medio hay otro paraacutemetro

Argumentos mediante un array

Si no encontroacute alguna utilidad a la anterior forma de pasar valores variashybles quizaacutes necesite utilizar un array para pasarlos El ejemplo siguiente usa esta estrategia y algunos trucos maacutes como el operador ternario y los array asociativos

ltphp function capitales($datos)

$Pais = isset ($datos[Pais ] ) $datos [Pais] Espantildea $Capital = isset ($datos[Capital] ) $datos [Capital] Madrid $habitantes = isset ($datos[habitantes] ) $datos [habitantes] muchos return (La capital de $Pais es $Capital y tiene $habitantes habitantesltbrgt)

Introducimos en el array los datos uno por uno para que sea maacutes faacutecil de entender $datos [Pais] = Espantildea echo capitales($datos) $datos [Pais] = Portugal

108 Capiacutetulo 5

$datos [Capital] = Lisboa echo capitales($datos) $datos [Pais] = Francia $datos [Capital] = Paris $datos [habitantes] = muchiacutesimos echo capitales($datos) gt

Como puede ver la funcioacuten tiene un uacutenico argumento que contiene toshydos los datos que nuestro programa necesita Esta vez los valores por defecto los introducimos mediante el operador ternario que chequea si existe el dato referido al P a i s C a p i t a l o h a b i t a n t e s y si no existe se antildeaden los datos E s p a ntilde a Madr id y muchos El ejemplo utiliza la funcioacuten con 0 2 y 3 paraacutemetros La ventaja de este meacutetodo es que podraacute utilizar los argumentos que quiera y en el orden que necesite sin encasishyllarse en una forma especial de pasar los datos

Nota

Jgt Aunque todaviacutea no hemos visto el capiacutetulo 7 que trata con detalle el manejo dearrays el lector puede hacerse una idea de coacutemo funshycionan en el aacutembito de los paraacutemetros defunciones Si queda alshyguna duda de coacutemo utilizarlos siempre puede echar un breve vistazo al capiacutetulo 7 para aclarar esas lagunas

Funciones 109

Muacuteltiples argumentos con func_num_args()

Desde la versioacuten 4 PHP ofrece algunas funciones que pueden ser utilizashydas para recuperar los argumentos

Son muy similares al lenguaje C

bull func_num_args() Devuelve el nuacutemero de argumentos que recibe la funcioacuten desde la que es llamada

bull func_get_arg() Devuelve uno a uno los argumentos pasados de la sishyguiente forma func_get_arg(0) func_get_arg(l) func_get_arg(5)

bull func_get_args() Devuelve un array con todos los argumentos pasashydos a la funcioacuten con los iacutendices del array empezando desde 0

Cualquiera de estas funciones daraacute un error si son llamadas fuera del enshytorno de una funcioacuten y f u n c _ g e t _ a r g () produciraacute un fallo si es llashymada con un nuacutemero maacutes alto que los argumentos que se reciben

Las funciones anteriores dan una ventaja a largo plazo ya que si durante el periacuteodo de vida de una funcioacuten necesita antildeadir alguacuten argumento maacutes puede capturar sin necesidad de cambiar el coacutedigo de las llamadas o el de definicioacuten de la funcioacuten

En el ejemplo siguiente puede comprobar coacutemo se utiliza este meacutetodo

ltphp function capitales()

$numero_argumentos = func_num_args() $Pais = $numero_argumentos gt 0 func_get_arg(0) Espantildea $Capital = $numero_argumentos gt 1 func_get_arg(1) Madrid $habitantes = $numero_argumentos gt 2 func_get_arg (2) muchos return (Nuacutemero de argumentos es $numero_arguraentos La capital de $Pais es $Capital y tiene $habitantes habitantesltbrgt)

echo capitales() echo capitales(Portugal Lisboa) echo capitales(Francia Paris muchiacutesimos) gt

Esta forma de utilizar los argumentos sigue teniendo una limitacioacuten Los argumentos deben ser pasados en un lugar determinado sino la funcioacuten no haraacute bien su trabajo Utilizar los paraacutemetros como array es el meacutetodo maacutes flexible y el maacutes utishylizado en los programas PHP Auacuten asiacute es muy uacutetil cuando no sepa cuaacutentos datos necesita manejar una funcioacuten Podemos utilizarlo para funciones que sumen todos los parame-

110 Capiacutetulo 5

tros que introduzca o concatenen todas las palabras como el ejemplo sishyguiente

ltphp function concatenar()

$resultado = $numero_argumentos = func_num_args() $array_parametros = func_get_args() for ($x = 0 $x lt= $numero_argumentos $x++)

$resultado = $resultado $array_parametros[$x]

return $resultadoltbrgt

echo concatenar(Hola Mundo) echo concatenar(Esto es una prueba dela potencia de este meacutetodo) gt

Llamadas por valor

Por defecto las llamadas a funciones se hacen por valor Esto quiere decir que las variables que se utilizan como paraacutemetros se copian al entorno de la funcioacuten

Todos los cambios de valor que sufra la variable en este entorno no afecshytaraacuten al programa fuera de la funcioacuten

ltphp function elevado($nuraero$ iacutendice)

$resultado = $numero for ($x = $indice $x gt 0 $x--)

$resultado = $resultado $nuraero

$numero = $resultado return $numero

$numero = 2 $indice = 5 echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt echo $numero elevado a $indice es igual a elevado ($numero$ indice) ltbrgt gt

El resultado por pantalla es

2 elevado a 5 es igual a 64 2 elevado a 5 es igual a 64

Funciones 111

El ejemplo anterior calcula el resultado de $numero elevado a $ Iacute n d i c e La funcioacuten e l e v a d o () crea un bucle para multiplicar $numero por las veces que indica el $ iacute n d i c e y lo va almacenando en la variable temporal $resultado

Cuando el bucle termina este resultado se vuelve a pasar a la variable $ numero que es devuelta como salida de la funcioacuten Cuando volvemos a ejecutar la funcioacuten con los mismos paraacutemetros vemos que la variable $nu-mero no ha cambiado en la ejecucioacuten anterior porque en realidad lo que se pasa es una copia del valor y todas las modificaciones se hacen sobre la copia y no sobre la variable original

Llamadas por referencia

PHP 5 ofrece actualmente dos caminos diferentes para cambiar sus argushymentos en la definicioacuten de la funcioacuten y en la llamada a la misma

Las variables pasadas por referencia pueden ser modificadas durante el proceso de una llamada porque lo que se pasa no es una copia sino la variable en siacute misma

Para pasar variables por referencia hay que utilizar el operador (amp) deshylante de la variable

Lo mejor es verlo en un ejemplo

ltphp function elevado(amp$numeroamp$indice)

$resultado = $numero for ($x = $iacutendiacutece $x gt 0 $x--)

$resultado = $resultado $numero

$numero = $resultado return $numero

$numero = 2 $ iacutendice = 5 echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt echo $numero elevado a $indice es igual a elevado($numero$ indice) ltbrgt gt

El resultado por pantalla es ahora

2 elevado a 5 es igual a 64 64 elevado a 5 es igual a 68719476736

El funcionamiento es exactamente igual pero el resultado es distinto El operador (amp) hace que la variable $numero pueda ser modificada dentro de la funcioacuten y guarde este nuacutemero fuera de ella

Tambieacuten puede forzar a una funcioacuten a tomar argumentos por referencia aunque esta capacidad de PHP puede desaparecer en futuras versiones del lenguaje Las llamadas pueden hacerse de la siguiente forma

$numero = 2 $indice = 5 echo $numero elevado a $indice es igual a elevado(amp$numeroamp$indice)ltbrgt echo $numero elevado a $indice es igual a elevado(amp$numeroamp$indice)ltbrgt

El resultado es exactamente igual que al poner la referencia en la definishycioacuten de la funcioacuten

Referencia a variables

Las referencias pueden usarse tambieacuten fuera de las funciones en el aacutembishyto de las variables El ejemplo siguiente muestra coacutemo trabaja el operador (amp) con las variables

ltphp $nombre = Luis Miguel

Funciones 113

$apelliacutedos = Cabezas Granado $nombre auxiliar es simplemente una copia de $nombre $nombre_auxiliar = $nombre-$nombre_referencia es una referencia a la variable $nombre_referencia = amp$nombre echo $nombre $apellidosltbrgt $nombre_auxiliar = Alberto echo $nombre $apellidosltbrgt $nombre_referencia = Felipe echo $nombre $apellidosltbrgt gt

$nombre__aux i l i a r es una copia de la variable $nombre y por mucho que la cambiemos $nombre permaneceraacute con el mismo valor En cambio la variable $nombre_ref e r e n c i a es un alias de $nombre por lo tanto todos los cambios que se hagan en cualquiera de las dos variables les afecshytaraacute por igual

Funciones variables

Uno de los trucos que se pueden hacer con PHP es utilizar variables para almacenar el nombre de funciones Si una variable almacena el nombre de una funcioacuten simplemente tendraacute que antildeadir unos pareacutentesis al final de la variable para hacer la llamada correctamente

ltphp function saludo_maniana()

return (Buenos Diacuteas)

function saludo_tarde()

return (Buenas Tardes)

function saludo_noche()

return (Buenas Noches) $horario = tarde $funcion_variable = saludo_$horario echo $funcion_variable () gt

En el ejemplo anterior tenemos tres funciones que nos saludan depenshydiendo del horario en el que ejecutemos el programa Este valor se recoge en la variable $ h o r a r iacute o Sabemos que todas las funciones comienzan con la palabra saludo_ Si a la variable $f u n c i o n _ v a r iacute a b l e le concatenashymos el valor de $ h o r a r i o tenemos como resultado el nombre de la fun-

1 1 4 Capiacutetulo 5

cioacuten que nos daraacute el saludo Para que esto funcione antildeadimos dos siacutemboshylos de pareacutentesis al final de la expresioacuten

Resumen

Si el capiacutetulo anterior daba rienda suelta a su imaginacioacuten para comenzar con el desarrollo de pequentildeos scripts despueacutes de leer este capiacutetulo estaraacute en situacioacuten de realizar un gran proyecto Ahora que conoce el secreto para almacenar en distintos archivos funciones y partes de un programa escrishyto en PHP podraacute crear aplicaciones maacutes extensas y complejas

Ahora bien debe tener en cuenta que hay que tener cuidado con el alcanshyce de las variables y los pasos por valor y referencia aspecto muy relevanshyte en el capiacutetulo referido a los objetos

En este capiacutetulo aprenderaacute a

bull Diferenciar entre las comillas simples y las comillas dobles bull Trabajar con cadenas de muacuteltiples liacuteneas bull Concatenar varias cadenas bull Generar nuevas cadenas de caracteres a partir de una original bull Eliminar los espacios en blanco de las cadenas bull Convertir a mayuacutesculas o minuacutesculas bull Definir patrones de verificacioacuten de cadenas

116 Capiacutetulo 6

Introduccioacuten

Si pensamos en los tipos de datos que circulan por la red llegaremos a la conclusioacuten de que una gran porcioacuten la ocupan las imaacutegenes animaciones en Macromedia Flash videos o subprogramas escritos en Java La otra gran porcioacuten mayoritaria son los textos o las cadenas de caracteres

Las cadenas de caracteres o string son secuencias de caracteres que pueshyden ser tratadas como una unidad asignadas a variables pasadas como paraacutemetros a funciones o enviadas como salida al navegador Un string se diferencia de otro tipo de dato en PHP 5 porque va encerrado entre comishyllas dobles ( ) o simples ( )

Cadena entre comillas dobles Cadena entre comillas simples

PHP interpreta de distinta forma las cadenas que van entre comillas doshybles y las que van entre comillas simples Losstrings entre comillas dobles pueden sustituir ciertos siacutembolos por acciones como la inclusioacuten del vashylor de una variable Las comillas simples simplemente muestran todo el contenido sin atender a caracteres especiales Podemos ver un ejemplo donde sucede esto

ltphp $variable = Domingo $frase_l = Hoy es $variable el cielo estaacute gris $frase_2 = Hoy es $variable el cielo estaacute gris echo $frase_l echo $frase_2 gt

El resultado en el navegador es

Hoy es Domingo el cielo estaacute gris Hoy es $variable el cielo estaacute gris

Como se puede observar la cadena $f r a s e _ l es capaz de sustituir la vashyriable por su valor por el simple hecho de estar entre comillas dobles

Propiedades de las cadenas

iacutendices de string

Si pensamos en las cadenas como una sucesioacuten de caracteres en un orden determinado podemos llegar a desear acceder libremente a parte de los

Cadenas de caracteres y expresiones regulares 117

caracteres Esto es posible gracias a los siacutembolos de llave ( ) y un iacutendice numeacuterico que se corresponderaacute con la posicioacuten del caraacutecter que buscamos El ejemplo muestra coacutemo crear una funcioacuten que duplica las letras de una cadena aprovechando esta forma de acceder a los caracteres

ltphp function duplicar_caracteres($cadena)

$tamanio = strlen ($cadena) $cadena_auxiliar = for ($x = 0$x lt $tamanio $x++)

$cadena_auxiliar = $cadena_auxiliar $cadena$x $cadena$x

return $cadena_auxiliar

$cadena = Duplicar las letras echo duplicar_caracteres($cadena)iexcl gt

La salida por pantalla como puede adivinar es

118 Capiacutetulo 6

Operadores

En este punto aprovecharemos para hacer un breve repaso de los operashydores de string vistos en el capiacutetulo 3 En otros lenguajes como Java se utiliza el operador suma (+) para unir dos cadenas En PHP este mismo resultado se obtiene con el operador punto ( ) Asiacute podemos concatenar varias cadenas de la forma siguiente

ltphp $cadenal = Hola $cadena2 = Mundo $cadena3 = iexclQueacute tiacutepico $supercadena = $cadenal $cadena2 $cadena3 echo $supercadena gt

Es faacutecil intuir que el operador puede concatenar caracteres y variables de tipo string de forma conjunta Es posible que desee ahora antildeadir texto a una cadena ya existente esto se puede hacer de dos formas muy similashyres La primera es asignando a la variable su valor maacutes el valor a antildeadir de la siguiente forma

ltphp $cadenal = Hola $cadena2 = Mundo $cadenal = $cadenal $cadena2 echo $cadenal gt

O utilizando el operador de concatenacioacuten y asignacioacuten ( = ) como en el ejemplo

ltphp $cadenal = Hola $cadena2 = Mundo $cadenal = $cadena2 echo $cadenal gt

Sintaxis para muacuteltiples liacuteneas

Existe en PHP una forma maacutes de introducir cadenas aparte de las comishyllas muy recomendable para largos textos o un considerable conjunto de etiquetas HTML La sintaxis es muy sencilla y comienza con el operador (ltltlt) seguido de una etiqueta que indica el principio del texto Despueacutes de esto podemos escribir un conjunto de caracteres muy numerosos y para

Cadenas de caracteres y expresiones regulares 119

finalizar la etiqueta de fin El ejemplo muestra coacutemo almacenar un forshymulario en una variable

ltphp $formulario = ltltltINICIO ltformgt ltiacutenput type=text name=Nombre value=Luiacutes Miguel Cabezasgt ltbrgt ltinput type=submit name=submit value=Enviar gt ltformgt INICIO echo $formulario gt

Siempre debe comenzar por el operador (ltltlt) seguido de un identifica-dor por ejemplo INICIO Despueacutes se incluye el texto en este caso un forshymulario y para finalizar la misma etiqueta de inicio Esta forma de almacenar datos permite utilizar indistintamente comillas simples o doshybles dentro de una variable La imagen 62 muestra el resultado del script

Funciones de string

Si conoce el lenguaje C podraacute comprobar que las funciones de manejo de caracteres son muy parecidas en nombre y uso Los desarrolladores de PHP

120 Capiacutetulo 6

siempre han querido que exista esta similitud para facilitar el aprendizaje del lenguaje

La mayoriacutea de las funciones existentes en PHP 5 tienen una homologa en C

Tamantildeo de la cadena

La funcioacuten s t r l e n () devuelve como resultado el tamantildeo en caracteres de la cadena que pasemos de paraacutemetro Este valor puede asignarse a una variable como indica el ejemplo

ltphp $cadena = Esta cadena tiene muchas letras $numero_letras = strlen($cadena) echo cadena tiene $numero_letras caracteres gt

Simplemente imprime

cadena tiene 31 caracteres

Posicioacuten de los caracteres

Para crear buenos motores de buacutesqueda en nuestros sitios Web necesitashyremos potentes herramientas que sean capaces de buscar caracteres cashydenas o patrones coincidentes dentro de textos extensos La funcioacuten s t r p o s () encuentra en un string la posicioacuten de un caraacutecter determinado

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de a es strpos($cadena a) ltbrgt echo La primera ocurrencia de m es strpos($cadena m) ltbrgt gt La s a l i d a en el navegador no es o t ra que La primera ocur renc ia de a es 3 La primera ocur renc ia de m es 18

Si s t r p o s () se utiliza para averiguar la posicioacuten de la primera L mashyyuacutescula de $ cadena vemos que nos devuelve un 0 esto es asiacute porque el iacutendice de caracteres comienza en 0 como pasa en muchos lenguajes de programacioacuten Si no se encuentra ninguna ocurrencia del caraacutecter buscashydo el resultado seraacutease

Cadenas de caracteres y expresiones regulares 121

La funcioacuten s t r p o s () tambieacuten puede utilizarse para buscar varios caracshyteres seguidos en una misma cadena

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de tiene es strpos($cadenatiene) ltbrgt gt

Si lo que nos interesa es encontrar caracteres buscando desde el final de la cadena la funcioacuten que tenemos que utilizar es s t r r p o s () (la letra r que se antildeade viene del ingleacutes reverse) El ejemplo anterior nos sirve para comshyprobar el funcionamiento de la funcioacuten

ltphp $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de a es strpos($cadena a ) ltbrgt echo La primera ocurrencia desde atraacutes de a es strrpos($cadena a) ltbrgt gt

siendo el resultado

La primera ocurrencia de a es 3 La primera ocurrencia desde atraacutes de a es 29

Comparacioacuten

El operador (==) nos puede servir para evaluar si dos cadenas de caracteshyres son iguales dentro de una estructura de control Ademaacutes tenemos la funcioacuten s t r c m p ( ) que compara bit a bit dos cadenas de caracteres Atenshydiendo al valor de salida de la funcioacuten podemos obtener los siguientes resultados

bull Si el valor que se obtiene es 0 las dos cadenas son exactamente igual

bull Si obtenemos un valor negativo el primer string es maacutes pequentildeo que el segundo

bull Si obtenemos un valor positivo el primer string es maacutes grande que el segundo ltphp $cadenal = Prueba $cadena2 = Prueba if (strcmp($cadenal$cadena2) == 0)

echo Las dos cadenas son iguales elseif (strcmp($cadenal$cadena2) lt 0)

echo La cadenal es menor que la cadena2

122 Capiacutetulo 6

else echo La cadenal es mayor que la cadena2

gt

La comparacioacuten anterior soacutelo da como resultado dos cadenas iguales si las dos cadenas son exactamente iguales haciendo distincioacuten entre mashyyuacutesculas y minuacutesculas

Para evitar este problema podemos utilizar la funcioacuten s t r c a s e c m p ( ) que no es sensible a mayuacutesculas Asiacute s t r c a s e c m p (HoLa hOlA) da como resultado 0 es decir las dos cadenas son iguales

Buacutesqueda de caracteres

Siguiendo con las buacutesquedas de texto la funcioacuten s t r s t r () recibe como paraacutemetros una cadena de caracteres donde buscar y otra con un conjunshyto de caracteres que queremos encontrar Si se encuentra el patroacuten de buacutesshyqueda el resultado seraacute una cadena de caracteres que comenzaraacute justo en el patroacuten hasta el final del string primero Si no se encuentra el patroacuten el resultado seraacutefalse

lt php $cadena = Esta cadena tiene muchas letras echo La primera ocurrencia de cadena es strstr ($cadenacadena) ltbrgt

gt

Como cabe esperar el resultado es La primera ocurrencia de cadena es cadena tiene muchas letras

Seleccioacuten de subcadenas

La funcioacuten s u b s t r () permite seleccionar un conjunto de caracteres de una cadena quedando intacto el string original Puede tomar varios paraacuteshymetros

bull s u b s t r ( c a d e n a iacute n d i c e ) Cadena es el conjunto de caracteres que queremos cortar e iacute n d i c e la posicioacuten a partir de la cual se cortaraacute la cadena hasta el final

bull s u b s t r ( cadena iacute n d i c e numero) Cadena es el conjunto de cashyracteres que queremos cortar e iacute n d i c e la posicioacuten a partir de la cual se cortaraacute la cadena tantas posiciones como indique el nuacutemero

Cadenas de caracteres y expresiones regulares 123

Por ejemplo

ltphp $cadena = Esta cadena tiene muchas letras Devuelve la cadena completa echo substr($cadena 0) echo ltbrgt Desde el caraacutecter 12 hasta el final echo substr($cadena 12) echo ltbrgt Devuelve 6 caracteres desde el caraacutecter 18 echo substr($cadena 186) echo ltbrgt Devuelve los 6 uacuteltimos caracteres echo substr($cadena -6) echo ltbrgt Desde la posicioacuten 26 contando desde atraacutes 6 caracteres echo substr($cadena -266) echo ltbrgt Empezando en el caraacutecter 4 y terminando en el 7 desde atraacutes echo substr($cadena 4-7) gt

El resultado lo podemos ver maacutes abajo Recuerde que la variable $ cade -na queda intacta

124 Capiacutetulo 6

Dependiendo de la posicioacuten del nuacutemero negativo s u b s t r () actuaraacute de una forma u otra

Tabla 61 Respuestas de la funcioacuten substr ()

Ejemplo Resultado

substr(Hola2) Devuelve la cadena completa empezando por el caraacutecter 2 substr(Hola-2) Devuelve la cadena completa empezando por el caraacutecter

2 esta vez empezando a contar desde atraacutes

substr(Hola13) El resultado son 3 caracteres empezando desde el caraacutecshyter 1

substr(Hola-32) Doscaracteres empezando desde el caraacutecter 3 contando desde la uacuteltima letra

substr(Hola2-1) Devuelve un conjunto de caracteres que estaacuten desde la posicioacuten 2 a la posicioacuten 1 comenzando desde atraacutes

substr(Hola-2-3) No tiene aplicacioacuten posible

Funciones de limpieza de cadenas

Sirven para limpiar espacios en blanco al principio de la cadena al final o en cualquier parte desde el principio al final y son respectivamente l t r i m ( ) chop () y t r i m () Su aplicacioacuten es tan sencilla que bastaraacute un ejemplo para entender su funcionamiento

ltphp $salto_linea = n $cadena = cadena con varios espacios en blanco echo $salto_linea $cadena tamantildeo strlen($cadena) echo ltbrgt echo $salto_linea ltrim($cadena) tamantildeo strlen(ltrim($cadena)) echo ltbrgt echo $salto_linea chop($cadena) tamantildeo strlen(chop($cadena)) echo ltbrgt echo $salto_linea trim($cadena) tamantildeo strlen(trim($cadena)) gt

Cada liacutenea realiza una de las operaciones vistas e imprime el resultado de la cadena en el navegador junto con el tamantildeo de la cadena

La figura 64 muestra el resultado por pantalla

126 Capiacutetulo 6

Sustitucioacuten de cadenas

La funcioacuten s t r _ r e p l a c e () toma como paraacutemetros un conjunto de cashyracteres a buscar un grupo que debe sustituirse por el anterior y una cashydena de caracteres sobre la que actuar

ltphp $cadena = Esta cadena tiene muchas letras $cadena = str_replace(EstaEste$cadena) echo str_replace(cadenaconjunto$cadena) gt

Si en la cadena existiera maacutes de una instancia del conjunto buscado todas las ocurrencias quedariacutean cambiadas

ltphp cadena = Esta cadena tiene muchas letras y cadenas $cadena = str_replaceacute(EstaEste$cadena) echo str^replace(cadenaconjunto$cadena) gt

El resultado es Este conjunto tiene muchas letras y conjuntos

Truco

Puede probar esta funcioacuten para cambiar todos iexclos caracteres de un tipo de una cadena de iexcla siguiente forma s t r _ r e p l a c e (h j hola h o l a )

Funciones de mayuacutescula y minuacutescula

Las funciones s t r t o l o w e r () y s t r toupper () devuelven la cadena que se pasa como argumento completamente en minuacutescula o mayuacutescula resshypectivamente

ltphp $cadena = Hay palabras en MAYUacuteSCULAS y en minuacutesculasltbrgt echo strtolower($cadena) echo strtoupper($cadena) gt

El resultado es hay palabras en mayuacutesculas y en minuacutesculas HAY PALABRAS EN MAYUacuteSCULAS Y EN MINUacuteSCULAS

Si lo que realmente nos interesa es que la primera letra de un texto apashyrezca como letra Capital o que letras iniciales de cada palabra en una fra-

Cadenas de caracteres y expresiones regulares 127

se aparezcan en mayuacutescula tenemos las funciones u c f i r s t ( ) y u c w o r d s ( )

ltphp $cadena = habiacutea una vezltbrgt echo ucfirst($cadena) $cadena2 = linux user group echo LUG significa ucwords($cadena2) gt

Expresiones regulares

Las funciones vistas anteriormente basan su potencia en la buacutesqueda o susshytitucioacuten de los caracteres de una cadena pero son poco uacutetiles cuando tratashymos de comprobar si un conjunto de caracteres cumple un formato determinado Si solicitamos mediante un formulario un correo electroacutenico necesitamos saber a priori si ese correo por lo menos estaacute bien construido

luisnccextremaduraorg luiszendcom

La idea es poder descartar de alguna forma los correos escritos de esta manera

l u i s (Snccextremaduraorg E s p a c i o en medio

128 Capiacutetulo 6

LUISzendcom En mayuacutesculas luisaupexorg Dos

Las expresiones regulares son patrones de buacutesqueda dentro de cadenas Estos patrones se construyen mediante caracteres especiales que cumplen unas reglas determinadas

Tabla 62 Reglas de expresiones regulares

Ejemplo Regla

aabb Los caracteres no especiales como un grupo de letras se escriben como de costumbre

A Indica que hay que buscar el patroacuten desde el principio de la cadena $ Este simbolo obliga al patroacuten a cumplirse hasta el final de la

cadena Simboliza cualquier caraacutecter

Indica que puede haber O o maacutes instancias de una expresioacuten + Indica que puede haber 1 o maacutes instancias de una expresioacuten [ab] Indica que se puede encontrar el caraacutecter a o el b y la expresioacuten

seriacutea correcta Lo podemos acompantildear de [ab] para evaluar si hay varias letras seguidas del tipo a o b

[a-z] Indica que se puede elegir entre un rango de caracteres que va desde la a hasta la z

Si queremos utilizar cualquiera de los anteriores caracteres como parte del patroacuten tendremos que utilizar eacuteste siacutembolo para indicarle a PHP que es un literal

Como ejemplo vamos a intentar hacer un patroacuten que verifique si un coshyrreo electroacutenico estaacute correctamente construido o no Seriacutea faacutecil pensar en una expresioacuten parecida a la siguiente

[ a - z ] + [ a - z ] + o r g

La primera parte [ a - z ] + nos dice que aceptaraacute una letra o conjunto de letras sin espacios y en minuacutesculas que pueden corresponderse con el nombre de usuario de la cuenta de correo Despueacutes aceptaraacute un siacutembolo seguido de otro conjunto de caracteres correspondientes al servidor de correo La uacuteltima parte de la expresioacuten la componen los siacutembolos que indican que tiene que aparecer un punto que separe la descripcioacuten del servidor del dominio y la cadena o r g que obliga a que todos los correos sean de dominio no gubernamental

Cadenas de caracteres y expresiones regulares 129

La expresioacuten anterior tiene algunas limitaciones que veremos como solshyventar La primera es que se puede aplicar a cualquier texto con indepenshydencia del tamantildeo Si en alguna parte de ese texto aparece un conjunto de caracteres que cumpla con la expresioacuten la validacioacuten seriacutea true Esto no es bueno cuando queremos chequear si un correo es introducido correctashymente La solucioacuten es aplicar las reglas de inicio y fin que obligan a que el comienzo de la cadena y el final sean parte de la expresioacuten

[ a - z ] + [ a - 2 ] + o r g $

Tambieacuten podemos encontrarnos con que existen correos introducidos coshyrrectamente pero el dominio es otro distinto a org Esta vez la solucioacuten es introducir el operador O loacutegico | que permite elegir entre varias opcioshynes

^ [ a - z ] + [ a - z ] + ( o r g | c o m | n e t ) $

Por uacuteltimo un problema menor aunque habitual en el aacutembito de los coshyrreos electroacutenicos es la utilizacioacuten de signos de puntuacioacuten para separar nombres y apellidos y servidores de servidores virtuales Por ejemplo el correo siguiente es correcto pero no seriacutea evaluado por la expresioacuten anteshyrior

l u iacute s c a b e z a s n c c a u p e x o r g

Una posible solucioacuten es

[ a - z | ] + [ a - z | ] + ( o r g | c o m ( n e t ) $

Comprobar expresiones regulares

La funcioacuten e reg () es capaz de comprobar si una cadena se corresponde con el patroacuten que se pasa como paraacutemetro Toma dos argumentos obligashytorios una expresioacuten regular y una cadena de caracteres donde buscar el patroacuten Seguidamente puede ver un ejemplo completo de utilizacioacuten de expresiones regulares y la funcioacuten

ltphp $correo = luiscabezasnccaupexorg $correol = LUISnccaupexorg $correo2 = luiscabezasnccaupexorg if (ereg ( [a-z|]+[a-z|]+ (org|com|net)$$correo))

echo El correo $correo se aceptaltbrgt else

echo El correo $correo no cumple el patroacutenltbrgt

iacutef (ereg(^ [a-z|]+ [a-z|]+ (org|comjnet)$$correol) )

echo El correo $correol se aceptaltbrgt

130 Capiacutetulo 6

else echo El correo $correol no cumple el patroacutenltbrgt

if (ereg(A [a-zj]+ [a-zj]+ (org|com|net)$$correo2))

echo El correo $correo2 se aceptaltbrgt else

echo El correo $correo2 no cumple el patroacutenltbrgt gt

El resultado por pantalla es

Puesto que hay muchos usuarios acostumbrados a escribir su correo elecshytroacutenico completamente en mayuacutesculas se hace necesario comprobar este contratiempo tambieacuten Lo maacutes raacutepido es utilizar la funcioacuten e r e g i () que funciona exactamente igual que e r e g ( ) pero no es sensible a mayuacutescula o minuacutescula El ejemplo anterior lo podemos arreglar de la siguiente forma

ltphp $correo = LUISnccaupexorg if (ereg([a-z|]+[a-z|]+(org|com|net)$$correo$pepe))

echo El correo $correo se aceptaltbrgt else

echo El correo $correo no cumple el patroacutenltbrgt

gt

Cadenas de caracteres y expresiones regulares 131

Nota

e reg () y e r e g i () tienen un tercer argumento opcional del tipo array Si iexcla expresioacuten regular la dividimos en pequentildeas parshytes entre pareacutentesis cada ocurrencia encontrada en la cadena se va almacenando como un elemento del array

Reemplazar patrones

e r e g _ r e p l a c e () y e r e g i _ r e p l a c e () tiene tres paraacutemetros El prishymero es una expresioacuten regular el segundo un string por el que se cambiashyraacuten todas las ocurrencias del patroacuten y por uacuteltimo una cadena donde buscar Como antes la diferencia entre las dos es uacutenicamente que la prishymera es sensible a mayuacutesculas El siguiente ejemplo muestra el funcionashymiento

ltphp $texto = El correo es de luisnccaupexorg echo ereg_replace([a-z|]+[a-z|]+(org|com|net)Luis Miguel$texto) gt

Asiacute da como resultado el cambio del correo electroacutenico por el nombre de la persona asociada

Resumen

Desde hace unos antildeos se ha puesto de moda una serie de productos donshyde prima el contenido frente al disentildeo Los CMS (Content Manager System) son programas la mayoriacutea escritos en PHP que permiten gestionar mushycho contenido escrito por diferentes personas El tratamiento de los textos se agudiza al maacuteximo en este caso siendo indispensable la utilizacioacuten de expresiones regulares para verificar los datos nuevos que puedan incor- porarse Ademaacutes suelen llevar un buscador capaz de encontrar patrones determishynados dentro de las noticias expuestas Este capiacutetulo le ha servido para conocer funciones para concatenar recorshytar o verificar cadenas Con esto bien aprendido ya puede comenzar a crear su propio CMS

En este capiacutetulo aprenderaacute a

bull Comprender queacute es un array y coacutemo se define bull Trabajar con funciones que definen listas de datos bull Diferenciar entre los distintos meacutetodos para recorrer los array

bull Ordenar los conjuntos de datos con diferentes meacutetodos bull Crear pilas y colas

134 Capiacutetulo 7

Introduccioacuten

Un array es una coleccioacuten de valores con un uacutenico nombre Para acceder a los distintos valores de la variable se utiliza un iacutendice numeacuterico o alfanu-meacuterico Nos vamos a servir de la definicioacuten de un array en el lenguaje C para ver la potencia de este tipo de datos en PHP La definicioacuten es la siguiente

int mi_array[100] Esto es C

Lo primero que debe llamarnos la atencioacuten es que la variable estaacute predefishynida como i n t (entero) En PHP los arrays no tienen que definirse de una forma concreta sino que pueden tomar distintos tipos de valores enteshyros caracteres objetos etceacutetera Lo siguiente es que en C se necesita sashyber de antemano el nuacutemero de valores maacuteximo que podraacute tomar el array Esto no es necesario en PHP ya que podraacute ir creando valores nuevos a medida que lo vaya necesitando Lo uacuteltimo es que en C el iacutendice para acshyceder a los 100 valores distintos debe ser numeacuterico en cambio en PHP el iacutendice puede ser numeacuterico o alfanumeacuterico

ltphp $mi_array[l] = 23 $mi_array[2] = Este valor es un string $mi_array[ejemplo] = Esto es un array asociativo gt

Creacioacuten de arrays

Vamos a ver tres formas distintas de crear un array dentro de un script de PHP

Asignacioacuten directa

El camino maacutes simple y por otro lado loacutegico es asignar valores cuando se necesiten La primera vez que asignemos un valor el array se crearaacute en el entorno

ltphp $mi_array[l] = 23 Asignacioacuten directa gt

De esta forma tenemos un valor asignado al iacutendice 1 del array Puede asigshynar cualquier iacutendice en la creacioacuten de este tipo de dato e incluso no asig-

Conjuntos de datos del tipo array 135

nar ninguno de forma que PHP se encarga de asociar un iacutendice distinto para cada valor

ltphp $mi_array[] = 23 Empieza en el iacutendice 0 $mi_array[] = 54 iacutendice 1 gt

array()

Esta funcioacuten crea un array con los valores que pase como datos de entrashyda Los iacutendices seraacuten antildeadidos automaacuteticamente empezando desde 0

Si no asigna paraacutemetros a a r r a y ( ) la funcioacuten le devolveraacute un array vaciacuteo

ltphp $mi_array = array(2345762365) gt

El meacutetodo es similar a

ltphp $mi_array[0] = 23 $mi_array[l] = 4 5 $mi_array[2] = 76 $mi_array[3] = 23 $mi_array[4] = 65 gt

La funcioacuten a r r a y () permite tambieacuten antildeadir iacutendices a los valores que se introducen

Para ello se utiliza el operador =gt de esta forma

ltphp $mi_array = array0 =gt 23 1 =gt 45 2 =gt 76) gt

Tambieacuten es posible antildeadir iacutendices que no sean correlativos o iacutendices alf-anumeacutericos incluso mezclar los dos tipos

ltphp $mi_array = a r r a y ( c e r o =gt 23 uno =gt 45 2 =gt 7 6 ) gt

Para recuperar cualquier valor se utiliza el iacutendice dentro de los corchetes

ltphp $mi_array = array(cero =gt 23 uno =gt 45 2 =gt 76) echo $mi_array [ uno] ltbrgt echo $mi_array[2] gt

136 Capiacutetulo 7

Funciones que devuelven arrays

La uacuteltima forma de obtener un array es utilizando alguna de las funcioshynes que devuelven este tipo de datos

Es muy frecuente que las funciones que manejan bases de datos devuelshyvan las ocurrencias dentro de un array

Por ejemplo la funcioacuten r a n g e () devuelve un array con valores numeacuterishycos que van desde un nuacutemero de inicio hasta un nuacutemero final tal y como se muestra en el ejemplo

ltphp $mi_array = range(120130) gt

Esta funcioacuten crea un array empezando desde el iacutendice 0 y el valor 120 hasta el iacutendice 10 y el valor 130

Arrays multidimensionales

Hasta aquiacute hemos visto ejemplos de arrays de una sola dimensioacuten PHP soporta el uso de arrays de varias dimensiones faacutecilmente aunque son complejos de entender y de usar El array siguiente es de 5 dimensiones

ltphp $ m i _ a r r a y [ l ] [ 1 ] [ 2 3 ] [ 4 3 ] [ 0 ] = A r r a y de 5 d i m e n s i o n e s gt

Cada iacutendice encerrado entre corchetes corresponde a una dimensioacuten disshytinta En realidad cada dimensioacuten es un array que se introduce como vashylor dentro de la dimensioacuten anterior

Asiacute podraacute crear un array multidimensional de la siguiente forma

ltphp $colores = array(fuertessuaves) $colores [fuertes] = array ( rojo =gt FF0000 verde =gt 00FF00 azul =gt 0000FF)

$ c o l o r e s [ s u a v e s ] = a r r a y ( r o s a =gt FE9ABC a m a r i l l o =gt FDF189 malva =gt 9 A 2 F 6 8 ) echo $colores[fuertes] [rojo] gt

Para recuperar los valores se utilizan un iacutendice del primer array (fuertes o suaves) y un iacutendice de alguno de los dos arrays secundarios

Conjuntos de datos del tipo array 137

Otra forma de definir el array anterior es

ltphp

$colores = array( fuertes =gt array ( rojo =gt FF0000 verde =gt 00FF00 azul =gt 0000FF)

suaves =gt array ( rosa =gt FE9ABC amarillo =gt FDF189 malva =gt 9A2F68))

echo $colores[fuertes] [rojo] gt

Propiedades de arrays

Existen numerosas funciones que son capaces de averiguar datos de los arrays tales como el tamantildeo si un valor forma parte del conjunto o si un determinado iacutendice estaacute registrado

count()

Cuenta el nuacutemero de elementos que contiene un array

ltphp echo elementos de 1 dimensioacuten count ($colores) ltbrgt echo elementos de 2 dimensiones count ($colores[fuertes]) gt

El ejemplo anterior se basa en la definicioacuten del array de colores inicializa-do antes Para contar el nuacutemero de elementos debe ponerse tambieacuten la dimensioacuten Si el array es de una sola dimensioacuten no hace falta La funcioacuten s i z e o f () actuacutea de la misma forma

in_array()

Busca dentro de un array un valor pasado como paraacutemetro y si lo encuenshytra devuelve el valor true si no devuelve false Toma dos argumentos el valor a buscar y el array doacutende buscar

ltphp $colores = array (rojoverdeamarilloazul) if (in_array(rojo$colores))

echo Se ha encontrado el valor rojo

138 Capiacutetulo 7

e l s e echo No se ha encontrado

gt

Borrar ocurrencias

Para borrar un elemento simplemente se utiliza la misma funcioacuten que borra las variables definidas unset ()

ltphp $colores = array (rojoverdeamarilloazulrosa) echo El nuacutemero de elementos de colores es count ($colores) ltbrgt unset ($colores[2]) echo El nuacutemero de elementos de colores es count ($colores) ltbrgt gt

Se puede observar que para borrar un elemento hay que conocer el iacutendishyce El resultado del ejemplo por pantalla es

El nuacutemero de elementos de colores es 5 El nuacutemero de elementos de colores es 0

Advertencia

Debe tener cuidado el lector con utilizar unset () con el nombre de un array sin iacutendice pues esto causaraacute el borrado del conjunto de datos en su totalidad Unset ($colores) borra el array comshypleto unset ($colores [2] borra soacutelo el iacutendice 2 del conjunto

Interactuar con arrays

Anteriormente tuvo la oportunidad de conocer las estructuras de control existentes en PHP La estructura f oreach quedoacute en el aire para tratarlo a fondo en el presente capiacutetulo El uso es asiacute

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) foreach ($colores as $valor)

echo (El valor es $valorltbrgt)

gt

Conjuntos de datos del tipo array 139

La construccioacuten anterior recorre el array desde el principio En el ejemplo se puede ver que f oreach toma el array a recorrer y sus valores los va almacenando en la variable $ v a l o r a medida que el bucle se ejecuta Existe una segunda construccioacuten que permite recuperar el iacutendice y el valor Veashymos un ejemplo de esto

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) foreach ($ciacuteudades as $iacutendiacutece =gt $valor)

echo (El iacutendice $indice tiene el valor $valorltbrgt)

gt

La salida en el navegador nos la muestra la figura 71

Es un meacutetodo muy bueno para imprimir los valores de un array que tiene iacutendices numeacutericos y alfanumeacutericos

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia] = Paris foreach ($ciudades as $indice =gt $valor)

echo (El Iacutendice $indice tiene el valor $valorltbrgt)

gt

140 Capiacutetulo 7

Funciones para avanzar en un array

Cada vez que creamos un array dentro de un programa PHP se crea un puntero que permite recorrer en su totalidad el conjunto de valores Este puntero se inicializa al valor inicial del array La funcioacuten c u r r e n t () deshyvuelve el valor al que apunta el puntero La funcioacuten n e x t () hace avanshyzar el puntero una posicioacuten en el conjunto de datos

Si el puntero se encuentra al final del conjunto n e x t () devuelve un vashylor false El ejemplo siguiente muestra coacutemo utilizar estas funciones para recorrer un array

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia] = Paris do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

while (next($ciudades) ) gt

Podemos crear una funcioacuten que realice este traacutemite

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) Sciudades[Espantildea] = Madrid $ciudades[Portugal] = Lisboa $ciudades[Francia ] = Paris

function recorre($ciudades) do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

Jwhile (next($ciudades))

recorre($ciudades) recorre($ciudades) gt

La funcioacuten r e c o r r e () utiliza un array como paraacutemetro y va utilizando las funciones de introspeccioacuten para sacar los resultados Puesto que los valores son pasados por valor la funcioacuten r e c o r r e () crea una copia de los datos que recibe y genera el resultado de la figura 72

De esta forma no hay manera de controlar el puntero porque siempre que pase la variable $ c i u d a d e s el puntero comenzaraacute desde el principio

Conjuntos de datos del tipo array 141

La forma de arreglar esto es hacer las llamadas por referencia r e c o r r e (Sc$ciudades) r e c o r r e (amp$ciudades)

142 Capiacutetulo 7

Ahora ya no es una copia de $ c iudades lo que se pasa como paraacutemetro sino una referencia al valor real Esto hace posible tener una memoria de la situacioacuten del puntero Una vez recorrido elarray el puntero queda fijado al final del conjunto de datos Para volver al principio se puede utilizar la funcioacuten r e s e t () que enviacutea al puntero al principio La funcioacuten puede quedar asiacute

function recorre($ciudades) if (current($ciudades))

reset($ciudades)

do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

Jwhile (next($ciudades))

Ahora lo que hacemos es comprobar si el puntero estaacute al final del array si esto es asiacute se llama a la funcioacutenreset 0 y el puntero se coloca al prinshycipio

Funciones para retroceder en un array

La funcioacuten prev () retrocede una posicioacuten el puntero y la funcioacuten end () se coloca al final de una lista de valores Esto puede ser uacutetil para mostrar el contenido en sentido inverso como puede ver en la nueva funcioacuten que hemos creado

ltphp $ciudades = array (BadajozMeacuteridaCaacuteceresPlasencia) $ciudades[Espantildea] = Madrid $ciudades[Portugal ] = Lisboa $ciudades[Francia ] = Paris function recorre($ciudades)

if ( lcurrent($ciudades)) reset($ciudades)

do

$valor = current($ciudades) echo (El valor es $valorltbrgt)

jwhile (next($ciudades))

function recorre_atras($ciudades)

end($ciudades) do

$valor = current($ciudades)

Conjuntos de datos del tipo array 143

echo (El valor es $valorltbrgt) while (prev($ciudades))

recorre(amp$ciudades) recorre_atras(amp$ciudades) gt

El navegador muestra El valor es Badajoz El valor es Meacuterida El valor es Caacuteceres El valor es Plasencia El valor es Madrid El valor es Lisboa El valor es Paris El valor es Paris El valor es Lisboa El valor es Madrid El valor es Plasencia El valor es Caacuteceres El valor es Meacuterida El valor es Badajoz

Por uacuteltimo para obtener el valor del iacutendice puede utilizar la funcioacuten key() La funcioacuten r e c o r r e () la puede actualizar de la siguiente forma

function recorre($ciudades) if ( current($ciudades) )

reset($ciudades)

do

$valor = current($ciudades) $indice = key($ciudades)

echo ($indice valor $valorltbrgt)

while (next($ciudades))

Intercambio de valores

La funcioacuten a r r a y _ f l i p () intercambia los valores de iacutendices y datos es decir los iacutendices seraacuten guardados como datos y los valores seraacuten sus nueshyvos iacutendices

ltphp function recorre ($numero)

foreach ($numero as $indice =gt $valor) echo $indice $valorltbrgt -

144 Capiacutetulo 7

$numero = array(uno =gt ldos =gt 2 tres =gt 3cuatro =gt 4) echo (Nuacutemerosltbrgt ) recorre($numero) echo (Nuacutemeros intercambiadosltbrgt) recorre(array_fliacutep$numero)) gt

El resultado es el esperado

Nuacutemeros uno 1 dos 2 tres 3 cuatro 4 Nuacutemeros intercambiados 1 uno 2 dos 3 tres 4 cuatro

Puede ver el resultado en la figura 74

Inversioacuten del contenido

Tambieacuten es posible ordenar a la inversa una lista de datos Esto se consishygue con la funcioacuten a r r a y _ r e v e r s e ()

Conjuntos de datos del tipo array 1 4 5

Si modifica el coacutedigo anterior tendraacute

echo (Nuacutemeros intercambiadosltbrgt ) recorre(array^reverse($numero))

Dando como resultado

Nuacutemeros uno 1 dos 2 tres 3 cuatro 4 Nuacutemeros intercambiados cuatro 4 tres 3 dos 2 uno 1

Mezcla de los valores

Si necesita alguna vez elegir un valor aleatorio de un array la funcioacuten shu-f f le () puede ser de gran ayuda ya que mezcla todos los valores cada vez que se ejecuta Parte del coacutedigo puede ser este

echo (Nuacutemeros mezcladosltbrgt ) shuffle($numero) recorre($numero)

Pilas

Las pilas son estructuras de datos que se utilizan mucho en el mundo de la informaacutetica La filosofiacutea baacutesica de las pilas es que todos los valores deshyben introducirse en un orden especiacutefico y soacutelo podemos recuperar esos valores en el orden inverso estricto al que fueron insertados Las pilas LIFO (Last ln First Out el uacuteltimo en entrar es el primero en salir) utilizan unas funciones especiacuteficas que permiten manejar todos los datos A r r a y _ p u s h () permite insertar en la pila un dato y a r r a y _ p o p () exshytrae un valor Es necesario antes que nada definir la variable como array pues ninguna de las funciones descritas lo hace

A r r a y _ p u s h () y a r r a y _ p o p () toman como argumento la variable array y los valores a introducir

lt php $pila = array() array_push($pilaunodostres)

146 Capiacutetulo 7

array_jpush($pilacuatrocinco) while ($valor = arrayjop($pila) )

echo valor extraiacutedo es $valorltbrgt

gt

El resultado por pantalla muestra que la extraccioacuten de los valores se hace en orden inverso del que fueron introducidos

valor extraiacutedo es cinco valor extraiacutedo es cuatro valor extraiacutedo es tres valor extraiacutedo es dos valor extraiacutedo es uno

Ordenacioacuten de los valores

Finalmente PHP ofrece una gran variedad de funciones para ordenar arrays Las funciones pueden verse en la tabla siguiente

Tabla 71 Funciones de ordenacioacuten

Funcioacuten Explicacioacuten

asort() Ordena de forma ascendente el array pasado como argumento Ordena las parejas iacutendicevalor atendiendo al dato Es un buen meacutetodo para los arrays asociativos

arsort() Igual que asort () pero ordena en sentido descendente ksort() Ordena de forma ascendente el array pasado como argumento

Ordena las parejas iacutendicevalor atendiendo esta vez al iacutendice

krsort() Igual que ksort () pero ordena en sentido descendente

sort() Ordena de forma ascendente el array pasado como argumento Se pierde el valor asociativo entre el iacutendice y el valor

rsort() Igual pero en orden descendente

Puede ver actuar todas las funciones de ordenacioacuten en el ejemplo sishyguiente

ltphp function recorre ($numero)

foreach ($numero as $indice =gt $valor) echo $indice $valorltbrgt

Conjuntos de datos del tipo array 147

$pi la = array(cinco = gt5uno = gtl cuatro = gt4dos = gt2 tres = gt3) echo Array sin ordenarltbrgt recorre($pila) echo Ordenacioacuten asort()ltbrgt asort($pila) recorre($pila) echo Ordenacioacuten arsort)ltbrgt arsort($pila) recorre($pila) echo Ordenacioacuten ksort()ltbrgt ksort($pila) recorre ($pila) echo Ordenacioacuten krsort()ltbrgt krsort ($pila) -recorre($pila) echo Ordenacioacuten sort()ltbrgt sort($pila) recorre($pila) echo Ordenacioacuten rsort()ltbrgt rsort($pila) recorre($pila) gt

La figura 75 muestra todos los tipos de ordenacioacuten que puede utilizar sobre un array

148 Capiacutetulo 7

Resumen

En este capiacutetulo ha conocido el tipo de variable estrella de PHP el array Controlar los meacutetodos y las funciones para extraer la informacioacuten le daraacute ventaja en los capiacutetulos posteriores Muchas funciones que tienen que ver con el manejo de datos como funciones de bases de datos XML o generashycioacuten de plantillas devuelven un array como respuesta El tipo array es el vehiacuteculo estaacutendar para la recuperacioacuten de datos estrucshyturados como veremos en los proacuteximos capiacutetulos

En este capiacutetulo aprenderaacute a

bull Crear formularios para pasar datos entre paacuteginas

bull Utilizar las variables suacuteper-globales para recibir la informacioacuten de un formulario

bull Diferenciar entre los meacutetodos de enviacuteo GET y POST

bull Encontrar posibles errores revisando las variables suacuteper-globales

150 Capiacutetulo 8

Introduccioacuten

Hasta ahora en los capiacutetulos anteriores hemos visto coacutemo construir dishyversos programas en PHP con un limitado radio de accioacuten La verdadera potencia del lenguaje reside en la aplicacioacuten de las teacutecnicas aprendidas a traveacutes de varias paacuteginas Web pasando informacioacuten de unas a otras Como veremos maacutes adelante las dos teacutecnicas principales son el uso de formulashyrios y la utilizacioacuten de la barra de direccioacuten para pasar los valores

Argumentos GET

Los argumentos GET pasan la informacioacuten como parte de la URL Cuando utilice esta forma de trabajar las parejas de variable valor podraacuten verse en la casilla de direccioacuten del navegador Para probar esto podemos escrishybir un pequentildeo script que guardaremos como paacutegina Web

lthtmlgt ltbodygt ltphp echo Variables pasadas mediante GETltbrgt foreach ($_GET as $indice =gt $valor)

echo $indice $valor

gt ltbodygt lthtmlgt

Si ejecuta el coacutedigo anterior veraacute que uacutenicamente se imprime en pantalla el texto que muestra la orden echo En realidad esto es correcto puesto que no hemos introducido ninguna variable tipo GET a la Web Para hashycerlo debemos escribir el nombre de la paacutegina Web seguido de un siacutembolo de interrogacioacuten () y el conjunto de parejas de variable valor separadas del siacutembolo (amp)

La direccioacuten queda algo asiacute f o r m u l a r i o php v a r i a b l e l = H o l a M u n d o amp v a r i a b l e 2 = 1234 Ahora el resultado es diferente El bucle f o shyr e a c h inspecciona el array $_GET e imprime en pantalla

Variables pasadas mediante GET variablel Hola Mundo variable2 1234

El array $_GET es considerado en PHP 5 una variable suacuteper-global Este en concreto almacena todas las variables pasadas entre paacuteginas mediante

Paso de informacioacuten entre formularios 151

el meacutetodo GET Para extraer el valor de una variable pasada por este meacuteshytodo soacutelo hay que escribir $_GET [ n o m b r e _ v a r i a b l e ] en la paacutegina que recibe los datos

Advertencia

En versiones anteriores de PHP para recuperar el valor de una variable simplemente habiacutea que escribir un siacutembolo $ delante del nombre como $ n o m b r e _ v a r i a b l e Esto es porque el paraacutemeshytro register_globals del fichero de configuracioacuten php i n i estaacute en PHP 5 a off

Formularios con GET

La forma maacutes utilizada para recabar informacioacuten acerca de los usuarios es emplear formularios HTML Los formularios pueden hacerse escribiendo en un editor de texto las etiquetas HTML o utilizando alguacuten editor Web profesional como Macromedia Dreamweaver Netscape Composer o Nvu La siguiente paacutegina Web llamada f o r m u l a r i o php muestra coacutemo reshycoger informacioacuten

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt

ltpgtIntroduzca sus datos personales ltpgt ltform name=formulario method=GET action=formulario2 php gt lttable width=50 border=0 cellspacing=0 cellpadding=0gt lttrgt lttd width=24gtNombrelttdgt lttd width=76xinput name=nombre type=text id=nombrextdgt

lttrgt lttrgt lttdgtApellidoslttdgt lttdxiacutenput name=apellidos type=text id=apellidos2gtlttdgt

lttrgt lttrgt lttdgtCorreolttdgt lttdxinput name=correo type=text id= correo xtdgt

lttrgt lttrgt lttdgtEstado civil lttdgt lttdxselect name= estado id= estado gt ltoption value=SolterogtSolteroltoptiongt ltoption value=CasadogtCasadoltoptiongt

152 Capiacutetulo 8

bullcoption value=DivorciadogtDivorciadoltoptiongt ltoption value=ViudogtViudoltoptiongt

ltselectgtlttdgt lttrgt lttrgt lttdgtNampuacutemero hijos lttdgt lttdgt 0 ltinput name=hijos type=radio value=0 checkedgt

1 ltinput name=hijos type=radio value=lgt 2 ltinput name=hijos type=radio value=2gt 3 ltinput name=hijos type=radio value=3gtlttdgt

lttrgt lttrgt lttdgtGustoslttdgt lttdgt Informampaacutetica ltinput type=checkbox name=gustos []

value=Informaacuteticagt Buceo ltinput type=checkbox name=gustos [] value=Buceogt Magia ltinput type=checkbox name=gustos [ ] value=Magiagt Jazz ltinput type=checkbox name=gustos [] value=Jazzgtlttdgt

lttrgt lttrgt lttdxinput type=submit name=Submit value=Enviargtlttdgt lttdgtampnbsplttdgt

lttrgt lttablegt

ltformgt ltpgtampnbsp ltpgt ltbodygt lthtmlgt

La figura 81 muestra el aspecto en el navegador Hay varios aspectos a tener en cuenta Lo primero es que el apartado a c t i o n de la etiqueta ltFORMgt contiene la paacutegina Web a la que se enviaraacuten los datos y el apartashydo method permite seleccionar el meacutetodo de enviacuteo por ahora utilizareshymos el meacutetodo GET La paacutegina f o r m u l a r i o 2 php recoge la informacioacuten del formulario y la imprime en pantalla utilizando un bucle f o r e a c h a la variable suacuteper-global $_GET

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidosltpgt ltphp foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

gt ltbodygt lthtmlgt

Para sacar los datos hemos utilizado un bucle que busca todos los valores dentro de $__GET Otra forma de hacerlo es imprimir los datos uno a uno

154 Capiacutetulo 8

si sabemos el nombre de las variables definidas en el formulario anterior de la siguiente forma $_GET [ n o m b r e ] $_GET [ a p e l l i d o s ] $_GET [ c o r r e o ]

Existen en el formulario visto varias teacutecnicas de recogida de informacioacuten Los cuadros de texto que permiten escribir valores alfanumeacutericos lista de seleccioacuten y botones de opcioacuten es donde podemos elegir una de las opciones existentes y casillas de verificacioacuten que permiten elegir 0 o maacutes opciones existentes Todas estas partes del formulario tienen una variable asociada que puede buscarse en $_GET

El uacutenico meacutetodo que puede plantear alguacuten problema es el que utiliza cashysillas de verificacioacuten Puesto que podemos elegir varias opciones eacutestas son enviadas como un array y deben recuperarse atendiendo a esta razoacuten

Advertencia

Para que los valores de las casillas de verificacioacuten sean enviados como array hay que declararlas en el formulario como tal escrishybiendo dos siacutembolos de corchetes en la propiedad ntildeame asociada a las casillas por ejemplo lt i n p u t t y p e = c h e c k b o x n a m e = g u s t o s [] v a l u e = I n f o r m aacute t i c a gt

La paacutegina f o r m u l a r i o 2 php queda de esta forma para que pueda recishybir los gustos de los usuarios

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidos ltpgt ltphp foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

echo ltbrgtGUSTOSltbrgt $gustos = $_GET[gustos] foreach ($gustos as $indice =gt $valor)

echo $indice $valorltbrgt gt ltbodygt lthtmlgt

La figura 83 muestra la mejora incluida en el programa Ahora es capaz de recuperar los gustos de los usuarios e imprimirlos en pantalla Para esto

Paso de informacioacuten entre formularios 155

hemos antildeadido un bucle nuevo que inspecciona los valores enviados al array $gustos

Paso de informacioacuten con GET

Si se fija en la barra de direccioacuten de los navegadores cuando visita paacutegishynas Web sobre noticias o carritos de la compra en la URL van aparecienshydo variables que tienen que ver con los distintos menuacutes que existen en la Web

El siguiente ejemplo muestra una pequentildea revista digital escrita en pocas liacuteneas y en una sola paacutegina Web que cambia sus noticias eligiendo las disshytintas opciones del menuacute

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitIacuteonalEN

httpwwww3orgTRhtml4loosedtdgt lthtmlgt ltbodygt ltphp $menu = array (1 =gt Editorial 2 =gt Opinioacuten 3 =gt Regional 4 =gt Nacional) echo (--Revista Digital --ltbrxbrgt) echo (--MENU--ltbrgt ) foreach ($menu as $indice =gt $valor)

echo (lta href = Iacutendexphpmenu=$indicegt$valorltaxbrgt)

156 Capiacutetulo 8

j

echo ( ltbrgt--NOTICIAS--ltbrgt) switch ($_GET[menuacute])

case 1 echo (Editorial) break

case 2 echo (Opinioacuten) break

case 3 echo (Regional) break

case 4 echo (Nacional) break

default echo (Noticias de Portada) break

gt ltbodygt lthtmlgt

El array $menu se carga de los distintos valores que podemos ir seleccioshynando

En la actualidad estos valores se suelen extraer de una base de datos

Para mostrar el menuacute se hace un bucle donde se extraen todos los valores e iacutendices del array y se ponen como valores en los enlaces

echo (lta href=Iacutendexphpmenu=$indicegt$valorltaxbrgt)

Los enlaces siempre se dirigen a la paacutegina principal pero con un valor distinto en la variable menuacute

La segunda parte de la Web es una eleccioacuten muacuteltiple mediante la estrucshytura s w i t c h donde en funcioacuten del valor de la variable menuacute pasada por GET se eligen unas noticias vi otras

Puede ver el resultado en la figura 84

echo (lta href=Iacutendexphpmenu=$indicegt$valorltaxbrgt)

Los enlaces siempre se dirigen a la paacutegina principal pero con un valor distinto en la variable menuacute

La segunda parte de la Web es una eleccioacuten muacuteltiple mediante la estrucshytura s w i t c h donde en funcioacuten del valor de la variable menuacute pasada por GET se eligen unas noticias u otras

Puede ver el resultado en la figura 84

Argumentos POST

La utilizacioacuten del meacutetodo GET es totalmente inseguro porque no hay forshyma de ocultar datos privados en la direccioacuten Web tales como la contraseshyntildea de entrada o el nuacutemero de cuenta bancaria

El meacutetodo POST arregla estos problemas siendo el preferido de los desa-rrolladores Este meacutetodo es tan sencillo como cambiar en el formulario el meacutetodo de enviacuteo de datos

ltpgtIntroduzca sus datos personalesltpgt ltform name=formulario method=POST action=formulario2 php gt

lttable width=50 border=0 cellspacing=0 cellpadding=0gt

En cuanto a la recuperacioacuten de los datos tambieacuten debe cambiar el nombre de la variable suacuteper-global $_GET por $_POST de esta manera

ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtmlgt ltbodygt ltpgtDatos introducidosltpgt ltphp foreach ($_POST as $indice =gt $valor)

echo $indice $valorltbrgt

e c h o ltbrgtGUSTOSltbrgt $ g u s t o s = $ _ P O S T [ g u s t o s ]

158 Capiacutetulo 8

foreach ($gustos as $indice =gt $valor) echo $indice $valorltbrgt

gt ltbodygt lthtmlgt

Variables suacuteper-globales

Desde PHP 4 se vienen utilizando los arrays suacuteper-globales para almaceshynar los valores que pasan de unas paacuteginas a otras se almacenan en el orshydenador del usuario o en el servidor En PHP 5 el uso de estas variables se hace obligatorio para recuperar todos los valores Las variables a utilizar son

bull $_GET Almacena las variables que se pasan desde un formulario meshydiante el meacutetodo GET

bull $_POST Almacena las variables pasadas por POST

bull $_COOKIE Guarda los valores que estaacuten almacenados en cookies Ya veremos en capiacutetulos sucesivos coacutemo utilizarlo

bull $_SESSlON bull Guarda las variables que se pasan entre sesiones

bull $_SERVER Contiene numerosos valores relativos al servidor

bull $_FILES Los archivos que enviemos a traveacutes de un formulario seshyraacuten recogidos en este array

Una equivocacioacuten en el nombre de una variable puede llevarle a dar vuelshytas sobre el coacutedigo hasta encontrar el error Por eso es necesario conocer el contenido de las variables suacuteper-globales asiacute podraacute averiguar si estaacute pasando los datos correctamente La funcioacuten siguiente se puede utilizar cada vez que le surja un error de este tipo La funcioacuten muestra todos los valores de los arrays suacuteper-globales

ltphp function depuracioacuten() echo --Variables GET--ltbrgt foreach ($_GET as $indice =gt $valor)

echo $indice $valorltbrgt

echo --Variables POST--ltbrgt foreach ($_POST as $indice =gt $valor)

echo $indice $valorltbrgt

echo --Variables COOKIES--ltbrgt

Paso de informacioacuten entre formularios 159

foreach ($_COOKIE as $indice =gt $valor) echo $iacutendiacutece $valorltbrgt

echo --Variables SESSION--ltbrgt foreach ($_SESSION as $indice =gt $valor)

echo $iacutendiacutece $valorltbrgt

echo --Variables SERVER-~ltbrgt foreach ($_SERVER as $indice =gt $valor)

echo $indice $valorltbrgt

depuracioacuten () gt

La figura 85 muestra los valores de todas las variables suacuteper-globales

Resumen

Hasta ahora soacutelo habiacuteamos tenido la oportunidad de crear programas en PHP que realizaran tareas en una uacutenica paacutegina Web

Este capiacutetulo ha dado una visioacuten praacutectica de coacutemo utilizar los conceptos aprendidos para escribir programas distribuidos en varias paacuteginas

160 Capiacutetulo 8

Aunque no ha aprendido ninguna funcioacuten nueva ha descubierto el vershydadero secreto del disentildeo de una Web dinaacutemica el paso de variables

Si viene de otras versiones de PHP tendraacute que tener en cuenta que la forshyma de recuperar las variables es a partir de la versioacuten 43 a traveacutes de las variables suacuteper-globales

En este capiacutetulo aprenderaacute a

bull Diferenciar entre clase y objeto bull Crear clases que hereden de otras clases bull Utilizar los modificadores pr iacutevate protected ypubl ic

bull Crear meacutetodos estaacuteticos y finales bull Guardar el estado de un objeto mediante la sentildealizacioacuten bull Recuperar informacioacuten referente a las clases meacutetodos y propiedades

162 Capiacutetulo 9

Introduccioacuten

PHP comenzoacute su andadura como un simple lenguaje de scripts A medishyda que las versiones avanzaban se fueron incluyendo algunas caracteshyriacutesticas que permitiacutean programar con orientacioacuten a objetos Con la aparicioacuten de PHP 5 los desabolladores tenemos una verdadera platashyforma de programacioacuten orientada a objetos gracias a la potencia del nuevo engine Zend 20 que permite ejecutar maacutes raacutepido y eficientemenshyte este tipo de programas

La programacioacuten orientada a objetos utiliza los elementos c l a s e y o b shyj e t o con punto de inicio Actualmente en las carreras teacutecnicas es posishyble encontrar ensentildeanzas sobre lenguajes orientados a objetos como Java o C++

Nota

En realidad Java y C++ son considerados como seudo lenguajes orientados a objetos Un ejemplo de lenguaje puro es SmallTalk o su versioacuten graacutefica Squeak (httpsqueaklinexorg) con muchos antildeos de antiguumledad

La programacioacuten orientada a objetos en PHP 5 no necesita una sintaxis muy diferente sino que es una aproximacioacuten a la realidad en otro camino diferente al acostumbrado Por ejemplo si piensa en un programa que tenga que averiguar la letra del DNI de un cliente lo normal es que cree una funcioacuten con un paraacutemetro al que le pase el nuacutemero de DNI y le deshyvuelva la letra buscada

Un desarrollo orientado a objetos pensariacutea en cada problema como una idenshytidad uacutenica como un objeto Puesto que el DNI siempre va asociado a una persona puede crear un objeto que identifique a personas y dentro de ese objeto programar una funcioacuten (meacutetodo en este caso) que calcule la letra La aproximacioacuten procedural (crear una funcioacuten) no asocia esa funcioacuten a persoshynas directamente y le podriacutea pasar cualquier nuacutemero entero recibiendo una respuesta vaacutelida En cambio la aproximacioacuten de objetos crea la funcioacuten dentro del objeto c l i e n t e y soacutelo permite mediante teacutecnicas que veremos maacutes adelante recuperar la letra del DNI de una persona

La programacioacuten orientada a objetos desarrolla nuevos conceptos y termishynologiacuteas que deben aprenderse correctamente para generar buen coacutedigo

Programacioacuten orientada a objetos 163

Definicioacuten de clases

Una clase es un tipo de dato que contiene en una misma estructura vashyriables y funciones Una clase es una especie de plantilla desde la que los objetos son instanciados y toman su valor Desde una clase se pueden consshytruir varios objetos del mismo tipo La definicioacuten es la siguiente

class pagina_Web

var $titulo function getTitulo()

return $this-gttitulo

Mediante la palabra reservada c l a s s definimos una clase completa Utishylizando va r podemos definir las variables que utilizaremos en el desarroshyllo del programa La palabra reservada va r desapareceraacute en versiones siguientes de PHP a favor de las palabras publ ic p r iacute v a t e y p r o t e c -ted Las funciones se definen como en el capiacutetulo 5 siempre que esteacuten dentro de la construccioacuten de la clase En este capiacutetulo vamos a definir una clase completa cuya misioacuten seraacute mostrar una paacutegina Web Podemos seshyguir con el ejemplo ampliando las funciones

ltphp class pagina_Web

var $titulo function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

function getTitulo() return $this-gttitulo

function cabecera() echo (lthtmlxheadxtitlegt) echo $this-gttitulo echo ( lttitlexheadxbodygt) bull

function cuerpo() echo(Este es el cuerpo de la paacutegina Web)

164 Capiacutetulo 9

function pie ( )

echo (ltbodyxhtmlgt)

function mostrar_pagina()

echo $thiacutes-gtcabecera () echo $this-gtcuerpo()

echo $this-gtpie()

Como puede ver la clase se divide en varias funciones y en una sola vashyriable La variable $ ti t u l o guardaraacute el tiacutetulo deacute la paacutegina Web Las funshyciones c a b e c e r a ( ) c u e r p o () y p i e () son las encargadas de mostrar las distintas partes de una Web

Estas funciones se llaman desde la f u n c i oacute n m o s t r a r _ p a g i n a ( ) Es inteshyresante observar que en unas pocas liacuteneas de coacutedigo hemos definido un objeto que podriacutea utilizarse como base de muchas aplicaciones El operador $ t h i s es una variable que contiene el objeto actual desde el que la invocamos Para acceder dentro de un objeto a funciones o variashybles propias debe anteponerse al nombre de eacutestas la expresioacuten $ t h i s - gt Para acceder desde la funcioacuten m o s t r a r _ p a g i n a () a cualquiera de las funciones de la clase tendraacute que escribir

$this-gtcabecera () $this-gtcuerpo ( ) $this-gtpie ()

Instancia de clase

Para que el coacutedigo funcione necesita crear el objeto Esto se hace utilizanshydo el operador new seguido del nombre de la clase

$ p a g i n a = new p a g i n a _ W e b ( )

Con el coacutedigo anterior hemos creado un objeto que contiene todas las vashyriables y funciones de la clase pag ina_Web ( ) La variable que contiene ese objeto es $pag ina

Para acceder a las funciones desde el nuevo objeto creado tenemos que utilizar la variable que contiene al objeto en este caso $ p a g i n a seguido del operador - gt y el nombre de la funcioacuten Para mostrar la Web tenemos que seguir estos sencillos pasos

$ p a g i n a = new p a g i n a _ W e b ( )

Programacioacuten orientada a objetos 165

$pagina-gtsetTitulo(Paacutegina Web nueva) $pagina- gtmostrar__pagina ( )

Funcioacuten constructor

Existen algunas funciones especiales en la definicioacuten de una clase La maacutes importante es el constructor Esta se ejecuta cada vez que se crea un nueshyvo objeto y permite crear las variables iniciales que se necesitan como el tiacutetulo de la Web o el autor El nombre de la funcioacuten debe ser c o n s -t r u c t () Nuestro constructor se encargaraacute de crear el tiacutetulo de la paacutegina Web que estamos creando

funct ion c o n s t r u c t ( $ t i t u l o )

$this-gtsetTitulo($titulo)

Herencia

La programacioacuten orientada a objetos permite heredar de otras clases Con esta teacutecnica puede ahorrar mucho tiempo de trabajo La clase hija (clase que hereda de otra) adquiere estas propiedades

bull Automaacuteticamente obtiene todas las variables miembro de la clase padre

bull Tambieacuten obtiene todas las funciones miembro de la clase padre que funcionaraacuten exactamente de la misma forma

bull La clase hija puede a su vez definir nuevas variables y funciones

La sintaxis es la siguiente

class pagina_Web_formulario extends pagina_Web

function formulario_inicio() Escribir el coacutedigo necesario

La palabra reservada e x t e n d s indica que la nueva clase creada seraacute una extensioacuten (heredaraacute) de la clase que se escribe justo a la derecha de la deshyfinicioacuten Puede crear un objeto formulario a partir de la clase pagina_Web de la siguiente forma

class pagina_Web_formulario extends pagina_Web

166 Capiacutetulo 9

function formulariacuteo_inicio($accion)

echo (ltform action=$acciongt)

function formulario_fin() echo (ltformgt)

function formulario_caj a_texto($nombre) echo ($nombre ltinput type=text name=$nombregt)

function formulario_boton() echo (ltinput type=submit name=Submit

valuacutee = Enviargt )

function mostrar_pagina () $this-gtcabecera () $this- gtf ormulario__inicio ( Iacutendex php) $this- gtf ormulario__caj a_texto (Nombre) $this-gtformulario_boton() $this-gtformulario_fin()

$this- gtpie ()

Si ahora ejecuta el coacutedigo instanciando la clase que hemos creado puede ver que las funciones c a b e c e r a () p i e ( ) incluso el constructor pueshyden ser utilizadas auacuten no perteneciendo a la clase p a g i n a _ W e b _ f o r -m u l a r i o

$formulario = new pagina_Web_formularioPagina con f o r m u l a r i o ) $formular io-gtmostrar_pagina ( )

La figura 91 muestra la ejecucioacuten del objeto anterior

Meacutetodos o funciones de objeto

Cuando definimos una clase hija las funciones de la clase padre son autoshymaacuteticamente heredadas Se llama redefinicioacuten de meacutetodos a la creacioacuten de funciones en la clase hija con el mismo nombre que en la clase padre En el ejemplo anterior la funcioacuten m o s t r a r _ p a g i n a ( ) de la clase pag ina_Web_f o r m u l a r i o estaacute redefinida ya que existe una funcioacuten con

Programacioacuten orientada a objetos 167

el mismo nombre en la clase pag ina_Web Al instanciar el objeto y ejecushytar el meacutetodo m o s t r a r _ p a g i n a ( ) el meacutetodo que se ha definido es la clase hija

PHP 5 con su nuevo motor Zend Engine 2 introduce la palabra reservashyda f i n a l

Si en la clase padre ponemos delante de cualquier funcioacuten la palabra f i n a l eacutesta funcioacuten no podraacute ser sobrecargada en las clases que la heshyreden

Tambieacuten podemos declarar clases completas como f i n a l lo que signifishycaraacute que no podraacuten ser heredadas

final function mostrar_pagina()

echo $this-gtcabecera() echo $this-gtcuerpo()

echo $this-gtpie()

Si definimos la funcioacuten anterior como f i n a l en la clase pag ina_Web la clase p a g i n a _ W e b _ f o r m u l a r i o no podraacute tener una funcioacuten con este mismo nombre y mostraraacute un error en pantalla La figura 92 muestra el error que se produce al intentar sobrecargar un meacutetodo que estaacute marcado como f i n a l

Herencia encadenada

Algunos lenguajes de programacioacuten permiten heredar de varias clases a la vez esto es conocido como herencia muacuteltiple PHP 5 no permite herenshycia muacuteltiple pero siacute herencia encadenada es decir permite heredar de varias clases padres correlativamente Un ejemplo es

class A

class B extends A

class C extends B

class D extends C

Valores y alcance de variables

En versiones anteriores de PHP los objetos eran pasados por valor a otras funciones por lo tanto el estado de los objetos no se conservaba En PHP 5 los objetos son pasados por defecto por referencia gracias al Zend Engine 2

ltphp

Programacioacuten orientada a objetos 169

class Nombre

i var $nombre function setNombre($nombre)

$this-gtnombre = $nombre

function getNombre() return $this-gtnombre

function cambiaNombre($obj eto$nombre)

$objeto-gtsetNombre($nombre)

$luis = new Nombre $luis-gtsetNombre(Luis Miguel) echo El nombre del objeto es $luis-gtgetNombre() ltbrgt cambiaNombre($luisPedro) eche El nombre del objeto es $luis-gtgetNombre() ltbrgt gt

El coacutedigo muestra coacutemo cambiar las propiedades de un objeto desde una funcioacuten con PHP 5 El resultado en el navegador puede comprobarlo en la figura 93

170 Capiacutetulo 9

Dentro de los objetos debe tener tambieacuten cuidado con el alcance de las variables Las variables definidas fuera del entorno del objeto no son acshycesibles desde los meacutetodos de las clases a menos que anteponga la palashybra g l o b a l

Miembros puacuteblicos privados y protegidos

Mientras no se especifique otra cosa los meacutetodos y propiedades de una clase son siempre puacuteblicos es decir son accesibles desde fuera del objeto de la forma o b j e t o - gtf u n c i oacute n Pero existe un camino para que las vashyriables y los meacutetodos no puedan ser accedidos desde fuera del objeto Eche un vistazo ahora al objetopagina_Web Su variable $ t i t u l o es puacuteblico porque no lo hemos definido de alguna forma especial Para cambiar el valor de esta variable podriacutea utilizar la funcioacuten asociada o directamente haciendo $ o b j e t o - gt t i t u l o = nuevo v a l o r Esta forma de actuar rompe con la filosofiacutea de la programacioacuten orientada a objetos Como norshyma general las propiedades de los objetos deben estar ocultas al entorno exterior y tomar sus valores desde funciones definidas dentro del objeto

Meacutetodos privados

Si declaramos un meacutetodo o propiedad como privada soacutelo se podraacute acceshyder a eacutel desde la clase que lo define Las clases que hereden de una clase con meacutetodos privados no tendraacuten acceso a eacutestos meacutetodos y tampoco seraacute posible desde fuera del objeto hacer llamadas Para hacer un meacutetodo o propiedad privado soacutelo hay que anteponer la palabra p r iacute v a t e delante de la declaracioacuten

class pagina_Web

priacutevate $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

priacutevate function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

De esta manera la clase p a g i n a _ W e b _ f o r m u l a r i o que hereda de pagina_Web no puede acceder directamente a la funcioacuten s e t T i t u l o ()

Programacioacuten orientada a objetos 171

de la siguiente forma $ t h i s - gt s e t T i t u l o ( T i t u l o n u e v o ) porque obtenemos un error de acceso ilegal Despueacutes de esta modificacioacuten soacutelo es posible dar un tiacutetulo a la paacutegina Web a traveacutes del constructor que como siacute estaacute dentro de la clase tiene potestad para utilizarla

Meacutetodos protegidos

Los meacutetodos protegidos son menos restrictivos que los privados Cuando declaramos un meacutetodo como protegido su visibilidad es en la clase que lo declara y en todas las clases que lo heredan El ejemplo anterior puede modificarse de la siguiente forma

c l a s s pagina_Web

protected $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

protected function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

Meacutetodos puacuteblicos Por defecto todos los meacutetodos y propiedades que se declaren en un objeshyto son puacuteblicos a menos que lleven asociados la palabra p r o t e c t e d o p r iacute v a t e Como buena praacutectica de programacioacuten las variables deben deshyfinirse como privadas o protegidas para que no puedan modificarse desshyde fuera del objeto Ademaacutes deben llevar dos meacutetodos puacuteblicos asociados s e t V a r i a b l e () para dar un nuevo valor a la variable y g e t V a r i a b l e () para recibir el valor actual de la propiedad Veamos el ejemplo

class pagina_Web

private $titulo function construct($titulo)

$this-gtsetTitulo($titulo)

public function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

172 Capiacutetulo 9

public function getTitulo()

return $this-gttitulo

Interfaces

En proyectos profesionales a veces es necesario que un equipo de varias personas trabajen juntas En este caso se hace imprescindible definir unas pautas generales de trabajo para que el resultado final sea el esperado Si el desarrollo consiste en programar varios objetos el analista de la aplicashycioacuten puede definir la estructura baacutesica en papel o crear una pequentildea planshytilla con meacutetodos que el objeto final deberiacutea tener obligatoriamente Esta plantilla es un i n t e r f a c e y permite definir una clase con funciones deshyfinidas pero sin desarrollar que obliga a todas las clases que lo imple-menten a declarar estos meacutetodos como miacutenimo

i n t e r f a c e Web

public function setTitulo($titulo = Titulo por defecto)

public function getTitulo()

La interface anterior define la estructura baacutesica que queremos para el obshyjeto declarando las funciones setTitulo y getTitulo Para que una clase haga uso de la i n t e r f a c e se declara de la siguiente forma

class pagina_Web implements Web

Clases abstractas

Un i n t e r f a c e no permite crear el cuerpo de ninguna funcioacuten dejando esta tarea a las clases que la implementen Las clases abstractas permiten definir funciones que deben implementarse obligatoriamente en los objetos que hereden y ademaacutes permiten definir funciones completas que pueden heredarse Las clases abstractas deben llevar la palabra rese rvadaabs t rac t en la declaracioacuten de la clase y en todos los meacutetodos que soacutelo definan su nombre

abstract class Web

protected $titulo

Programacioacuten orientada a objetos 173

public function setTitulo($titulo = Titulo por defecto)

$this-gttitulo = $titulo

a b s t r a c t pub l i c funct ion g e t T i t u l o ( )

En lugar de un i n t e r f a c e hemos optado por utilizar una clase abstracshyta porque tenemos claro que el meacutetodo s e t T i t u l o () tiene que funcioshynar asiacute Tambieacuten se define el meacutetodo abstracto g e t T i t u l o () que obligatoriamente debe ser declarado en la clase que herede de eacutesta En realidad un i n t e r f a c e es una clase que tiene todos sus meacutetodos absshytractos

Clases con meacutetodos estaacuteticos

En PHP 5 puede declarar funciones dentro de una clase que no utilicen propiedades o meacutetodos de la misma Estos meacutetodos pueden calcular valoshyres numeacutericos hacer una conexioacuten a una base de datos o comprobar que un correo electroacutenico esteacute bien definido Aunque no existe ninguna palashybra reservada para definirlo son conocidos como meacutetodos estaacuteticos y pueshyden ser utilizados sin necesidad de instanciar un objeto

ltphp class Nombre

protected $nombre public function getNombre(

return $this-gtnombre

public function setNombre($nombre)

$this-gtnombre = $nombre

public function NombreDefecto()

return Luis Miguelltbrgt

$luis = new Nombre echo $luis-gtNombreDefecto() Tambieacuten se puede acceder al nombre por defecto echo NombreNombreDefecto() gt

174 Capiacutetulo 9

Para acceder a un meacutetodo estaacutetico desde el cuerpo del programa se escrishybe el nombre de la clase que lo implementa seguido del operador ( ) y el nombre del meacutetodo En el ejemplo vemos que se puede acceder al meacutetoshydo NombreDef e c t o () creando un objeto o mediante la construccioacuten Nombre NombreDef e c t o Si intenta llamar a un meacutetodo que no es estaacutetico de esta forma se imprimiraacute un error en pantalla La figura 94 muestra el error que recibe si intenta llamar a un meacutetodo no estaacutetico desshyde fuera de un objeto

Llamadas a funciones padre

El operador ( ) se puede utilizar tambieacuten dentro de una clase para hacer llamadas a funciones de la clase padre que esteacuten sobrecargadas Si define un constructor para la clase padre y otro para la clase hijo cuando cree el objeto el constructor que se ejecuta es el de nivel infeshyrior el constructor hijo Para llamar al constructor padre debe utilizarshyse la nomenclatura N o m b r e _ c l a s e _ p a d r e c o n s t r u c t ()

ltphp class Nombre

protected $nombre

Programacioacuten orientada a objetos 175

f unet ion construct ( $nombre)

$this-gtnombre = $nombre

publie function getNombre() return $this-gtnombre

publie function setNombre($nombre) $this-gtnombre = $nombre

publie function NombreDefecto() return Luis Miguelltbrgt

class Apellido extends Nombre

protected $apellidos function construct($nombre$apellidos)

$this-gtapellidos = $apellidos Nombre construct(Snombre)

publie function getApellidos () return $this-gtapellidos

$luis = new Apellido(Luis MiguelCabezas Granado) echo $luis-gtgetNombre() ltbrgt echo $luis-gtgetApellidos() gt

Puede ver que el constructor de la clase Ape l l ido inicializa la variable $ape-11 idos y seguidamente llama al constructor de la clase padre Nombre Esta forma de actuar puede resultar complicada si no conoce el nombre de la clase padre La solucioacuten a este pequentildeo inconveniente la tenemos en la palabra parent que hace alusioacuten a la clase de la que heredamos El coacutedigo anterior puede quedar de esta forma

class Apellido extends Nombre

protected $apellidos function construct($nombre$apellidos)

$this-gtapellidos = $apellidos

176 Capiacutetulo 9

p a r e n t cons t ruc t ($nombre) public function getApellidos()

return $this-gtapellidos

Sobrecarga de meacutetodos

Algunos lenguajes de programacioacuten orientados a objetos permiten declashyrar maacutes de un meacutetodo con el mismo nombre La definicioacuten de estos meacutetoshydos variacutea en el nuacutemero de paraacutemetros o en los tipos de datos de los argumentos PHP 5 no permite sobrecarga de meacutetodos pero puede simushylar esta actuacioacuten empleando la teacutecnica de las funciones con un nuacutemero variable de paraacutemetros El constructor de la clase A p e l l i d o puede queshydar de la siguiente forma

class Apellido extends Nombre

protected $apellidos function construct($nombre)

if (func_num_args()= = 2 ) $apellidos = func_get_arg(1) $this-gtnombre = $nombre $this-gtapellidos = $apellidos parent construct($nombre)

else $this-gtnombre = $nombre $this-gtapellidos = $apellidos parent construct($nombre)

public function getApellidos()

return $this-gtapellidos

Sentildealizacioacuten

Los objetos son en realidad un conjunto de datos y funciones que guarshydan una serie de estados de ejecucioacuten Este conjunto de bits se pueden al-

Programacioacuten orientada a objetos 177

macenar en un momento dado y recuperar justo en el mismo estado en el que se encontraba cuando lo guardamos Esta teacutecnica se llama sentildealizashycioacuten y permite almacenar y recuperar el conjunto de bits que forman un objeto

PHP 5 ofrece dos funciones s e r i a l i ze () y u n s e r i a l i z e ( ) que toshyman como paraacutemetro un objeto y devuelven una cadena de caracteres Los objetos serializados los podemos almacenar en base de datos ficheros etshyceacutetera

$luis = new Apellido(Luis Miguel) echo $luis-gtgetNombre() ltbrgt echo $luis- gtgetApellidos () -$manuel = serialize($luis) $pedro = unserialize($manuel) echo $pedro-gtgetNombre ()

El coacutedigo anterior crea el objeto $ l u i s y utiliza los meacutetodos propios de la clase y los heredados Despueacutes utilizamos la funcioacuten s e r i a l i z e () para grabar el estado del objeto como un conjunto de caracteres en la variable $manuel La variable $pedro contiene el resultado de aplicar u n s e r i a shyl i z e () a $manuel

De esta forma conseguimos recuperar el objeto $ l u i s con los datos que ya habiacuteamos almacenado

Funciones de manejo de clases

Las funciones siguientes son uacutetiles para recuperar informacioacuten sobre la herencia de las clases sobre meacutetodos o variables miembro o llamadas a las funciones

Tabla 91 Funciones de clases

Funcioacuten Descricioacuten

ge t c l a s s () Devuelve el nombre de la clase que iexclmplementa el objeto pasado como paraacutemetro

g e t _ p a r e n t _ c l a s s 0 Devuelve el nombre de la clase padre

c l a s s _ e x iacute s t ( ) Si el paraacutemetro es el nombre de una clase devuelve un true

g e t _ d e c l a r e d _ c l a s s () Devuelve un array con el nombre de todas las clases definidas en el coacutedigo actual

178 Capiacutetulo 9

Funcioacuten Descricioacuten

i s _ s u b c l a s s _ o f () Toma dos paraacutemetros Si el primer paraacutemetro es una subclase del segundo paraacutemetro la funcioacuten devuelve un true

i s _ a ( ) g e t _ c l a s s _ v a r s ( ) Devuelve un array con parejas variable valor de una clase que tengan valores por

defecto

g e t _ o b j e c t _ v a r s () Devuelve un array con parejas variable valor de un objeto que tengan valores por defecto

method_ex is ts () Toma dos paraacutemetros Si el objeto pasado tiene un meacutetodo con el nombre del segundo paraacutemetro la funcioacuten devuelve true

ge t_c lass_method () Devuelve un array de meacutetodos definidos en una clase

Puede ver el funcionamiento de la funcioacuten g e t _ c l a s s () en el ejemplo siguiente y el resultado en la figura 95

$luis = new Nombre echo $luis-gtNombreDefecto() echo La variable $luis es un objeto del tipo get_class($luis)

Programacioacuten orientada a objetos 179

Resumen

Existe en el mundo de los desabolladores de PHP una antigua disputa sobre la mejor forma de afrontar un proyecto Web Unos opinan que la forma maacutes raacutepida de crear una Web es realizar funciones separadas en ficheros y desde las paacuteginas del proyecto hacer las llamadas necesarias

La otra vertiente opina que merece la pena dedicar un poco maacutes de tiemshypo al desarrollo de objetos porque despueacutes redundaraacute en un gran benefishycio en futuros programas En realidad depende del proyecto Si soacutelo necesita crear un formulario para recibir datos de un usuario quizaacute no merezca la pena crear un objeto y siacute algunas funciones de control Si su proyecto va a ser muy extenso la recomendacioacuten es que prepare un comshypendio de objetos que se interrelacionen para llevar a buen teacutermino el programa

Puesto que el libro versa sobre PHP 5 y sus mejoras con respecto a las vershysiones anteriores intentaremos en los capiacutetulos siguientes realizar la mashyyoriacutea de los ejemplos en metodologiacutea orientada a objetos

En este capiacutetulo aprenderaacute a

bull Abrir y cerrar ficheros de lectura y escritura

bull Utilizar funciones para leer el contenido de un fichero

bull Realizar programas para la escritura de informacioacuten en un fichero

bull Gestionar los ficheros y directorios de un sistema operativo

bull Crear ficheros de configuracioacuten

bull Generar cabeceras para la descarga de archivos

182 Capiacutetulo 10

Introduccioacuten

Antes de que la proliferacioacuten de los gestores de bases de datos se hiciera efectiva los lenguajes de programacioacuten utilizaban el acceso a ficheros para almacenar sus datos Asiacute los lenguajes COBOL Pascal o incluso C comenshyzaron a utilizar el manejo de archivos en aquellos programas que necesishytaban guardar datos para recuperarlos posteriormente

Actualmente la informacioacuten puede almacenarse en ficheros o en bases de datos Los ficheros pueden almacenar textos que pueden ser leiacutedos faacutecilshymente por nosotros y por un ordenador Ademaacutes existe una serie de utishyl idades que permiten al sistema operat ivo (gnuLinux o MacOSX) interactuar con ellos hacer buacutesquedas etceacutetera

Nota

El sistema operativo Windows tiene algunas restricciones con resshypecto al manejo de ficheros y no se recomienda para gestionar los archivos

Funciones de lectura y escritura de ficheros

Existen en PHP 5 un conjunto muy numeroso de funciones que permishyten manejar ficheros de diferentes formas La idea baacutesica para trabajar con ficheros es la siguiente

bull Abrir el fichero para su lectura escritura

bull Leer el fichero

bull Cerrar el fichero (puede hacerse maacutes tarde)

bull Realizar las operaciones necesarias en el contenido

bull Escribir los datos

Abrir el fichero

La funcioacuten f open () asigna a una variable un puntero (un descriptor) al fichero que quiera abrir La variable puede utilizarse despueacutes para hacer cualquier tipo de operacioacuten Si el fichero que intenta abrir no existe o no puede utilizarse en ese momento f open () devolveraacute un valor false

Ficheros y almacenamiento de datos 183

Los ficheros pueden abrirse en varios modos tal y como indica la tabla 101

Tabla 101 Modos de apertura de los ficheros

Modo Explicacioacuten

Soacutelo lectura (r) Soacutelo permite leer el fichero Si intenta hacer otra cosa le saldraacute un error

Lectura y escritura si existe el Permite leer y escribir un fichero que exis-fichero (r+) ta El contenido del fichero no se borra

sino que se escribe a continuacioacuten Soacutelo escritura (w) Soacutelo se puede escribir Sobrescribe cualshy

quier fichero afectado Escritura y lectura (w+) Si el fichero no existe intenta crearlo Escritura al final (a) Escribe siempre al final del fichero tanto si

existe como si no Lectura y escritura al final (a+) Escribe al final del fichero y permite leer

Desde la versioacuten 4 de PHP puede abrir ficheros remotos que esteacuten almashycenados en servidores Asiacute podraacute utilizar el protocolo HTTP o FTP para recuperar datos remotamente Puede ver como ejemplo varias formas de abrir un fichero con f open ()

ltphp Los ficheros HTTP solo pueden abrirse de lectura $descriptor = fopen(httpwwwluisyfernandanet noticiastxtr) FTP permite abrir ficheros de lectura y escritura $descriptor2 = fopen(ftp usuariocontrasentildealuisyfernandanetnoticiastxtr) Apertura normal de un fichero guardado en el ordenador local $descriptor3 = fopen(noticiastxt a+) gt

Lectura de ficheros

f r e a d () tiene como paraacutemetro un descriptor de fichero devuelto por la funcioacuten f o p e n () y el tamantildeo del bloque de datos que queremos leer

$variable = fread($descriptor 4000)

Normalmente no conoceraacute el tamantildeo del fichero y por lo tanto debe utishylizar alguna teacutecnica para leerlo correctamente Lo maacutes sencillo es apoyar-

184 Capiacutetulo 10

se en la funcioacuten f i l e s i z e () que devuelve el tamantildeo en bytes del fichero que pase como argumento Asiacute la lectura anterior quedariacutea

$variable = fread($descriptor filesize(noticiastxt))

Advertencia

Tiene que notar que el lector f i l e s i z e () no toma como paraacuteshymetro el descriptor devuelto por la funcioacuten f o p e n O sino el nombre del fichero que estamos tratando

La funcioacuten anterior devuelve un bloque completo de caracteres leiacutedos desde un fichero y puede hacerse poco manejable cuando intente buscar alguacuten dato especiacutefico PHP 5 posee algunas funciones para leer liacutenea a liacuteshynea desde un fichero f r e a d () tiene como paraacutemetros el descriptor del fichero y un bloque maacuteximo de caracteres a leer La utilizacioacuten praacutectica es la siguiente

ltphp $descriptor = fopen (librotxta +) $linea_numero = 1 while (feof($descriptor))

$linea = fgets ($descriptor4096) echo liacutenea nuacutemero $numero_linea es $linea $linea_numero++

f c l o s e ($desc r ip to r ) gt

El bucle actuacutea hasta que la funcioacuten f e o f () encuentra el final del fichero apuntado por el descriptor Mientras que no sea el fin del fichero la funshycioacuten f g e t s () iraacute leyendo liacutenea a liacutenea todo el contenido e imprimieacutendoshylo en pantalla

La forma ideal de trabajar con ficheros es ir leyendo poco a poco su conshytenido para poder buscar datos que nos interesen en cada liacutenea o conshyjunto de caracteres Existe una funcioacuten que nos permite almacenar todo el contenido de un fichero en un array para su posterior proceso con las funciones propias de las colecciones de datos La funcioacuten e x p l o d e () toma como paraacutemetros un caraacutecter por donde cortar la cadena y el nomshybre de la variable que contiene los datos Podemos ver su funcionamienshyto en el ejemplo

ltphp $descriptor = fopen (librotxta+) $linea__numero = 1

Ficheros y almacenamiento de datos 185

$archivo = while ( feof($descriptor) )

$linea = fgets($descriptor4096) $archivo = $archivo liacutenea nuacutemero $numero__linea es

$linea $1inea_numero++

fclose($descriptor) $lista = explode( $archivo) gt

En este caso e x p l o d e () busca en la variable $ a r c h i v o todos los espashycios en blanco y va almacenando en el array caracteres que esteacuten entre dos ocurrencias (entre dos espacios) Asiacute obtenemos una gran lista de palashybras almacenadas por separado que hacen muy faacutecil buscar ordenar o borrar cualquier contenido

Por uacuteltimo la funcioacuten f ge te () permite leer un fichero caraacutecter a caraacutecshyter Esto es muy uacutetil cuando construimos un parse (un programa que inshyterpreta el contenido de un fichero) y debemos ir evaluando las palabras letra por letra para actuar en consecuencia

Escritura de ficheros

Las funciones para escribir ficheros son tan sencillas de utilizar como las de lectura La funcioacuten principal f w r i t e () escribe en un fichero apuntashydo por un descriptor una cadena de caracteres Es imprescindible que el fichero esteacute abierto en uno de los modos de escritura para que no deacute error

Veamos ahora un ejemplo completo El coacutedigo siguiente es un pequentildeo libro de visitas donde todo aquel que navegue por nuestra Web puede dejar mensajes de agradecimiento y aacutenimo Aunque no es el mejor libro de visitas escrito nunca siacute es un buen ejemplo de coacutemo utilizar la lectura v escritura de archivos dentro de un entorno orientado a objetos

ltphp class libro_visitas

priacutevate $tamano priacutevate $nombre priacutevate $descriptor priacutevate $contenido function construct($nombre)

$this-gtnombre = $nombre

i

186 Capiacutetulo 10

public function leer_libro)

$this-gtdescriptor = fopen ($this-gtnombrea+) $this-gttamano=filesize($this-gtnombre) if ($this-gttamano gt 0)

$this-gtcontenido = fread($this-gtdescriptor $this-gttamano)

fclose ($this-gtdescriptor) return $this-gtcontenido

pub l i c funct ion esc r ib i r__ l ib ro ($riombre $texto)

$ t h i s - gt d e s c r i p t o r = fopen ($this-gtnombrea+) $nombre = lt t r x t d bgcolor=CCCCCCgt$nombrelttdgtlttrgt $texto = lt t r x t d bgcolor=FFFFFFgt$textolt tdx t rgt f w r i t e ( $ t h i s - gt d e s c r i p t o r $ n o m b r e ) f w r i t e ( $ t h i s - gt d e s c r i p t o r $ t e x t o ) f c l o s e ($ th i s -gtdesc r ip to r )

gt ltDOCTYPE HTML PUBLIC -W3CDTD HTML 401 TransitionalEN httpwwww3orgTRhtml4looacutesedtdgt lthtralgt ltheadgt lttitlegtLibro de visitaslttitlegt ltmeta http-eguiv=Content-Type content=texthtml charset=iso-8859-lgt ltheadgt ltbodygt ltp align=centerxstronggtLibro de visitas ltstrongxpgt lttable width=100 border=0 cellspacing=0 cellpadding=0gt

ltphp if (isset ($_POST[nombre ] ) |] isset($_POST[texto]))

$libro = new libro_visitas(librotxt) $librogtescribir_libro($_POST[nombre]$_POST[texto])

$libro_ver = new libro__visitas(librotxt) echo $libro_ver-gtleer_libro() gt lttablegt ltform action=librophp raethod=POST gt Nombre ltinput name=nombre tYpe=text id=nombregt

ltpgt ltpgtTexto

Ficheros y almacenamiento de datos 187

lttextarea name=texto id= tex togtlt tex ta reagt ltpgt ltpgt

ltinput type=submit name=Submit value=Enviar gt ltpgt ltformgt ltbodygt lthtmlgt

La figura 101 muestra el resultado del libro de visitas Como puede ver el coacutedigo tiene dos partes diferenciadas La primera es la definicioacuten de una clase con tres meacutetodos que es la encargada de almacenar y recuperar los datos La segunda parte es el coacutedigo HTML que nos permite visualizar los comentarios de las personas que nos visitan Lo maacutes recomendable es seshyparar ambas partes en dos ficheros distintos y hacer uso de la funcioacuten r e q u i r e _ o n c e () para utilizar el coacutedigo PHP

Si se fija en el coacutedigo HTML hay una parte central escrita en PHP que comprueba si existen datos pasados mediante el meacutetodo POST es decir si existen datos para escribir en el fichero Si es asiacute creamos el objeto $1 lishyb r o y llamamos al m eacute t o d o e s c r i b i r _ l i b r o ( ) que se encarga de guarshydar los datos correctamente Si no hay datos que guardar simplemente se crea un objeto y se lee el archivo donde estaacuten los comentarios

188 Capiacutetulo 10

La clase l i b r o _ v i s i t a s escribe en el fichero filas de una tabla que desshypueacutes se interpretan en el HTML colocando todo correctamente

Sistema de ficheros y directorios

Existe un conjunto de funciones que permiten manejar ficheros y directoshyrios del sistema Estas funciones son muy parecidas a comandos de Unix gnuLinux y seguramente le resulten familiar al lector

Copiar borrar y renombrar

Las operaciones baacutesicas de manejo de ficheros y que se aprenden cuando comenzamos a utilizar un sistema operativo concreto son las de copia borrado y modificacioacuten

Para copiar un fichero se utiliza la funcioacuten copy ( ) que toma como paraacuteshymetros el fichero que quiere copiar y el destino donde quiere guardar la copia

Puede antildeadir un meacutetodo nuevo a la clase l i b r o _ v i s i t a s para que reashylice funciones de copia de seguridad

public function copia_seguridad()

c o p y ( $ t h i s - gt n o m b r e c o p i a t x t )

La siguiente funcioacuten u n l i n k ( ) toma como paraacutemetro el nombre de un fichero y lo borra Puede hacer uso de esta funcioacuten para ampliar su clase y permitir que se puedan borrar los ficheros que almacenan los libros de visitas

public function borrar_libro()

unlink($this-gtnombre)

Como el meacutetodo c o p i a _ s e g u r i d a d () soacutelo permite almacenar un fichero puede ampliar su gama de meacutetodos y antildeadir uno que le deacute la posibilidad de renombrar el fichero c o p i a t x t a otro nombre

public function renombrar_copia($nuevo_nombre)

rename ($this- gtnombre $nuevo__nombre)

Ficheros y almacenamiento de datos 189

Funciones de comprobacioacuten

Es necesario antes de borrar copiar o renombrar un fichero hacer una comprobacioacuten miacutenima para saber si el fichero existe

De esta forma evitaraacute errores innecesarios y tendraacute maacutes control en el flujo de su programa

La funcioacuten f i l e _ e x i s t s () comprueba si un fichero existe dando el valor tnte en caso afirmativo yfalse en caso contrario

El meacutetodo b o r r a r _ l i b r o () puede quedar de la siguiente forma

public function borrar_libro()

if (file_exists($this-gtnombre))

unlink($this-gtnombre)

En los sistemas operativos UNIX gnuLinux todos los recursos hardware se corresponden con un fichero Puede que alguna vez necesite saber el tipo de fichero con el que va a tratar (fichero directorio recurso) La funshycioacuten f i l e t y p e () devuelve un valor que indica el tipo de fichero que coshyrresponde al valor pasado como paraacutemetro

Tabla 102 Tipos de ficheros

Valor Descripcioacuten

fifo Es de tipo FIFO

char Dispositivo de caraacutecter

dir Directorio

block Dispositivo especial de bloques

link Enlace

file Fichero

unknown Tipo desconocido

Ademaacutes de la funcioacuten anterior existe un conjunto de funciones que preshyguntan directamente al archivo por su tipo y el resultado es true ofalse en funcioacuten de la veracidad de la pregunta Las funciones i s _ d i r ( ) i s__execu tab le () i s _ f i l e () y i s _ l i n k ( ) preguntan a su argumento si es del tipo directorio ejecutable fichero o enlace respectivamente

190 Capiacutetulo 10

Directorios

Es muy uacutetil disponer de un gestor de ficheros Web que nos permita naveshygar entre los archivos y directorios Para hacer esto en PHP existen dos meacutetodos El primero utiliza las funciones o p e n d i r ( ) r e a d d i r () y c l o -s e d i r ( ) muy parecidas en su funcionamiento a f open () f r e a d () y f c i oacute s e ( ) Lo mejor es ver coacutemo trabajan juntas con un ejemplo

ltphp $directorio = $descriptor = opendir($directorio) while ($entrada = readdir($descriptor) )

if (is_dir($directorio$entrada) ) echo [Directorio] $entrada ltbrgtbull

elseif ( is__f ile ($directorio $entrada) ) echo [Fichero] $entrada ltbrgt

closedir($descr iptor) gt

Como puede intuir no existe ninguna diferencia significativa entre abrir un fichero o abrir un directorio Lo primero es crear un puntero hacia el directorio que quiera observar y guardarlo en $ d e s c r i p t o r El bucle va leyendo entrada por entrada con la funcioacuten r e a d d i r () y dependiendo

Ficheros y almacenamiento de datos 191

del resultado de las funciones i s _ d i r () o i s _ f i l e () se imprimiraacute el directorio o el fichero pertinente

Existe una segunda forma de visualizar lo mismo pero utilizando proshygramacioacuten orientada a objetos PHP 5 provee un objeto que implementa toda la loacutegica vista anteriormente La funcioacuten d i r () devuelve un objeto que permite examinar el directorio pasado como paraacutemetro El objeto poshysee un meacutetodo llamado r e a d () que va leyendo todas las entradas y un meacutetodo c i oacute s e ( ) que cierra el objeto El ejemplo anterior puede verse asiacute

ltphp $directorio = $fichero = dir(directorio) while ($entrada = $fichero-gtread())

if (is_dir(directorioentrada)) echo [Directorio] $entrada ltbrgt

elseif (is_file($directorio$entrada)) echo [Fichero] $entrada ltbrgt

$ f i c h e r o - gt c l o s e ( ) gt

Ficheros de configuracioacuten

Cuando sea un excelente programador en PHP 5 necesitaraacute conocer teacutecshynicas para almacenar datos de configuracioacuten en un fichero Una teacutecnica habitual es crear un fichero con variables de PHP que toman los valores adecuados y en el transcurso del programa utilizar una llamada a la funshycioacuten r e q u i r e j o n e e () para poder utilizarlas De esta forma podriacuteamos utilizar el siguiente ejemplo como configuracioacuten para conectar a una base de datos

ltphp servidor = localhost usuario = luis $password = secreta $base_datos = anaya gt

Otra alternativa es utilizar un tipo de fichero de configuracioacuten que utiliza la misma estructura que el fichero php i n i La estructura es la siguiente

Los comentarios van despueacutes de un punto y coma

192 Capiacutetulo 10

[Base__datos] servidor=localhost usuario=luis password=secreta base_datos=anaya Creamos un nuevo apartado [Preferencias] color=rojo tamanio=medio fuente=verdana

Este archivo almacena las variables que necesite en el transcurso del proshygrama

Para leerlo existe una sentencia especial que almacena el resultado en un array Para acceder a cada uno de los campos hay que utilizar la notacioacuten de un array de dos dimensiones como muestra el ejemplo La figura 103 muestra el resultado de leer un archivo de configuracioacuten

ltphp $configuracion = parse_ini_file(configuracioacuteniniTRUE) Ejemplos de variables echo $configuracion[Base__datos] [servidor] echo $configuracion[Preferencias] [fuente] gt

Ficheros y almacenamiento de datos 193

Manejo de ficheros en el servidor

Conociendo todas las posibilidades que ofrece PHP 5 a la hora de controshylar archivos llega la hora de aplicar a la praacutectica casos reales de funcionashymiento Los dos usos maacutes comunes de manejo de ficheros en la Web tienen que ver con la subida de los mismos a un servidor o con la descarga desshyde una paacutegina Web

Subida de ficheros

Cuando utilice un formulario Web puede introducir los datos solicitados a traveacutes de cajas de texto listas desplegables o botones de seleccioacuten Adeshymaacutes existe una etiqueta HTML que permite elegir un fichero de nuestro ordenador local y subirlo al servidor Puede crear un formulario miacutenimo que contenga la etiqueta en el siguiente ejemplo

ltHTMLgt ltBODYgt ltform action=subirphp method=POST enctype=multipartform-datagt Introduce el fichero ltinput type=file name=fichero gtltbrgt ltinput type=hidden ntildeameTAMANIO valueacute = 1000gt ltinput type=subraitgt ltformgt ltBODYgt ltHTMLgt

Como puede ver el atributo e n c t y p e debe tener el valor m u l t i p a r t = f o r m - d a t a para que el formulario trabaje correctamente Ademaacutes heshymos antildeadido una etiqueta llamada TAMANIO que guarda el valor maacutexishymo en bytes que nuestro script va a permitir subir Esto debe controlarse en la Web que reciba los datos mediante PHP Puede ver el aspecto graacutefishyco en la figura 104

Cuando el formulario se enviacutea PHP detecta automaacuteticamente que hemos enviado un fichero y lo almacena en un directorio temporal del servidor La Web que recibe los datos introduce dentro de la variable suacuteper-global 3_FILES [ nombre_f i c h e r o ] un conjunto de propiedades tales como el nombre del fichero subido el nombre temporal del recurso el tamantildeo o si ha tenido alguacuten error la subida Vamos a ampliar el formulario con coacuteshydigo para el manejo de ficheros

ltHTMLgt ltBODYgt ltform action=subirphp method=POST enctype=multipartform-datagt

194 Capiacutetulo 10

Introduce el fichero ltinput type=file name=ficherogtltbrgt ltinput type=submit gt ltformgt ltPHP

$fichero = $_FILES[fichero] foreach ($_FILES[fichero] as $indice =gt $valor)

echo $indice $valorltbrgt if ($_POST[TAMANIO]lt$_FILES[fichero] [size])

echo ltbrgtEl fichero tiene un tamantildeo adecuado copy ($_FILES[fichero] [tmp_name]archivotxt)

else echo ltbrgtEl fichero es demasiado grande

gt

ltBODYgt ltHTMLgt

i n L )T^ M ^ ir 7~n l a

L- I r

1 1 1 4 t r 1 c c - 1 r

f - 1 tlf 1 4 4

1 l 1 1 4 4 1

directorios ocultos Cenes ar

Terminado

f f t Eacute f l U B M I - B [luis] v Moziacutella Firefc V E l GIMP bull $ ^ C 7

Figura 104 Formulario de entrada de ficheros

El resultado muestra un formulario donde debe introducir un fichero que puede ver en la figura 105

Cuando activa el botoacuten de subida la paacutegina vuelve a cargar pero esta vez muestra informacioacuten sobre el fichero y si el tamantildeo es adecuado o no para su almacenamiento Nos hemos apoyado en la construccioacuten foreach para averiguar las proshypiedades del fichero subido

Ficheros y almacenamiento de datos 195

Si el tamantildeo en bytes que tenemos puesto como liacutemite en el formulario es menor que el tamantildeo del archivo se utiliza la funcioacuten c o p y () para coshypiar el fichero y guardarlo en el servidor

Descarga de ficheros

Normalmente dejamos al lenguaje HTML el trabajo de enlazar los archishyvos que deseamos que los usuarios de nuestra Web puedan descargar Esto se puede hacer simplemente con un enlace del tipo

lthtmlgt ltBODYgt lta href=ejemplozipgtPincha aquiacute para descargarltagt ltBODYgt ltHTMLgt

Cuando hacemos clic en el enlace normalmente el navegador averigua el tipo de fichero que vamos a descargar (ZIP PDF imagen) y nos muestra una pequentildea ventana con informacioacuten sobre el fichero

Imagine ahora que los ficheros que queremos poner en descarga se geneshyran en ese mismo instante como los archivos PDF Tenemos que seguir una pauta distinta para permitir la descarga desde el sitio Web utilizanshydo cabeceras HTTP La figura 106 muestra la ventana del navegador que recibe la cabecera MIME

196 Capiacutetulo 10

ltphp $fichero = ejemplozip $mimeType = appliacutecationzip Si el navegador es Explorer u Opera cambiamos el tipo de cabecera if (strpos($_SERVER[HTTP_USER_AGENT]MSIE 5) |[

strpos($_SERVER[HTTP_USER_AGENT]Opera 7)) $mimeType = applicationx-download

Se genera la cabecera header(content-disposition attachment f ilename = ej emplo__personal zip) header(content-type $mimeType) header(content-length filesize($fichero)) Se enviacutea el archivo al navegador readfile($fichero) gt

Los tipo MIME identifican el tipo de fichero y lo asocian a una aplicacioacuten determinada en un sistema operativo determinado Si utiliza el tipo MIME de PDF en un sistema Windows la aplicacioacuten asociada puede ser Acrobat Reader de Adobe Casi todos los archivos llevan asociado un tipo MIME y sirve entre otras cosas para que el navegador reconozca el tipo de archishyvo que estaacute descargando y optar por mostrarlo directamente en pantalla o guardarlo en alguna ubicacioacuten del disco duro Si comprueba antes el nomshybre del navegador que ha solicitado la descarga puede cambiar el tipo para que sea compatible con distintas versiones Las cabeceras HTTP deshyben generarse con la funcioacuten h e a d e r () y debe ser lo primero que se enshyviacutea al navegador Si enviacutea alguacuten dato o etiqueta antes que la cabecera obtendraacute un error

Ficheros y almacenamiento de datos 197

La cabecera que utilizamos en este caso es la de enviacuteo de un fichero del tipo MIME indicado y tamantildeo calculado con la funcioacuten f i l e s i z e ( ) No es necesario que el archivo que vaya a enviar tenga el mismo nombre en la descripcioacuten de la cabecera que en el servidor

Finalmente la funcioacuten r e a d f i l e () lee el fichero completamente y lo enviacutea al navegador

Resumen

Situados ya en el ecuador del libro podemos asegurar que estaacute preparado para enfrentarse a programas serios Los conceptos baacutesicos los aprendioacute en los capiacutetulos 1 2 3 4 5 6 y 7 El capiacutetulo 8 le mostroacute la forma de utilishyzar las variables entre varias paacuteginas Web y el 9 la verdadera potencia de uso de PHP 5

Este capiacutetulo le ha mostrado la forma de guardar datos para que permashynezcan almacenados indefinidamente y meacutetodos para abrir cerrar copiar o borrar los ficheros que utilice Aunque no es el mejor meacutetodo para guarshydar los datos muchas aplicaciones existentes se sirven de las funciones de archivos en vez de la utilizacioacuten de bases de datos

Los dos capiacutetulos siguientes le guiaraacuten por el apasionante mundo de los gestores de bases de datos La potencia de estos gestores le permitiraacute errashydicar de sus scripts la gestioacuten de datos mediante ficheros A partir de enshytonces la gestioacuten de archivos quedaraacute relegada al manejo de ficheros graacuteficos copias o gestioacuten de la configuracioacuten

En este capiacutetulo aprenderaacute a

bull Crear sus propias bases de datos con el lenguaje SQL bull Realizar consultas con SQL para insertar modificar o borrar registros

bull Conocer las funciones baacutesicas de SQLite

bull Recuperar los datos de una tabla y el nuacutemero de registros bull Moverse entre los registros de una base de datos

200 Capiacutetulo 11

Introduccioacuten

Este capiacutetulo pretende ser una introduccioacuten al lenguaje estructurado de consulta (SQL) que es primordial conocer a la hora de utilizar alguna base de datos relacional Puesto que no es un libro dedicado a SQL soacutelo vereshymos las estructuras baacutesicas del lenguaje para poder realizar nuestros ejemshyplos por eso recomiendo leer alguacuten libro deciicado a consultas SQL para sacar el maacuteximo partido a las bases de datos

Tambieacuten conoceremos la nueva implementacioacuten de PHP 5 para bases de datos SQLite Lejos de ser un gestor de bases de datos es sencillamente una libreriacutea que nos permite tratar un fichero de iexcla misma forma que utishylizamos una base de datos SQLite viene instalado en los binarios de PHP 5 y no utiliza ninguacuten puerto de conexioacuten externo tan soacutelo funciona cuanshydo se hace una llamada a las funciones de SQLite

SQL

La estructura baacutesica de una base de datos SQL es muy sencilla Los datos de una base de datos se almacenan en tablas donde cada fila identifica uniacutevocamente a un elemento distinto Por ejemplo la tabla de usuarios tendraacute tantas filas como usuarios tenga la paacutegina Web Cada tabla puede definir varias columnas Las columnas hacen referencia a las propiedades de cada fila Por ejemplo la tabla de usuarios podriacutea tener como columshynas el coacutedigo de usuario el nombre los apellidos y la direccioacuten postal

Nota

Hoy en diacutea tedas las aplicaciones profesionales escritas en PHP se basan en la interaccioacuten entre el coacutedigo y los datos almacenados en alguna base de datos Recomiendo al lector que no escatime esfuerzos en aprender el lenguaje SQL pues le seraacute muy uacutetil para realizar despueacutes aplicaciones basadas en cualquier base de datos MySQL SQLite SQL Server o incluso Oracle

El lenguaje SQL nos permite elegir varias filas atendiendo a un criterio insertar nuevas filas actualizar los datos o borrarlas con las sentencias SELECT INSERT UPDATE y DELETE respectivamente Este lenguaje per-

Bases de datos con SQL y SQLite 201

mite soacutelo manipular los datos contenidos en las tablas Si quiere modificar la estructura tiene que apoyarse en el lenguaje de definicioacuten de datos que le permite crear nuevas tablas o bases de datos insertar nuevas propiedashydes en forma de columnas o borrar tablas con las sentencias CREacuteATE ALTER v DROP respectivamente Para seguir los ejemplos vamos a basarshynos en una pequentildea base de datos con tres tablas

Tabla 1 1 1 Usuario

id_usuario nombre cuenta

1 Luis Miguel 7011

2 Mariacutea Fernanda 3454

3 Pedro 3445

4 Javier 1123

La tabla de U s u a r i o s tiene 4 filas Cada una de ellas es diferente a las demaacutes y el paraacutemetro que las identifica uniacutevocamente es i d _ u s u a r i o En Espantildea todas las personas tienen un coacutedigo numeacuterico el DNI que las identifica y las hace distintas frente a otras personas que tengan el mismo nombre y apellidos En las tablas ocurre lo mismo Necesitamos un coacutedigo numeacuterico que nos identifique personas distintas Las dos propiedades sishyguientes son el nombre y la c u e n t a del banco para hacer los pagos

Tabla 112 Producto

id_producto nombre precio

1 ratoacuten 6

2 portaacutetil 1000

3 libro PHP5 20

La tabla de P r o d u c t o s es muy similar a la de U s u a r i o s e identifica toshydos los productos que se pueden encontrar en nuestra Web de venta

Tabla 113 Carrito

id_compra id_usuario Jd_producto

1 1 1

202 Capiacutetulo 11

idcompra iexcldusuario id_producto

2 1 2

3 2 1

4 3 3

La tabla C a r r i t o de la compra mantiene un listado que relaciona los usuashyrios con los productos que han comprado Si se fija en la primera fila el i d_compra es el nuacutemero de factura que debe ser distinto siempre en el antildeo actual el i d _ u s u a r i o es 1 lo que quiere decir que el usuario 1 Luis Miguel ha comprado el producto 1 un ratoacuten de PC Si ha entendido esto ya podemos empezar a ver las sentencias SQL para manejar los datos

SELECT

Este es el comando principal que usaraacute en todas sus aplicaciones de bases de datos La sintaxis baacutesica es la siguiente

SELECT campol campo2 campo3 FROM tabla WHERE condicioacuten

La sentencia SELECT permite escoger los campos que especifiquemos de un conjunto de filas que cumplan una condicioacuten escrita despueacutes de la claacuteushysula WHERE Por ejemplo para recuperar todos los nombres de los usuashyrios almacenados en la tabla U s u a r i o tendriacuteamos que hacer

SELECT nombre FROM Usuario

El resultado es una columna con todos los nombres

Luis Miguel Maria Fernanda Pedro Javier

Advertencia

Si se fija iexcla claacuteusula WHERE no aparece porque estamos seleccioshynando todas iexclas filas Si quisieacuteramos seleccionar todas las filas cuyo i d _ u s u a r i o sea mayor que 2 tendriacuteamos que antildeadir WHERE i d_usua r io gt 2

Bases de datos con SQL y SQLite 203

Si necesita utilizar todos los campos de una tabla puede utilizar el siacutemboshylo para seleccionar todos

SELECT FROM U s u a r i o

Un uacuteltimo truco permite conocer el nuacutemero de filas que cumplen la conshydicioacuten Si despueacutes de la sentencia SELECT escribimos c o u n t ( ) el gesshytor de bases de datos nos contaraacute el nuacutemero de filas implicadas en la seleccioacuten

SELECT c o u n t ) ) FROM U s u a r i o

El resultado devuelto es 4 el nuacutemero de usuarios dados de alta

Uniones

Imagine ahora que queremos conocer el nombre de los usuarios que han comprado un producto determinado Si nos fijamos en la tabla C a r r i t o soacutelo podemos sacar el i d _ u s u a r i o con lo aprendido hasta ahora

Existe la posibilidad de cruzar varias tablas Cuando unimos dos tablas lo que realmente pasa es que obtenemos como resultado una tabla mayor con la suma del nuacutemero de columnas de las tablas y tantas filas como inshydique la multiplicacioacuten de las filas de las tablas implicadas

Si hacemos algo asiacute

SELECT FROM Usuario Carrito

El resultado es la unioacuten de las tablas Usuario y Carrito cuyo resultado tiene la suma de las columnas (3 + 3) y la multiplicacioacuten de las filas (4 x 4)

Tabla 114 UsuarioxCarrito

idusuario nombre cuenta id_carrito id_usuario idproducto

1 Luis Miguel 7011 1 1 1

1 Luis Miguel 7011 2 1 2

1 Luis Miguel 7011 3 2 1

1 Luis Miguel 7011 4 3 3

2 Ma Fernanda 3454 1 1 1

2 Ma Fernanda 3454 2 1 2

2 Ma Fernanda 3454 3 2 1

2 Ma Fernanda 3454 4 3 3

204 Capiacutetulo 11

idusuario nombre cuenta id_carrito id_usuario id_producto

3 Pedro 3445 1 1 1

3 Pedro 3445 2 1 2

3 Pedro 3445 3 2 1

3 Pedro 3445 4 3 3

4 Javier 1123 1 1 1

4 Javier 1123 2 1 2

4 Javier 1123 3 2 1

4 Javier 1123 4 3 3

Aquiacute es donde realmente se necesita utilizar la claacuteusula WHERE Lo que queshyremos conocer es el nombre de los usuarios que han comprado el producto nuacutemero 1 Al hacer una unioacuten lo primero que tenemos que hacer es eliminar las filas repetidas mediante una sentencia que relacione las dos tablas Si se fija bien puede ver que la columna i d _ u s u a r i o aparece en las dos tablas por lo tanto es una buena referencia Observe la siguiente sentencia SQL

SELECT FROM Usuario Carrito WHERE Usuario id_usuario = Carrito id__usuario

Lo que hemos hecho es crear una unioacuten de dos tablas donde cada fila debe tener las dos columnas i d _ u s u a r i o iguales

Como las dos tablas tienen el mismo nombre para la columna i d _ u s u a r i o es necesario anteponer la tabla a la propiedad para que la consulta funshycione de la siguiente forma U s u a r i o i d _ u s u a r i o o C a r r i t o i d _ u s u a r i o

El resultado de la sentencia anterior es

Tabla 115 UsuarioxCarrito

idusuario nombre cuenta id_carrito idusuario id_producto

1 Luis Miguel 7011 1 1 1

1 Luis Miguel 7011 2 1 2

2 Ma Fernanda 3454 3 2 1

3 Pedro 3445 4 3 3

Bien ahora tenemos un conjunto de datos que nos da el nombre de los usuarios que han comprado algo en nuestra tienda Si queremos averi-

Bases de datos con SQL y SQLite 205

guar quieacuten ha comprado el producto nuacutemero 1 tendremos que modificar la sentencia

SELECT FROM Usuario Carrito WHERE Usuarioid_usuario - Carritoid_usuario AND id_producto = 1

El resultado ahora se acerca maacutes a la realidad de lo que necesitamos

Tabla 116 UsuarioxCarrito

id_usuario nombre cuenta id_carrito id_usuario id_producto

1 Luis Miguel 7011 1 1 1

2 Ma Fernanda 3454 3 2 1

Acotando un poquito maacutes la sentencia

SELECT nombre FROM Usuario Carrito WHERE Usuarioid_usuario = Carritoid_usuario AND id_producto = 1

Ahora el resultado siacute es el esperado

Tabla 117 Nombre de los usuarios que han comprado el producto 1

nombre

Luis Miguel

Ma Fernanda

Dominar la sentencia SELECT con todas sus variaciones es un trabajo duro de varios meses o antildeos pero la recompensa se recoge en los primeros pashysos cuando comenzamos a ver la potencia del lenguaje y el uso en los disshytintos gestores de bases de datos

INSERT

Para poder seleccionar los datos primero hay que poder insertarlos en las tablas La sentencia necesaria para introducir nuevos datos es

INSERT INTO tabla (columnal columna2 columna3) VALUacuteES (valorl valor2 valor3)

206 Capiacutetulo 11

El resultado de esta operacioacuten es la inclusioacuten de un registro nuevo en la tabla en las columnas indicadas y con los valores dados Aquellas columshynas que no aparezcan no tomaraacuten valor en ese registro o tomaraacuten el vashylor NULL Para insertar un nuevo cliente en la tabla de U s u a r i o puede utilizar la sentencia

INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (5 Feo Joseacute 78 98)

La tabla resultante quedaraacute de esta forma

Tabla 118 Usuario

idusuario nombre cuenta

1 Luis Miguel 7011

2 Ma Fernanda 3454

3 Pedro 3445

4 Javier 1123

5 Feo Joseacute 7898

UPDATE

Se utiliza para editar informacioacuten que ya estaacute almacenada en la base de datos En otras palabras podemos cambiar selectivamente cierta informashycioacuten sin tener que borrar un registro e insertarlo de nuevo

La sintaxis baacutesica es

UPDATE tabla SET carapol = valorl campo2 = valor2 campo3 = valor3 WHERE condicioacuten

La condicioacuten se utiliza para seleccionar el nuacutemero de filas a las que afectashyraacute el cambio Si no ponemos nada se supone que la actualizacioacuten de datos se hace sobre todas las filas de una tabla por eso es necesario poner algushyna condicioacuten

Podemos utilizar UPDATE para cambiar el nuacutemero de cuenta de uno de los usuarios

UPDATE Usuario SET cuenta = 4455 WHERE id_usuario = 2

Lo que hemos hecho es cambiar el nuacutemero de cuenta de Mariacutea Fernanda de 3454 a 4455

Bases de datos con SQL y SQLite 207

DELETE

Eacutes la sentencia maacutes peligrosa de las vistas Permite borrar de uno a varios registros de una tabla La sintaxis es

DELETE FROM tabla WHERE condicioacuten

Si se omite la claacuteusula WHERE se borran todas las filas de una tabla Es aconsejable no precipitarse en el uso de esta opcioacuten y detenerse antes un momento a recapacitar si se necesita realmente dejar la tabla vaciacutea La fila que contiene al usuario Javier puede borrarse de la siguiente forshyma

DELETE FROM Usuario WHERE nombre=Javier

Definicioacuten de tablas

El primer paso para poder interactuar con los datos de una tabla es su creacioacuten Para este fin se utiliza la sentencia CREacuteATE que define los campos y el tipo de datos que se va a almacenar en cada columna

Ll formato simplificado es CREacuteATE TABLE tabla (columnal tipo_dato columna2 tipo_dato columna3 tipo_dato)

Los tipos de datos de SQL estaacutendar pueden variar dependiendo del gesshytor de bases de datos que utilice pero baacutesicamente pueden ser

Tabla 119 Tipos de datos en SQL 92

Especificacioacuten Tipo de dato

INT INTEGER Entero grande

SMALLINT Entero pequentildeo

REAL FLOAT Coma flotante

DEC DECIMAL Decimal

CHAR(n) CHARACTER(n) Alfanumeacuterico de longitud fija n

208 Capiacutetulo 11

Especificacioacuten Tipo de dato

VARCHAR(n) Alfanumeacuterico de longitud variable como maacutexishy

mo n caracteres

DATE Fecha

TIME Hora

TIMESTAMP Instante Conjunto de Fecha y Hora de un momento determinado

Con estos datos podemos ver la definicioacuten de la tabla de U s u a r i o

CREacuteATE TABLE Usuario (id_usuario INTEGER nombre CHAR(255)

cuenta INTEGER)

Si alguno de los campos es obligatorio es decir si siempre que realice una insercioacuten de nuevos datos necesita que ciertos campos sean introducidos obligatoriamente puede utilizar la sentencia NOT NULL despueacutes de la deshyfinicioacuten del campo

El campo nombre es obligatorio en la tabla U s u a r i o ya que un registro de usuarios sin almacenar su nombre no tiene sentido

CREacuteATE TABLE Usuario (id_usuario INTEGER nombre CHAR(255) NOT

NULL cuenta INTEGER NOT NULL)

El i d _ u s u a r i o identifica un registro y soacutelo uno No puede haber en la misma tabla dos nuacutemeros iguales en esta columna La forma de encontrar raacutepidamente una fila determinada es preguntar por este dato

La clave primaria de una tabla es un identificador uacutenico en cada tabla y que puede utilizarse para relacionar una tabla con otra En nuestro ejemshyplo podemos ver claramente que i d _ u s u a r i o es la clave primaria de la tabla U s u a r i o

CREacuteATE TABLE Usuario (id_usuario INTEGER PRIMARY KEY nombre

CHAR(255) NOT NULL cuenta INTEGER NOT NULL)

SQLite

SQLite es una libreriacutea que implementa un conjunto de sentencias bastanshyte amplio de SQL 92 estaacutendar La libreriacutea es muy pequentildea y 2 oacute 3 veces maacutes raacutepida que los gestores de bases de datos MySQL o PostgreSQL Neshycesita muy poco tiempo de ejecucioacuten y muy poca memoria para el proceshyso No se necesita administrar la base de datos fuera del entorno de

Bases de datos con SQL y SQLite 209

programacioacuten ya que no es un servidor Existe un problema derivado de esto

SQLite se basa en el almacenamiento de datos en un fichero por lo tanto cada vez que se almacenan datos el fichero que contiene los registros se bloquea durante el tiempo de la actualizacioacuten y no permite a otros usuashyrios interactuar Si la base de datos se utiliza solamente para leer la veloshycidad seraacute muy elevada pero si la utilizamos para actualizar constanteshymente los datos SQLite perderaacute maacutes tiempo negociando los bloqueos del fichero que dando servicio

Entre las caracteriacutesticas de SQLite tenemos

bull Implementa muchas funcionalidades de SQL 92 incluido disparadoshyres y transacciones

bull Proteccioacuten de integridad de datos con cominit y r o l l b a c k

bull Los ficheros de datos pueden moverse de servidor y seguiraacuten funcioshynando

bull Soporta bases de datos de 2 Terabytcs

bull El coacutedigo fuente es de dominio puacuteblico

Creacioacuten de bases de datos

La interfnce de programacioacuten de la extensioacuten SQLite es muy similar al gesshytor de bases de datos MySQL y PostgeSQL La diferencia principal es que SQLite aunque acepta la definicioacuten de datos con la sentencia CREacuteATE internamente soacutelo diferencia entre valores alfanumeacutericos o valores numeacuteshyricos es decir que podemos omitir el tipo de los campos en la definicioacuten de las tablas

La funcioacuten s q l i t e _ o p e n () recibe como paraacutemetro el nombre de una base datos Si la base de datos no existe la crea Ademaacutes de esta funcioacuten neceshysitaremos otra para poder enviar consultas a la base de datos La funcioacuten s q l i t e _ s i n g l e _ q u e r y () toma como paraacutemetros la base de datos creada con s q l i t e _ o p e n () y un literal con la sentencia SQL que queremos ejeshycutar

El ejemplo siguiente crea la base de datos de usuario e inserta las filas que estamos utilizando para aprender el lenguaje SQL

ltphp

$base_datos = sqlite_single_open(Usuariodb) $consulta = CREacuteATE TABLE Usuario

(id_usuario PRIMARY KEY

210 Capiacutetulo 11

nombre CHARIacute2 55) NOT NULL

cuenta INTEGER NOT NULL)

sqlite__query ( $base_datos $ consulta)

$consultal = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (1 Luis Miguel7011)

$consulta2 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (2 Mariacutea Fernanda3454 )

$consulta3 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (3 Pedro3445)

$consulta4 = INSERT INTO Usuario (id_usuario nombre cuenta)

VALUacuteES (4 Javier1123)

sqlite_single_query($base_datos$consultal)

sqlite_ single_query($base_datos$consulta2 )

sqlite_ single_query($base_datos$consulta3)

sqlite_ single_query($base_datos$consulta4)

gt

De esta forma se ha creado la tabla U s u a r i o pero hemos necesitado hashycer 4 consultas adicionales para antildeadir los datos Esto se puede simplifishycar utilizando la funcioacuten s q l i t e _ q u e r y ( ) que acepta maacutes de una liacutenea de SQL Vamos a crear de esta forma la tabla P r o d u c t o y C a r r i t o

ltphp

$consulta = CREacuteATE TABLE Producto

(Iacuted_producto INTEGER PRIMARY KEY

nombre CHAR(255) NOT NULL

precio INTEGER NOT NULL)

INSERT INTO Producto (id_producto nombre precio)

VALUacuteES (1 Ratoacuten 6)

INSERT INTO Producto (idjroducto nombre precio)

VALUacuteES (2 Portaacutetil1000)

INSERT INTO Producto (id_producto nombre precio)

VALUacuteES (3 Libro PHP520)

sqlite_query($base_datos$consulta)

consulta = CREacuteATE TABLE Carrito

(id^compra INTEGER PRIMARY KEY

id^usuario INTEGER NOT NULL

id^producto INTEGER NOT NULL)

INSERT INTO Carrito (id^compra id_usuario id_producto)

VALUacuteES (1 1 1)

INSERT INTO Carrito (id^compra id_usuario id_producto)

VALUacuteES (2 1 2)

INSERT INTO Carrito (id_compra id_usuario id_producto)

VALUacuteES (3 2 1)

INSERT INTO Carrito (id_compra id_usuario idjroducto)

VALUacuteES (4 3 3)

sqlite_query($base_datos$consulta)

gt

Bases de datos con SQL y SQLite 211

Algunos gestores de bases de datos necesitan antildeadir una sentencia espeshyciacutefica para que uno de los campos sea auto incremental es decir que su valor aumente poco a poco sin necesidad de antildeadirlo nosotros en realishydad es gestionado por la propia base de datos

Los campos enteros que llevan asociada la sentencia PRIMARY KEY autoshymaacuteticamente son tratados como campos auto incremeacutentales y en las oacutershydenes INSERT se puede omitir la inclusioacuten del valor porque SQLite le daraacute el valor correlativo de la fila que le corresponda

Uacuteltimos cambios en una tabla

Hay veces que necesitamos saber el uacuteltimo valor auto incremental que SQLite ha generado para asociar una imagen o un archivo a un registro de una tabla Para aver iguar este dato p o d e m o s usar la funcioacuten sqlite_last_insert_rowid()

ltphp $base_datos = sqlite_open(Usuariodb) sqlite_single_query($base_datosINSERT INTO Usuario (nombre cuenta) VALUacuteES (Joseacute A2677)) $ultimo_usuario = sqlite_last_insert_rowid($base_datos) sqlite_single_query($base_datosINSERT INTO Producto (nombre precio) VALUacuteES (Ibook1200)) $ultimo_producto = sqlite_last_insert__rowid($base_datos) sqlite_single_query($base_datosINSERT INTO Carrito (id_usuario id_producto) VALUacuteES ($id_usuario$id_producto)) gt

En el ejemplo puede ver la posible utilizacioacuten de la funcioacuten Con ella exshytraeraacute el uacuteltimo usuario y el uacuteltimo producto introducido y aprovecharaacute para insertarlos en la tabla de compras

Otra funcioacuten muy uacutetil es s q l i t e _ _ c h a n g e s ( ) que devuelve el nuacutemero de filas afectadas por una consulta anterior

Si borra varias filas esta funcioacuten le devolveraacute el nuacutemero de filas que han sido borradas como puede ver en la figura 1 1 1

lt php $base_datos = sqlite_open(Usuariodb)

sqlite_single_query($base_datosUPDATE Usuario set cuenta =

2 2 2 2) echo Nuacutemero de filas afectadas

sqlite_changes($base_datos) gt

Seleccioacuten de datos

Como hemos visto antes la funcioacuten s q l i t e _ q u e r y () da la posibilidad de hacer cualquier tipo de consulta vista al principio del capiacutetulo

Las sentencias CREacuteATE INSERT DELETE o UPDATE no necesitan devolshyver ninguacuten dato pero la sentencia SELECT tiene que devolver los datos requeridos

La variable que obtiene los datos se considera como un recurso y debe aplicarse una funcioacuten para recuperar las filas una a una

Lo podemos comprobar con un ejemplo cuyo resultado se muestra en la figura 112

lt php $base_datos = sqlite_open(Usuariodb) ^resultado = sqlite_query($base_datosSELECT FROM Usuario) if ( $resultado)

echo Parece que hay un error else

while ($fila = sqlite_fe tch__array ($resu l taaacuteo) ) foreach ($fila as $indice =gt $valor)

echo $indice $valorltbrgt

gt

Despueacutes de hacer una consulta con la funcioacuten s q l i t e _ q u e r y ( ) la vashyriable $ r e s u l t a d o recibe un tipo de dato que no es manejable La funshycioacuten s q l i t e _ f e t c h _ a r r a y () extrae de la variable $ r e s u l t a d o todas las filas devueltas en forma de array Para ello hemos construido un bucle w h i l e donde la variable $f i l a va recibiendo los registros

Para acceder a cada columna de un registro simplemente tenemos que hacer uso de la variable como si fuera un array y como iacutendice el nombre de la columna o el nuacutemero de registro de esta forma $f i l a [nombre] $ f i l a [ c u e n t a ] $ f i l a [ 0 ] $ f i l a [ l ]

Dentro del bucle hemos utilizado otro bucle f o r e a c h para mostrar por pantalla todos los valores del array

SQLite orientado a objetos

Puesto que la potencia de PHP 5 radica en la fuerte orientacioacuten a objetos es de agradecer que SQLite provea alguacuten objeto para la interaccioacuten con bases de datos SQLite tiene una potente interface orientada a objetos que puede ser usado para un eficaz manejo de los datos librando al progra-mador de crear su propio objeto con las funciones procedurales El objeto se llama S Q L i t e D a t a b a s e () y el constructor recibe como paraacutemetro la base de datos

214 Capiacutetulo 11

El ejemplo muestra coacutemo utilizarlo aunque el lector ya conoceraacute el funshycionamiento baacutesico de los objetos

lt php $base_datos = new SQLiteDatabase(Usuariodb) $consulta = CREacuteATE TABLE Usuario

(id^usuario INTEGER PRIMARY KEY nombre CHAR(2 55) NOT NULL cuenta INTEGER NOT NULL) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (1 VLuis Miguel7 011) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (2 VMariacutea Fernanda3454) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (3 Pedro3445) INSERT INTO Usuario (id_usuario nombre cuenta) VALUacuteES (4 Javier1123)

$base_datos-gtquery($consulta) gt

El meacutetodo q u e r y ( ) funciona exactamente igua l que la funcioacuten s q l i t e _ q u e r y ( ) pero soacutelo recibe como paraacutemetro la consulta ya que la base de datos va impliacutecita en el objeto

Seleccioacuten de registros

Las consultas SELECT se tratan de manera parecida a lo visto anteriorshymente Puesto que estamos utilizando un objeto para recibir el resultado de una consulta tendremos que utilizar meacutetodos que nos permitan maneshyjarlos En la figura 113 puede ver el resultado

ltphp

$base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtquery($consulta) while ($resultado-gtvalid() )

$fila = $resultado-gtcurrent() echo $fila[0] ltbrgt echo $fila[l] ltbrgt echo $fila[2] ltbrgt $ resultado- gtnext () bull

gt

El meacutetodo v a l id () da un resultado true si existen valores que no se han mostrado si devuelve false es que ya hemos extraiacutedo todas las filas El meacutetodo c u r r e n t () nos da la fila actual deacutela consulta La variable $f i l a

Bases de datos con SQL y SQLite 215

obtiene un array con los datos del registro actual Para avanzar de registro en la consulta se utiliza el meacutetodo n e x t ( )

Funciones de Array para recuperar datos

SQLite ofrece tambieacuten un nuacutemero de nuevas funciones que simplifican y aceleran la recogida de informacioacuten de la base de datos Por ejemplo el meacutetodo A r r a y Q u e r y () devuelve un array de dos dimensiones donde la primera dimensioacuten indica el nuacutemero de la fila y la segunda dimensioacuten el nuacutemero de columna de esa fila Si la variable $ r e s u l t a d o recoge el resultado de A r r a y Q u e r y ( ) puede acceder a los registros de la siguienshyt e forma $ r e s u l t a d o [ 0 ] [ 0 ] $ r e s u l t a d o [ l ] [ 0 ] $ r e s u l t a -do [2] [3] Puede utilizar alguacuten bucle foreach para sacar todos los datos

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtArrayQuery($consulta) $filas = 0 while (isset ($resultado [$filas] ) )

foreach ($resultado[$filas] as $indice =gt $valor) echo $indice $valorltbrgt

$filas++

216 Capiacutetulo 11

gt

Ademaacutes de esta forma de trabajar puede hacer que el resultado de la consulshyta se devuelva en forma de objeto PHP 5 permite utilizar la construccioacuten fo-reach para interactuar con objetos v recuperar los datos de la siguiente forma

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario bullresultado = $base_datos-gtunbufferedQuerv($consulta) foreach ($resultado as $valor)

echo Svalor[0]ltbrgt echo $vaior[1]ltbrgt echo $valor[2]ltbrgt

gt

La construccioacuten unbuf f e r edQuery () devuelve las filas en forma de objeshyto y ademaacutes no almacena el resultado en buffer por lo que es muy raacutepida

Nuacutemero de filas

La extensioacuten SQLite posee un meacutetodo para determinar el nuacutemero de camshypos devueltos en una consulta en un resultado El meacutetodo n u m F i e l d s () se encarga de devolver este resultado Para poder utilizarlo debe recupeshyrar los datos con la funcioacuten unbuf f e r e d Q u e r y () y el objeto devuelto seraacute el que le indique el nuacutemero de campos que almacena

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtunbufferedQuery($consulta) $numero_filas = $resultado-gtnumFields() echo El nuacutemero de filas es $numero_filas foreach ($resultado as $valor)

echo $valorf0]ltbrgt echo $valor[1]ltbrgt echo $valor[2]ltbrgt

gt

Moverse entre registros

En muchos casos querraacute utilizar la menor memoria posible y se haraacute inshydispensable utilizar el meacutetodo unbuf f e r e d Q u e r y ( ) aunque esto hace perder funcionalidad y puede no resultar la mejor eleccioacuten

Bases de datos con SQL y SQLite 217

Por ejemplo imagine que quiere saber cuaacutentas filas devuelve un resulshytado

Usando unbuf f e r e d Q u e r y () tenemos que hacer un bucle para contar una a una las filas del resultado Con la funcioacuten q u e r y () tan soacutelo hay que llamar al meacutetodo numRows () para conocer el nuacutemero de registros implicados en la consulta

Las consultas con q u e r y () permiten ademaacutes recuperar la informacioacuten en el orden que queramos y no secuencialmente

El ejemplo siguiente muestra coacutemo utilizar una consulta para ver los reshygistros empezando desde el uacuteltimo hasta el primero

ltphp $base_datos = new SQLiteDatabase(Usuariodb) $consulta = SELECT FROM Usuario $resultado = $base_datos-gtquery($consulta) $numero_filas = $resultado-gtnumRows() $resultado-gtseek($numero_filas-1) do

$fila = $resultado-gtcurrent () foreach ($fila as $valor)

echo $valorltbrgt

while ($resultado-gthasPrev() ampamp $resultado-gtprev()) gt

218 Capiacutetulo 11

El meacutetodo s e e k () se mueve a traveacutes del resultado y permite posicionar-nos en el registro que pasemos como paraacutemetro El meacutetodo h a s P r e v () es true si existe un registro previo y p r e v () es true si ha sido posible moshyverse a un registro anterior La figura 114 es un fiel reflejo del funcionashymiento

Resumen

SQLite es una de las caracteriacutesticas estrella de PHP 5 Se ha incluido para que no necesite instalar un gestor de bases de datos para sus proyectos Esto hace maacutes sencillo distribuir aplicaciones porque no dependen de un software adicional tan soacutelo de PHP 5

SQLite es a la vez un servidor de bases de datos y un cliente La libreriacutea permite operar con la mayor parte de las instrucciones de SQL posee un mayor juego de instrucciones que MySQL 4

Pero como todo lo bueno tiene una pequentildea pega Como SQLite trata las bases de datos como ficheros del sistema operativo cuando un usuario hace una conexioacuten para escribir datos el fichero queda bloqueado para inclusiones de otros usuarios Cuando termina la insercioacuten del primer usuario el segundo tendraacute acceso a escribir los datos Por lo tanto SQLite es muy recomendable cuando realice proyectos donde la mayor parte de las veces se hacen lecturas de la base de datos como un perioacutedico digital o un WebLog En otro caso es mejor utilizar un gestor de bases de datos como MySQL que veraacute en el siguiente capiacutetulo

En este capiacutetulo aprenderaacute a

bull Conocer la forma de conectarse a un servidor de bases de datos bull Realizar consultas y recuperar los datos de distintas formas bull Recuperar el nuacutemero de filas que intervienen en una consulta

bull Crear nuevas bases de datos y tablas

220 Capiacutetulo 12

Introduccioacuten

PHP 5 soporta muchos de los gestores de bases de datos relacioacutenales exisshytentes en el mercado Las dos alternativas maacutes comunes son ProstgreSQL y MySQL

Aunque PostgreSQL es mucho mejor en cuanto a caracteriacutesticas y funcioshynes soportadas del SQL 92 estaacutendar MySQL se ha hecho maacutes popular en el ambiente de los servidores Web Cuando los servidores Web ofrecen su sershyvicio como LAMP se refieren a Linux + Apache + MySQL + PHP

Este capiacutetulo cubre las operaciones maacutes comunes que los desarrolladores de PHP pueden hacer con MySQL desde recuperar o modificar datos buscar textos o hacer una copia de seguridad de la base de datos

Administracioacuten de usuarios

Una gran parte del uso de la seguridad y efectividad de MySQL tiene que ver con comprender el sistema de privilegios MySQL permite dar permishysos al detalle basaacutendose en grupos usuarios conexiones y comandos a utilizar En teoriacutea se puede dar privilegios a ciertos usuarios para que soacutelo puedan escribir en algunas columnas de varias tablas Es una buena idea dar a cada usuario los permisos miacutenimos necesarios para que pueda inte-ractuar con su base de datos En realidad en un mundo ideal no deberiacutea preocuparse por dar permisos a los usuarios o crear bases de datos Si su trabajo profesional se basa en el desarrollo de aplicaciones su adminisshytrador de bases de datos deberiacutea poner a punto el servidor de MySQL para facilitar su trabajo Si se estaacute interesado en conocer los entresijos del servishydor de bases de datos recomiendo al lector que lea la documentacioacuten o-line de la Web wwwmysql com o consiga uno de los muchos libros que tratan el tema

En el Apeacutendice A puede ver coacutemo instalar MySQL y dar los permisos neshycesarios para que pueda probar los ejemplos

Conexioacuten a MySQL

La conexioacuten no puede ser maacutes sencilla Es un proceso de dos pasos

bull Se conecta con el servidor de MySQL

PHP 5 y MySQL 221

bull Se solicita la conexioacuten a una base de datos especiacutefica Es importante recordar que MySQL es un servidor que puede estar alojashydo en el mismo ordenador que PHP 5 o en otro diferente Por eso la coshynexioacuten se hace de forma distinta a SQLite

Para conectar a MySQL es necesario enviar como paraacutemetros la direccioacuten del servidor el usuario y la contrasentildea

ltphp $servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras Conexioacuten al servidor de bases de datos $descriptor = mysql_connect($servidor$usuario $pass) Se selecciona la base de datos mysql_select_db($base_datos$descriptor) Se cierra la conexioacuten cuando terminemos mysql__close ( $descriptor) gt

La funcioacuten m y s q l _ c o n n e c t () permite conectar a un servidor En este caso hemos puesto como servidor a l o c a l h o s t porque estamos utilizanshydo nuestro ordenador local para hacer las pruebas

Otra cuestioacuten importante es que el servidor MySQL puede almacenar varias bases de datos de un mismo usuario por eso tenemos que utilizar la f u n c i oacute n m y s q l _ s e l e c t _ d b ( ) para seleccionar la que queremos utishylizar

Por uacuteltimo tenemos la funcioacuten m y s q l _ c l o s e () que se encarga de ceshyrrar una conexioacuten con el servidor

El ejemplo siguiente muestra coacutemo se puede crear una clase reutilizable en todos los proyectos que sirva para conectarse a una base de datos

ltphp class Servidor_Base_Datos

private $servidor private $usuario private $pass private $base_datos private $descriptor function construct($servidor$usuario$pass$base_datos)

$this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtpass = $pass

222 Capiacutetulo 12

$this-gtbase_datos = $base_datos $this-gtconectar_base_datos()

priacutevate function conectar_base_datos()

$this-gtdescriptor = mysql__connect($this-gtservidor$this-gtusuario$this-gtpass) mysql_select_db($this-gtbase_datos$this-gtdescriptor)

$servidor = localhost $usuario = luis $pass = secreto $base_datos = Usuario $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) gt

Nota

No he antildeadido al objeto ninguacuten tipo de control de errores ya que veremos ese tema con profundidad en el capiacutetulo 17

Seleccionar datos

Existen diferentes formas de recuperar datos desde MySQL pero los maacutes usados son seguramente m y s q l _ f e t c h _ q u e r y () y m y s q l _ q u e r y () Si leyoacute el capiacutetulo anterior sobre S Q L i t e no tendraacute ninguacuten problema para asimilar el funcionamiento de estas funciones

Vamos a antildeadir dos meacutetodos nuevos a la definicioacuten de la clase anterior para que nos pueda servir en otras aplicaciones

public function consulta($consulta)

$this-gtresultado = mysql_query($consulta$this-gtdescriptor)

public function extraer_registro ()

if ($fila = mysql_fetch_array($this-gtresultadoMYSQL_ASSOC)) bull return $fila

else return false

PHP 5 y MySQL 223

El meacutetodo c o n s u l t a () recibe una sentencia SQL que debe ejecutarse en la base de datos apuntada por el descriptor $ t h iacute s- gt d e s c r i p t o r

El meacutetodo e x t r ae r _ r eg i s t r o ( ) comprueba con la funcioacuten m y s q l _ f e t c h _ a r r a y () si existen ficheros en el resultado de la conshysulta

En caso afirmativo devuelve un arraxj con los datos de ese registro En el capiacutetulo anterior vimos que un registro pasado comoarray permitiacutea acceder a las columnas mediante un iacutendice numeacuterico ($f i la [0] ) o meshydiante el nombre de la columna (($f i l a [ i d _ u s u a r i o ]))

La directiva MYSQL_ASSOc elimina la posibilidad de extraer los datos con un Iacutendice numeacuterico mejorando la recuperacioacuten en Jos bucles del foreach El ejemplo siguiente muestra coacutemo utilizar los nuevos meacutetodos

ltphp Primero se antildeade el fichero que contiene la clase require_once(MySQLphp) $servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $usuario-gtconsulta (seslect from Usuario) while ($fila = $usuario-gtextraer_registro() )

foreach ($fila as $indice =gt $valor) echo $indice $valorltbrgt

gt

El coacutedigo anterior recupera la clase del fichero MySQL php e inicializa las variables necesarias para conectar con la base de datos

Tambieacuten podemos utilizar un fichero de configuracioacuten como el que vishymos en el capiacutetulo 10 para almacenar los datos de la conexioacuten

La variable $ u s u a r i o recoge la creacioacuten del objeto de conexioacuten y utiliza el meacutetodo c o n s u l t a () para recuperar el nombre de los usuarios de nuesshytra Web

Para extraer todos los datos nos encontramos con un bucle que va recupeshyrando un arraxj por registro almacenaacutendolo en $f i l a

Utilizando f o r e a c h podemos extraer todas las columnas de la fila indishycada

La figura 121 presenta el resultado del script

Manipulacioacuten de datos

Seleccionar datos de una base de datos es soacutelo el principio la potencia de SQL nos permite tambieacuten insertar actualizar y borrar filas de una tabla Con el objeto que hemos creado es muy sencillo hacer consultas del tipo INSERT UPDATE o DELETE llamando al meacutetodo c o n s u l t a ()

Insertar una fila

Para insertar una fila con nuestro objeto tendremos que definir la consulshyta y ejecutar el meacutetodo c o n s u l t a ()

ltphp require_once(MySQLphp) $servidor = localhost -$usuario = root $pass = $base_datos = Compras $insertar = INSERT INTO Usuario (nombrecuenta) VALUacuteES (Cristina2119) $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) ^usuario-gtconsuIta($insertar) gt

PHP 5 y MySQL 225

Actualizar una fila

Antes de actualizar una fila necesita identificar la fila o filas de la tabla que quiere cambiar En este ejemplo se ha utilizado una sentencia SE-LECT para averiguar primero el valor id_usuar io de Luis Miguel y desshypueacutes proceder a cambiar su cuenta bancaria

ltphp require_once(MySQLphp) $serviacutedor = localhost $usuario = root $pass = $base_datos = Compras $consulta = SELECT id_usuario FROM Usuario WHERE nombre=Luis Miguel $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $id_usuario = $fila[id_usuario] $actualizar = UPDATE Usuario SET cuenta=9999 WHERE id_usuario=$id_usuario $usuario-gtconsulta($actualizar) gt

En un caso praacutectico UPDATE puede utilizarse para modificar los datos introducidos en un formulario Web

Borrar una fila

Para borrar una fila puede seguir el mismo camino que se ha utilizado antes para actualizar Primero averiguumle el registro que quiere eliminar y despueacutes ejecute la consulta con la sentencia DELETE

ltphp require_once(MySQLphp) $servidor = localhost usuario = luis $pass = secreto $base_datos = Compras $consulta = SELECT id_usuario FROM Usuario WHERE nombre=Luis Miguel $usuario = new Servidor_Base_Datos$servidor$usuario$pass$base_datos) $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $id_usuario = $fila[id_usuario ]

226 Capiacutetulo 12

$borrar = DELETE FROM Usuario WHERE id_usuario = 1$id_usuario $usuario-gtconsulta($borrar) gt

Errores con las comillas

Examinemos ahora el coacutedigo siguiente ltPHP require_once(MySQLphp) if (isset ($_POST[nombre] ) ]| isset ($_POST[cuenta ]) )

$servidor = localhost $usuario = root $pass = $base_datos = Compras $nombre = $_POST[nombre ] $cuenta = $_POST[cuenta] $usuario = new Servidor_Base_Datos($servidor$usuario $pass$base_datos) $insertar = INSERT INTO Usuario(nombrecuenta) VALUacuteES ($nombre$cuenta) $usuario-gtconsulta ($insertar)

gt ltHTMLgt ltBODYgt ltform action=formulario_Usuario php method=POSTgt Nombre ltINPUT type=text name=nombregtltbrgt Cuenta ltINPUT type=text name=cuentagtltbrgt ltinput type=submit name=Enviar gt ltformgt ltBODYgt ltHTMLgt

El pequentildeo formulario que muestra la figura 122 permite insertar en la tabla Usuario nuevos clientes Los campos de texto que recogen el nombre y la cuenta pueden recibir cualquier tipo de caraacutecter hay ciertos siacutembolos que pueden provocar que un programa falle y son utilizados malintencionadamente por hackers para corromper el sistema Si en la casilla destinada a escribir el nombre escribe un nombre y en medio una comilla simple y otra doble tal y como muestra el ejemplo

Luis Migue1 Cabezas Granado

PHP 5 y MySQL 227

El meacutetodo c o n s u l t a () intentaraacute ejecutar

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Migue1 Cabezas Granado))

iquestPuede ver el problema Cuando MySQL lee la sentencia cree que es

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Migue

El resto de la sentencia causaraacute un error y fallaraacute la consulta La solucioacuten es antildeadir el siacutembolo de escape delante de la comilla simple para que MySQL tome el siacutembolo como un simple caraacutecter

mysql_query(INSERT INTO Usuario(nombrecuenta) VALUacuteES ( Luis Miguel Cabezas Granado))

Existen tres soluciones para antildeadir el siacutembolo de escape a todas las comishyllas que aparezcan en campo de texto

bull Lo primero que puede hacer es configurar el archivo phpini activanshydo la opcioacuten m a g i c _ q u o t e s _ g p c Con esta opcioacuten a todos los datos pasados entre paacuteginas Web por los meacutetodos GET y POST se les inserta automaacuteticamente siacutembolos de escape en las comillas que aparezcan

bull Si m a g i c _ q u o t e s no estaacute activo en su servidor PHP 5 tiene la funshycioacuten a d d s l a s h e s ( ) que tiene el mismo cometido que la opcioacuten anshyterior Si m a g i c _ q u o t e s estaacute activo no podraacute utilizar esta funcioacuten porque se antildeadiriacutean dos siacutembolos de escape

228 Capiacutetulo 12

bull El tercer camino muy similar a a d d s l a s h e s usa la funcioacuten m y s q l _ e s c a p e _ s t r i n g Esta funcioacuten antildeade siacutembolo de escape a las comillas simples comillas dobles caracteres de final de fichero y reshytorno de carro Es un meacutetodo implementado por MySQL por eso es maacutes recomendable utilizar a d d s l a s h e s

Para saber si el fichero phpini tiene activado m a g i c _ q u o t e s existe la funcioacuten g e t _ m a g i c _ q u o t e s _ g p c ( ) Puede antildeadir algunas liacuteneas de coacutedigo a su formulario para que controle este tipo de error de la siguiente forma

ltphp require_once(MySQLphp) if (isset($_POST[nombre]) || isset($_POST[cuenta ]))

$servidor = localhost $usuario = luis $pass = secreto $base_datos = Compras if (get_magic_quotes_gpc())

$nombre = $_POST[nombre] $cuenta = $__POST [cuenta ]

else $nombre = addslashes($_POST[nombre]) $cuenta = addslashes($_POST[cuenta])

$usuario = new Servidor_Base_Datos($servidor$usuario $pass$base_datos) $insertar = INSERT INTO Usuario(nombrecuenta) VALUacuteES ($nombre$cuenta ) $usuario-gtconsulta($insertar)

gt

Contando filas

A menudo es uacutetil conocer el nuacutemero de filas devueltas por una consulta antes de hacer cualquier cosa con el resultado Puede averiguar el nuacutemeshyro de filas mediante el uso de alguna funcioacuten de PHP o la utilizacioacuten de MySQL para obtener el nuacutemero de registros

Contar filas con PHP

La funcioacuten mysql_num_rows () devuelve el nuacutemero de filas seleccioshynadas

PHP 5 y MySQL 229

Su uso puede ampliar el objeto de bases de datos

public function numero_filas()

return mysql_num_rows($this-gtresultado)

Ademaacutes de esta funcioacuten tenemos mysql_num_f i e l d s ( ) que devuelve el nuacutemero de campos del una tabla es necesaria cuando hacemos una conshysulta de datos y no sabemos cuaacutentas columnas hemos seleccionado

Contar filas con MySQL

La alternativa es utilizar una consulta de SQL con la sentencia c o u n t ( ) Esto requiere hacer dos consultas una para obtener el nuacutemero de filas y otra para obtener el resultado

Utilicemos el objeto para realizar la operacioacuten

ltphp

require_once(MySQLphp) $servidor = localhost $usuario = root $pass = $base_datos = Compras $usuario = new Servidor_Base_Datos($servidor$usuario$pass$base_datos) $consulta = select count() as numero_filas from Usuario $usuario-gtconsulta($consulta) $fila = $usuario-gtextraer_registro() $numero_filas = $fila[numero_filas] $consulta = select from Usuario $usuario-gtconsulta($consulta) echo El nuacutemero de filas es $numero__f ilasltbrgt while ($fila = $usuario-gtextraer_registro())

foreach ($fila as $indice =gt $valor) echo $indice $valorltbrgt

gt

La primera sentencia SELECT cuenta el nuacutemero de filas y al resultado le da el nombre numero__f i l a s

Para acceder al nuacutemero se hace como siempre leyendo el resultado del irray $f i l a [ numero_f i l a s ]

La figura 123 muestra el resultado

Contar filas afectadas

Es posible que sea necesario saber cuaacutentas filas han sido afectadas desshypueacutes de antildeadir actualizar o borrar algunas filas

La funcioacuten m y s q l _ a f f e c t e d _ r o w s () devuelve el nuacutemero de registros afectados despueacutes de un cambio en las filas de una tabla Actualizando nuestra clase tenemos

public function filas_afectadas()

return mysql_affected_rows($this-gtdescriptor)

Uacuteltimo nuacutemero insertado

Cuando utilice campos auto numeacutericos en una tabla e inserte un nuevo registro seraacute uacutetil conocer el nuacutemero de la uacuteltima fila insertada

Para obtener este nuacutemero tan solo t iene que u t i l izar la funcioacuten m y s q l _ i n s e r t _ i d ( ) Se puede utilizar de la siguiente forma

public function ultima_fila()

PHP 5 y MySQL 231

return mysql_insert_id($this-gtdescriptor)

Buacutesquedas dentro de una tabla

La forma de buscar ocurrencias en una columna es utilizar la sentencia LIKE de SQL

SELECT FROM Usuario WHERE nombre LIKE Luis

El siacutembolo es un comodiacuten es decir puede sustituir a cualquier caraacutecter dentro de la columna donde busque

Definicioacuten de bases de datos

Como indicamos antes lo ideal es que un administrador de MySQL le genere las bases de datos y las tablas Despueacutes de esto con su usuario y contrasentildea podraacute hacer las consultas que tenga autorizadas

En muchos casos la figura del administrador de bases de datos no existe y es el desarrollador el que asume este papel En este caso le interesaraacute conocer la forma de crear desde un script sus bases de datos

Creacioacuten de bases de datos

Para crear una base de datos tiene que utilizar la funcioacuten m y s q l _ c r e a t e _ db () Recibe dos paraacutemetros el primero es el nombre de la base de datos que quiere crear y el segundo el descriptor devuelto por la funcioacuten m y s q _ c o n n e c t () La funcioacuten m y s q l _ d r o p _ d b () borra la base de dashytos del gestor de MySQL

ltphp $descriptor = mysq_connect($servidor $usuario $clave) mysql_create_db(Nueva_Base $descriptor) gt

Creacioacuten de tablas

La creacioacuten de tablas debe hacerse a traveacutes del lenguaje de consultas SQL como vimos en el capiacutetulo anterior Como ya sabe la funcioacuten m y s q l _

232 Capiacutetulo 12

q u e r y () acepta consultas de distintos tipos Aprovechando esto puede incluir una consulta para crear una tabla nueva

SQLite es una base de datos poco tipada es decir que soacutelo es capaz de almacenar dos tipos de datos nuacutemeros o caracteres En cambio MySQL es fuertemente tipada porque tiene un elevado conjunto de tipos para aplicar a sus columnas La tabla 121 muestra algunos tipos de datos que puede aplicar en la sentencia CREacuteATE

Tabla 121 Tipos de datos de MySQL

Nombre Tamantildeo Uso

BIT BOOLEAN 1 byte Almacena valores desde 0 a 255 sin

signo o -128 a 127 con signo SMALLINT 2 bytes De 0 a 65535 sin signo y de -32768 a

32767 con signo

MEDIUMINT 3 bytes De 0 a 16777215 sin signo o-8388608 a 8388607

INT INTEGER 4 bytes De0a4294967295ode-2147483648a 2147483647

BIGINT 8 bytes De 0 a 18446744073709551615 o -9223372036854775808a 9223372036854775807

FLOAT(precisioacuten) De 4 a Nuacutemero de coma flotante con precisioacuten

8 bytes

DATE 3 bytes Almacena una fecha

DATETIME 8 bytes Almacena una fecha con la hora y minutos

VARCHAR(nuacutemero) Nuacutemero Almacena tantos caracteres como indi-bytes ca el nuacutemero El tamantildeo es menor que

255 caracteres

TINYBLOB TINYTEXT Mayor que Almacena caracteres 255 bytes

BLOB TEXT Maacutes de Almacena un nuacutemero elevado de carac-64 kb teres

Como ejemplo puede ver el siguiente coacutedigo

lt $descriptor = mysq_connect($servidor $usuario $clave) mysql_create_db(Concesionario $descriptor) mysql_ select_db ( Concesionario) -

PHP 5 y MySQL 233

$consulta = CREacuteATE TAELE vehiacuteculos ( Iacuted_vehicul0 INT NOT NULL AUTO_INCREMENT PRIMARY KEY color VARCHAR(25) fecha_compra DATETIME)

$resultado = mysql_query($consulta) $mensaje = mysql_drop_db(Concesionario) gt

La columna i d _ v e h i c u l o identifica a un uacutenico vehiacuteculo de la tabla Como puede ver en MySQL tiene que antildeadir algunos modificadores a la columshyna para identificar sus caracteriacutesticas Estos modificadores son obligatoshyrios en MySQL Por ejemplo en SQLite no hace falta antildeadir ninguna propiedad para que el valor se incremente automaacuteticamente En MySQL es necesario especificar la propiedad AUTO_lNCREMENT Es obligatorio ademaacutes que todas las columnas tengan un tipo de dato definido

Resumen

MySQL es sin duda el sistema maacutes utilizado a escala mundial La mayor parte de las aplicaciones en PHP estaacuten escritas para MySQL porque da una fiabilidad y velocidad absolutas Hay que decir tambieacuten que la vershysioacuten 4 tiene bastantes restricciones con respecto a otros gestores de bases de datos como PostgreSQL pero se iraacuten solventando en las futuras vershysiones

Si terminoacute el capiacutetulo con eacutexito todaviacutea le queda un paso por andar La extensioacuten de MySQL que hemos utilizado es la que viene por defecto funshycionando con PHP 5 Recientemente se ha creado desde cero una nueva forma de interactuar con MySQL que permite hacer transacciones o conshysultas almacenadas (de la forma que lo hace Oracle) La extensioacuten se llashyma MySQLi y por su leve dificultad se escapa del objetivo de este libro

En este capiacutetulo aprenderaacute a

bull Diferenciar entre sesiones cookies y cabeceras HTTP bull Utilizar sesiones para ocultar variables entre usuarios y paacuteginas Web bull Almacenar la configuracioacuten de un usuario con cookies

bull Enviar informacioacuten de cabecera viacutea Web

236 Capiacutetulo 13

Introduccioacuten

Una sesioacuten es un periacuteodo de tiempo durante el cuaacutel una persona detershyminada ve un nuacutemero de diferentes paacuteginas Web de un determinado doshyminio

El protocolo HTTP no tiene forma alguna de distinguir un usuario que se conecte desde Espantildea de otro que se conecte desde Japoacuten PHP 5 proshyvee un mecanismo que permite antildeadir cierto nivel de diferenciacioacuten enshytre usuarios

Miremos un ejemplo

ltHTMLgt ltBODYgt ltphp switch ($_GET[opcioacuten ] )

case 1 echo La opcioacuten es 1 break

case 2 echo La opcioacuten es 2 break

case 3 echo La opcioacuten es 3 break

gt ltBODYgt ltHTMLgt

Esta paacutegina elige una de las opciones en funcioacuten del paraacutemetro GET que obtenga Como ya sabe GET pasa todos los valores junto a la direccioacuten Web y es visible para nosotros

El meacutetodo GET no es muy funcional cuando necesite pasar datos comproshymetidos a traveacutes de varias paacuteginas Web POST resuelve en parte este proshyblema

Este meacutetodo permite pasar entre paacuteginas las variables que quiera queshydando ocultas para el usuario A priori parece una buena forma de oculshytar datos pero nos encontramos que es necesario un formulario en cada paacutegina para utilizarla

Las sesiones y las variables de sesioacuten permiten pasar datos entre paacuteginas sin necesidad de utilizar formularios y es la mejor forma para ocultar dashytos comprometidos

Sesiones y Cookies 237

Sesiones en PHP 5

Las sesiones deben soportar

bull Detectar que durante el transcurso de la navegacioacuten por varias paacutegishynas Web la sesioacuten permanece invariable

bull Almacenar informacioacuten que formaraacute parte de una sesioacuten en concreto

PHP trabaja con una combinacioacuten de meacutetodos que son capaces de ocultar variables y cookies de las que hablaremos en un apartado posterior

Instanciando sesiones

El primer paso que nuestro script debe realizar es la llamada a la funcioacuten s e s s i o n _ s t a r t () Esta funcioacuten registra una sesioacuten en el servidor y la identifica con una cadena de 32 caracteres Cada persona que entre en ese mismo instante en la Web desde un ordenador diferente obtendraacute un iden-tificador distinto

La funcioacuten s e s s i o n _ s t a r t () debe incluirse en todas las paacuteginas Web que formen parte de la aplicacioacuten porque no soacutelo se encarga de iniciali-zar la sesioacuten sino que tambieacuten se encarga de mantener la misma sesioacuten durante el proceso La funcioacuten actuacutea de la siguiente forma

bull Si no existe una sesioacuten activa crea una nueva con un identificador

bull Si existe una sesioacuten que puede ser recuperada se extrae la sesioacuten y las variables asociadas ltphp session_start() gt ltHTMLgt ltBODYgt ltphp echo La variable de sesioacuten es SID gt ltBODYgt ltHTMLgt

La figura 131 muestra la variable de sesioacuten En el momento en que elscript escribe cualquier cosa el servidor termina de enviar las cabeceras HTTP y empieza a enviar el contenido No se puede enviar una nueva cabecera cuando ya estamos enviando el cuerpo de la Web Puesto que la funcioacuten s e s s i o n _ s t a r t () utiliza cabeceras para pasar la informacioacuten de sesioacuten

Sesiones y Cookies 239

La primera vez que instanciamos una sesioacuten seacute crea una constante llamashyda S ID que contiene el identificador de 32 caracteres que nos identifica

Variables de sesioacuten

Existe una variable suacuteper-global que se encarga de almacenar las variashybles que quiere pasar entre paacuteginas de una sesioacuten El array $_SESSION permite almacenar datos de cualquier tipo para recuperarlos en otras paacuteshyginas que tengan la misma sesioacuten El coacutedigo para propagar variables de sesioacuten puede ser tan sencillo como la paacutegina s e s i o n l php

ltphp session_start () gt ltHTMLgt ltBODYgt ltphp $_SESSION[nombre] = Luis Miguel Caberas $_SESSION[edad] = 29 echo lta href = sesion2phpgtPasar variablesltagt gt ltBODYgt ltHTMLgt

La vatvabie suacutepex-^toacutebal almacena valores de d-feteate tupo y creamas UTJ enlace a la paacutegina s e s i o n 2 php para poder recuperarlos

ltphp session_start () gt ltHTMLgt ltBODYgt ltphp echo Mostrar las variables de sesioacutenltbiacutegt foreach ($_SESSION as $indice =gt $valor)

echo $indice $valorltbrgt

echo Mostrar las COOKIESltbrgt foreach ($_COOKIE as $indice =gt $valor)

echo $indice $valorltbrgt gt ltBODYgt ltHTMLgt

Si se apoya en el bucle foreach podraacute extraer todos los valores pasados desde la Web s e s i o n l php Como curiosidad hemos introducido un bucle que extrae las variables almacenadas en c o o k i e s y puede ver en

Nota

Como veremos maacutes adelante iexclas cookies son pequentildeos contenishydos que se almacenan en el ordenador local Las cookies son muy utilizadas por los servidores Web para guardar las preferencias de un usuario o alguacuten dato interesante En realidad son variables que se guardan en el ordenador local del usuario y pueden ser resshycatadas por PHP en alguna otra ocasioacuten en la que se necesite

Problemas con los navegadores

Un problema muy comuacuten es que el usuario tenga por razones de segurishydad desactivada la opcioacuten de permitir c o o k i e s en su navegador El proshyb lema es que el o rdenador local no va a aceptar nuestra variable PHPSESSID y todas las paacuteginas creeraacuten que no existe sesioacuten activa y no podraacuten recuperar las variables Se puede resolver con unas pocas liacuteneas de coacutedigo para la paacutegina s e s i o n l php

ltphp

Sesiones y Cookies 241

session_start() gt ltHTMLgt ltBODYgt ltphp $_SESSION[nombre] = Luis Miguel Cabezas $_SESSION[edad] = 29 $id_sesion = SID echo lta href=sesion2php$id_sesiongtPasar variablesltagt gt ltBODYgt ltHTMLgt

Esta forma de trabajar implica tener que pasar en todos los enlaces el iden-tificador de sesioacuten La forma correcta de hacerlo es la que muestra el ejemshyplo ya que produce una URL de este tipo s e s i o n 2 phpPHPSESSID = 9 0 9 7 c 4 3 a a 8 6 d 3 4 5 9 b l 6 6 d 7 1 c 4 e a 4 c 9 3 0

Nota

Si quiere que PHP sea transparente manejando el paso de variashybles a traveacutes de c o o k i e s o viacutea el meacutetodo GET necesita tener configurado PHP 5 con las directivas - e n a b l e - t r a n s - s i d y - e n a b l e - t r a c k - v a r s Si estas opciones no estaacuten activashydas el uacutenico traacutemite para utilizar variables es pasar mediante GET o POST el identificado de sesioacuten corno en el ejemplo anterior

Funciones para el manejo de sesiones

La tabla 131 muestra algunas funciones interesantes con la descripcioacuten de uso

Tabla 131 Funciones relacionadas con las sesiones

Funcioacuten Descripcioacuten

session_start() Inicia una sesioacuten y permite almacenar variables en la

estructura $ _ S E S S I O N

session_destroy() Elimina todas las variables de sesioacuten

session_name() Devuelve el nombre de la sesioacuten normalmente PHPSES-SID

session_id() Devuelve los 32 caracteres que forman el identificador de sesioacuten

242 Capiacutetulo 13

Con las funciones relacionadas en la tabla anterior podemos construir un objeto que nos facilite el manejo de sesiones en nuestras aplicaciones

ltphp class sesioacuten

function constructor()

session_start() public function set($nombre$valor)

$_SESSION[$nombre] = $valor public function get($nombre)

if (isset ($_SESSION[$nombre] ) ) return $_SESSION[$nombre]

else return false

public function borrar_variable($nombre)

unset ($_SESSION[$nombre] ) public function borrarsesiacuteon()

$_SESSION = a r r a y O s e s s i o n _ d e s t r o y ( )

gt

Las paacuteginas s e s i o n l php y s e s i o n 2 php pueden manejarse ahora con la clase que hemos creado de la siguiente forma

ltphp require_once (clase__sesion php) $sesioacuten = new sesioacuten() gt ltHTMLgt ltBODYgt ltphp $sesioacuten-gtset(nombreLuis Miguel Cabezas) $sesioacuten-gtset(edad29) $id_sesion = SID echo lta href=sesion2php$id_sesiongtPasar variablesltagt gt ltBODYgt ltHTMLgt

Sesiones y Cookies 243

Cookies

Una cookie es una pequentildea parte de informacioacuten que queda almacenashyda en el ordenador local de los usuarios de una paacutegina Web Debe conteshyner siempre un nombre y un valor Es muy usual utilizar cookies para guardar preferencias de cada usuario en el uso de una Web pero hay que tener cuidado con el nuacutemero de variables que se pueden almacenar pues norshymalmente hay un maacuteximo de 20 por dominio seguacuten el navegador

En PHP 5 la funcioacuten s e t c o o k i e () se encarga de registrar las cookies durante el enviacuteo de las cabeceras Para recuperar el valor tiene que utilizar la variable suacuteper-global $_COOKIE

setcookie()

La funcioacuten s e t c o o k i e () normalmente tiene 2 argumentos el nombre de la variable y el valor Ademaacutes podemos pasar varios paraacutemetros que permiten dar un tiempo de vida a las variables asociar un dominio o aseshygurar el enviacuteo mediante HTTPS

La tabla 132 muestra en orden todos los argumentos que puede recibir una cookie

Tabla 132 Argumentos de la funcioacuten setcookie()

Argumento Tipo Descripcioacuten -

nombre caraacutecter El nombre de la variable cookie valor caraacutecter El valor que debe almacenar la variable Si este

valor no se indica la cookie seraacute automaacuteticashymente borrada

tiempo de vida entero Indica el tiempo de vida de unacookie Si el valor es 0 la variable nunca expiraraacute Si indica un nuacutemero entero tendraacute el tiempo que la variable permaneceraacute activa El valor hay que asignarlo en tiempo absoluto (como el devuelto por la funcioacuten mkt ime ())

ruta entero Permite distinguir entre dos variables con el mismo nombre pero llamadas desde distinta ruta en el servidor La cookie nombre llamada desde la ruta fo ro seraacute distinta a la cookie nombre llamada desde la ruta usuario

244 Capiacutetulo 13

Argumento Tipo Descripcioacuten

dominio caraacutecter Asegura el dominio de servidor que puede leerla cookie

Secure entero (0 Si el argumento es 1 la cookie soacutelo seraacute enviada oacute 1) a traveacutes de una conexioacuten segura HTTPS

Borrar una cookie

Borrar una cookie es faacutecil Si llama a la funcioacuten s e t c o o k i e () con los misshymos argumentos que para habilitarla excepto el valor la variable se elimishynaraacute del sistema local del usuario Si usa los paraacutemetros r u t a y dominio deben aparecer tambieacuten y con los mismos valores

Como de costumbre vamos a implementar una pequentildea clase para maneshyjar las cookies

ltphp

class Cookie

function constructor()

El constructor no hace nada

public function set($nombre$valor$expire=0$ruta= $dominio=$seguro=0)

setcookie($nombre$valor$expire$ruta$dominio$seguro)

public function get($nombre)

if (isset ($_COOKIE [$nombre] )) return $_COOKIE[$nombre] else return false

public function borrar_cookie($nombre)

setcookie($nombre$valor$expire$ruta$dominio$seguro

gt

El argumento tiempo de vida debe proporcionarse en valor de tiempo absoluto Esto a veces puede resultar incoacutemodo y seriacutea maacutes sencillo pro-

Sesiones y Cookies 245

porcionar el tiempo de vida de la variable en minutos o segundos La clase anterior solicita el tiempo en segundos y se encarga de antildeadir esos segundos al valor absoluto haciendo maacutes simple la asignacioacuten

Para ver coacutemo funciona podemos utilizar la Web c o o k i e l php

ltphp require_once(clase_cookiephp) $cookie = new CookieO $cookie-gtset(nombreLuis Miguel10) gt ltHTMLgt ltBODYgt ltphp echo La COOKIE es $cookie-gtget(nombre) echo lta href = cookie2phpgtPasar variablesltagt gt ltBODYgt ltHTMLgt

Como puede ver es muy sencilla la asignacioacuten de cookies y su recupeshyracioacuten

Cabeceras HTTP

Las funciones s e t c o o k iacute e () o s e s s i o n _ s t a r t () introducen su conteshynido en una cabecera HTTP sin necesidad de especificacioacuten por el usuashyrio Es posible enviar cabeceras desde PHP con la utilizacioacuten de la funcioacuten h e a d e r () La funcioacuten h e a d e r () es muy simple tan soacutelo toma como arshygumento un conjunto de caracteres que seraacute la cabecera a enviar Por ejemshyplo una forma muy uacutetil de redirigir una paacutegina a otra es utilizando la cabecera Location

lt php if (isset($_GET[usuario] ) ampamp $_GET[usuario] == Luis)

header(Location httpwwwluisyfernandanet)

gt lthtmlgt ltbodygt Si ve esta paacutegina su nombre no es Luis ltbodygt lthtmlgt

Este script evaluacutea si en la variable suacuteper-global $_GET existe un identifi-cador llamado u s u a r i o y si su valor es L u i s En caso afirmativo se enviacutea

246 Capiacutetulo 13

la cabecera al navegador que invita a cargar la Web especificada En caso negativo se enviacutea la paacutegina Web que hay despueacutes de la estructura if

Este tipo de uso de las cabeceras puede servir para redireccionar a una paacutegina de error cuando un usuario intente entrar sin permiso o cometa un fallo en la entrada de un nombre o correo electroacutenico

Resumen

Las sesiones resuelven los problemas muy comunes de seguridad El uso conjunto de sesiones cookies y cabeceras HTTP permiten un control absoshyluto sobre las variables de la aplicacioacuten Casi todos los programas que necesitan autentificar un usuario (como una tienda on-line) se sirven de estas teacutecnicas Pero el lector no debe quedarse aquiacute hay muchas cabeceras distintas que pueden ser uacutetiles en diferentes momentos como la autenticacioacuten viacutea HTTP

248 Capiacutetulo 14

Introduccioacuten

XML (Lenguaje de Marcas eXtensible) forma parte de SGML (Lenguaje de Marcas Generalizado eStandar) Auacuten asiacute no es necesario saber nada de SGML para utilizar XML El lenguaje XML define una estructura de documentos que pueden ser leiacutedos por personas y por ordenadores

El camino maacutes sencillo para comprender XML es pensar en coacutemo se utilishyzan los documentos HTML Estos documentos estaacuten estructurados y funshycionan con etiquetas y atributos Las etiquetas van encerradas entre siacutembolos de mayor y menor (ltbgt) y deben cerrarse de la misma forma antildeadiendo un siacutembolo de barra invertida (ltbgt) Los documentos HTML tienen una ortografiacutea especiacutefica es decir unas reglas que definen la forshyma correcta de estructurar un documento por ejemplo la etiqueta ltBODYgt debe ir siempre despueacutes de ltHEADgt o s ino existe eacutesta de ltHTMLgt Adeshymaacutes HTML contiene un diccionario cerrado de etiquetas que definen el lenguaje y no podemos utilizar otras que no esteacuten especificadas

En cambio XML no tiene un diccionario de etiquetas Las etiquetas que aparecen son las que nosotros mismos creamos La uacutenica norma que teneshymos que seguir es que toda etiqueta de inicio (ltcoche gt) debe tener una etiqueta de fin ( lt c o c h e gt )

El documento siguiente muestra un archivo XML bien formado

ltxml version=10 gt ltbibliotecagt lttema id=informaacuteticagt

ltlibrogt lttitulogtManual Imprescindible de PHP 5lttitulogt ltautorgtLuis Miguel Cabezas Granadoltautorgt

ltlibrogt ltlibrogt

lttitulogtDelphi 7lttitulogt ltautorgtMarco Cantultautorgt

ltlibrogt ltlibrogt

lttitulogtDelphi 6 y Kylixlttitulogt ltautorgtFrancisco Charte Ojedaltautorgt

ltlibrogt lttemagt

ltbibliotecagt

Como puede ver la estructura del documento es muy similar a la de una paacutegina Web Estaacute formado por etiquetas y atributos cuya definicioacuten pueshyde inventarse sobre la marcha es decir las etiquetas lt l i b r o gt lt t i t u -

Lectura y escritura de archivos XML 249

l o gt o lt s e c c i o n gt podriacutean tener un nombre totalmente diferente pero no asiacute en HTML que estaacute obligado a mantener el lenguaje definido Algushynos navegadores como Mozilla interpretan los ficheros XML como en la figura 141

Un documento XML estaacute obligado a cumplir ciertas normas que permishyten definir un texto bien formado

bull Debe tener un uacutenico elemento raiacutez Soacutelo puede haber un par de etishyquetas que diferencien el inicio y el final del documento como en HTML donde se utiliza ltHTMLgt y lt HTMLgt

bull Los elementos deben ser hereditarios La estructura lt A x B x B gt lt Agt se permite pero no la siguiente lt A x B x A x B gt En la primera forma la etiqueta ltAgt envuelve a la etiqueta ltBgt que es la forma coshyrrecta de escribir un documento XML HTML sin embargo permite la segunda forma de componer un documento ltA HREF=indexphpgt ltBxAx Bgt

bull Todos los elementos tienen que tener una etiqueta de cierre La pareja ltt i tulogtltt i tulo es correcta HTML permite etiquetas sin cerrar como ltBgt o ltLIgt

bull Los elementos pueden tener entre las dos etiquetas cualquier tipo de contenido como lttitulogtManual imprescindible de PHP 5lttitulogt

250 Capiacutetulo 14

bull Los caracteres amp lt gt las comillas simples y las comillas dobles estaacuten prohibidas como contenido y deben utilizarse siacutembolos de escape para utilizarlas

SAX DOM y SimpleXML

Lo primero que tenemos que hacer antes de leer archivos XML es conocer las tres formas existentes con sus ventajas e inconvenientes

bull SAX Es maacutes ligero y faacutecil de aprender trata los archivos XML como un flujo de datos que se leen poco a poco

bull DOM Lee el fichero completo y crea un objeto en memoria Permite crear archivos desde cero

bull SimpleXML Es el maacutes sencillo de utilizar Los elementos se pueden leer con un simple f o r e a c h

SAX

Se utiliza para parsear elementos XML Estaacute basado en eventos lo que sigshynifica que el parse hace llamadas a determinadas funciones dependiendo de los elementos que examina

Los eventos de SAX son proporcionados por PHP en forma de funcioacuten Al parsear se reconocen piezas de XML como etiquetas de inicio o fin datos o entidades externas y cada una de estas piezas hace una llamada a un evento El procedimiento para parsear un archivo XML con SAX debe seshyguir los siguientes pasos

bull Determinar queacute clase de eventos queremos manejar

bull Escribir una funcioacuten que maneje cada evento Es muy comuacuten escribir una funcioacuten para manejar los datos y las etiquetas de inicio y de fin

bull Crear el parse usando la funcioacuten x m l _ p a r s e r _ c r e a t e () y hacer la llamada con x m l _ p a r s e ()

bull Liberar la memoria usada con la funcioacuten x m l _ p a r s e r _ f r e e ( )

Hemos creado un objeto para leer archivos XML En principio no hace gran cosa tan solo examina las etiquetas de inicio y fin y las imprime en pantalla pero con esto bastaraacute para aprender la peculiar estructura de un parse SAX

ltphp

Lectura y escritura de archivos XML 251

class xml

function construct($fichero_xml)

$this-gtfichero_xml = $fichero_xml $this-gtxml_parser=xml_parser_create()

Puesto que el parse lo creamos desde un objeto debemos registrar la incidencia con xml_set_object

xml_set_obj ect($this~ gtxml_parser$this) Funciones de callback para manejar XML mediante SAX

xml_set_element_handler($this-gtxml_parserelemento_ inicioelemento_fin) if (($fp = fopen($this-gtfichero_xmlr)))

die (Error de Entrada y Salida)

while ($datos = fread($fpfilesize($this-gtfichero_xml)))

if (xml_parse($this-gtxml_parser$datos feof($fp)))

die (Fallo en el XML) xml_error_string(xml_get_error_ code($this-gtxml_parser))

xml_parser_free($this-gtxml_parser)

function elemento_inicio ($parser$nombre$atributos)

echo $nombreltbrgt

function elemento_fin ( $parser$nombre)

echo $nombreltbrgt

$biblioteca = new xml(bibliotecaxml) gt

Si guarda la clase en un archivo llamado c l a s e _ x m l php podraacute usarla en sus proyectos tan soacutelo con instanciar el objeto Si comienza por el consshytructor veraacute que el paraacutemetro que recibe es el archivo que quiere par-sear Debe crear el parse con la f u n c i oacute n x m l _ p a r s e _ c r e a t e () y despueacutes registrarlo en PHP como un objeto mediante la funcioacuten x m l _ s e t _ o b -j e c t () Si crea un parse fuera de la estructura de un objeto no haraacute falta hacer la llamada a la funcioacuten anterior

252 Capiacutetulo 14

La funcioacuten x m l _ s e t _ h a n d l e r () indica al parse que los eventos encarshygados de encontrar las etiquetas de inicio y de fin seraacuten manejadas con las funciones que se pasan como paraacutemetro En este c a s o e l e m e n t o _ i n i c i o ( ) se ejecutaraacute cada vez que se encuentre una etiqueta de inicio y e l e m e n t o _ f in ) cuando se encuentre la etiqueta de cierre

La uacuteltima parte del constructor lee el archivo pasado como argumento y analiza los datos a traveacutes de la funcioacuten x m l _ p a r s e ( ) que inicia la seshycuencia de anaacutelisis Si ejecuta una instancia de la clase comprobaraacute que el navegador muestra todas las etiquetas de inicio y de fin con una rigurosa herencia La figura 142 muestra las etiquetas leiacutedas del archivo XML

Para poder ver los datos tiene que antildeadir una nueva funcioacuten que maneje ese evento La f u n c i oacute n x m l _ s e t _ c h a r a c t e r _ d a t a _ _ h a n d l e r () permite manejar el evento que se dispara cada vez que se encuentra un dato entre dos etiquetas Esta funcioacuten tendraacute que antildeadirla al constructor despueacutes del meacutetodo que maneja los eventos de etiquetas

xml_set_character_data_handler($this-gtxml_parserdatos)

Ademaacutes de esto tendraacute que incluir una nueva funcioacuten que se encargaraacute de mostrar los datos

function datos($parser$valor)

Lectura y escritura de archivos XML 253

echo $v9lorltbrgt

Nota

Los eventos antildeadidos deben iexcllevar Jos argumentos necesarios para recuperar los datos Cada vez que cree un par se del tipo SAX las funciones tienen que tener los paraacutemetros que indicamos en nuesshytra clase de ejemplo

Despueacutes de comprobar el funcionamiento de la clase puede modificarla para que haga algo realmente uacutetil como mostrar ordenadamente los dashytos del fichero Las funciones de la clase pueden quedar de esta forma

function elemento_inicio ($parser$nombre$atributos)

switch($nombre) case TEMA

$tema = $atributos [ ID ] bull echo Tema $temaltbrgt break

case TITULO echo ltbgt break

case AUTOR echo - break

function elemento_fin ($parser$nombre)

switch($nombre) case TITULO

echo ltbgt break

case AUTOR echo ltbrgt break

function datos($parser$valor)

echo $valor

En este caso el parser iraacute analizando las etiquetas que nos interesan y reashylizaraacute una accioacuten determinada Por ejemplo cuando se comprueba la exis-

254 Capiacutetulo 14

tencia de una etiqueta TITULO escribimos en HTML la etiqueta de negrishyta ltBgt para resaltar este dato como muestra la figura 143

Elaborando un poco maacutes la clase obtendraacute un objeto de gran utilidad que podraacute recuperar informacioacuten de bases de datos o archivos de configurashycioacuten

DOM

Esta API define un completo camino para crear definir y parsear archivos XML D O M es una recomendacioacuten del consorcio World Wide Web

La idea baacutesica consiste en que todos los archivos XML pueden verse como un conjunto de nodos que forman parte de un aacuterbol Empezando desde el elemento raiacutez del que todos los elementos nacen como hijos cualquier programa deberiacutea ser capaz de crear una estructura loacutegica del documento

La API puede utilizarse para leer archivos en memoria modificarlos y volver a escribir el archivo con los nuevos datos

DOM estaacute escrito en metodologiacutea orientada a objetos y todos los nodos son instancias de diferentes objetos

Lectura y escritura de archivos XML 255

Usar DOM para leer archivos

El siguiente coacutedigo muestra un archivo XML muy simple

ltxml version=l0 gt lttema id=informaacuteticagt

lttitulogtManual Imprescindible de PHP 5lttitulogt lttemagt

Si parseamos este documento con DOM la etiqueta t i t u l o seraacute consideshyrada un nodo y ademaacutes un hijo del nodo raiacutez que en este caso es tema Esta parte queda maacutes o menos clara debido a la jerarquiacutea de etiquetas que tiene XML La controversia llega con el texto que hay en el nodo tema que no se considera como una parte sino como un nodo independiente cuyo valor es el texto Manual I m p r e s c i n d i b l e de PHP 5 Este nodo permite recuperar el valor con el meacutetodo n o d e V a l u e

Vamos a ver los pasos necesarios para leer el archivo b i b l i o t e c a xml ya que difiere bastante la metodologiacutea con respecto a SAX

Todo es un objeto

PHP 5 implementa una clase DOM para representar los archivos XML llashymada domDocument Como ya sabe para instanciar la clase soacutelo tiene que hacer uso del operador de objetos

$biblioteca = new domDocument

La extensioacuten D O M sigue las especificaciones de XML y trata los espacios en blanco como contenido Esto significa que si entre dos etiquetas existe un espacio el contenido seraacute tratado como un objeto de texto Para evitar fallos de este tipo puede ejecutar el siguiente meacutetodo

preserveWhiteSpace = f a l s e

Lo siguiente que tendraacute que hacer es leer el archivo b i b l i o t e c a xml con el meacutetodo l o a d () del objeto $ b i b l i o t e c a Si el contenido XML se almacena en una variable puede utilizar el meacutetodo loadXML ()

$biblioteca-gtload(bibliotecaxml)

A partir de aquiacute ya puede recuperar el contenido del fichero atendienshydo a sus preferencias En SAX teniacutea que leer el documento completo e ir preguntando etiqueta por etiqueta para averiguar todos los autores que estaban dados de alta en el archivo XML En D O M puede recupeshyrar esta informacioacuten usando g e t E l e m e n t s B y T a g n a m e () que devuelshyve un conjunto de objetos que coinciden con la etiqueta que pase como paraacutemetro

256 Capiacutetulo 14

ltphp Instanciamos el objeto $biblioteca = new domdocument Anulamos la posibilidad de que un espacio en blanco sea un obj eto $biblioteca-gtpreserveWhiteSpace = false Leemos el archivo XML $biblioteca-gtload(bibliotecaxml) Buscamos todas las etiquetas libro $libros = $biblioteca-gtgetElementsByTagname(libro) Imprimimos todos los libros foreach ($libros as $libro)

echo $libro-gtfirstChild-gtnodeVaiue ltbrgt

gt

La variable $ l i b r o s es en realidad un objeto de la clase d o m n o d e l i s t y guarda una relacioacuten de nodos cuya etiqueta es l i b r o es decir hemos seleccionado todos los libros del archivo Con un bucle f o r e a c h podeshymos sacar todos los valores Antes vimos que el texto asociado a un nodo es un nodo hijo con un valor determinado por eso debe llamar al meacutetodo f i r s t C h i l d

El hijo de la etiqueta l i b r o es el texto asociado y su valor lo podemos recibir llamando a n o d e V a l u e

El resultado es la lista de libros

Manual Imprescindible de PHP 5 Delphi 7 Delphi 6 y K y l i x

Atributos

Para recuperar los atributos de los nodos estaacute el meacutetodo g e t A t t r i b u -te ( ) al que tiene que pasar como argumento el nombre del atributo El archivo b i b l i o t e c a xml tiene una uacutenica etiqueta con el atributo id pero nos sirve para mostrar coacutemo funciona el meacutetodo

ltphp $biblioteca = new domdocument -$biblioteca-gtpreserveWhiteSpace = false $biblioteca-gtload(bibliotecaxml) $temas = $biblioteca-gtgetElementsByTagname(tema) foreach ($temas as $tema)

echo $tema-gtgetAttribute(id)

gt

El resultado es el nombre del tema o temas que esteacuten almacenados

Lectura y escritura de archivos XML 257

Buacutesquedas muacuteltiples

Nuestro objetivo final es mostrar todos los tiacutetulos con sus autores ordeshynados por temaacutetica Conociendo ya los meacutetodos principales para recorrer los objetos DOM es sencillo pensar en un coacutedigo que implemente lo que pedimos

ltphp $biblioteca = new domdocument Sbiblioteca-gtpreserveWhiteSpace = false $biblioteca-gtload(bibliotecaxml) $biblioteca-gtdocumentElement $temas = $biblioteca-gtgetElementsByTagname(tema)bull foreach ($temas as $tema)

echo Tema $tema-gtgetAttribute(id) ltbrgt $libros = $tema-gtgetElementsByTagname(libro) foreach ($libros as $libro)

echo ltbgt $libro-gtfirstChild-gtnodeValue ltbgt - $autores = $libro-gtgetElementsByTagname(autor) foreach ($autores as $autor)

echo $autor-gtfirstChild-gtnodeValue ltbrgt

gt

Aunque es un poco maacutes complejo el fundamento baacutesico es ir utilizando bucles para leer los hijos de un nodo determinado hasta recuperar todos los datos necesarios

Escribir archivos XML con DOM

D O M permite hacer maacutes cosas que la simple impresioacuten de los datos en pantalla Se puede utilizar para crear nuevos documentos con el nivel de jerarquiacutea que quiera Para hacer esto debe apoyarse en la creacioacuten de obshyjetos de la clase domElement ()

Vamos a crear un script para crear el siguiente archivo XML ltxml ve r s ion=1 0gt lt b i b l i o t e c a gt

lttemagtTextolttemagt lt b i b l i o t e c a gt

Para crearlo necesita instanciar una serie de objetos que empieza por la creacioacuten de un documento DOM mediante la utilizacioacuten del objeto d o shymdocument ()

ltphp

258 Capiacutetulo 14

$biblioteca = new doradocument(10) $raiz = new domelement(biblioteca) $raiz = $biblioteca-gtappendChild($raiz) $tema = new domelement(temaTexto) $tema = $raiz-gtappendChild($tema) $biblioteca-gtsave(bibliotecaxml) gt

La variable $ r a i z es el objeto que contendraacute todo el documento Para crear las etiquetas tiene que utilizar el meacutetodo a p p e n d C h i l d ( ) El objeto que llama al meacutetodo contendraacute como hijo al elemento que se pasa como paraacuteshymetro

Si se fija en el ejemplo $tema es un nuevo elemento que tendraacute la etiqueshyta tema

Para que $tema sea un hijo de la raiacutez debe hacer que el objeto padre $ r a i z llame al meacutetodo a p p e n d C h i l d () con el paraacutemetro $tema

Para grabar el resultado final el objeto D O M tiene que llamar al meacutetodo s a v e ( ) El fichero b i b l i o t e c a xml lo puede crear con el coacutedigo sishyguiente

ltphp $biblioteca = new domdocument(10) $raiz = new domelement(biblioteca) $raiz = $biblioteca-gtappendChild($raiz) $tema = new domelement(tema) $tema = $raiz-gtappendChild($tema) $tema-gtsetAttribute(idinformaacutetica) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloManual Imprescindible de PHP 5 bull $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autor Luis Miguel Cabezas Granado) $autor = $libro-gtappendChild($autor) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloDelphi 7 ) $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autorMarco Cantu) $autor = $libro-gtappendChild($autor) $libro = new domelement(libro) $libro = $tema-gtappendChild($libro) $titulo = new domelement(tituloDelphi 6 y Kylix) $titulo = $libro-gtappendChild($titulo) $autor = new domelement(autor Francisco Charte Ojeda) $autor = $libro-gtappendChild($autor) $biblioteca-gtsave(bibliotecaxml) gt

Lectura y escritura de archivos XML 259

El conjunto de liacuteneas de coacutedigo anterior crea un archivo completo XML Quizaacute sea mejor dividir el texto en funciones recursivas que permitan teshyclear menos a la hora de crear los documentos pero eso ya es trabajo para el lector El meacutetodo s e t A t t r i b u t e () antildeade un atributo al objeto que hace la llamada el primer argumento seraacute el nombre del atributo y el segundo su valor La llamada a domelement () puede tener uno o dos valores Si lleva un atributo significaraacute que el nombre de la etiqueta seraacute ese paraacutemeshytro Si se llama con dos paraacutemetros el primero seraacute el nombre de la etiqueta y el segundo un objeto de texto que se antildeadiraacute como texto hijo del nodo

Modificar archivos XML

La verdadera potencia de D O M reside en el poder de gestionar los archishyvos para antildeadir modificar o eliminar nodos La mayoriacutea de los algoritmos que realizan alguna de estas operaciones se basan en la buacutesqueda de los nodos para posteriormente antildeadir hijos nuevos o eliminar los encontrashydos Para antildeadir nuevos elementos se hace como cuando creamos el ficheshyro b i b l i o t e c a xml con el meacutetodo a p p e n d C h i I d ( ) Antes de antildeadir nuevos nodos tiene que localizar el lugar exacto donde quiere antildeadir las etiquetas El ejemplo siguiente muestra coacutemo antildeadir un nuevo nodo tema

ltphp $biblioteca = new domdocument(10) $biblioteca-gtload(bibliotecaxml) $raiz = $biblioteca-gtdocumentElement $tema_nuevo = new domelement(tema) $tema_nuevo = $raiz-gtappendChild($tema_nuevo) $tema_nuevo-gtsetAttribute (id ficcioacuten ) $biblioteca-gtsave(biblioteca2xml) gt

Los pasos son los que ya ha aprendido Cargue el documento y cree un objeto llamado $ r a i z que se convierta en la etiqueta raiacutez mediante el meacutetodo documentElement Cree un nuevo elemento del tipo tema y antildeaacuteshydalo para despueacutes insertar el atributo que se necesita Por uacuteltimo guarde el archivo en el fichero b i b l i o t e c a 2 xml

SimpleXML

Probablemente el punto maacutes fuerte de PHP 4 fue la incorporacioacuten de heshyrramientas para el soporte de XML PHP 5 le da una vuelta maacutes a la tuerca

260 Capiacutetulo 14

implementando nuevas herramientas de lectura elaboracioacuten y modificashycioacuten de archivos XML basado en la libreriacutea l i b x m l 2 y una nueva API llamada SimpleXML

Si XML es un lenguaje bien construido y legible por personas y ordenadoshyres los programas para manipular estos archivos deberiacutean ser tambieacuten sencillos de utilizar SimpleXML nace con esta premisa permitiendo leer un fichero completo con una sola instruccioacuten e inmediatamente despueacutes poder leer los datos como conjunto de variables PHP

El conjunto de funciones que pertenece a la API SimpleXML es nuevo en PHP 5 Mantiene una absoluta flexibilidad a favor de la simplicidad y bajo nivel de memoria usado SimpleXML utiliza el menor nuacutemero de liacuteneas de coacutedigo para leer o escribir datos en un fichero XML El e jemplo s iguiente muestra coacutemo p o d e m o s parsear el a rch ivo b i b l i o t e c a xml

ltphp $biblioteca = simplexTnl_load_fiie(bibliotecaxml) foreach ($biblioteca-gttema as $tema)

echo Tema es $tema[id] ltbrgt foreach ($tema-libro as $libro)

echo ltbgt $libro-gttitulo ltbgt -

echo $libro-gtautor ltbrgt

gt

Lo primero que llama la atencioacuten es que en apenas 10 liacuteneas de coacutedigo se ha conseguido extraer todos los datos necesarios a diferencia de SAX o DOM

La funcioacuten s implexml__load_f i le () crea un objeto con el archivo XML que pase como argumento

A partir de aquiacute puede acceder a todos los datos asiacute como acceder a las variables de los objetos

echo $biblioteca-gttema-gtlibro [0] -gttitulo echo $biblioteca-gttema-gtlibro[1]-gttitulo

Para extraer el contenido que necesita lo maacutes sencillo es crear una estrucshytura de bucles f o r e a c h para ir sacando los datos ordenados

El nombre SimpleXML es totalmente descriptivo aunque no hay que conshyfundir la palabra simple con baacutesico La prueba de su potencia estaacute en que los desarrolladores de PEAR van a utilizar SimpleXML para desarrollar su libreriacutea de SOAP

Lectura y escritura de archivos XML 261

Resumen

XML se ha convertido en un estaacutendar para el intercambio de informacioacuten en Internet Numerosas aplicaciones estaacuten construidas con alguacuten tipo de tecnologiacutea que implementa XML como XML-RPC RSS o SOAP

En este capiacutetulo ha aprendido a leer y escribir documentos de tres formas posibles La maacutes completa sin duda es DOM que permite ademaacutes de leer archivos escribir y modificarlos a nuestro antojo El problema es que pueshyde resultar algo complicado de entender al principio y quizaacute no merezca la pena en aplicaciones sencillas

En el capiacutetulo siguiente conoceraacute la verdadera aplicacioacuten praacutectica Basaacutenshydonos en SimpleXML y en DOM crearemos algunas clases para leer archishyvos de noticias o ejecutar funciones definidas en un ordenador remoto

264 Capiacutetulo 15

Introduccioacuten

Existen en el mercado muchas publicaciones que hablan sobre XML y sus tecnologiacuteas derivadas En estos libros que suelen ser de unas 1000 paacuteginas se hace un recorrido por todos los rincones de XML DTD XLST etceacutetera Si lee alguna publicacioacuten de este tipo puede quedar desencanshytado porque entre tantos conceptos no se ve una aplicacioacuten real de la tecnologiacutea

Como este libro es eminentemente praacutectico me gustariacutea que el lector aprenshydiera dos metodologiacuteas que se utilizan actualmente en la Web RSS y XML-RPC La primera describe una forma de exportar informacioacuten noticias o datos al exterior para que desde cualquier paacutegina Web puedan leerse La segunda es una forma de trabajar que permite ejecutar funciones que esshytaacuten almacenadas en un ordenador remoto

Compartir informacioacuten con RSS

RSS es un mecanismo para publicar informacioacuten sobre el contenido de un sitio Web y es muy comuacuten utilizarlo para dar las uacuteltimas noticias Esto permite introducir en su sitio Web un documento XML con noticias de otras paacuteginas

La versioacuten original de RSS la 090 fue creada por Netscape con el objetishyvo de crear portales servidores de noticias de distinta categoriacutea pero reshysultoacute algo complejo de utilizar La versioacuten 091 mucho maacutes simple la desarrolloacute la empresa UserLand Software quien lo comercializoacute como parte de sus productos basados en paacutegina Web como los Weblogs

Un tercer grupo de desabolladores independientes basaacutendose en los coshymienzos de RSS la versioacuten 090 escribioacute una nueva revisioacuten basada en RDF esta versioacuten recibe el nombre de RSS 10 Desde la aparicioacuten de la versioacuten 01 UserLand Software ha seguido desarrollando las versiones 092 093 094 y la 20

Distintos formatos

Existen 7 formatos distintos y como programador deberiacutea ser lo suficienshyte habilidoso como para manejar cualquiera de ellos Pero como el conteacute-

Aplicaciones praacutecticas de XML 265

nido lo produce la Web que desea exportar su informacioacuten tendraacute que tener en cuenta las caracteriacutesticas de cada formato

Tabla 151 versiones de RSS

Versioacuten Desarrollo Descripcioacuten Status Recomendacioacuten

090 Netscape Obsoleta No usar por la apashyricioacuten de 10

091 UserLand Simple Muy popular Sencilla y faacutecil de pero obsoleta migrar a la versioacuten por la aparicioacuten 20 de 20

092 UserLand Permite texto Obsoleto por Mejor usar la 20 093 enriquecido y la 20 094 metadatos

10 Grupo de Basado en Muy estable Usar si necesitamos desarrollo RDF y exten- especificaciones RSS-DEV sible con avanzadas

moacutedulos

20 UserLand Exter=Aacuteble corraquo EsteWe y ef Uso de caraacutecter moacutedulos Faacutecil continuo general con meta-de migrar desarrollo datos y texto enri-desde cualquier quecido versioacuten 09

Como ejemplo vamos a leer el RSS 10 de la Web del autor wwwluisy fernandanet que contiene esta informacioacuten

ltxml version=10 encoding=iso-8859-1 gt ltrdfRDF xmlnsrdf=httpwwww3org19990222 -rdf-syntax-ns xmlns=httpmynetscapecomrdfsimple09gt

ltchannelgt lttitlegtwwwluiacutesyfernandanetlttitlegt ltlinkgthttpwwwluisyfernandanetiacutendexphp

blogId=2ltlinkgt ltdescriptionxdescriptiongt

ltchannelgt ltitemgt

lttitlegtPHP 5 en la liacutenea de salidalttitlegt ltdescriptiorvgtiacuteuumladi Gutwampias dice que en 24 horas estaraacute lista la nueva versioacuten de PHP5 bull que nervios ampltbr

266 Capiacutetulo 15

ampgtPara el que no pueda esperar la Releacutease Candidate 4 estaacute en amplta href =ampquothttp snapsphpnet~andiampquotampgthttpsnapsphpnet ~andiampltaampgtampltbrampgt ampltbrampgtampltbrampgtlt descriptiongt

ltlinkgthttpwwwluisyfernandanetiacutendexphpop=View ArticleampamparticleId=41ampampblogId=2ltlinkgt ltitemgt

lt itemgt lttitlegtGalopiacuten 10lttitlegt ltdescriptiongt amplt a

href=ampquothttpwwwluisyfernandanetresserverphp blogId=2amp amp resource=DSCN0840 JPG ampquot ampgt amplt img align=ampquot rightampquot style=ampquotmargin 5pxampquot border=ampquotOampquot alt=ampquotRueda de prensaampquot src=ampquothttpwwwluisyfernandanetresserver phpblogId=2ampampresource=DSCN0 840JPGampampmode=previewampquot ampgtampltaampgt

Hoy se ha presentado en la AAVV de La Antigua en Meacuterida la versioacuten 10 de Galopiacuten una herramienta escrita en PHP por dos desarrolladores extrementildeos Tras los forcejeos con la prensa y las salidas con quite de los implicados nos quedamos con la miel en los labios deseando probar la aplicacioacuten y porqueacute no destriparla para ver como funciona el chismeampltbr ampgtEl que quiera descargarla puede hacerlo desde la Web de sinuh en amplta href=ampquothttp galopinsinuhorgampquotampgtgalopinsinuhorgampltaampgtampltbr

ampgtScltbxSiacutegpound ampltbr ampgtltdescriptiongt ltlinkgthttpwwwluisyfernandanet

indexphpop=ViewArticleampamparticleld=4 0ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtEL TIEMPO DE MERIDAlttIacutetlegt ltdescriptiongt Hace unos diacuteas empeceacute escribir alguna cosilla para averiguar

la temperatura que hay en Meacuterida Los datos los recojo de la Web del Instituto Nacional de Meteorologiacutea y los plasmo en una tabla Si quieres puedes utilizar los datos llamando a la Web amplt a href = ampquothttpwwwluisyfernandanet clase_tiempophpLOCALIDAD=MERIDAampquotampgthttp wwwluisyfernandanetclase_tiempophpLOCALIDAD=MERIDAamplt aampgtampltbr ampgtDonde pone LOCALIDAD se puede poner alguna poblacioacuten distinta como CORIA CACERES BADAJOZUNIVERSIDAD etcampltbr ampgtEl moacutedulo estaacute en fase alfa y el dibujito que aparece puede que no corresponda con la realidad pero es un avance )ampltbr ampgtEn unas semanas implementareacute el servicio en SOAP como lo hace weathercomampltbr ampgtSaludosampltbr ampgtampltbr ampgtampltbr ampgtampltbrampgt

Aplicaciones praacutecticas de XML 267

ampltbr ampgtltdescriptiongt ltlinkgthttpwwwluisyfernandanet

indexphpop=ViacuteewArticleampamparticleld=3 6ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtPHP 5 a punto de caramelolttitlegt ltdescriptiongtHace un par de diacuteas en la lista interna de

desarrolladores de PHP Andi Gutmans ha escrito que PHP5 ya estaacute horneado y le falta un poquito de chocolate para salir al mercado Estaacuten teniendo alguacuten problemilla con libreriacuteas que controlan el acceso a memoria pero se preveacute que la primera versioacuten estable salga esta semana ampltbr ampgtamplta href=ampquothttpwwwzendcomlistsphp-dev2004 07 msg00059htmlampquot ampgtNotica de Zend ampltaampgtampltbr ampgtampltbr ampgtltdescriptiongt

ltlinkgthttpwwwluisyfernandanet indexphpop=ViewArticleampamparticleld=3 3ampampblogId=2ltlinkgt ltitemgt ltitemgt lttitlegtOpenOffice2htm en Sourceforgelttitlegt ltdescriptiongt Acaban de aceptar el Proyecto OpenOffice2htm

en sourceforge ellos sabraacuten lo que hacen Lo que pasa es que tengo un pequentildeo problema entre tanto menuacute de administracioacuten de ficheros documentos etc me pierdo y por ahora no he podido subir ninguacuten fichero de la clase Espero aclararme estos diacuteas y tener listo la primera Releacutease en amplta href=ampquothttpwwwluisyfernandanet wwwsourceforgecomampquotampgtwwwsourceforgecomamplt aampgtampltbr ampgtampltbrampgtampltbr ampgtltdescriptiongt

ltlinkgthttpwwwluisyfernandanet indexphpop=ViewArticleampamparticleld=17ampampblogId=2ltlinkgt ltitemgt ltrdfRDFgt

El archivo anterior muestra las uacuteltimas noticias de la Web www lu i sy fernadanet sobre PHP y proyectos en los que el autor estaacute involucrado

Si se fija no es maacutes que un archivo XML con un formato determinado

Puede verlo en la figura 151

Tiene dos partes diferenciadas

bull Una parte de descripcioacuten del documento entre las etiquetas ltchan-n e l gt En esta zona puede encontrar el tiacutetulo de Web donde estaacuten las noticias la URL del archivo RSS y una descripcioacuten de la temaacutetica que aborda

bull Otra zona entre los nodos lt i t emgt que contiene todas las noticias que quiere exportar

Leer un archivo RSS

En el capiacutetulo anterior vimos coacutemo parsear un archivo XML creado por nosotros mismos Esta vez tenemos que extraer el contenido que nos inshyteresa de un archivo con un formato determinado Vamos a crear un peshyquentildeo objeto que sea capaz de insertar en nuestra Web las noticias de la paacutegina wwwluisyfernandanet Por supuesto vamos a utilizar SimpleXML por ser una de las herramientas estrella de PHP 5

ltphp class SimpleRSS

priacutevate $RSS function construct($fichero)

$this-gtRSS = simplexml_load_file($fichero)

public function parsea_item() foreach ($this-gtRSS-gtitem as $item)

$this-gtparsea_titulo($item) $this-gtparsea_descripcion($item) $this-gtparsea_enlace($item)

private function parsea_titulo($item)

Aplicaciones praacutecticas de XML 269

echo $item-gttitle bull ltbrgt echo lthrgt

priacutevate function parsea_descripcion ($item)

echo $item-gtdescription ltbrgt

priacutevate function prsea_enlace($item)

echo $item-gtlink bull ltbrgt

public function paiacutesea_cabecera()

ampc^o Titilo- laquo St^va-^SSS-gtet^trade^l-gttltLe -JaxV- echo Web $this-gtRSS-gtchannel-gtlink ltbrgt echo lthrgt

$RSS = new SimpleRSS(httpwwwluisyfernandanet rssphpcategoryId = 3ampblogId=2 ) $RSS-gtparsea_cabecera () $RSS-gtparsea_item() gt

Si ejecuta el programa tendraacute como resultado las uacuteltimas noticias sobre PHP del portal wwwluisyfernandanet separadas por liacuteneas horizontashyles El meacutetodo puacuteblico p a r s e a _ i t e m () es el encargado de extraer notishycia a noticia y mandarlas al navegador Este meacutetodo hace 3 llamadas a 3 meacutetodos distintos que se encargan de recuperar el tiacutetulo el enlace a la noticia y la descripcioacuten Hemos separado los meacutetodos para que cada lector personalice la forma de visualizar los distintos datos Mi forma particular puede verla en la fishygura 152 Por ejemplo el tiacutetulo podriacutea mostrarlo en azul y el texto en gris todo metido en una tabla-

Escribir archivos RSS

Los archivos XML y en particular los archivos RSS pueden generarse de la misma forma que creamos un fichero de texto antildeadiendo etiquetas con cierto criterio a un archivo de texto pero la opcioacuten maacutes correcta es utilizar DOM para generar nuestros propios documentos de noticias Como ya sabe la extensioacuten DOM permite antildeadir borrar y modificar eleshymentos a lo largo de un documento en cualquier orden

Para este cometido tenemos la siguiente clase que nos va a generar docushymentos RSS a partir de cualquier fuente de datos

ltphp class GeneraRSS

priacutevate documento private $raiz priacutevate $channel private $titulo private $enlace private descripcioacuten private $item function construct() $this-gtdocumento = new domdocument(1bull0 ) $this-gtinicio ( )

private function inicio() $this-gtraiz = $this-gtdocumento-gtcreateElement(rdfRDF ) $this-gtraiz-gtsetAttribute(xmlnsrdfhttpwwww3org1999 0222-rdf-syntax-ns) $this-gtraiz-gtsetAttribute(xmlnshttppurlorgrss10) $this-gtraiz = $this-gtdocumento-gtappendChild($this-gtraiz)

Aplicaciones praacutecticas de XML 271

pub l i c funct ion c a n a l ( $ t i t u l o $ e n l a c e $ d e s c r i p c i o n $ s o b r e )

$this-gtchannel = $this-gtdocumento-gtcreateacuteElement(channel) $this-gtchannel = $ th i s -gtra iz -gtappendChi ld ($ th i s -gtchanne l ) $ th i s -gt t i tu lo=$th i s -gtdocumento-gtcrea teElement ( t i t l e ) $ th i s -gt tex to t i t u lo=$ th i s -gtdocumen to -gtc rea t eTex tNode($ t i tu lo ) $ t h i s - gt t i t u l o - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o t i t u l o ) $ t h i s - gt c h a n n e l - gt a p p e n d C h i l d ( $ t h i s - gt t i t u l o ) $ t h i s - gt e n l a c e = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l s m e n t ( l i n k ) $ th i s -gt tex toen lace=$th i s -gtdocumento-gtcrea teTextNode($en lace) $ t h i s - gt e n l a c e - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o e n l a c e ) $ th i s -gtchanne l -gtappendChi ld ($ th i s -gten lace ) $ t h i s - gt d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( d e s c r i p t i o n ) $ t h i s - gt t e x t o d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e T e x t N o d e ( $ d e s c r i p c i o n ) $ t h i s - gt d e s c r i p c i o n - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o d e s c r i p c i o n $ th i s -gtchanne l -gtappendCh i ld ($ th i s -gtdesc r ipc ion )

pub l i c funct ion i t em_nuevo($ t i tu lo $en lace $descr ipcion)

$this-gti tem = $this-gtdocumento-gtcreateElltment( i tem) $ this-gti tem = $ th i s -gtra iz -gtappendChi ld ($ th i s -gt i t em) $ t h i s - gt t i t u l o = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( t i t l e ) $ th i s -gt t ex to t i t u lo=$ th i s -gtdocumen to -gtc rea t eTex tNode ($ t i t u lo ) $ t h i s - gt t i t u l o - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o t i t u l o )

$ t h i s - gt i t e m - gt a p p e n d C h i l d ( $ t h i s - gt t i t u l o ) $ t h i s - gt e n l a c e = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( l i n k ) $ th i s -gt tex toen lace=$th i s -gtdocumento-gtcrea teTextNode($en lace) $ t h i s - gt e n l a c e - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o e n l a c e ) $ t h i s - gt i t e m - gt a p p e n d c h i l d ( $ t h i s - gt e n l a c e ) $ t h i s - gt d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e E l e m e n t ( d e s c r i p t i o n ) $ t h i s - gt t e x t o d e s c r i p c i o n = $ t h i s - gt d o c u m e n t o - gt c r e a t e T e x t N o d e ( $ d e s c r i p c i o n ) $ t h i s - gt d e s c r i p c i o n - gt a p p e n d C h i l d ( $ t h i s - gt t e x t o d e s c r i p c i o n ) $ t h i s - gt i t e m - gt a p p e n d C h i l d ( $ t h i s - gt d e s c r i p c i oacute n ) $ th i s -gt i t ems [ ]=$ th i s -gt i t em

public function grabar($fichero) $this-gtdocumento-gtsave($fichero)

^documento = new GeneraRSS () ^documento-gtcanal (wwwluisyfernandanet httpwwwluisy fernandanet La Web del auto) $docimeito-gtitev1_YYievo VMaiwial Imprescindible de PHP 5 http- v iwwluisyfernandanet Ya a la v e n t a )

272 Capiacutetulo 15

$documento-gtitem_nuevo(Nueva releacutease de PHP 5http wwwiuisyfernandanetLa nueva releacutease corrige algunos fallos) Sdocumento-gtgrabar(miRSSxml) gt

La clase anterior se puede guardar en un archivo independiente y utilizar cuando sea necesario en el transcurso de un proyecto

Aunque no implementa todas las especificaciones de RSS 10 puede utilishyzarse para generar noticias de nuestra base de datos

Nota

Si desea modificar ia ciase para que contemple todas las opciones de Ja especificacioacuten RSS 10 puede visitar ia Web httpllpurtorgl rss10

En el capiacutetulo anterior vimos coacutemo se puede generar un archivo XML con una sucesioacuten de llamadas a meacutetodos Esta vez hemos encapsulado todas las llamadas en varios meacutetodos que se encargan de generar la parte de descripcioacuten del RSS y por otro lado las noticias

El meacutetodo c r e a t e E l e m e n t () se encarga de crear nuevos nodos para desshypueacutes encadenarlos c o n a p p e n d C h i l d () a los nodos padre Para crear un nodo de texto sin embargo tenemos que utilizar el meacutetodo c r e a t e T e x t -Node () una vez creado el nodo de texto tenemos que asociarlo a un nodo-elemento (una etiqueta)

El uacuteltimo paso es hacer una llamada al meacutetodo s a v e () con el nombre del fichero como paraacutemetro para guardar el archivo RSS

Servicios Web XML-RPC

El trabajo como programador puede llevarle a desarrollar aplicaciones para distintos Sistemas Operativos y en distintos lenguajes de prograshymacioacuten

Si en alguacuten momento necesita comunicar dos programas que estaacuten funshycionando en maacutequinas distintas (un servidor Windows y otro gnuLinux) y escritos con lenguajes diferentes puede que XML-RPC sea la solucioacuten perfecta

El mecanismo permite que el ordenador cliente pueda acceder a los meacutetoshydos del ordenador servidor y ejecutar rutinas almacenadas remotamente

Aplicaciones praacutecticas de XML 273

Este apartado muestra alguacuten ejemplo de coacutemo implementar y explotar un servicio Web con la libreriacutea de clase IXR creada por Simoacuten Willison bajo el auspicio de Open Source

Una llamada XML-RPC consiste en dos partes una pregunta y una resshypuesta

Cada una de las partes es un archivo XML que contiene los paraacutemetros solicitados al servidor o los datos devueltos

Una pregunta al servidor puede ser como la que sigue

ltmethodCalIgt ltmethodNamegtconteritgetNotiacuteciasltmethodNamegt ltparamsgt

ltparamgt ltvaluexintgt23ltiacutent gtltvaluegt

ltparamgt ltparams gt

ltmethodCallgt

Como puede ver es un archivo XML con una definicioacuten determinada La etiqueta ltmethodNamegt contiene el nombre del meacutetodo que debe llamarse en el servidor y ltparamgt contiene un paraacutemetro que se le pasaraacute al meacutetoshydo de la llamada

El documento anterior seraacute transmitido viacutea HTTP mediante POST al sershyvidor de XML-RPC que parsearaacute el documento ejecutaraacute la funcioacuten y devolveraacute un documento similar con los datos de la respuesta

Clase IXR

IXR es un conjunto de clases que implementa un servidor y un cliente de XML-RPC

Nota

Puede encontrar la libreriacutea en la Web httpscriptsiricutiocom xmlrpc o en la paacutegina del libro en httpunuzunnaiamulti-mediacom

Lo mejor de la programacioacuten orientada a objetos es que no necesita saber coacutemo funcionan las clases que utilice soacutelo conocer el uso correcto de los meacutetodos Asiacute puede utilizar la clase IXR de la manera que vamos a ver sin conocer siquiera el formato de los archivos XML-RPC

274 Capiacutetulo 15

Cliente XML-RPC

Los servicios XML-RPC tienen una direccioacuten Web con una paacutegina Web escrita en PHP Si escribe la direccioacuten completa en el navegador se proshyduciraacute un error porque la Web esperaraacute que mande mediante POST un archivo XML Para utilizar sus servicios Web o los servicios Web de alshyguna empresa como UserLand tiene que utilizar un cliente XML-RPC escrito en este caso en PHP 5 En este caso vamos a utilizar la clase IXR__Client de la libreriacutea IXR El ejemplo muestra coacutemo utilizar el cliente en varios pasos

bull Crear un objeto cliente con la URL pasada como paraacutemetro

bull Usar el meacutetodo q u e r y () para hacer la consulta al servicio Web

bull Extrae el resultado con el meacutetodo g e t R e s p o n s e ()

Lo primero que vamos a hacer es implementar un pequentildeo objeto para recuperar la fecha de un servidor remoto

ltphp require_once(IXR_Libraryincphp) class XMLRPCFechacliente

private $cliente function construct($url$debug=false) $this-gtcliente= new IXR__Client ($url) $this-gtcliacuteente-gtdebug=$debug

function getFecha($argumentol) if ($this-gtcliente-gtquery(fechagetFecha$argumentol)) trigger_error($this-gtcliente-gtgetErrorCode () $this-gtcliente-gtgetErrorMessage()) return false

return $this-gtcliente-gtgetResponse ()

gt

La clase X M L R P C F e c h a c l i e n t e implementa dos meacutetodos El construcshytor crea un objeto cliente IXR que recibe el servidor de servicios Web El meacutetodo g e t F e c h a () tramita la peticioacuten de la fecha con el servidor y obshytiene una respuesta que devuelve a la paacutegina Web Si todo va bien el sershyvidor enviaraacute la fecha del lugar donde esteacute

La llamada a q u e r y () tiene como paraacutemetro primero el nombre del meacuteshytodo que debe ejecutar el servidor y como segundo paraacutemetro un argu-

Aplicaciones praacutecticas de XML 275

mentoacute que puede pasarse La Web que quiera mostrar esta informacioacuten debe crear el objeto anterior maacutes o menos como se muestra en el siguiente ejemplo

ltphp require_once(XMLRPCFechaclientephp) $servidor=httpwwwluisyfernandanetFechaphp $fechaRemota= new XMLRPCFechacliente($servidor) echo $fechaRemota-gtgetFecha(Hoy) gt

Si evaluacutea el coacutedigo en tan soacutelo 4 liacuteneas puede recibir cualquier tipo de informacioacuten que el servidor tenga Para ello debe crear una variable que contenga el nombre del servidor y la paacutegina PHP que contiene el prograshyma de respuesta La instanciacioacuten del objeto X M L R P C F e c h a c l i e n t e y la llamada al meacutetodo g e t F e c h a () es suficiente para desencadenar la coshynexioacuten con el servidor

Servidor XML-RPC

En el apartado anterior ha visto que puede utilizar servicios Web ofrecishydos por otras empresas para averiguar la hora de un Paiacutes remoto el camshybio de moneda el tiempo o incluso el cataacutelogo de libros de una conocida tienda on-line Pero lo realmente interesante es poder crear sus propios servicios Web

La clase IXR_Server hace la mayoriacutea del trabajo por usted que puede emplear el tiempo en inventar nuevos servicios Web

Hemos creado una clase que implementa el servicio g e t F e c h a ( ) que el objeto cliente utiliza

ltphp require_once(IXR_Libraryincphp) class XMLRPCFechaservidor extends IXR_Server

function construct()

$this-gtIXR_Server(array(fechagetFecha =gt thisgetFecha)) function getFecha($argumentol)

if ($argumentol==Hoy) $fecha = La fecha remota es date(d-m-Y)

else

$fecha = Especifique un dia

2 7 6 Capiacutetulo 15

re turn $fecha

gt

La clave para entender el funcionamiento del servidor estaacute en el construcshytor Aquiacute se crea un array con el nombre de los meacutetodos que se pueden utilizar desde fuera

El primer valor f e c h a g e t F e c h a es el nombre que el cliente debe emshyplear para recuperar la Fecha del Servidor y el segundo valor t h i s g e t Fecha es el meacutetodo perteneciente al servidor que se ejecutaraacute cuando reciba una pregunta a esa funcioacuten

La figura 153 muestra el dato que obtiene el cliente

La definicioacuten del meacutetodo que enviacutea la fecha se hace como ya estamos acosshytumbrados

Lo que hemos visto es soacutelo la definicioacuten de la clase pero necesitamos una paacutegina Web de apoyo que instancie el objeto y lo ejecute Puede ser tan sencillo como

ltphp require_once(XMLRPCFechaservidorphp) $servidor= new XMLRPCFechaservidor() gt

Aplicaciones praacutecticas de XML 277

Usos de XML-RPC

Los ejemplos que hemos visto no son especialmente excitantes pero dan una idea de lo sencillo que es exportar cualquier tipo de informacioacuten La verdadera potencia de los servicios Web es que permiten disfrutar de nueshyvas funcionalidades de las que no disponemos Podriacuteamos crear un servishycio Web que permitiera a usuarios de PHP 4 utilizar nuestro objeto de SimpleXML pero esto lo dejo en manos del lector

Resumen

XML se ha convertido en los uacuteltimos antildeos en un estaacutendar libre para el inshytercambio de informacioacuten Incluso Microsoft poco amiga de los archivos abiertos estaacute implementando servicios en XML con su plataforma NET

Despueacutes de leer este capiacutetulo podraacute crear elegantes paacuteginas que contenshygan noticias relevantes sobre cualquier tema y exportarlas a otras paacuteginas amigas gracias a la tecnologiacutea RSS

En cuanto a la creacioacuten de servicios Web existe una controversia entre dos desarrollos principales XML-RPC y SOAP de Microsoft SOAP (Simshyple Object Access Protocol) es una implementacioacuten muy extensa de Microshysoft para la creacioacuten de servicios Web Pese a que su definicioacuten aboga por la simpleza (Protocolo Simple) la paradoja es que es mucho maacutes complishycada de utilizar que XML-RPC y por eso se escapa de los objetivos de este libro

Una de las nuevas caracteriacutesticas de PHP 5 es la inclusioacuten de una extenshysioacuten para la generacioacuten de servidores y clientes SOAP pero todaviacutea estaacute en fase experimental

El futuro cercano puede estar en SOAP asiacute que recomiendo al lector visishytar algunas paacuteginas Web sobre el tema para comenzar a entender su funshycionamiento

280 Capiacutetulo 16

Introduccioacuten

La construccioacuten de un sitio Web no soacutelo debe contar con textos bases de datos y funciones escritas en PHP para manejar los datos Existe un gran abanico de posibilidades que pueden dotar a la paacutegina de contenido multishymedia (imaacutegenes v sonidos) y que ademaacutes pueden ser procesados de alshyguna forma por PHP

Entre las funciones maacutes baacutesicas de interactuacioacuten con las imaacutegenes PHP puede realizar graacuteficos de barras para mostrar resultados estadiacutesticos antildeadir una marca de agua a todas nuestras fotografiacuteas o mostrar una reacuteshyplica de las imaacutegenes en un formato maacutes reducido para poder seleccionar entre un conjunto de ellas

La mayoriacutea de los ejemplos utilizan la libreriacutea graacutefica GD para PHP que puede instalarse faacutecilmente en los tres Sistemas Operativos maacutes comunes (gnuLinux MacOSX y Windows)

Graacuteficos HTML

Antes de entrar de lleno en las maravillas que ofrece la libreriacutea graacutefica GD vamos a realizar un pequentildeo ejemplo para aprovechar las posibilidades del lenguaje HTML para la creacioacuten de estadiacutesticas graacuteficas Esta posibilishydad nos permite realizar estudios graacuteficos baacutesicos sin tener que instalar ninguacuten paquete adicional a PHP

Puede decantarse por este meacutetodo o por utilizar la libreriacutea dependiendo de la complejidad de su proyecto

Vamos a crear como ejemplo un sistema de votacioacuten electroacutenico que cuente los votos de cada participante y los almacene en una base de datos Vashymos a utilizar el gestor SQLite visto en el capiacutetulo 11 Para tal fin hemos creado una clase de conexioacuten a SQLite muy parecida a la clase de conexioacuten de MySQL

ltphp

class Servidor_Base_Datos

priacutevate $base_datos priacutevate $descriacuteptor priacutevate ^resultado function construct($base_datos)

Generacioacuten de graacuteficos con PHP 5 281

$this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtpass = $pass $this-gtbase_datos = $base_datos $this-gtconectar_base_datos()

priacutevate function conectar_base_datos( )

$thiacutes-gtdescriptor = sqlite_open($this-gtbase_datos)

i public function consulta($consulta)

$this-gtresultado = sqlite_query($consulta $this-

gtdescriptor) public function extraer__registro ()

if ($fila = sqlite_fetch_array($this-

gtresultadoSQLITE_ASSOC)) return $fila

else return false

gt

Los meacutetodos son praacutecticamente iguales y la forma de utilizar el objeto es exactamente igual que en los ejemplos del capiacutetulo 12

Los datos que vamos a manejar en la encuesta son parte de una pequentildea tabla que almacenaraacute el nombre del Lenguaje de Programacioacuten que prefeshyrimos y el nuacutemero de votos que le hemos dado Podemos inicializar la base de datos con el siguiente script

ltphp requirejonee(clase_SQLitephp) $base_datos = new Servidor_Base_Datos(votacionesdb) $base_datos-gtconsulta(creacuteate table lenguaje (id_lenguaje INT PRIMARY KEY lenguaje CHAR(255) votos INT))

$base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees ( PHP 0) ) $base_datos-gtcoacutensulta(insert into lenguaj e (lenguaj evotos) valuacutees (JSPeuro)) $base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees (ASP 0) )

282 Capiacutetulo 16

$base_datos-gtconsulta(insert into lenguaje (lenguajevotos) valuacutees (COLD FUSIOacuteN0)) $base_datos-gtconsulta(select from lenguaje)

while ($fila = $base_datos-gtextraer_registro ()) echo $fila [lenguaje] $fila[votos] ltbrgt

gt

Todo deberiacutea serle familiar Lo que hacemos es crear una tabla nueva en la base de datos e insertar los lenguajes objetivo de la encuesta Por uacuteltishymo hacemos una comprobacioacuten para ver si los datos estaacuten almacenados en la base de datos Lo siguiente que vamos a ver es una Web con un formulario para elegir el lenguaje que maacutes nos agrada En la zona inferior de la paacutegina tenemos un contador que nos indica el nuacutemero de votos

ltphp

Primero comprobamos si tenemos un voto

$base_datos = new Servidor_Base_Datos(votaciones2db)

Si hemos votado sumamos el valor al nuacutemero de votos almacenado

if (isset($_POST[voto] ) )

$voto = $_POST[voto] $base_datos-gtconsulta(select votos from lenguaje where id_lenguaj e=$voto) $numero_votos = $base_datos-gtextraer_registro() $numero_votos = $numero_votos[votos] $numero_votos + + $base_datos-gtconsulta(update lenguaje set votos= $numero_votos where id_lenguaje = $voto)

gt lthtmlgt ltbodygt iquestQueacute lenguaje de programacioacuten prefieres

Formulario que permite votar

ltform action=votophp method=post gt ltselect name=votogt ltphp $base_datos-gtconsulta (select from lenguaje) while ($fila = $base_datos-gtextraer_registro () )

$id_lenguaje = $fila[id_lenguaje] $lenguaje = $fila [lenguaje]

Generacioacuten de graacuteficos con PHP 5 283

echo ltoption value=$id_lenguajegt$lenguajeltoptiongt

gt ltselectgt ltinput type=submit name=Enviar value=Enviar gt ltformgt lttablegt ltphp $base_datos-gtconsulta(select from lenguaje) while ($fila = $base_datos-gtextraer_registro () )

$lenguaje = $fila [lenguaje] $votos = $fila [ votos] echo lt t rx tdgt$ lengua j e lt t d x t d gt $votos vo toslt tdgtlt

t r gt

gt lt t ab l egt ltbodygt lthtmlgt

Como puede ver es un mecanismo muy sencillo de entender La parte principal es el formulario que permite elegir entre los 4 lenguajes de script Si enviamos un voto la misma paacutegina recibiraacute el dato y actualizaraacute la base de datos mostrando posteriormente los votos que tienen los lenguajes En la figura 161 puede ver el resultado

284 Capitulo 16

Graacuteficos de barras

Despueacutes de todo este coacutedigo estaraacute preguntaacutendose por las imaacutegenes geshyneradas automaacuteticamente Todaviacutea no hemos hecho nada de eso pero en el coacutedigo siguiente tiene la clave de este apartado Baacutesicamente jugamos con 4 imaacutegenes r o j o png v e r d e p n g a z u l png y a m a r i l l o png Cada imagen tiene un tamantildeo de 1 piacutexel de ancho y alto El truco estaacute en hacer un caacutelculo porcentuado de los valores de votos con respecto al que mayor votos tiene

De ahiacute sacamos el ancho de la imagen Una vez encontrado este ancho se le pasa a la propiedad w i d t h de la etiqueta lt imggt y obtenemos un graacutefishyco con imaacutegenes de distintos anchos es decir obtenemos un graacutefico de barras estadiacutestico

El coacutedigo puede ser como el siguiente

ltphp $imagenes = array(rojopngazulpngverdepngamarillopng) $base_datos-gtconsulta(select from lenguaje) while ($fila = $base_datos-gtextraer_registro() )

$id_lenguaje = $fila [ id_lenguaje ] $lenguaje = $fila [lenguaje] $votos = $fila[votos] $ancho = dame_ancho($votos$id_lenguaje) $imagen = $ imagenes[$ id_ lengua je -1] echo lt t r x t d gt $ l e n g u a j e - $votos v o t o s lt t d x t d x i m g src=$imagen width=$ancho h e i g h t = 2 0 gt lt t d x t r gt

function dame_ancho($votos)

$base_datos2 = new Servidor_Base_Datos(votaciones2db) $base_datos2-gtconsulta(select max(votos) as maacuteximo from lenguaje) $numero_votos = $base_datos2-gtextraer_registro() $maximo_votos = $numero_votos[maacuteximo] return (intval($votos)300)intval($maximo_votos)

gt lttablegt

Antes generaacutebamos una tabla con los lenguajes y el nuacutemero de votos Ahora generamos los lenguajes y calculamos con la funcioacuten dame_an-cho () el porcentaje con respecto al mayor valor de cada uno de los votos de los lenguajes La figura 162 muestra los graacuteficos de barras de la votacioacuten electroacutenica

Libreriacutea GD

La libreriacutea graacutefica GD estaacute escrita en lenguaje C y permite crear y manipushylar graacuteficos faacutecilmente Permite importar y exportar graacuteficos de distinto tipo (GIF JPG y PNG) La filosofiacutea de los archivos GIF y PNG es casi la misma Estos dos archivos guardan en memoria el conjunto completo de piacutexeles con su color concreto y comprimen el resultado para que el archishyvo final no sea muy pesado Los archivos JPG tambieacuten estaacuten comprimishydos pero se basan en algoritmos complejos que permiten un mayor rendimiento y la hacen muy propicia para usarse con fotografiacuteas

Tipos MIME

El estaacutendar MIME se concibioacute originariamente para identificar los difeshyrentes contenidos que podemos enviar por correo electroacutenico Actualmente se utiliza para describir el tipo de archivo que enviamos a traveacutes de Intershynet Es importante conocer los tipos MIME para trabajar con las libreriacuteas GD

En general antes de recibir la respuesta del servidor eacuteste debe enviarnos una cabecera anunciando el tipo de contenido que vamos a recibir usando una cabecera especial C o n t e n t - T y p e PHP por defecto enviacutea el tipo

286 Capiacutetulo 16

MIME t e x t h t m l (documento HTML) Cuando utilice la libreriacutea GD necesitaraacute enviar una cabecera con el tipo de la imagen

ltphp header(Content-Type imagepng) gt

Tabla 161 Tipos MIME

Formato de imagen MIMEacute

JPG iexclmagejpeg

PNG imagepng

GIF imagegif

BMP imagebmp

SVG imagexml+svg

Mostrar una imagen en pantalla

Normalmente utilizamos la etiqueta ltimggt de HTML para mostrar una imagen en un lugar determinado de nuestra paacutegina Web La propiedad s r c debe indicar una imagen determinada con formato coshynocido La liacutenea siguiente mostraraacute en pantalla el logotipo de php

ltimg src=phppnggt

La libreriacutea graacutefica GD tambieacuten permite enviar imaacutegenes con el uso de unas funciones determinadas Como ejemplo vamos a ver coacutemo mostrar el misshymo logotipo esta vez utilizando GD

ltphp $imagen = imagecreatefrompng(phppng) header(Content-Type imagepng) imagepng($imagen) gt

Advertencia

La etiquete ltimggt de nuestra paacutegina Web debe apuntar ahora al

archivo PHP que genera la imagen ltimg s r c = imagen php gt

La funcioacuten i m a g e c r e a t e f rompng () recupera una imagen de un archishyvo y crea un descriptor en la variable $ imagen Para mostrar la imagen

Generacioacuten de graacuteficos con PHP 5 287

tiene que enviar la cabecera del tipo de archivo graacutefico que quiere mosshytrar y despueacutes enviar la imagen con imagepng ()

A simple vista parece demasiado esfuerzo para algo que resuelve perfecshytamente la etiqueta ltimggt pero examine el siguiente coacutedigo

ltphp

$imagenes = array(phppngzendpngparispng) Semilla aleatoria srand( (double)microtime 01000000) $aleatorio = rand(02) $fichero = $imagenes[$aleatorio] $imagen = imagecreatef rompng ($f ichero) header(Content-Type imagepng) imagepng($imagen) gt

El array $ i m aacute g e n e s contiene varios archivos graacuteficos en PNG Generashymos un nuacutemero aleatorio y recuperamos la imagen que ocupa la posicioacuten del nuacutemero

Los siguientes pasos son exactamente iguales a los vistos anteriormente El script muestra una imagen distinta cada vez que lo ejecutamos y puede servir para crear una Web con distintos banners aleatorios Puede ver el resultado en la figura 163

288 Capiacutetulo 16

Crear imaacutegenes en miniatura

Si su paacutegina Web permite enviar fotografiacuteas quizaacute necesite mostrar un gran nuacutemero de ellas en una sola paacutegina HTML permite poner un ancho determinado a la imagen aunque el tamantildeo permaneceraacute invariable Lo ideal es crear dos versiones de cada fotografiacutea Una en miniatura con poco peso en bites y otra la original que puede ser mostrada cuando se haga clic en la imagen pequentildea

Gracias a la libreriacutea GD podraacute modificar el tamantildeo de las fotografiacuteas que quiera Vamos a crear una clase para generar fotografiacuteas con la mitad de tamantildeo

ltphp class imagen

priacutevate $archivo priacutevate $ imagen priacutevate $dimensiones function construct($archivo)

$this-gtarchivo = $archivo $this-gtimagen = imagecreatefromjpeg($archivo) $this-gtdimensiones = getimagesize ($archivo)

i

public function imagen_original()

header(Content-Type imagejpeg) imagejpeg$this-gtimagen)

public function imagen_miniacuteatura()

$dimensionx = $thiacutes-gtdimensiones[0] 2 $dimensiony = $this-gtdimensiones[1] 2 $this-gtminiatura = imagecreatetruecolor($dimensionx $dimensiony) imagecopyresampled($this-gtminiatura $this-gtimagen 0 0 0 0 $dimensionx $dimensiony $this-gtdimensiones[0] $this-gtdimensiones[1])header (Content-Type imagejpeg) imagejpeg($tnis-gtminiatura)

$fotografia = new imagen($_GET[fotografiacutea])

if ($_GET[modo]==original)

$fotografia-gtimagen_original()

Generacioacuten de graacuteficos con PHP 5 289

else $fotografia-gtimagen_miniatura()

gt

La clase estaacute especializada en construir imaacutegenes con la mitad de tamantildeo Para que funcione tiene que hacer una l lamada a la url c l a s e _ imagen php pasando como paraacutemetros GET el nombre de la fotografiacutea y el modo (tamantildeo original o miniatura)

El constructor de la clase rescata el archivo graacutefico y averigua las dimenshysiones X e Y con la funcioacuten g e t i m a g e s i z e ()

El meacutetodo i m a g e n _ o r i g i n a l () funciona exactamente igual que el ejemshyplo anterior El meacutetodo i m a g e n _ m i n u a t u r a () divide entre 2 las dimenshysiones capturadas de la imagen y crea un entorno de trabajo con esas dimensiones con la funcioacuten i m a g e c r e a t e t r u e c o l o r ( ) En este momenshyto la variable $ m i n i a t u r a del objeto tiene un espacio de memoria asigshynado para almacenar un graacutefico pero estaacute vaciacuteo Lo que hacen las liacuteneas siguientes es redimensionar y copiar la imagen original a nuestro entorno de trabajo La funcioacuten i m a g e c o p y r e s a m p l e d () copia la imagen guarshydada en el segundo paraacutemetro en el espacio de trabajo del primer paraacuteshymetro

Los argumentos 3 y 4 son las coordenadas X e Y donde empezaraacute a pegarshyse la imagen copiada y el 5 y 6 las coordenadas desde las que se empezaraacute a copiar la imagen original Los siguientes paraacutemetros son el ancho y alto de las imaacutegenes destino y origen

Una vez copiada la imagen al espacio de trabajo ya podemos mostrarla enviando la cabecera y la imagen con la funcioacuten image j pg ( )

Vamos a crear una Web que haga uso de esta clase

lthtmlgt ltbodygt ltform action=imagenphp method=POST enctype=multipart form-datagt Elige un archivo de imagen jpg ltinput type=file name=ficherogt ltinput type=submit name=Enviar value=Enviargt ltformgt ltphp if (isset($_FILES[fichero] ) )

echo Imagen Originalltbrgt $fotografia = $_FILES[fichero][tmp_name] copy($fotografia$_FILES[fichero] [ntildeame]) $foto_copia = $_FILES[fichero] [ntildeame] ampmodo= original

290 Capiacutetulo 16

$url = clase_imagenphpfotografia=$foto_copia echo ltimg src=$urlgt echo Imagen Miniaturaltbrgt $foto_copia = $_FILES[fichero ] [ntildeame] ampmodo= miniatura $url = clase_imagenphpfotografia=$foto_copia echo ltimg src=$urlgt

gt ltbodygt lthtmlgt

La paacutegina Web muestra un formulario que nos da la posibilidad de enviar al servidor una fotografiacutea de nuestro ordenador

Si le damos a enviar la paacutegina nos mostraraacute la fotografiacutea en su versioacuten original y en su versioacuten reducida como puede comprobar en la figura 164

Generar una marca de agua

Otro problema comuacuten sencillo de resolver es la creacioacuten de marcas de agua sobre las fotografiacuteas que ofrecemos en nuestra Web La marca de agua puede ser un graacutefico o un texto que insertamos encima de la fotografiacutea original

Generacioacuten de graacuteficos con PHP 5 291

Una forma sencilla de implementar marcas de agua es antildeadiendo un meacuteshytodo nuevo a la clase

priacutevate function marca_agua()

$this-gtmarca_agua = imagecreatefrompngphppng) $dimensiones = getimagesize(phppng) $posicionx = $this-gtdimensiones [0] - $dimensiones [0] $posiciony = $this-gtdimensiones [1] - $dimensiones [1] imagecopy($this-gtimagen $this-gtmarca_agua $posicionx $posiciony 0 0 $dimensiones [0] $dimensiones[1] )

Podemos llamar al meacutetodo desde el constructor para que la imagen guarshyde la informacioacuten de la fotografiacutea grabada e inserte la marca en alguna parte de la misma Tambieacuten podemos generar un texto como marca de agua

Vamos a antildeadir un nuevo meacutetodo a la clase para poder marcar las fotoshygrafiacuteas

priacutevate function marca_texto()

$color = imagecolorallocate($this-gtiraagen 25500) iacutemagestriacuteng($thiacutes-gtimagen 4 0 0 Hecho con PHP5

$color)

La figura 165 muestra la inclusioacuten de una marca de agua graacutefica y otra marca de agua de texto

292 Capiacutetulo 16

La funcioacuten i m a g e a l l oacute c a t e () crea un color con los componentes RGB como paraacutemetros La funcioacuten devuelve un nuacutemero que identifica al color creado en la imagen La funcioacuten i m a g e s t r i n g () imprime un texto de color determinado en la imagen El segundo paraacutemetro es el tipo de fuenshyte que queremos introducir

Graacuteficos estadiacutesticos profesionales con JpGraph

JpGraph es una libreriacutea escrita en PHP que permite crear todo tipo de graacuteshyficos estadiacutesticos en dos y tres dimensiones Hace uso de la libreriacutea graacutefica GD en su versioacuten 2 Se puede descargar de la paacutegina wwwjpgraphorg

JpGraph tiene dos licencias de uso Una gratuita para proyectos no coshymerciales y con caraacutecter educativo y otra de caraacutecter comercial de pago Le recomiendo leer ambas licencias para comprobar que puede utilizarshylas

Para instalar la libreriacutea tiene que copiar el directorio con las clases en la ruta donde guarde su aplicacioacuten o en la ruta de buacutesqueda de PHP 5

Graacuteficos de barras

El ejemplo maacutes sencillo es la creacioacuten de un graacutefico con varios valores en el que podemos ver todos los valores interconectados entre siacute por unas liacuteneas

ltphp require_once (jpgraphjpgraphphp) require_once (jpgraph jpgraph_linephp) $datosy = array(11O81251913157) Creamos el graacutefico $grafico = new Graph(350250) $grafico-gtSetScale (textlin) Creamos una nueva linea de puntos $puntos =new LinePlot($datosy) $puntos-gtSetColor(blue) Antildeadimos los puntos al graacutefico $grafico-gtAdd($puntos) Se muestra el graacutefico $grafico-gtStroke ()

bull gt

Suponiendo que la libreriacutea esteacute guardada en la carpeta j p g r a p h haceshymos u n r e q u i r e _ o n c e () de la clase principal j p g r a p h php y de la clase que utilizaremos para graacuteficos de liacutenea j p g r a p h _ l i n e php La variable $ d a t o s y guarda diez valores que pueden identificar el nuacutemero de visishytas a nuestra Web o el nuacutemero de ventas por meses de un artiacuteculo Para crear un graacutefico tiene que crear el objeto Graph con el ancho y alto que quiere que tenga en la Web Lo siguiente es configurar la escala en la que apareceraacute el graacutefico Lo mejor es echar un vistazo al manual para eleshygir el que maacutes le convenga en cada momento

Seguidamente cree un conjunto de puntos con el meacutetodo L i n e p l o t () con los valores del array $ d a t o s y Puede elegir tambieacuten el color de la liacuteshynea resultado con el meacutetodo S e t C o l o r ()

Para finalizar antildeada los valores al graacutefico y mueacutestrelo con S t r o k e ()

Con estas liacuteneas hemos conseguido crear el graacutefico de la figura 166

Puede antildeadir algunas caracteriacutesticas maacutes a sus graacuteficos como tiacutetulos en

los ejes colores o varias liacuteneas de valores para comparar datos

Para antildeadir tiacutetulos a los graacuteficos le pueden servir las liacuteneas siguientes

$graf ico-gttitle-gtset (Graacutefico JpGraph) -

294 Capiacutetulo 16

$grafico-gtxaxis-gttitle-gtset(dia) $grafico-gtyaxis-gttitle-gtset(visitas)

El meacutetodo t i t l e genera un tiacutetulo asociado al objeto inmediatamente anshyterior Si el objeto es $ g r a f i c o el tiacutetulo seraacute el de la imagen completa Si el objeto anterior es el eje x o el eje y ( x a x i s o y a x i s ) el tiacutetulo corresshyponderaacute con cada uno de los ejes Puede ver el resultado en la figura 167

Ademaacutes puede antildeadir tantos datos como quiera para hacer un estudio comparativo de varios datos Para hacer esto debe repetir algunos pasos pero con distintos valores

$datosy2 = array(12378543127) $puntos2 = new LinePlot($datosy2) $puntos2-gtSetColor(red) $grafico-gtAdd($puntos2) $puntos-gtSetLegend(Europa) Spuntos2-gtSetLegend(America) $grafico-gtlegend-gtPos(00505rightcenter)

Como vimos en el ejemplo anterior podemos antildeadir otro array lleno de valores crear una nueva liacutenea de puntos con un color determinado y asoshyciarlo finalmente con el graacutefico que estamos creando como puede ver en

Graacuteficos en 3D

JpGraph realiza casi cualquier tipo de graacutefico estadiacutestico Uno de los maacutes utilizados es el graacutefico de quesito donde podemos evaluar por porcioshynes el dato de mayor amplitud soacutelo con un vistazo El ejemplo siguiente muestra coacutemo hacer un graacutefico de este tipo

ltphp include (jpgraph jpgraphphp) include (jpgraph jpgraph_piephp) include (jpgraph jpgraph_pie3dphp)

$datos = array(4 0So21 33)

$grafico = new PieGraph(300200) $grafico-gtSetShadow()bull

$grafico-gttitle-gtSet(Graacutefico de quesito) $pl = new PiePlot30($datos) $pl-gtSetAngle(20)

Generacioacuten de graacuteficos con PHP 5 295

la figura 168 Las uacuteltimas 3 liacuteneas antildeaden una leyenda en la parte derecha del graacutefico es decir un pequentildeo graacutefico explicativo de las liacuteneas de datos

296 Capiacutetulo 16

$pl-gtSetSize (05) $pl-gtSetCenter (045) $pl-gtSetLegends($gDateLocale-gtGetShortMonth())

$grafic0-gtAdd($pl) $grafic0-gtStroke ()

Para crearlo primero tiene que incluir los archivos j p g r a p h _ p i e php y j p g r a p h ^ p i e 3 d php que permitiraacuten instanciar el tipo de graacutefico P i e P l o t 3 D El meacutetodo SetShadowC) crea una sombra en eiacute contorno exterior del graacutefico La instanciacioacuten del graacutefico circular se hace sobre la variable $pi que empieza a tomar forma con las propiedades S e t A n -g l e () y S e t C e n t e r () que permiten definir el aacutengulo del graacutefico con respecto a la vista frontal y el centrado del graacutefico con respecto a la caja que lo contiene La fase final es antildeadir el quesito al graacutefico creado y mostrarlo en pantalla Una mejora del graacutefico anterior puede ser resaltar la porcioacuten del graacutefico que tiene mayor valor y separarlo notablemente Esto puede hacerse antildeadiendo la liacutenea siguiente

$ p l - gt E x p l o d e S l i c e ( 1 )

El graacutefico de quesito se muestra en la figura 169

Generacioacuten de graacuteficos con PHP 5 297

Resumen

El tratamiento de imaacutegenes desde PHP 5 nos da la posibilidad de crear proyectos muy profesionales Tanto la posibilidad de crear graacuteficos mas pequentildeos marcas de agua o texto sobreimpresos como la de generar esshytadiacutesticas en tiempo real crean un potencial que no todas las paacuteginas Web saben aprovechar

Existen algunos proyectos como K++ que permiten crear imaacutegenes del tipo Flash y que merece la pena indagar en la buacutesqueda de contenido orishyginales para nuestro portal

300 Capitulo 17

Introduccioacuten

Si estaacute familiarizado con otros lenguajes de programacioacuten como C o Java ya conoceraacute algunos mecanismos que permiten manejar errores y excepshyciones Una de las nuevas caracteriacutesticas que PHP 5 incluye es un objeto de manejo de excepciones con una sintaxis muy similar a Java El manejo de excepciones es una herramienta muy potente que podraacute apreciar una vez que comprenda el concepto y haga buen uso del objeto en su coacutedigo Estas funciones permiten depuiacutear condiciones de error reshycuperar situaciones inesperadas y presentar interfaces limpias de errores

Errores y Excepciones

Lo primero que tenemos que hacer es no pensar en una excepcioacuten como si fuera un error Una excepcioacuten es una condicioacuten que se experimenta en un programa inesperadamente y no puede ser manejada por el coacutedigo que hemos escrito Generalmente no causan la parada del programa pero siacute es posible detectarla para que continuacutee normalmente Las excepciones si son tratadas correctamente pueden dar maacutes fiabilidad a su aplicacioacuten y librarle de muchos dolores de cabeza Aunque si no son correctamente utilizadas pueden crear maacutes problemas que resolverlos Debe tomar un tiempo para determinar si necesita crear sus propios meacuteshytodos de manejo de errores y si es asiacute veraacute que a la larga resulta maacutes grashytificante Como ejemplo vamos a ver una pieza de coacutedigo que simula la recepcioacuten de un identificador de usuario y su posible comprobacioacuten en una base de datos Tal y como puede ver se comprueba que los tres prishymeros caracteres sean usr que el tamantildeo en caracteres sea al menos de 9 y que exista en una base de datos

ltphp extraemos el usuario por GET $usuario_id = $_GET[usuario_id ] Si existe el usuario escribimos el mensaje CORRECTO if (usuario_valido($usuario_id))

echo ERROR El usuario $usuario_id no existe else

echo CORRECTO El usuario $usuario_id existe

function usuario_valido($usuario_id)

Gestioacuten de errores en PHP 5 301

$cadena = usr Comprobaciones de usuario if ( (strstr ($usuario_id$cadena) == false) [[

(strpos($usuario_id$cadena) = 0)) return false

if (strlen ($usuario__id) lt 9) return false

if (existe__base_datos ($usuario_id) )

return true else

return false

gt

Como puede ver cualquier condicioacuten que estaacute dentro de la funcioacuten que valida los usuarios puede dar un resultado negativo y soacutelo uno de ellos daraacute un resultado positivo si el usuario existe en la base de datos

Las excepciones permiten distinguir entre distintos tipos de errores y manejarlos dependiendo de su naturaleza

La clase Exception

La clase Except ion se ha creado en PHP 5 para manejar las anomaliacuteas producidas En vez de utilizar comprobaciones que evaluacutean si es falso o verdadero una determinada condicioacuten se utiliza una instancia de la clase Except ion que captura los errores y permite mostrar un mensaje de error personalizado

ltphp extraemos el usuario por GET $usuario__id = $_GET [ usuario_id] Si existe el usuario escribimos el mensaje CORRECTO try

if ( lusuario_valido($usuario_id)) echo ERROR El usuario $usuario_id no existe

else echo CORRECTO El usuario $usuario_id existe

catch(Exception $ex)

Devuelve el mensaje de error $mensaje = ($ex-gtqetMessage() ) echo $mensaje

302 Capiacutetulo 17

function usuario_valido($usuario_id) $cadena = usr Comprobaciones de usuario if ( (strstr ($usuario_id$cadena) == false) |

(strpos($usuario_id $cadena) = 0)) throw new Exception ($usuario_id no contiene el

prefijo)

if (strlen($usuario_id) lt 9)

throw new Exception (El tamantildeo de $usuario_id es menor de 9 caracteres)

if (existe_base_datos($usuario_id) )

return false else

return false

Gestioacuten de errores en PHP 5 303

Como puede ver las excepciones se crean de una manera algo diferente En el momento en el que se escribe th row new E x c e p t i o n los errores que no se controlen con el flujo normal del programa son utilizados como excepciones separadas del resto de la aplicacioacuten

Bloque Try Catch

Las excepciones son controladas por el bloque t r y c a t c h Todo el coacutedishygo que escriba y que pueda generar un error se incluiraacute dentro de una estructura t r y Si dentro del bloque t r y se encuentra un error la ejecushycioacuten del coacutedigo se para y se pasa el control al bloque c a t c h Este bloque se consuita para encontrar la excepcioacuten que ha producido el error de acuershydo con el coacutedigo que hemos escrito

Una de las cosas maacutes convenientes de utilizar excepciones es que puede mostrar tanta informacioacuten o tan poca como quiera El objeto E x c e p t i o n tiene varios meacutetodos para manejar sus propios errores El coacutedigo siguiente muestra coacutemo utilizar t h row e inmediatamente capshyturar la excepcioacuten Podemos capturar tambieacuten algunos paraacutemetros uacutetiles

ltphp try

throw new Exception(Error de sintaxis) catch (Exception $ex)

Mensaje de error $mensaje = ($ex-gtgetMessage ()) Coacutedigo de error configurable $codigo = ($ex-igetCode()) Fichero del error $fichero = ($ex-gtgetFile ( ) ) Linea donde se ha producido el error $linea = ($ex-gtgetLine())

echo Error nuacutemero $codigo $mensaje en el fichero $fichero en la linea $linea

gt

El mensaje de error que se muestra es muy tiacutepico en PHP Como es totalshymente configurable puede generar su propio formato de Mensaje de Error que puede ver en la figura 172

Aunque en este ejemplo el coacutedigo que captura la excepcioacuten soacutelo tiene una liacutenea podraacute incluir dentro del bloque varias liacuteneas o funciones dentro que actuaraacuten de la misma forma

Heredar de (a clase Exception

PHP 5 permite definir sus propias clases qulta heredan de la clase E x c e p shyt i o n Puede hacerlo de la siguiente forma

ltphp class Excepcioacuten extends Exception

function construct($mensaje)

parent Exception($mensaj e)

gt

El siguiente ejemplo muestra coacutemo crear clases propias que manejan erroshyres a partir de la clase E x c e p t i o n

ltphp $usuario_id = $_GET[usuario_id] try

if f J usuario_valido ($usuario__id) ) [ echo ERROR El usuario $usuario id no existe

Gestioacuten de errores en PHP 5 305

else echo CORRECTO El usuario $usuario_id existe

catch(MiExcepcion $ex)

$cadena = usr if ((strpos($usuario_id$cadena) == false) |]

(strpos($usuario_id$cadena) = 0)) $mensaje = $ex-gtgetMessage()

catch(OtraExcepcion $ex)

if (strlen($usuario_id) lt 9) $mensaje = $ex-gtgetMessage()

Definicioacuten de las clases que heredan de Exception class MiExcepcion extends Excepcioacuten

function construct($mensaje)

parentException($mensaje)

class OtraExcepcion extends Excepcioacuten

function construct($mensaje)

parent Exception($mensaj e)

echo $mensaje function usuario_valido($usuario_id)

$cadena = usr if ((strpos($usuario_id$cadena) == false) ||

(strpos($usuario_id$cadena) = 0)) throw new MiExcepcion(Usuario $usuario_id no

contiene el prefijo )

if (strlen($usuario_id) lt 9) throw new OtraExcepcion(Usuario tiene menos de 9

caracteres)

gt

Limitaciones de PHP 5

El objeto de excepciones es totalmente nuevo en PHP 5 Debido a esto algunas funcionalidades creadas en otros lenguajes de programacioacuten como

306 Capiacutetulo 17

Java no han sido todaviacutea implementadas por ejemplo el uso de los meacutetoshydos f i n a l ly () y t h r o w s () Los errores comunes de PHP que se muesshytran en el navegador no son mapeados a excepciones automaacuteticamente Esta funcionalidad seraacute implementada en versiones posteriores de PHP Los errores que no pueden ser controlados por E x c e p t i o n pueden mashynejarse con otras teacutecnicas de programacioacuten

Control de errores sin excepciones

Si ya conoce algunas versiones de PHP sabraacute que hay multitud de funcioshynes capaces de controlar errores incluidos los errores nativos de PHP controladores personalizados de error y los errores de usuario

Errores nativos de PHP

PHP genera 3 tipos de error dependiendo de su seriedad

bull Notice No son errores severos y no crean problemas complejos Por defecto no se muestran en pantalla cuando suceden a menos que dishygamos lo contrario en el archivo de configuracioacuten php i n i

bull Warning Alguna parte del coacutedigo ha causado un error pero la ejecushycioacuten continuacutea

bull Fatal error Un problema serio que hace abortar la ejecucioacuten del proshygrama

Cada tipo de error es representado por una constante diferente E_USER_NOTICE E_USER_WARNING y E_USER_ERROR Puede elegir el nivel de error que quiere mostrar en pantalla con la funcioacuten e r r o r _ r e p o r t i n g ( )

ltphp Mostrar errores fatales error_reporting(E_USER_ERROR) Mostrar advertencias y notificaciones error_reporting(E_USER_WARNING | E_USER_NOTICE) Mostrar todos los errores error_reporting (E__USER__ALL) gt

El manejo de errores queda limitado la mayoriacutea de veces a los del tipo warn ing Los errores fatales se consideran tan criacuteticos que no pueden conshytrolarse y la ejecucioacuten del programa queda suspendida

Gestioacuten de errores en PHP 5 307

Controladores de error

Cuando suceda un error que no tenga contemplado en su aplicacioacuten pueshyden aparecer mensajes en la pantalla que no interesa mostrar La solucioacuten es crear su propia funcioacuten para controlar y mostrar errores

ltphp function errores($errormensaje$fichero$linea)

echo ltbgt ERROR ltbxbrgt echo Sentimos comunicarle que se ha producido un error echo Tipo de error $error $mensaje en $fichero en la linea $linea

gt

Con estas liacuteneas hemos creado una funcioacuten que muestra el error producishydo pero con un disentildeo acorde a nuestra paacutegina Web Puede mostrar tanta informacioacuten como quiera El siguiente paso es llamar a la funcioacuten s e t _ e r r o r _ h a n d l e r () para que PHP sepa que nuestra funcioacuten e r r o shyr e s () se va a encargar a partir de ahora de gestionar los posibles fallos en el flujo del programa

ltphp set_error_handler(errores) gt

308 Capiacutetulo 17

Con el coacutedigo anterior todos los errores producidos del nivel que tenga permitido ( f a t a l e r r o r w a r n i n g o n o t i c e ) seraacuten enviados a la funshycioacuten e r r o r e s () para mostrar su mensaje particular

Errores de usuario con trigger_error()

Desde PHP 4 puede usarse una funcioacuten para identificar los errores proshyducidos por los usuarios muy parecida a la funcioacuten de PHP 5 th row () La funcioacuten t r i g g e r _ e r r o r () genera un error del tipo que quiera ( f a shyt a l e r r o r warn ing o n o t i c e ) y seraacute gestionado por PHP o por su propio gestor de errores

ltphp error_reporting(E_ALL) function errores($error$mensaje$fichero$linea)

echo ltbgt ERROR ltbxbrgt

echo Sentimos comunicarle que se ha producido un error echo Tipo de error $error $mensaje en $fichero en la liacutenea $ linea

set_error_handler(errores)

if (1 = 0 ) trigger_error( Esto es falso E_USER_NOTICE)

gt

Es mejor u t i l izar s iempre la funcioacuten t r i gg e r _ e r r o r ( ) con s e t _ e r r o r _ h a n d l e r () El error que creemos puede ser de cualquiera de los 3 tipos existentes en PHP En este caso generamos un error no t i -ce para indicar que la condicioacuten es falsa

Depuracioacuten de errores

El manejo de errores puede ahorrar esfuerzos a la hora de depurar el funshycionamiento oacuteptimo de su coacutedigo pero tambieacuten puede crear algunos doshylores de cabeza si empieza a suprimir algunos fallos

La f u n c i oacute n e r r o r _ l o g () crea un archivo donde se iraacuten almacenando las ocurrencias de su coacutedigo Con el siguiente ejemplo podraacute capturar todos los errores producidos en el programa para despueacutes hacer un estudio de lo que ha pasado

ltphp

Gestioacuten de errores en PHP 5 309

try if ($usuario = Luis)

throw new Exception(El usuario no existe)

catch (Exception $ex)

$mensaje = ($ex-gtgetMessage() ) $codigo = ($ex-gtgetCode() ) $fichero = ($ex-gtgetFile()) $linea = ($ex-gtgetLine()) $log_mensaje =date(Hi d-m-Y) Error $codigo en

$fichero en la liacutenea $linea Error $mensaje error_log($log_mensaj e3 UsersluisSiteserrorlog) echo $log_mensaje

gt

Nota

Los ficheros l o g son muy utilizados en los Sistemas Operativos para mantener un registro de incidencias Los ficheros l o g guarshydan desde el nuacutemero de veces que ha entrado un usuario hasta los errores que se han producido en el inicio del sistema

La funcioacuten e r r o r _ l o g () puede pasar como segundo paraacutemetro un nuacuteshymero entero que identifica el tipo de error y queacute hacer con eacutel

bull 0 Se utiliza el mecanismo del sistema operativo bull 1 Enviacutea el error a una direccioacuten de correo especificada como cuarto

paraacutemetro (Debe formar parte de una cabecera) bull 2 Enviacutea el error a traveacutes de una sesioacuten de depuracioacuten de PHP (Debe

estar habilitado el modo depuracioacuten)

bull 3 Enviacutea el error a un fichero

Resumen

Como puede darse cuenta la mayoriacutea de los programas incluidos en el libro no tienen ninguacuten tipo de control de errores He preferido evitarlos para ganar en claridad y no tener que empezar explicando los bloques Try Catch desde el principio A partir de ahora sieacutentase libre para modifishycar todos los scripts a su antojo para que sean maacutes fiables y seguros

310 Capiacutetulo 17

El desarrollo de las posteriores versiones de PHP permitiraacute manejar los errores maacutes faacutecilmente El futuro de las excepciones no ha hecho maacutes que empezar con la versioacuten 5 de PHP y se esperan mejoras suculentas con respecto a las anteriores Pese a esto muchas libreriacuteas ya incluyen sus proshypios controles de error como la de MySQL o PEAR

312 Capiacutetulo 18

Introduccioacuten

Transferir ficheros de un ordenador a otro es una tarea que sucede milloshynes de veces a lo largo del diacutea en Internet Ya no es un problema comparshytir un fichero entre dos ordenadores ubicados entre distintos puntos del mundo Los dos meacutetodos maacutes utilizados son el protocolo FTP y el correo electroacutenico

Los ficheros pueden ser transferidos simplemente dejaacutendolos en alguacuten lugar puacuteblico de nuestro servidor Web o utilizando alguacuten programa para enviarlos El protocolo FTP y el correo electroacutenico son programas indeshypendientes que deben estar instalados en el servidor para poder usarse Son dos programas del tipo cliente servidor Para poder utilizar cualshyquiera de los dos servicios anteriores debe conectarse a un servidor en un ordenador remoto y enviar los datos

FTP

Para utilizar el protocolo FTP tiene que tener habilitada la opcioacuten cuando instale PHP Puede utilizar FTP para enviar ficheros en un script escrito en PHP desde alguna paacutegina Web Para conectar a un servidor tendraacute que utilizar la siguiente funcioacuten

$conexioacuten = f tp__connect ( www l u i s y f ernanda net)

Tambieacuten puede utilizar una direccioacuten IP para la conexioacuten $conexioacuten = f tp_connect (12 7 0 0 1)

Nota

La direccioacuten IP identifica un uacutenico ordenador dentro de Internet

La IP 127001 apunta a nuestro propio ordenador

El servidor FTP contiene un listado de usuarios a los que les permite la conexioacuten Dependiendo del usuario que se conecte el servidor le permitishyraacute descargar unos archivos u otros

El siguiente paso es autentificarse como usuario del servidor de FTP con la funcioacuten

ftp_login($conexioacuten $usuario $clave)

Conexiones desde PHP 5 313

Como paraacutemetros tiene que pasar la conexioacuten establecida anteriormente el usuario y la contrasentildea

Advertencia

El protocolo FTP no es seguro El usuario y la contrasentildea se enshyviacutean en formato de texto y podriacutean ser capturados por alguacuten proshygrama sniffer que se encuentre entre su ordenador y el servidor de destino

Como de costumbre puede encapsular todas las funciones para hacer una clase que permita conectar a un servidor

ltphp class ftp

priacutevate $serviacutedor priacutevate $usuario priacutevate $clave priacutevate $conexion priacutevate $login function construct($servidor$usuario $clave)

set_time_limit(0) $this-gtservidor = $servidor $this-gtusuario = $usuario $this-gtclave = $clave $thiacutes-gtconectar($this-gtservidor)

priacutevate function conectar($servidor)

$this-gtconexion = ftp_connect($servidor21 30) priacutevate function loginFtp($usuario$clave)

$this-gtlogin = ftp_login($this-gtconexion usuario $clave)

$ftp = new ftp(127001luissecreto) gt

Como puede ver el meacutetodo constructor utiliza la funcioacuten set__t ime_ l i m i t () Normalmente los script de PHP tienen un tiempo de vida deshyterminado en el fichero de configuracioacuten php i n i Este tiempo suele ser de 30 segundos y es una proteccioacuten para que si un programa se queda

314 Capiacutetulo 18

bloqueado y su ejecucioacuten lleva maacutes de ese tiempo automaacuteticamente queshyde cancelada su ejecucioacuten

La funcioacuten s e t _ t i m e _ l i m i t () le da la posibilidad de ampliar el tiemshypo de ejecucioacuten al nuacutemero de segundos que indique como paraacutemetro Si el argumento es un 0 el tiempo de ejecucioacuten seraacute infinito

La funcioacuten f t p _ c o n n e c t () tambieacuten puede llevar como paraacutemetros el puerto de conexioacuten (por defecto es el 21) y el nuacutemero de segundos que tardaraacute PHP en volver a intentar la conexioacuten si el intento anterior ha sido fallido

Mostrar los archivos remotos

Despueacutes de conectar con el servidor de FTP lo maacutes usual es recuperar un listado de ficheros que estaacuten en el servidor La funcioacuten f t p _ n l i s t () extrae el nombre de los archivos del directorio que pasemos como paraacuteshymetro

El resultado es un array

public function ver($directoriacuteo = )

$this-gtarchivos = ftp_nlist($this-gtconexion$directorio) foreach ($this-gtarchiacutevos as $archivo)

echo $archivoltbrgt

Puede antildeadir el meacutetodo anterior a la clase f t p La funcioacuten f t p _ n l iacute s t () utiliza la conexioacuten almacenada en el constructor de la clase y recibe un listado de ficheros que guarda como array en la variable $this-gtarchivos

Maacutes adelante utilizando un bucle f o r e a c h podraacute extraer todos los nombres e imprimirlos en pantalla como puede comprobar en la figushyra 181

Si no es la primera vez que utiliza el protocolo FTP sabraacute que al conecshytar con un servidor lo maacutes comuacuten es que conecte en el sistema raiacutez donshyde encontraraacute los archivos y directorios que puede utilizar La funcioacuten f t p _ c h d i r () permite cambiar de directorio dentro del sistema de fishycheros

Si en alguacuten momento no sabe en queacute directorio se encuentra puede hashycer uso de la funcioacuten f tp_pwd ( ) que le daraacute la ruta completa de su situacioacuten

Descargar y Enviar ficheros

Puede descargar ficheros con la funcioacuten f tp_ge t () El siguiente ejemshyplo descarga un fichero despueacutes de hacer la conexioacuten

ftp_get($conexioacuten nuevoFicherotxtFicherotxtFTP_ASCII)

El nombre nuevoFichero t x t se corresponde con el nombre del ficheshyro que tendraacute el archivo despueacutes de ser descargado y F iche ro t x t es el archivo remoto que queremos descargar El uacuteltimo paraacutemetro FTP_ASCI I le dice al FTP el tipo de archivo que va a ser descargado Los modos que puede elegir son FTP_ASCI I o FTP_BINARY Los ficheros binarios son archivos escritos en el lenguaje maacutequina como los archivos graacuteficos Ademaacutes puede enviar archivos al servidor con la funcioacuten f tp_put () El siguiente ejemplo muestra coacutemo subir un archivo al servidor

ftp_put($conexion nuevoFicherotxtFicherotxtFTP_ASCII)

Como en el ejemplo anterior n u e v o F i c h e r o t x t seraacute el nombre del archivo en el servidor remoto y F i c h e r o t x t el archivo que vamos a enviar El ejemplo siguiente descarga todos los archivos con extensioacuten PHP en nuestro ordenador local

public function descargaPHP($directorio = )

316 Capiacutetulo 18

$this-gtarchivos = ftp_nlist($this-gtconexion$directorio) foreach ($this-gtarchivos as $archivo)

if (ereg(php$archivo)) if ( f ile__exists ($archivo) )

ftp_get($this-gtconexion$archivo$directorio $archivoFTP_ASCII)

else

echo Fichero $archivo ya existeltbrgt

else

echo El archivo $archivo no es de PHPltbrgt

Otras funciones de FTP

Ademaacutes de las funciones descritas en este capiacutetulo existen otras muchas para el manejo del protocolo FTP

Tabla 181 Funciones comunes al manejo de FTP

Funciones Descripcioacuten

ftp_cdup($conexion) Cambia al directorio inmediatamente

superior al directorio actual ftp_chdir($conexioacuten Cambia al directorio que pasemos como

nombre directorio) paraacutemetro

ftp_close($conexion) Cierra una conexioacuten FTP

ftpconnect(servidor) Establece una conexioacuten con el servidor

ftp_delete($conexioacuten ruta) Borra un fichero del servidor

ftp_exec($conexioacuten comando) Ejecuta un comando del sistema remoto

ftp_fget($conexioacuten $descriptor Descarga un fichero y vuelca los datos Ficherotxt FTP_ASCII) en un fichero abierto en el ordenador

local

ftp_fput($conexioacuten $descriptor Enviacutea un archivo a un fichero abierto Ficherotxt FTP_ASCII)

ftp_get($conexioacuten nuevoFicherotxt Recupera un fichero de un servidor Ficherotxt FTP_ASCII)

ftp_put($conexioacuten nuevoFicherotxt Enviacutea un fichero al servidor

Ficherotxt FTP_ASCII)

Conexiones desde PHP 5 317

Funciones Descripcioacuten

ftp_login($conexiexcloacuten $usuario $clave) Autentifica al usuario en el servidor ftp_mdtm($conexioacutenFicherotxt) Recupera la fecha de la uacuteltima actualishy

zacioacuten del fichero ftp_mkdir($conexioacuten directorio) Crea un directorio

ftp_nlist($conexioacuten directorio) Recupera la lista de archivos de un directorio

ftp_pwd($conexion) Obtiene el nombre del directorio actual ftp_rename($conexioacuten Cambia de nombre un archivo remoto ArchivoAntiguoArchivoNuevo) ftp_size($conexionFicherotxt) Devuelve el tamantildeo de un fichero ftp_systype($conexion) Permite obtener el tipo de sistema

Correo electroacutenico

La aplicacioacuten maacutes utilizada sin duda en Internet es el correo electroacutenico La explosioacuten de Internet y la expansioacuten de servidores gratuitos que ceden cuentas de correo a todos los usuarios ha permitido que el crecimiento de los e-tnail se dispare en estos uacuteltimos antildeos

Para lograr la comunicacioacuten a traveacutes del correo electroacutenico han de intershyvenir numerosas piezas de un puzzle

La mayor parte del modelo utiliza

bull Servidor TCP IP Se encarga de mantener activos para la conexioacuten diversos servicios como FTP SMTP o POP

bull MTA (Mail Transfer Agent) Acepta correo de otros servidores SMTP y busca una ruta para que los correos lleguen a su destino

bull Cola de correo Recipiente donde se almacenan todos los correos enshytrantes dirigidos a una persona

bull MUA (Mail User Agent) Programa muy liviano para leer el correo elecshytroacutenico normalmente desde el servidor

bull Servidor POP IMAP Recibe peticiones de lecturas de correo El sershyvidor chequea si hay correos nuevos y los enviacutea al cliente

bull MLM (Mailing List Manager) Este software ayuda a enviar grandes cantidades de correo

318 Capiacutetulo 18

Enviar correo desde PHP

Soacutelo existe una funcioacuten para enviar correo electroacutenico desde PHP 5 La funcioacuten mail () devolveraacute un valor true si los datos son enviados correcshytamente La forma maacutes sencilla de utilizar esta funcioacuten la puede ver en el ejemplo siguiente

ltphp $resultado = mail ( luisaacutenccextremadura org Ejemplo de Asunto Cuerpo del mensaje) if ($resultado)

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt

El primer paraacutemetro recibe el correo de la persona a la que quiere enviar el mensaje El segundo es un resumen del contenido de su carta electroacutenishyca y por uacuteltimo el tercer paraacutemetro es el mensaje que quiere transmitir Puede dividir la funcioacuten en variables para que sea maacutes sencillo de utishylizar

ltphp $correo = luisnccextremaduraorg $asunto = Ejemplo de Asunto $cuerpo = Cuerpo del mensaje $resultado = mail($correo $asunto $cuerpo) if ($resultado)

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt

Hay veces que necesitaraacute algo maacutes de control sobre lo que quiera enviar o necesite enviar un correo a varias personas a la vez Esto es posible antildeashydiendo cabeceras adicionales a la funcioacuten mail

ltphp $correo = luisnccextremaduraorg $asunto = Ejemplo de Asunto $cuerpo = Cuerpo del mensaje $cabecera = From fernandarnbccpedronccextremaduraorgrnContent-type textplainrnX-mailer PHP phpversion () $resultado = mail($correo $asunto $cuerpo $cabecera) if ($resultado)

Conexiones desde PHP 5 319

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

La cabecera muestra coacutemo enviar junto al correo la direccioacuten de la persoshyna que lo enviacutea y una copia del mismo mensaje al correo pedroncc extremaduraorg Es necesario antildeadir los separadores r y n para indishycar un salto de liacutenea entre los paraacutemetros de la cabecera

Las cabeceras adicionales pueden antildeadir muchos tipos de informacioacuten entre los que se encuentran

bull El nombre del emisor

bull Correo del emisor

bull Correo de respuesta

bull X-mailer y nuacutemero de versioacuten

bull versioacuten MIME

bull Content-type

bull Codificacioacuten

bull Campo de copia y copia oculta

La funcioacuten m a i l () estaacute preparada para emitir mensajes sencillos pero hay muchas caracteriacutesticas que debe implementar con cabeceras Por eso han nacido una serie de libreriacuteas escritas en PHP que facilitan el enviacuteo de correos

La libreriacutea PHPMailer antildeade a la funcioacuten m a i l () muchas funcionalidashydes como ficheros adjuntos o correos HTML

PHPMailer

PHPMailer estaacute basado en programacioacuten orientada a objetos Contiene varios ficheros que deben guardarse en el directorio de PHP dedicado a libreriacuteas o en nuestro espacio de trabajo

La construccioacuten maacutes baacutesica es la siguiente

ltphp require_once(phpmailerclassphpmailerphp) $correo = new phpmailer() Datos personales del emisor $mail-gtFrom = luisnccextremaduraorg

320 Capitulo 18

$mail-gtFromName = Luis Miguel Cabezas

$mail-gtSubject = Mensaje de prueba

$mail-gtBody = Cuerpo del mensaje Direccioacuten de destino $mail-gtAddAddress(zeevSphpzendcomZeev Suraski)

if ( l$mail-gtSend()) echo Correo enviado correctamente

else echo El correo no ha podido enviarse

gt

Como puede ver las propiedades de la clase p h p m a i l e r son auto explishycativas El ejemplo va asociando cada propiedad a un dato necesario para el enviacuteo El meacutetodo A d d A d d r e s s () antildeade una direccioacuten de correo a la que enviar el mensaje y Send () lo enviacutea a traveacutes de Internet

Antildeadir un fichero adjunto

Existen tres meacutetodos para antildeadir un fichero adjunto a un mensaje dos para archivos y otro maacutes especiacutefico para imaacutegenes

bull AddAttachment(ruta nombre) Antildeade un fichero localizado en el servidor Este archivo se puede subir antes al servidor mediante un formulario

bull AddStringAttachment(caracteres fichero) Se puede utilizar para enviar ficheros almacenados en variables

bull AddEmbeddedImage(ruta cid nombre) Antildeade una imagen y pershymite antildeadirla al cuerpo de un correo HTML

Las liacuteneas siguientes se pueden antildeadir al ejemplo anterior para enviar un fotografiacutea almacenada en el servidor

if ($mail-gtAddAttachment(abuelojpgabuelojpg))

echo Falloacute al antildeadir un fichero adjunto

Para demostrar la teoriacutea anterior vamos a crear un pequentildeo formulario que permita enviar correo Es un coacutedigo muy sencillo pero permite enshyviar mensajes escritos en HTML e incluir imaacutegenes

ltphp if (isset($_POST[nombre]))

require_once(phpmailerclassphpmailerphp)

Conexiones desde PHP 5 321

$correo = new phpmailer() Datos personales del emisor $mail-gtFrom = luisnccextremaduraorg $mail-gtFxowpoundawgte = Luis Miguel Cabezas $mail-gtSubject = $_POST [ asunte ] $mail-gtBody = $_POST[mensaje] Direccioacuten de destino $mail-gtAddAddress($_POST[nombre]$_POST[correo]) if ($mail-gtAddEmbeddedImage($_FILES[imagen] [tmp_name 12 34 5 imagen))

echo Falloacute al antildeadir un fichero adjunto

if ( $mail-gtSend() )

echo Correo enviado correctamente else

echo El correo no ha podido enviarse

gt lthtmlgt ltbodygt ltform action=mailphp method=post enctype=multipartform-data name=formlgt lttable width=50 border=0 cellspacing=0

cellpadding=Ogt lttrgt

lttd width=28gtNombrelttdgt lttd width=72xinput name=nombre type=text

id=nombregtlttdgt lttrgt lttrgt lttdgtCorreolttdgt lttdxinput name=correo type=text id=correogtlttdgt

lttrgt lttrgt lttdgtAsuntolttdgt lttdxinput name=asunto type=text id= asuntogtlttdgt

lttrgt lttrgt lttdgtMensajelttdgt lttdxtextarea name= mensa j e rowS=5 id= mensa j e gtlt textareaxtdgt

lttrgt lttrgt lttdgtSelecciona imagen lttdgt lttdxinput name=imagen type=file id= imagen xtdgt

lttrgt lttablegt ltpgt

322 Capiacutetulo 18

ltinput type=submit name=Submit value=Enviargt ltPgt

lt formgt ltbodygt lthtmlgt

La figura 182 muestra un formulario capaz de enviar contenido HTML e imaacutegenes adjuntas

Resumen

PHP se ha promovido tanto debido a las numerosas extensiones que pershymiten hacer casi cualquier cosa En concreto las dos formas vistas para conectarse con un servidor le seraacuten muy uacutetiles para ofrecer servicios inshynovadores a sus usiiarios

La mayoriacutea de los portales Web que necesitan el registro de sus usuarios enviacutean por correo electroacutenico las contrasentildeas y los datos de inscripcioacuten La funcioacuten mail () le puede servir para hacer sus pequentildeos controles de usuarios

Conexiones desde PHP 5 323

Si se siente maacutes ambicioso tambieacuten puede utilizar PHPMailer para consshytruir una paacutegina Web que permita enviar o recibir correo electroacutenico La recomendacioacuten es que continuacutee investigando en la clase PHPMailer y en todo lo que ofrece que no hemos podido ver en este capiacutetulo

326 Capiacutetulo 19

Introduccioacuten

Como probablemente ya sabe el HTML no es el uacutenico formato para mosshytrar contenido en Internet Ademaacutes de los distintos tipos de imaacutegenes teshynemos varios formatos capaces de contener textos como Adobe PDF Macromedia Flash o algunos documentos alternativos escritos en XML como los archivos graacuteficos SVG (Graacuteficos Vectoriales Escalables) WML (Lenguaje de Marcas Inalaacutembrico) o XUL (Lenguaje de interfaz de Usuashyrio en XML con Mozilla) Cada uno de estos tipos de documentos tiene su propio terreno y de nosotros depende elegir cuaacutel o cuaacuteles utilizar para dotar a nuestra Web de mayores posibilidades

Los archivos Adobe PDF se han establecido como un estaacutendar en los doshycumentos de texto para la Web

Existen dos extensiones escritas para PHP PDFLib y C l ibPDF capaces de generar archivos PDF Desgraciadamente estas libreriacuteas son de uso coshymercial y requieren el pago de alguacuten tipo de licencia Ademaacutes de las extensiones anteriores tenemos una serie de aplicaciones escritas completamente en PHP que permiten llegar al mismo resultado como RampOS PDF o FPDF No son tan raacutepidas como las extensiones pero cumplen perfectamente nuestras expectativas

Libreriacutea FPDF

La libreriacutea FPDF creada en septiembre de 2001 no necesita licencia de uso ni tampoco alguna configuracioacuten especial de PHP Lo uacutenico que neshycesita es la libreriacutea que la puede descargar del sitio Web h t t p wwwfpdforg

La libreriacutea principal contiene la definicioacuten de una clase que debe instan-ciar para poder generar sus documentos Nuestro coacutedigo inicial deberiacutea ser algo parecido a

ltphp require__once ( f pdf fpdf php) $pdf = new FPDF() gt

El constructor se utiliza de esta forma con los valores por defecto que son paacutegina A4 con orientacioacuten vertical y el tamantildeo medido en miliacutemetros El primer paraacutemetro del constructor permite elegir entre orientacioacuten verti-

Creacioacuten de archivos PDF 327

cal (L) u horizontal (P) El segundo paraacutemetro sirve para que las medidas de referencia se hagan en base a puntos (pt) miliacutemetros (mm) centiacutemetro (cm) o pulgadas (in) El uacuteltimo paraacutemetro nos ofrece la oportunidad de elegir entre los diferentes formatos de paacutegina que existen A3 A4 A5 Let-ter y Legal

Nota

Hay que recordar que un punto es 172 pulgadas

$pdf = new FPDF( P cm A 4 )

Nuestro primer documento

El siguiente ejemplo muestra la creacioacuten baacutesica de un documento PDF de forma lineal

ltphp define(FPDF_FONTPATHfpdffont) require_once ( fpdffpdfphp) $pdf = new FPDF() $pdpound-gtAddPageU bull $pdf-gtSetFont(Arial 15) $pdf-gtWrite(155 Mi primer documento) $pdf-gtOutput() gt

La primera liacutenea define una constante que contiene la ruta donde estaacuten almacenadas las fuentes Despueacutes de las funciones que incluyen la clase y la instancia del objeto tenemos una serie de llamadas a meacutetodos que nos permiten manipular el documento a nuestro antojo

Advertencia

FPDF mantiene la posicioacuten de un cursor Las funciones que geneshyran texto imprimiraacuten los datos de acuerdo con la posicioacuten del curshysor en ese momento Es posible de todas formas cambiar de sitio el cursor con algunas funciones que veremos en este capiacutetulo

El meacutetodo AddPage () antildeade una paacutegina al documento con la orientashycioacuten que Le pida En este caso hemos antildeadido una con orientacioacuten vertical que es la elegida por defecto S e t F o n t () selecciona una fuente tomando

Funciones de texto

Meacutetodo Write()

Imprime el texto pasado como paraacutemetro en la posicioacuten que indica el curshysor La construccioacuten es

W r i t e ( a l t u r a t e x t o e n l a c e )

Los paraacutemetros son los siguientes

bull altura Altura de la celda bull texto Texto a imprimir bull enlace Podemos considerar el texto como un enlace a una paacutegina o a

una Web

Como ejemplo puede ver el primer coacutedigo que hemos realizado

328 Capiacutetulo 19

como paraacutemetro el tipo la propiedad (negrita cursiva) y el tamantildeo Por uacuteltimo tenemos una llamada a los meacutetodos Write () y Output () que escriben el texto en una posicioacuten determinada del documento y lo muesshytran en pantalla respectivamente como puede ver en la figura 191

Creacioacuten de archivos PDF 329

Meacutetodo Cell()

El meacutetodo c e l l () puede tomar hasta 8 paraacutemetros y es el encargado de imprimir en el documento PDF un cuadro de texto en la posicioacuten indicashyda El cuadro de texto puede tener un borde alrededor o en alguno de los lados

La construccioacuten es como sigue

cell(ancho altura texto borde liacutenea alineacioacuten relleno enlace)

Los dos primeros paraacutemetros son obligatorios los demaacutes opcionales A continuacioacuten vemos para queacute sirve cada paraacutemetro

bull ancho Ancho de la celda Si es 0 se considera el ancho total del folio

bull altura Altura de la celda

bull texto Texto a imprimir

bull borde Un 1 significa que llevaraacute borde Tambieacuten se pueden incluir algunos caracteres para indicar en cuaacutel de las partes de la celda debe llevar borde L R T y B significan Izquierda Derecha Arriba y Abajo respectivamente

bull liacutenea Cuando termine la llamada a la creacioacuten de la celda indica al generador de PDF doacutende debe colocar el cursor para continuar Un 0 indica a la derecha de la tabla un 1 en la siguiente liacutenea y un 2 seguido

bull alineacioacuten Acepta 3 caracteres L para alinear a la izquierda R a la derecha y C para texto centrado

bull relleno Indica con un 1 si la celda debe tener un relleno para diferenshyciarla del resto del folio

bull enlace Enlace devuelto por la funcioacuten A d d l i n k ()

Como ejemplo puede ver la forma de introducir un tiacutetulo en una paacutegina

lt php define(FPDF_FONTPATHfpdffont) require__once ( fpdffpdf php i $pdf = new FPDF()

$pdf-gtAddPage() $pdf-gtSetFont(Courier 1 0 ) $pdf-gtCell(80) $pdf-gtCell (2010 Titulo 11C) $pdf-gtOutput() gt

Una celda soacutelo puede contener el nuacutemero de caracteres que quepa en una liacutenea Si necesita mostrar maacutes liacuteneas de texto puede utilizar el meacutetodo

330 Capiacutetulo 19

Muiacute ti Ce 11 () que toma los mismo paraacutemetros que Ce 11 ( ) pero cuanshydo el texto llegue al final de la liacutenea se antildeade automaacuteticamente un salto a la liacutenea siguiente

Truco

Puede utilizar Ce 11 () para desplazar el cursor hacia la derecha antildeadiendo como paraacutemetro un ancho de 8 centiacutemetros (80 miliacuteshymetros) Despueacutes para imprimir el texto antildeada otra celda que inshycluya el literal Tiacutetulo centrado dentro de una celda con borde

Desplazamiento de los cursores

Existen varias funciones para colocar el cursor en distintas partes del doshycumento Se tX () y S e t Y () colocan el texto en el punto indicado en la medida seleccionada (centiacutemetros miliacutemetros etc)

Se tX () desplaza el cursor de izquierda a derecha tantas unidades como indique el paraacutemetro y S e t Y () de arriba hacia abajo Si se les pasa un nuacutemero negativo el origen se tomaraacute desde la derecha o desde abajo resshypectivamente

SetXY () toma dos valores y permite realizar las dos operaciones con una sola instruccioacuten

$pdf-gtSetXY(100100) $pdf-gtwrite(2Este texto se mostraraacute a 10 cm del margen)

Salto de paacutegina automaacutetico

El meacutetodo S e t A u t o P a g e B r e a k () activa o desactiva el salto de paacutegina automaacutetico

Esto quiere decir que si estaacute activado cuando el texto llegue al final de la paacutegina se crearaacute una paacutegina nueva para poder contener el resto El primer paraacutemetro debe ser true ofalse para activa o desactivar la proshypiedad

El segundo paraacutemetro indica la distancia desde la parte inferior que desshyencadena la llamada a una nueva paacutegina

Se tAutoPageBreak( t rue 20 )

El coacutedigo anterior activa el salto de paacutegina automaacutetico cuando el texto lleshygue a 2 centiacutemetros del margen inferior

Creacioacuten de archivos PDF 331

Sobrescribir los meacutetodos

La clase FPDF contiene algunos meacutetodos vaciacuteos que debe escribir usted si quiere que sus documentos queden profesionales Puede crear un objeto propio que herede del objeto FPDF e implementar algunas caracteriacutesticas avanzadas

Cabecera

La cabecera de un documento es un conjunto de texto escrito en la parte superior del folio y que debe aparecer en todas las paacuteginas La clase FPDF implementa el meacutetodo header () que se llama cada vez que existe un salto de paacutegina

Puesto que el meacutetodo estaacute vaciacuteo en FPDF tendraacute que crear un objeto nueshyvo que herede todos sus meacutetodos e implemente la cabecera

ltphp define ( FPDF_FONTPATH fpdffont ) requireonce(fpdffpdfphp) class PDF extends FPDF

function Header()

$this-gtSetFont(ArialB15) $this-gtSetX(70) $this-gtCell(100 10 Manual Imprescindible de PHP 510C) $this-gtLn(20)

$pdf = new PDF () for($i=l$ilt=200$i++) $pdf-gtCell(010Imprimiendo liacutenea nuacutemero $i0l)

$pdf-gtOutput () gt

El meacutetodo header () configura un tipo de letra determinado en negrita avanza el cursor 8 centiacutemetros hacia la derecha e imprime una celda con el tiacutetulo El meacutetodo Ln (2 0 ) inserta un salto de liacutenea cuya altura es determinada por el argumento

Para probar el objeto hemos hecho un bucle que imprime 100 liacuteneas y asiacute comprobar que la cabecera aparece invariable El resultado se puede obshyservar en la figura 192

Imagen de cabecera

Tambieacuten es posible antildeadir una imagen a la cabecera con el meacutetodo Ima-ge ( ) La construccioacuten es la siguiente

Image(fichero x y ancho alto tipo enlace)

Los paraacutemetros necesarios son fichero x e y La descripcioacuten de todos los argumentos es

bull fichero Indica la ruta hacia el fichero que va a insertar

bull x Posicioacuten en el eje x de la imagen

bull y Posicioacuten en el eje y de la imagen

bull ancho Ancho de la imagen

bull alto Alto de la imagen Si no se indica y el paraacutemetro ancho estaacute defishynido el alto se escala en funcioacuten del ancho

bull tipo El tipo de imagen Por ahora soacutelo se aceptan imaacutegenes JPG JPEG y PNG

bull enlace La imagen puede ser un enlace

Ahora que sabe coacutemo insertar imaacutegenes puede incluir en la cabecera el logotipo de su empresa o asociacioacuten

funct ion Header()

Creacioacuten de archivos PDF 333

$this-gtSetFontArialB15) $this-gtSetX(70) $this-gtCell(10010Manual Imprescindible de PHP 510C) $this-gtSetX(-20) $this-gtImage(phppng1705) $this-gtLn (20)

La figura 193 muestra una cabecera con una imagen insertada

Pie de paacutegina

De la misma forma puede sobrescribir el meacutetodo que imprime el pie de paacutegina de la clase FPDF

Este meacutetodo recibe el nombre de F o o t e r () y tiene el mismo tratamiento que la cabecera cada vez que existe un salto de paacutegina se hace una llamashyda al mismo Nuestro pie de paacutegina puede quedar de la siguiente forma

funct ion Footer()

$this-gtSetY (-15) $this-gtSetFont(Arial I 10) $this-gtCell (010 Paacutegina $this-gtPageNo() 00 C )

334 Capiacutetulo 19

S e t Y () nos coloca el cursor a 15 miliacutemetros del borde derecho Seguidashymente escoja el tipo de fuente Aria e imprima el nuacutemero de la paacutegina acshytual con el meacutetodo PageNo ()

Muchos documentos informan ademaacutes del nuacutemero de paacuteginas que tiene el texto Esto es complicado a primera vista porque a priori no podraacute saber cuaacutentas paacuteginas ocuparaacute su texto Existe un meacutetodo que se ejecuta cuando el documento es cerrado y sustituye una marca por el nuacutemero de folios con los que cuenta nuestro proyecto

function FooterO

$this-gtSetY(-15) $this-gtSetFont ( Anal I 10) $this-gtAliasNbPages() $this-gtCell(0 10 Paacutegina $this-gtPageNo()

nb 00 C)

El meacutetodo A l i a s N b P a g e s () cuenta el nuacutemero de paacuteginas cuando el doshycumento estaacute cerrado y sustituye la marca nb por este nuacutemero

Tablas

Una tabla no es maacutes que un conjunto de celdas colocadas en un orden determinado Podemos diferenciar entre la cabecera de la tabla que conshytendraacute las propiedades y los datos Si realiza una clase para escribir tashyblas puede hacer tambieacuten esa diferenciacioacuten cambiando el tipo de letra el tamantildeo o el color El coacutedigo siguiente muestra coacutemo se puede instaurar una clase para la creacioacuten de tablas faacutecilmente

ltphp define(FPDF_FONTPATHfpdffont) require_once(fpdffpdfphp) class PDF extends FPDF function tabla($cabecera$datos)

$this-gtcabecera ($cabecera) $this-gtdatos($datos)

function cabecera($cabecera) Cabecera

$this-gtSetFont(ArialB15)

Creacioacuten de archivos PDF 335

foreach($cabecera as $columna) $this-gtCell(407$columna1 0 C )

$this-gtLn()

function datos($datos) Datos

$this-gtSetFont(Arial12) foreach ($datos as $dato)

foreach ($dato as $columna) $this-gtCell(407$columna10 C )

$this-gtLn ()

$pdf = new PDF () $pdf-gtAddPage ()

$cabecera = array(UsuariosVisitasLocalidadTeleacutefono) $datos = array(array(Luis Miguel 12Badajoz555345678)

array(Mariacutea Fernanda 45 Meacuterida 234234654) array(Pedro Casas3Caacuteceres342123 890))

$pdf-gttabla($cabecera$datos) $pdf-gtOutput () gt

En este caso los datos se sacan de un array de dos dimensiones pero pueshyde utilizar la libreriacutea de bases de datos o la de XML creadas en los capiacutetushylos anteriores para extraerlos

Los datos los recibe el meacutetodo T a b l a ( ) que los enviacutea a sus corresponshydientes meacutetodos para ser tratados El funcionamiento baacutesico consiste en la creacioacuten repetitiva de celdas cuyo nuacutemero coincidiraacute con el nuacutemero de datos existentes en el array Todas las celdas se muestran seguidas dando sensacioacuten de ser una tabla como puede ver en la figura 194 Ahora que es casi un experto en la creacioacuten de tablas para facturas o alba-ranes en PDF puede dar un toque de color al relleno texto o liacuteneas de las celdas

Puede comprobar que con tan soacutelo tres liacuteneas de coacutedigo maacutes el aspecto visual del documento mejora considerablemente

function cabecera($cabecera)

Cabecera $this-gtSetFillColor (25500)

336 Capiacutetulo 19

$this-gtSetTextColor(255) $this-gtSetDrawColor(12 800) $this-gtSetFont(ArialB15) foreach($cabecera as $columna)

$this-gtCell(407$columna10C1)

$this-gtLn()

function datos($datos)

D a t o s $this-gtSetTextColor (1) $thiacutes-gtSetDrawColor (12 800) $this-gtSetFont ( Arial 12) foreach ($datos as $dato)

foreach ($dato as $columna) $this-gtCell(407$columna10C)

$this-gtLn ()

El resultado es mucho maacutes llamativo gracias a los meacutetodos que antildeaden color El meacutetodo S e t F i l l C o l o r () define el color de fondo de las celdas

Creacioacuten de archivos PDF 337

y los rectaacutengulos que no sean transparentes Puede ser expresado con un componente RGB o en escala de grises El valor se mantiene durante todo el documento hasta que se vuelva a invocar el meacutetodo

S e t T e x t C o l o r () y S e t D r a w C o l o r () funcionan de la misma forma actuando esta vez sobre el color del texto o el color de las liacuteneas y bordes de celda La figura 194 muestra los colores (tonos de grises en este caso) distintos que pueden tomar un archivo PDF

Enlaces

Una de las ventajas del formato PDF es que permite hacer enlaces intershynos es decir que si tiene un documento de 500 folios podraacute acceder a cada uno de los capiacutetulos haciendo clic en el iacutendice tal y como funcionan los enlaces en las paacuteginas Web

Un enlace externo es muy faacutecil de crear

$pdf-gtWrite(5wwwluisyfernandanethttpwwwluisyfernandanet)

Los meacutetodos dedicados a texto tienen un argumento para antildeadir un enlashyce que si es externo debe llevar la direccioacuten URL completa

338 Capiacutetulo 19

Crear un enlace interno es algo maacutes complicado Tiene que hacer uso del meacutetodo A d d l i n k ( ) que genera una referencia que debe ponerse en el lugar hacia donde quiere que se produzca el salto En ese lugar utilice el meacutetodo S e t L i n k () para cerrar el enlace

El coacutedigo de ejemplo puede aclarar el concepto

ltphp define(FPDF_FONTPATHfpdffont) require_once(fpdffpdfphp) $pdf = new FPDF() $pdf-gtAddPage () $pdf-gtSetFont(Arial 15) $enLace = $pdf-gtAddLink() $pdf-gtWrite(5Este texto contiene un enlace$enlace) $pdf-gtAddPage) $pdf-gtSetLink($enlace) $pdf-gtWrite (5 Enlace Interno) $pdf-gtOutput () gt

Lo uacutenico a destacar es la creacioacuten del enlace con AddLink ( ) La variable $ e n l a c e recoge el valor de referencia y se antildeade al texto de la liacutenea sishyguiente En este momento el texto contiene un enlace pero no sabemos hacia doacutende La solucioacuten estaacute en llamar al meacutetodo S e t L i n k () en la paacutegishyna de destino con la referencia de paraacutemetro

Resumen

Los archivos PDF se consideran desde hace unos antildeos ideales para la geshyneracioacuten de contenidos on-line As iacute revistas digitales como w w w phparchcom o wwwphpmagnet utilizan este sistema para vender su publicacioacuten

Ademaacutes de revistas digitales podemos encontrar empresas que hacen lleshygar las instrucciones de sus productos en PDF o realizan las facturas de los clientes on-line como el programa de facturacioacuten extrementildeo Galopiacuten (httpgalopinsinuhorg)

La generacioacuten de sus propios archivos ya no es un misterio y puede im-plementar clases muchos maacutes potentes que las mostradas en el libro para sus propios proyectos La inclusioacuten de colores imaacutegenes y tablas de disshytintos tipos haraacuten del lector un profesional de la edicioacuten Web

En este capiacutetulo aprenderaacute a

bull Conocer queacute es un sistema de plantillas con Smarty

bull Independizar el coacutedigo HTML de PHP bull Crear plantillas con variables y bucles bull Crear plugins propios y modificar los ya existentes bull Crear filtros para mejorar el proceso

340 Capiacutetulo 20

Introduccioacuten

Cuando PHP nacioacute fue considerado como un sencillo lenguaje para geneshyrar dinaacutemicamente etiquetas de HTML Tras la versioacuten 3 de PHP se antildeashydioacute un compendio de funciones complejas para el manejo de cadenas arrays y bases de datos lo suficientemente completas como para crear sishytios Web muy extensos

Despueacutes de la creacioacuten de entornos completos en PHP los desarrollado-res comenzaron a pensar que no era muy uacutetil mezclar coacutedigo PHP con coacutedigo HTML e inventaron una forma de independizar los dos lenguajes mediante el uso de plantillas El primer entorno de plantillas que apareshycioacute fue FastTemplate escrito originariamente en Perl

En un periacuteodo corto de tiempo aparecieron muchos programas que facilishytaban el uso de plantillas como vTemplate Xtemplate TemplatePower o SmartTemplate Todos permiten sustitucioacuten de variables bloques repetishytivos inclusioacuten de muacuteltiples plantillas y bloques opcionales con estructushyras del tipo i f La diferencia estaacute en que muchos de estos sistemas utilizan expresiones regulares y hace muy complicado su uso Ademaacutes la velocishydad con la que se generan las plantillas es una propiedad a tener en cuenshyta en un entorno de trabajo en produccioacuten

SmartTemplate aparecioacute en 1999 y es el predecesor de lo que hoy conoceshymos como Smarty Es un entorno muy similar a otros pero incluye caracshyteriacutesticas muy avanzadas que lo hacen uacutenico la compilacioacuten de plantillas Esto significa que Smarty lee la plantilla y crea un script escrito en PHP Una vez creado este script se ejecuta y muestra el resultado en pantalla Lo bueno es que la compilacioacuten soacutelo se hace la primera vez las veces sishyguientes Smarty comprueba si hay nuevos datos que mostrar y si no los hay se utiliza la plantilla escrita en PHP por lo que la ejecucioacuten se hace muy raacutepida Algunas de las caracteriacutesticas generales de Smarty son

bull Extremadamente raacutepido

bull Muy eficiente porque el parse de PHP hace todo el trabajo

bull Soacutelo se compilan las plantillas que cambien los datos

bull Podemos realizar funciones propias y modificadores de variables Esto hace que Smarty sea extensible por el usuario

bull Se pueden utilizar varios delimitadores como j ltmdashmdashgt

bull Las estructuras de control son manejadas directamente por el parse de PHP por lo tanto pueden ser tan complejas como quiera

Plantillas con Smarty 341

bull Se puede incluir coacutedigo PHP dentro de nuestras plantillas

bull Funciones configurables para el manejo de la cacheacute

bull Arquitectura de plugins ampliable

Instalacioacuten de Smarty

La instalacioacuten del entorno de Smarty es muy sencillo y pasa por descargar de la Web httpsmartyphpnet la uacuteltima actualizacioacuten del sistema El archivo comprimido consta de varias carpetas que deberiacutean estar dentro del directorio de libreriacuteas de PHP Tambieacuten es posible guardar la carpeta de Smarty junto con nuestros programas pero no es recomendable

Las libreriacuteas del sistema de plantillas incluidas dentro del directorio l i b s son

Smartyclassphp Smarty_Compilerclassphp Config_Fileclassphp debugtpl

Ademaacutes de estos archivos existen las carpetas c o r e y p l u g i n s que se encargan de controlar el flujo de los objetos de Smarty

Las plantillas que creemos las vamos a guardar en un directorio llamado t e m p l a t e s y las plantillas compiladas deberaacuten estar en t e m p l a t e s _ c

Advertencia

La carpeta t e m p l a t e s _ c debe permitir la escritura porque aquiacute se iraacuten guardando las plantillas compiladas

Utilizacioacuten baacutesica de Smarty

Durante el desarrollo del libro hemos visto algunas teacutecnicas para escribir limpiamente nuestro coacutedigo PHP mezclado con HTML Vamos a ver una clase implementada por nosotros que genera una Web desde PHP y desshypueacutes vamos a ver coacutemo hacer lo mismo desde Smarty

ltphp c l a s s PaginaWeb

342 Capiacutetulo 20

priacutevate $titulo function construct($titulo)

$this-gttitulo = $titulo

priacutevate function cabecera($titulo)

echo lthtmlgt echo ltheadgt -echo lttitlegt$tituloltheadgt echo ltheadgt echo ltbodygt

priacutevate function cuerpo()

echo Este es el cuerpo de nuestra Webltbrgt priacutevate function pie()

echo Pie creado con PaginaWeb class echo ltbodygt echo lthtmlgt

public function creaWeb()

$this-gtcabecera($this-gttitulo) $this-gtcuerpo () $this-gtpie ()

$pagina = new PaginaWeb(Pagina Web generada con PHP) $pagina-gtcreaWeb () gt

Lo que hace cada meacutetodo es generar las etiquetas necesarias para crear una paacutegina Web Imagine ahora un gran sitio Web con cientos de paacuteginas Web con distinto tipo de informacioacuten Cambiar el aspecto visual de esa Web seriacutea un trabajo muy laborioso de varios meses primero buscando doacutende se encuentran las etiquetas junto al coacutedigo PHP y segundo modishyficando todo el coacutedigo HTML para que cambie el aspecto visual Las planshytillas solucionan este problema en muy poco tiempo separando el coacutedigo de la presentacioacuten

El resultado se puede ver en la figura 201

La paacutegina Web siguiente p l a n t i l l a r t p l es la misma que genera la clase anterior pero esta vez creada como plantilla

plantillaltpl

Plantillas con Smarty 343

lthtmlgt ltheadgt lttitlegt$titulolttitlegt ltheadgt ltbodygt $cuerpo $pie ltbodygt lthtmlgt

Todas las etiquetas conservan el estilo de HTML antildeadiendo siacutembolos de llave donde debe aparecer contenido dinaacutemico $ t i t u l o $cuerpo y $pie son variables que reciben su valor desde el programa escrito en PHP

Nota

Todo lo que estaacute entre se considera un comentario

344 Capiacutetulo 20

Para poder asignar valores a la plantilla tiene que hacer una instancia de la clase Smar ty

Puede modificar el objeto anterior para que haga uso de plantillas

ltphp class PaginaWeb

priacutevate $titulo priacutevate $Web function construct($titulo)

$this-gttitulo = $titulo requiacutere_once(Smarty1 ibsSmartyclassphp) $this-gtWeb = new Smarty

priacutevate function cabecera($titulo)

$this-gtWeb-gtassign(titulo$this-gttitulo) priacutevate function cuerpo()

$this-gtWeb-gtassign(cuerpoEste es el cuerpo de nuestra Web)

priacutevate function pie ( )

$this-gtWeb-gtassiacutegn(pie Pie creado con PaginaWeb) public function creaWeb()

$this~gtcabecera($this-gttitulo) $this-gtcuerpo () $this-gtpie()

$this-gtWeb-gtdisplay(plantilla1tpl)

$pagina = new PaginaWeb(Pagina Web generada con PHP) $pagina-gtcreaWeb() gt

La clase es exactamente igual (con los mismos meacutetodos) pero ahora se encuentra libre de etiquetas HTML En su lugar aparecen asignaciones a variables de Smarty El constructor instancia un objeto desde la clase Smarshyty y lo guarda en $ t h i s - gtWeb Las asignaciones de variables se hacen con el meacutetodo a s s i g n () que tiene que recibir como primer paraacutemetro el nombre de la variable escrita en la plantilla y como segundo argumento el texto que debe aparecer en lugar de la variable

Plantillas con Smarty 345

Despueacutes de asignar todos los valores tendremos que llamar al meacutetodo d i s -p l a y () con la plantilla como argumento para que la Web aparezca en el navegador

Si se fija ahora en el directorio de las plantillas compiladas t e m p l a t e s _ c veraacute que ha aparecido un archivo que contiene el siguiente coacutedigo

ltphp Smarty versioacuten 263 created on 2004-08-15 130335

compiled from plantillaltpl gt lthtmlgt ltheadgt lttitlexphp echo $this-gt_tpl_vars [ titulo ] bull gt lttitlegt ltheadgt ltbodygt ltphp echo $this-gt_tpl_vars[cuerpo] gt

ltbrxbrgt ltphp echo $this-gt_tpl_vars[pie] gt

ltbodygt lthtmlgt

Como puede apreciar la compilacioacuten de una plantilla de Smarty consiste en cambiar los valores entre llaves por coacutedigo PHP que hace llamadas a las variables Esto lo convierte en un meacutetodo muy raacutepido porque es el mismo PHP el que se encarga de mostrar la plantilla ya compilada

Cuidado con los estilos CSS

Es muy uacutetil utilizar estilos CSS para definir los colores tipos de letra y demaacutes objetos de presentacioacuten que vamos a utilizar en nuestras paacuteginas Web

El problema surge porque su construccioacuten es de la siguiente forma

lts ty l e t y p e = t e x t c s s gt lt - -P colorgreen - - gt ltstylegt

Este estilo sirve para que los paacuterrafos sean por defecto de color verde El problema es que Smarty parsea todo lo que estaacute entre siacutembolos de llave como c o l o r g r e e n En este caso se produciriacutea un error porque el parse no identificariacutea ninguna funcioacuten estructura o variable de plantilla Para solucionar esto se pueden antildeadir las etiquetas l i t e r a l y l i t e -

346 Capiacutetulo 20

r a l que al ser parseadas su contenido se identifica como un comentashyrio y se salta hasta el siguiente juego de llaves

literal ltstyle type=textcssgt lt --P colorgreen mdash gt ltstylegt literal

Llamada a varias plantillas

Casi todas las paacuteginas Web pueden dividirse en varias partes bien difeshyrenciadas cabecera menuacute cuerpo pie

Con Smarty podraacute crear una Web simple que incluya todas las partes de la Web como un uacutenico archivo HTML o crear 4 plantillas distintas y 1 que las unifique por lo que seriacutea maacutes sencillo cambiar el aspecto de cada una de las partes

La funcioacuten i n c l u d e f i l e de Smarty permite antildeadir plantillas a un fishychero La plantilla principal puede ser de la siguiente forma

lthtmlgt ltheadgt lttitlegt$titulolttitlegt ltheadgt ltbodygt include file=cabeceratpl include file=cuerpotpl include file=$pie ltbodygt lthtmlgt

De esta forma podemos modificar alguna de las plantillas y automaacuteticashymente todas las Web que hagan referencia a la misma cambiaraacuten su asshypecto

Como puede ver la plantilla que genera el pie de paacutegina es una variashyble por lo tanto podemos pasar desde PHP el nombre de cualquier planshytilla en funcioacuten de alguacuten caacutelculo interno o de alguacuten dato de MySQL etceacutetera

Variables

Smarty acepta muchos tipos de variables diferentes

Plantillas con Smarty 347

Pueden ser utilizadas para mostrarse directamente o como paraacutemetro de alguna funcioacuten o modificador dentro de alguna estructura de control etshyceacutetera

$nombre $contactonombre $contacto [0] $persona-gtnombre config_load_file=configuracioacutenconf lttitlegttitulolttitlegt

El coacutedigo anterior contiene diferentes tipos de variables y la forma de imshyprimir el dato que nos interesa Para una variable del tipo array puede utilizar la forma asociativa $ c o n t a c t o nombre o la forma indicativa $ c o n t a c t o [0] Tambieacuten es posible mostrar las propiedades de un objeshyto haciendo referencia asiacute $ p e r s o n a - gtnombre

Por uacuteltimo Smarty posee una funcioacuten que permite cargar una configurashycioacuten de un fichero Con la instruccioacuten c o n f iacute g _ l o a d _ f iacute l e cargaraacute en memoria la configuracioacuten del fichero que deacute como argumento El fichero debe estar escrito de esta forma

titulo = Pagina Web con PHP nombre = Luis Miguel color = FFFFFF

Modificadores

Los modificadores se pueden aplicar a las variables funciones o cadenas de caracteres Eacutestos permiten embellecer el texto recortarlo o adecuarlo a un formato determinado Para utilizar un modificador tiene que especifishycar la variable seguido de un siacutembolo de tuberiacutea ( I ) y el nombre del modificador

lthtmlgt ltheadgt cambia el texto a mayuacutesculas lttitlegt$titulo|upperlttitlegt ltheadgt ltbodygt Recorta el texto a 10 caracteres y le suma tren puntos suspensivos $cuerpoiexcltruacutencate10 ltbrxbrgt $pie ltbodygt lthtmlgt

348 Capiacutetulo 20

La plantilla anterior contiene el modificador upper que convierte todos los caracteres que recibe en mayuacutesculas El modificador t r uacute n c a t e recorshyta el texto dejaacutendolo en 10 caracteres y le antildeade puntos suspensivos como puede apreciar en la figura 202 La tabla 201 contiene un conjunto de modificadores que pueden utilizarse en las plantillas

Tabla 201 Modificadores de Smarty

Modificador Descripcioacuten Paraacutemetros

capitalize Convierte la primera letra Ninguno de cada palabra a mayuacutescula

count_characters Se usa para contar los Ninguno caracteres de una variable

cat Concatena el paraacutemetro 1 El texto a concatenar pasado a la variable

count_paragraphs Cuenta el nuacutemero de paacuterrafos Ninguno que contiene una variable

count_words Cuenta el nuacutemero de palabras Ninguno

Plantillas con Smarty 349

Modificador Descripcioacuten Paraacutemetros

date_format Imprime en un formato 1 Formato de salida 2 Si determinado la fecha y hora la entrada estaacute vaciacutea acep-del sistema este paraacutemetro por defecto

default Valor por defecto de la 1 El valor por defecto variable Si no se asigna ninguacuten valor la variable tendraacute el valor por defecto

escape Antildeade caracteres de escape 1 html htmlall url quo-a la variable tes hex hexentity javas-

cript

indent Antildeade varios caracteres a 1 Nuacutemero de caracteres a la izquierda de la variable indentar 2 Caraacutecter elegishy

do para indentar

lower Convierte a minuacutescula todos Ninguno los caracteres

nl2br Convierte los saltos de liacutenea a ltbrgt

regexreplace Busca y reemplaza una 1 Expresioacuten regular 2 Ca-expresioacuten regular dena de texto a reemplazar

replace Reemplaza una cadena de 1 Cadena a reemplazar caracteres por otra 2 Cadena de texto que susshy

tituiraacute al paraacutemetro 1

spacify Inserta un caraacutecter determinado 1 Caraacutecter entre los caracteres de la variable Por defecto un espacio en blanco

string_format Formatea un texto 1 Formato del texto como lo usa s p r i n t f

strip Reemplaza todos los espacios Ninguno saltos de liacuteneas y fabuladores por un espacio en blanco

strip_tags Elimina todas las etiquetas Ninguno

truacutencate Recorta una variable el nuacutemero 1 Nuacutemero de caracteres a de caracteres que indiquen los recortar 2 Texto que debe paraacutemetros aparecer si se recorta 3

True permite recortar en mitad de una palabra

upper Convierte a mayuacutesculas todos los caracteres de una variable

350 Capiacutetulo 20

Es bueno saber que podraacute aplicar varios modificadores a una misma vashyriable Tiene que antildeadirlos en el orden en el que quiera que se ejecuten de izquierda a derecha

$cuerpo[upper|spacify j truacutencate20

Nota

Si la variable es un array se aplicaraacute el modificador a todos ss valores

Funciones

El gestor Smarty tiene varias funciones que se pueden utilizar dentro del aacutembito de las plantillas Ademaacutes puede crear sus propias funciones o modificar las que ya estaacuten construidas

foreach

El bucle foreach se utiliza para mostrar un array simple La sintaxis es algo distinta al bucle de PHP

lttablegt foreach from=$art is tas i tem=valor lt t r x t d gt $ v a l o r lt t d x t r gt foreach lt t ab legt

Lo puede utilizar para antildeadir los valores de un array a una tabla como en el coacutedigo anterior La construccioacuten maacutes baacutesica de fo reach recibe en el atributo f rom el array que contiene los valores El atributo item crea una variable de Smarty que recoge los valores del array y se puede utilizar para mostrar el valor unas liacuteneas maacutes abajo

Otra construccioacuten un poco maacutes compleja es lttablegt foreach name=buclel from=$artistas key=indice item=valor lttrxtdgt $indice $valor lttdxtrgt foreach lttablegt

Funciona exactamente igual que el anterior El atributo key recoge el vashylor del iacutendice del array y ntildeame da un nombre al bucle para poder acceder a eacutel desde las variables propias de Smarty

Plantillas con Smarty 351

Truco

Se puede acceder al bucle mediante la variable global de Smarty Esta variable es $ smar ty Para acceder al bucle puede hacerlo de la siguiente forma $ s m a r t y f o r e a c h b u c l e 1

El resultado de la ejecucioacuten de la plantilla es

0 Paquito DRivera 1 Michel Camilo 2 Jerry Gonzaacutelez

if elseif else

La construccioacuten i f es tan flexible como la sentencia de PHP Cada i f debe tener una pareja del tipo i f

if $artistas[0] = Michel Camilo El primer artista toca el saxofoacuten alto

else El primer a r t i s t a toca e l piano

i f

Ademaacutes de los operadores baacutesicos de PHP tambieacuten puede utilizar mushychos otros como eq ne neq g t l t l t e l e g t e g e i s even i s odd i s n o t odd no t mod d i v by e v e n by o odd by El coacutedigo siguiente es similar al anterior

if $artistas[0] ne Michel Camilo El primer artista toca el saxofoacuten alto

else

El primer artista toca el piano

if

php incluido en plantillas

Puede antildeadir a una plantilla coacutedigo PHP encerrado entre las etiquetas de Smarty php y phpiexcl Si recuerda la filosofiacutea de las plantillas separar el coacutedigo de la presentacioacuten no se me ocurre ninguna excusa para utilizar esta habilidad en alguacuten proyecto por si acaso alguien le encuentra alguacuten sentido su uso es muy sencillo

php Incluir aquiacute alguacuten coacutedigo escrito en PHP include_once(logotiposphp) Php

352 Capiacutetulo 20

assign

Crea una variable y le asigna un valor determinado

assign var=variable value=Michel Camilo El valor de $variable es $variable

Se utiliza en tiempo de ejecucioacuten de la plantilla

counter

Se utiliza para imprimir un contador en pantalla

counter start=0 skip=3 print=falseltbrgt counterltbrgt counterltbrgt counterltbrgt

El atributo s t a r t indica el nuacutemero desde el que va a empezar el contashydor y s k i p el nuacutemero que debe sumarse al contador cada vez que exista una ocurrencia Cada vez que el parse encuentre c o u n t e r se incremenshytaraacute el contador y el navegador mostraraacute el resultado Para el ejemplo anterior podemos obtener

3

6

9

cycle

Una funcioacuten interesante que permite alternar entre varios valores pasashydos Cada vez que se ejecuta se recupera un valor distinto hasta el final de los valores Cuando se llega al final de la lista se vuelve a empezar Es muy uacutetil cuando queremos mostrar valores en una tabla y que cada liacutenea de detalle muestre un color diferente

lttablegt foreach name=buclel from=$artistas key=indice item=valor lttr bgcolor=cycle valueacutes=EEEEEEd0d0d0gtlttdgt$indice $valorlttdxtrgt foreach lttablegt

En este caso el bucle genera nombres de artistas del Jazz Latino y los inshytroduce en una tabla Gracias a la funcioacuten c y c l e se pueden diferenciar unos de otros por tener los colores de fondo de cada liacutenea distintos

Plantillas con Smarty 353

Opciones avanzadas de Smarty

Existen muchos tutoriales en Internet sobre el sistema de plantillas Toshydos abarcan la forma de utilizar las funciones y variables del entorno pero pocos se ocupan de las caracteriacutesticas que lo hacen uacutenico

La arquitectura de Smarty estaacute escrita en PHP Los ficheros que contienen las funciones baacutesicas para que el parse pueda realizar su trabajo estaacuten dentro de c o r e Pero la mayoriacutea de las funciones de presentacioacuten estaacuten incluidas dentro de la carpeta de p l u g i n s

Plugins

Un plugin dentro de la estructura de Smarty es un pequentildeo programa que realiza una tarea determinada Por ejemplo todos los modificadores son plugins y cada uno se encarga de hacer algo con el texto Veamos la estructura del plugin c a p i t a l i z e que recordemos modifica la primera letra de cada palabra y la convierte a mayuacutescula

ltphp function smarty_modifiacuteer_capitalize($string)

return ucwords($string)

gt

El funcionamiento del plugin es obvio Tan soacutelo hace uso de una funcioacuten existente en PHP para mostrar el resultado Puesto que es tan sencillo vamos a crear un plugin que serviraacute para enfatizar nuestro texto en detershyminadas ocasiones

ltphp function smarty_modifier_enfatizar($string)

re turn ltbgt $ s t r ing ltbgt

gt

Para crear un plugin modi f icador cree un fichero con el nombre modif i e r nombre php y guaacuterdelo en el directorio d e p l u g i n s En este caso tendraacute que crear un archivo con el nombre modi f i e r e n f a t i z a r php El nombre de la funcioacuten tambieacuten debe llevar un nombre estructurado Nuestro modificador se llamaraacute s m a r t y _ m o d i f i e r _ e n f a t i z a r y reci-

354 Capiacutetulo 20

biraacute como paraacutemetro la cadena de caracteres que lo utilice Dentro de la funcioacuten puede antildeadir el coacutedigo que sea necesario para cumplir su propoacuteshysito y despueacutes devolver el valor con la funcioacuten re turn

En nuestro caso devolvemos la misma cadena pero antildeadiendo la etiqueta de HTML para mostrar el texto en negrita por lo que quedaraacute enfatizado Tambieacuten podemos antildeadir alguacuten paraacutemetro para elegir entre distintos tishypos de eacutenfasis

ltphp funetion smarty_modifier_enfatizar($string $parametrol)

switch ($parametrol)

case 1 return ltbgt $striacuteng ltbgt break-

case 2 return ltemgt $string ltemgt break

case 3 return i i iexcl $string break

default return ltbgt $string ltbgt

gt

Ahora tenemos tres formas distintas de mostrar un texto que llame la atenshycioacuten Para invocar desde la plantilla cualquiera de los tipos de eacutenfasis hashybraacute que separar el modificador con un siacutembolo de dos puntos ( )

$valor|enfatizar3

Filtros

Los filtros son funciones que realizan una tarea determinada en nuestra plantilla justo antes o despueacutes de que sea compilada Se pueden consideshyrar los pre-filtros y los post-filtros respectivamente Existe un tercer tipo de filtro que se ejecuta en el momento de la llamada al meacutetododisplay ()

Crear un filtro para Smarty es tan sencillo como crear un plugin Hay que seguir estrictamente la nomenclatura del archivo y del nombre de la funshycioacuten para que funcione correctamente

ltphp function smarty_jostfilter_HechoCon($compiled amp$smarty)

Plantillas con Smarty 355

return $compiled ltbgtHecho con Smartyltbgt

gt

El filtro HechoCon () es una funcioacuten que recibe como paraacutemetros la fuente de la paacutegina Web ya compilada y el objeto Smarty que estamos utilizanshydo Nuestro filtro HechoCon devuelve la Web y antildeade un pequentildeo texto que indica que ha sido creado con Smarty

Para poder utilizar el filtro tenemos que cargarlo antes de utilizar el meacuteshytodo d i s p l a y ( ) en nuestro coacutedigo Esto se hace con la funcioacuten l o a d _ f i l t e r ( )

$this-gtWeb- gtload__f ilter (pre trim) $this-gtWeb-gtload_filter(postHechoCon) $this-gtWeb-gtload_filter(outputcompress)

El primer paraacutemetro del meacutetodo l o a d _ f i l t e r () indica el tipo de filtro que vamos a cargar y el segundo el nombre que recibe

Resumen

Alguacuten lector se preguntaraacute despueacutes de entender correctamente lo bueno que es separar el coacutedigo de la presentacioacuten por queacute he esperado tanto tiempo en contar el secreto de Smarty La verdad es que es mejor aprenshyder PHP paso a paso haciendo pequentildeos programas con HTML embebishydo para despueacutes ir concibiendo la mejor forma de atajar los diferentes proyectos que nos propongan

Con Smarty tiene una viacutea libre de exploracioacuten maacutes porque muchas de sus caracteriacutesticas no han podido ser tratadas en este capiacutetulo Le queda aveshyriguar coacutemo utilizar la cacheacute los recursos (habilidad para leer de una base de datos una plantilla) y las numerosas funciones que hemos dejado en el tintero Una vez que conozca la potencia de Smarty no querraacute mezclar nunca maacutes su coacutedigo con HTML

358 Apeacutendice A

Antes de comenzar

El primer paso para desarrollar programas en PHP 5 es encontrar un sershyvidor donde hacer las pruebas del programa y posteriormente dejarlo almacenado para que los usuarios puedan utilizarlo Este servidor debeshyriacutea estar disponible las 24 horas del diacutea con una conexioacuten fija a Internet

Como esto puede ser algo complicado al principio vamos a ver los pasos necesarios para instalar un servidor de pruebas donde escribir nuestros primeros scripts

PHP 5 se distribuye como coacutedigo fuente listo para compilar en el sistema operativo que quiera El problema es que es algo complicado si nunca ha compilado un programa Por eso he elegido paquetes ya compilados que soacutelo necesitan ser instalados para comenzar a funcionar

Vamos a instalar los siguientes programas

bull Servidor Web Apache

bull PHP 5

bull MySQL 4

Instalacioacuten en MacOSX

Uno de los maacutes excitantes desarrollos Open Source ha sido la apertura parshycial del coacutedigo de la plataforma Macintosh Gracias a esto muchos usuashyrios estaacuten contribuyendo con la creacioacuten de paquetes de instalacioacuten como el de PHP 5

Apache

El servidor Web Apache es necesario para enviar las peticiones HTTP de los clientes

Afortunadamente Apache viene ya instalado en MacOSX Para ponerlo en funcionamiento tendraacute que seguir los siguientes pasos

bull Abra una Terminal

bull Entre como suacuteper usuario con el comando su

bull Introduzca la passzvord de suacuteper usuario

bull Escriba a p a c h e c t l s t a r t

La figura A l muestra los pasos realizados en el terminal para iniciar el servidor Web A partir de ahora puede probar si funciona Apache escribiendo en el nashyvegador la direccioacuten l o c a l h o s t como muestra la figura A2

360 Apeacutendice A

PHP5

Existe una Web dedicada al mundo de MacOSX que se actualiza todos los diacuteas

Su administrador L i y a n a g e es el encargado de crear paquetes con toshydas las versiones de PHP 5 que ven la luz que en el momento de redactar el libro es la 501

Para instalar PHP 5 tendraacute que descargar el paquete de

ht tp www2entropychdownloadEntropy-PHP-5-01-1dmg

Una vez copiado el archivo en su sistema soacutelo tiene que hacer doble clic en eacutel y seguir los pasos de instalacioacuten del sistema operativo como puede ver en la figura A3

MySQL 4

Los pasos son exactamente igual que en la instalacioacuten de PHP 5

El primer paso es descargar el paquete para MacOSXmysql - s t a n d a r d -4 0 2 0 - a p p l e - d a r w i n 7 3 0 -powerpc dmg que se encuentra en la seccioacuten de descargas de la Web wwwmysql com

El paquete se instala como cualquier paquete de MacOSX simplemente haciendo doble clic

Instalacioacuten de PHP 5 y MySQL 361

Comprobacioacuten final

Para comprobar que todo funciona correctamente tendraacute que seguir los pasos siguientes

bull Abra una Terminal

bull Entre como suacuteper usuario con el comando su

bull Introduzca la password de suacuteper usuario

bull Reinicie la ejecucioacuten de Apache para que acepte la nueva configurashycioacuten de PHP 5 con el comando a p a c h e c t l r e s t a r t

bull Inicie MySQL con el comando u s r l o c a l m y s q l - s t a n d a r d -4 0 2 0 - a p p l e - d a r w i n 7 3 O - p o w e r p c b i n m y s q l d - u r o o t

bull Cree una Web de prueba y guaacuterdela en la ruta del usuario para paacutegishynas Web Normalmente es U s e r s u s u a r i o S i t e s

bull Abra el navegador y escriba la direccioacuten del servidor junto con el nomshybre de la Web La direccioacuten seraacute parecida a esta l o c a l h o s t - u s u a shyr i o i n f o r m a c i oacute n php

El programa que hemos escrito para comprobar que todo funciona correcshytamente y muestra el contenido de la figura A4 es

ltphp

362 Apeacutendice A

p h p i n f o ( ) gt

En la figura A4 puede ver el funcionamiento de todo el sistema instalado

Instalacioacuten en Windows

Instalar un sistema completamente funcional en un sistema operativo Windows puede ser tan sencillo o tan complicado como quiera Existe un paquete de aplicaciones llamado XAMPP que contiene todo lo necesario para funcionar con Apache PHP 5 y MySQL

En la Web wwwapachefriendsorg puede encontrar un archivo de instashylacioacuten de Windows

Despueacutes de descargar el archivo tiene que hacer doble clic y seguir las instrucciones impresas en pantalla como muestra la figura A5

Una vez instalado en la ruta lniciogtProgramasgtapachefriendsgtxampp veraacute tres apartados importantes

bull xampp basic start Se encarga de iniciar Apache PHP 5 y MySQL

bull xampp basic stop Para la ejecucioacuten de los servidores

bull xampp httpdoc folder Carpeta donde tiene que guardar todos sus programas escritos en PHP 5

Para probar que todo funciona puede ejecutar el programa xampp bashys i c s t a r t abrir un navegador y escribir como direccioacuten l o c a l h o s t Si

Instalacioacuten en gnuuumlnux

Existen en el mercado varias versiones de gnuLinux como gnuLinEx 2004 SuSe RedHat Gentoo Cada una de ellas posee un sistema de paquetes distinto Puesto que no tenemos espacio para describir 3 formas diferenshytes de instalar PHP 5 nos conformaremos con describir un tema general que sirve para todos los sistemas gnuLinux

Como ya puede imaginar nos vamos a apoyar en X A M P P para gnushyLinux

Una vez descargada la versioacuten para gnuLinux en el disco duro tendraacute que descomprimirla en un directorio El archivo comprimido deberiacutea llamarse x a m p p - l i n u x - 1 4 7 t a r g z Para instalarlo debe seguir los pasos sishyguientes

bull Descomprima con el comando g z i p -d x a m p p - l i n u x - 1 4 7 t a r g z

bull Vuelva a descomprimir el archivo esta vez con t a r x v f x a m p p - l i -n u x - 1 4 7 t a r

Instalacioacuten de PHP 5 y MySQL 363

todo se instaloacute correctamente podraacute ver una Web parecida a la de la figushyra A6

364 Apeacutendice A

bull Se crearaacute una carpeta llamada lampp

bull Copie la carpeta al directorio op t con el comando cp -r lampp opt

bull Ya lo tiene instalado Para ejecutarlo debe ser suacuteper usuario e invocar el comando opt lampp lampp s t a r t

La figura A7 muestra un terminal con el comando de inicio

En la figura A8 puede ver la paacutegina de inicio de XAMPP tras poner en el navegador l o c a l h o s t como direccioacuten Web Todas las paacuteginas Web que genere tendraacute que guardarlas en el directorio op t l ampp h tdocs para poder verlas a traveacutes del navegador

Recomendacioacuten final

La forma maacutes raacutepida y sencilla de hacer funcionar PHP 5 en su sistema es la que hemos visto pero no es la mejor La forma maacutes recomendable que se escapa del enfoque de este libro es compilar su PHP 5 De esta manera tendraacute la posibilidad de antildeadir los

Instalacioacuten de PHP 5 y MySQL 365

moacutedulos y extensiones que realmente vaya a utilizar La recomendacioacuten es que navegue por la Web wwwphpnet e investigue la forma de compishylar su sistema

368 Apeacutendice B

Introduccioacuten

El archivophp i n i contiene informacioacuten de configuracioacuten que puede moshydificar a su antojo Es un fichero de texto que se lee cada vez que se inicia el servidor Web Apache Para averiguar la ruta del disco duro donde se almacena el archivo php i n i soacutelo tiene que fijarse en el apartado Conf i g u r a t i o n F i l e (php i n i ) Path de la Web que recibioacute al ejecutar phpinf o () La configuracioacuten contiene parejas de variables valores separadas por puntos y comas Los valores que tenemos que asignar suelen ser rutas del disco duro 10 Yes No On Off o True False Cada vez que cambie alguna parte de la configuracioacuten tendraacute que reini-ciar Apache para que los cambios surtan efecto

short_open_tag

Permite la forma corta de antildeadir scripts de PHP de la forma lt gt Si quiere utilizar funciones XML es mejor dejarlo a Off

disable_functions

Desactiva funciones que nos resulten peligrosas como el enviacuteo de correos funciones de red etceacutetera

max_execution_time

Tiempo maacuteximo de ejecucioacuten de un script PHP en el servidor

error_reporting

Muestra el nivel de error que configure cuando un script falla Los tipos de errores los puede ver en el capiacutetulo 17

register_globals

Esta configuracioacuten ya no se utiliza a partir de la versioacuten PHP 42 y estaacute destinada a desaparecer

Configuracioacuten de phpini 369

Si la activa todas las variables seraacuten pasadas como globales y no dentro de las variables suacuteper globales

magic_quotes_runtime

Antildeade el siacutembolo de escape cuando se pasan variables con los siacutembolos de comillas simples o dobles

include_path

Antildeade rutas donde puede almacenar libreriacuteas que pueda utilizar sus proshygramas

Resumen

Hemos visto las principales opciones de configuracioacuten del archivo php i n i La configuracioacuten es mucho maacutes extensa pero no merece la pena indagar en otras opciones a menos que vaya a dedicarse a la administrashycioacuten del Sistema

372 Apeacutendice C

Bibliografiacutea

El desarrollo del libro ha sido posible gracias a la consulta de numerosas publicaciones escritas paacuteginas Web y revistas profesionales que han dado una visioacuten actual de la programacioacuten en PHP 5 La bibliografiacutea presente en este libro muestra un compendio de libros revistas y paacuteginas Web que pueden ser uacutetiles al lector si decide ampliar sus conocimientos una vez terminado este libro

Libros de PHP 5

bull PHP5 and MySQL Bible Tim Converse y Joyce Park Completo libro que abarca numerosos temas Especializado en generar bases de datos con MySQL y PHP 5

bull The PHP Anthology Harry Fuecks El mejor libro sobre PHP esshycrito nunca Abarca casi todos los temas importantes a la hora de crear un sitio Web profesional Todos los scripts estaacuten cuidadosashymente pensados y orientados a objetos El autor es uno de los proshypulsores de los patrones de disentildeo

bull Learning PHP5 David Sklar Contenido muy sencillo pero direcshyto Para aprender PHP 5 desde 0

bull PHP5 for Dummies Janet Valade Un buen libro para aprender y profundizar en varias aacutereas Desde luego el teacutermino Dummies no le hace justicia porque a veces se hace algo complicado de seguir

bull Proyectos Profesionales PHP Ashish Wilfred Meeta Gupta Kartik Bhatnagar Proyectos orientados a PHP 4 pero muy bien construidos

bull PHP 4 Esteban Trigos Libro muy sencillo para iniciarse en PHP 4 bull PHP 5 Power Programming Andi Gutmans De uno de los creashy

dores de PHP Muy bien enfocado y con muacuteltiples temas bull Beginning PHP 5 Equipo Wrox Libro extenso sobre PHP 5 Cubre

todo lo que se puede conocer sobre PHP 5 En Octubre saldraacute la seshygunda parte llamada Proffesional PHP 5

Revistas profesionales

bull PHP Solutions Revista polaca traducida al espantildeol Contiene muy buenos artiacuteculos sobre desarrollo actual con PHP

Bibliografiacutea 373

bull PHP Magazine Revista alemana de gran alcance bull PHP Architect Revista canadiense donde habitualmente escriben

desabolladores como Harry Fuecks Marco Tabini o Andi Gutmans La misma editora de esta revista ha sacado el libro de estudio para preshysentarse al examen de Certificacioacuten de PHP

Paacuteginas Web

bull wwwphpsolmagorg Web de la revista PHP Solutions bull wwwphpmagnet Web de la revista PHP Magazine bull wwwphparchcom Web de la revista PHP Architect bull wwwsinuhorg Comunidad GnuLinux de Extremadura

bull wwwphpbuildercom Comunidad de usuarios con mucho coacutedishygo libre

bull wwwluisyfernandanet Web del autor bull wwwphppatternscom La Web de Harry Fuecks bull wwwphpnet Web oficial de PHP

bull wwwzendcom La empresa que hay detraacutes de PHP Ofrece curshysos y seminarios on-line

bull wwwcodewalkerscom Web con mucho coacutedigo libre

Page 6: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 7: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 8: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 9: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 10: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 11: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 12: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 13: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 14: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 15: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 16: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 17: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 18: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 19: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 20: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 21: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 22: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 23: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 24: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 25: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 26: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 27: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 28: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 29: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 30: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 31: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 32: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 33: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 34: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 35: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 36: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 37: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 38: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 39: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 40: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 41: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 42: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 43: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 44: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 45: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 46: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 47: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 48: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 49: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 50: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 51: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 52: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 53: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 54: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 55: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 56: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 57: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 58: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 59: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 60: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 61: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 62: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 63: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 64: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 65: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 66: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 67: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 68: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 69: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 70: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 71: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 72: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 73: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 74: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 75: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 76: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 77: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 78: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 79: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 80: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 81: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 82: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 83: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 84: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 85: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 86: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 87: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 88: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 89: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 90: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 91: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 92: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 93: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 94: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 95: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 96: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 97: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 98: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 99: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 100: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 101: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 102: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 103: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 104: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 105: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 106: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 107: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 108: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 109: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 110: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 111: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 112: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 113: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 114: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 115: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 116: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 117: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 118: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 119: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 120: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 121: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 122: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 123: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 124: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 125: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 126: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 127: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 128: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 129: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 130: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 131: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 132: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 133: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 134: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 135: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 136: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 137: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 138: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 139: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 140: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 141: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 142: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 143: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 144: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 145: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 146: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 147: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 148: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 149: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 150: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 151: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 152: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 153: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 154: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 155: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 156: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 157: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 158: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 159: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 160: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 161: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 162: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 163: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 164: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 165: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 166: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 167: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 168: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 169: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 170: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 171: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 172: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 173: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 174: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 175: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 176: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 177: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 178: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 179: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 180: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 181: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 182: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 183: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 184: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 185: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 186: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 187: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 188: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 189: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 190: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 191: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 192: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 193: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 194: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 195: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 196: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 197: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 198: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 199: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 200: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 201: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 202: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 203: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 204: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 205: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 206: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 207: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 208: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 209: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 210: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 211: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 212: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 213: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 214: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 215: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 216: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 217: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 218: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 219: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 220: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 221: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 222: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 223: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 224: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 225: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 226: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 227: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 228: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 229: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 230: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 231: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 232: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 233: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 234: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 235: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 236: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 237: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 238: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 239: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 240: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 241: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 242: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 243: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 244: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 245: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 246: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 247: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 248: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 249: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 250: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 251: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 252: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 253: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 254: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 255: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 256: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 257: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 258: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 259: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 260: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 261: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 262: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 263: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 264: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 265: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 266: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 267: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 268: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 269: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 270: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 271: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 272: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 273: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 274: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 275: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 276: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 277: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 278: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 279: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 280: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 281: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 282: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 283: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 284: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 285: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 286: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 287: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 288: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 289: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 290: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 291: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 292: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 293: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 294: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 295: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 296: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 297: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 298: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 299: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 300: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 301: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 302: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 303: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 304: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 305: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 306: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 307: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 308: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 309: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 310: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 311: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 312: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 313: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 314: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 315: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 316: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 317: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 318: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 319: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 320: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 321: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 322: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 323: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 324: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 325: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 326: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 327: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 328: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 329: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 330: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 331: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 332: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 333: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 334: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 335: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 336: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 337: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 338: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 339: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 340: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 341: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 342: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 343: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 344: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 345: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 346: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 347: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 348: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo
Page 349: Manual Imprescindible de PHP5 · A Zeev Suraski y Andi Gutmans, creadores de PHP 5, por crear el lengua je y tratarme como a uno de los suyos en los ¿seminar de . Además, tengo