manual imprescindible de php5 · a zeev suraski y andi gutmans, creadores de php 5, por crear el...
TRANSCRIPT
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