Anda di halaman 1dari 888

Razones para leer este libro ........................................................................................... Objetivos que puede alcanzar con este libro .............................................................

Concepto de PHP ............................................................................................................ Novedades de la versi6n 4.3 de PHP .......................................................................... Concepto de MySQL ....................................................................................................... Razones para utilizarPHPy MySQL .......................................................................... Alguna de las cualidades de PHP ................................................................................ Rendimiento ................................................................................................................ Integraci6n de base de datos ................................................................................... Bibliotecas incorporadas .......................................................................................... Coste .............................................................................................................................. Aprendizaje de PHP ............................................................................................... Portabilidad ................................................................................................................. C6digo fuente .............................................................................................................. Algunas de las ventajas de MySQL ............................................................................ Rendimiento ................................................................................................................ Bajo coste ...................................................................................................................... Facilidad de uso ......................................................................................................... Portabilidad ................................................................................................................. C6digo fuente .............................................................................................................. C6mo estd organizado este libro .................................................................................. . Finalmente .........................................................................................................................

31 32 33 33 34 34 35 35 35 36 36 36 36 36 37 37 37 37 37 37 38 38

Parte I Uso de PHP

......................................................................................39 1. Curso acelerado de PHP ..........................................................................40


Uso de PHP ....................................................................................................................... 42 Aplicaci6n de ejemplo: Bob's Auto Parts ................................................................... 42 El formulario de pedidos ........................................................................................ 43 Procesamiento del formulario .............................................................................. 44 C6mo incrustar PHP en HTML .................................................................................... 45 Estilos de etiquetas PHP ........................................................................................... 46 Instrucciones de PHP ................................................................................................ 47 Espacios en blanco ..................................................................................................... 47 Comentarios ................................................................................................................ 48 C6mo agregar contenido dinimico ............................................................................. 49 Llamada de funciones ............................................................................................... 49 Funci6n date() ............................................................................................................. 50 C6mo acceder a las variables de formulario ............................................................. 50 Variables de formulario ............................................................................................ 50 Concatenaci6n de cadenas ....................................................................................... 53 Literales y variables ................................................................................................... 54 Identificadores ............................................................................................................ 54 Variables declaradas por el usuario ............................................................................ 55 Asignacidn de valores a variables ............................................................................... 55 Tipos de variables ............................................................................................................ 55 Tipos de datos de PHP .............................................................................................. 56 Control de tipos ............................................................................................................... 56 Conversi6n de tipos .................................................................................................. 57 Variables de tip0 variable ........................................................................................ 57 . Constantes ......................................................................................................................... 58 Ambito de variables ........................................................................................................ 58 Operadores ........................................................................................................................ 59 Operadores aritmeticos ............................................................................................ 60 Operadores de cadena ............................................................................................... 61 Operadores de asignaci6n ....................................................................................... 61 Devoluci6n de valores de asignaci6n .............................................................. 61 Combinacidn de operadores de asignaci6n .................................................... 62 Increment0 y decrement0 previo y posterior ................................................ 62 Referencias ............................................................................................................. 63 Operadores de comparaci6n .................................................................................... 63 El operador iguales ............................. : .............................................................. 63 Otros operadores de comparaci6n ................................................................... 64 Operadores 16gicos ........................................................................... ........................ 64 Operadores bit a bit ................................................................................................... 65 Otros operadores ........................................................................................................ 66 Operador ternario ................................................................................................. 66

Operador de supresi6n de error ........................................................................ 66 Operador de ejecucibn ......................................................................................... 67 Uso de operadores: calcular 10s totales de 10s formularios ................................... 67 Precedencia y asociatividad: evaluacidn de expresiones ....................................... 69 Funciones de variables ................................................................................................... 70 C6mo probar y establecer tipos de variables ...................................................... 70 C6mo probar el estado de las variables ................................................................ 71 Reinterpretacibn de variables ................................................................................. 72 Estructuras de control ..................................................................................................... 72 Toma de decisiones con estructuras condicionales ................................................ 72 Las instrucciones if .................................................................................................. 72 Bloques de c6digo ...................................................................................................... 73 Instrucciones else ...................................................................................................... 73 Instrucciones elseif ................................................................................................. 74 Instrucci6n switch ...................................................................................................... 75 Comparacidn de condiciones diferentes............................................................... 77 Iteracibn: repeticion de acciones .................................................................................. 77 Bucles while ................................................................................................................. 78 Los bucles for y foreach ............................................................................................ 80 Bucles do ...while ......................................................................................................... 81 C6mo salir de una estructura de control o una secuencia de comandos ............ 81 Siguiente paso: guardar el pedido del cliente ......................................................... 82

2 Almacenamiento y recuperacibn de datos

........................................ 84

C6mo guardar datos para su lectura posterior ..................................................... 86 Almacenamiento y recuperaci6n de 10s pedidos de Bob ........................................ 86 Introducci6n a1 procesamiento de archivos .............................................................. 87 * C6mo abrir un archivo .................................................................................................. 88 Modos de archivo ....................................................................................................... 88 Uso de fopen() para abrir un archivo .................................................................... 88 C6mo abrir archivos a travks de FTP o HTTP ..................................................... 91 Problemas a1 abrir el archivo ................................................................................... 91 C6mo escribir en un archivo ................................................................................... 93 Parimetros de fwrite() ........................................................................................ 94 Formatos de archivo .......................................................................................... 94 C6mo cerrar un archivo .................................................................................................. 95 Lectura desde un archivo ............................................................................................... 95 Apertura de un archivo para su lectura: fopen() ................................................ 96 C6mo saber cuindo parar: feof() ............................................................................ 97 C6mo leer linea a linea: fgets(). fgetss() y fgetcsv() ........................................ 97 Lectura de todo el archivo: readfile(). fpassthruo. file()................................... 98 Lectura de un caricter: fget()+................................................................................ 99 Lectura de una longitud arbitraria de bytes: fread()........................................ 99 Otras funciones de archivo utiles .............................................................................. 100

fndice de contenidos

Comprobaci6n de la existencia de un archivo: file-exists() ........................... 100 C6mo averiguar el tamaiio de un archivo: filesize() ........................................ 100 Eliminaci6n de un archivo: unlink() ................................................................... 100 Navegaci6n dentro de un archivo: rewind(). fseek() y ftell() ........................ 101 Bloqueo de archivos ......................................................................................................102 La opci6n mis acertada: 10s sistemas de administracibn de base 103 de datos ................................................................................................................. Problemas con el uso de archivos planos ........................................................... 103 C6mo resolver estos problemas ............................................................................ 104 105 Lecturas adicionales ...................................................................................................... 105 A continuaci6n ...............................................................................................................

3 Uso de matrices

.......................................................................................106

i Q ~ es k una matriz? ................................................................................................ 108 Matrices indexadas numkricamente .......................................................................... 108 Inicializaci6n de matrices indexadas numkicamente .................................... 109 Acceso a 10s contenidos de matrices ................................................................... 109 Uso de bucles para acceder a la matriz ............................................................... 110 111 Matrices asociativas ...................................................................................................... Inicializaci6n de una matriz asociativa .............................................................. 111 C6mo acceder a elementos de matriz .................................................................. 111 Uso de bucles con matrices asociativas .............................................................. 111 113 Matrices multidimensionales ...................................................................................... 117 C6mo ordenar matrices ................................................................................................ 117 Uso de sort() .............................................................................................................. Uso de asorto y ksort() para ordenar matrices asociativas ............................ 117 Inversi6n del orden .................................................................................................. 118 Ordenaci6n de matrices~multidimensionales......................................................... 118 Ordenaciones definidas por el usuario .................................................. :............ 118 Ordenaciones de usuario inversas ....................................................................... 120 Reordenaci6n de matrices ............................................................................................ 120 Uso de shuffle() ........................................................................................................ 121 Uso de array-reverse() ............................................................................................ 122 Carga de matrices desde archivos ............................................................................. 123 Otras manipulaciones de cadenas ............................................................................. 125 Navegaci6n dentro de una matriz con each(). current(). reset(). end(). next(). pas(). and prev() ................................................................... 126 Aplicaci6n de cualquier funci6n a cada elemento de una matriz: array-walk() ................................................................................................ 126. C6mo contar elementos de una matriz: count(). sizeof(). and array-count-values() ......................................................................................... 128 Conversi6n de matrices en variables escalares: extract() ............................... 129 130 Lecturas adicionales ...................................................................................................... 130 A continuaci6n ...............................................................................................................
%

Desarrollo W e b con PHP y MySQL

4. Manipulaci6n de cadenas y expresiones regulares 132 Aplicaci6n de ejemplo: Smart Form Mail ................................................................. 133 Aplicaci6n de formato a cadenas ............................................................................... 136 Limpieza de cadenas: chop(). Itrim() y trim().................................................... 136 Aplicaci6n de formato a cadenas para presentaciones ................................... 136 Uso de formato HTML: la funci6n nl2br() .................................................... 136 Aplicaci6n de formato a una cadena para su impresi6n ........................... 137 Cambio de mayusculas y minusculas en una cadena ................................ 139
Aplicaci6n de formato a las cadenas para su almacenamiento: Addslashes0 y StripSlashes() .................................................................... 140 C6mo combinar y dividir cadenas con funciones de cadena .............................. 141 Uso de explode(). implode() y join() .................................................................... 142 Uso de strtok() .......................................................................................................... 142 Uso de substr() .......................................................................................................... 143 Comparaci6n de cadenas ............................................................................................ 144 Ordenaci6n de cadenas.strcmp(). strcasecmp() y strnatcmpo ....................... 144 Comprobaci6n de la longitud de una cadena con strlen() ............................. 145 C6mo buscar subcadenas y reemplazarlas con funciones de cadena ............... 145 Busqueda de cadenas en cadenas: strstr(). strchr(). strrchr(). stristr() ......... 146 Busqueda de la posicion de una subcadena: strpos(). strrpos() .................... 147 Sustituci6n de subcadenas: str-replace(). substr-replace() ...........................148 Introduccidn a las expresiones regulares ................................................................. 149 Los fundamentos ...................................................................................................... 150 Conjuntos y clases de caracteres .......................................................................... 150 Repetici6n .................................................................................................................. 152 Subexpresiones ......................................................................................................... 152 Recuento de subexpresiones ..................................................................................152 Anclajes a1 principio o a l final de una cadena ................................................... 152 Bifurcaci6n ................................................................................................................. 153 Cdmo buscar coincidencias de caracteres especiales ...................................... 153 Resumen de 10s caracteres especiales ................................................................. 153 Uso de estos elementos en Smart Form .............................................................. 154 Busqueda de subcadenas con expresiones regulares ........................................ 155 Sustituci6n de cadenas con expresiones regulares ................................................ 156 Divisidn de cadenas con expresiones regulares .....................................................156 Comparaci6n de funciones de cadenas y funciones de expresiones regulares ................................................................................... 157 Lecturas adicionales ...................................................................................................... 157 A continuaci6n ............................................................................................................... 157

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

5. Reutilizaci6n de c6digo y creaci6n de funciones 158 ~ P o qud r reutilizar cbdigo? .......................................................................................... 160 Costes .......................................................................................................................... 160 Legibilidad ................................................................................................................. 160

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

fndice de contenidos

Uniformidad .............................................................................................................. 160 Uso de require() e include() ......................................................................................... 161 Uso de require() ........................................................................................................ 161 Extensiones de nombre de archivo y require() .................................................. 162 Etiquetas de PHP y require() ................................................................................. 162 Uso de require() para plantillas de sitios Web ........................................................ 163 Uso de auto-prepend-file y auto-append-file ................................................. 167 Uso de include()........................................................................................................ 168 Uso de las funciones de PHP ...................................................................................... 170 Llamada de funciones ............................................................................................. 170 C6mo llamar a una funci6n no definida ............................................................. 171 Funciones y el uso de may6sculas y min6sculas ........................................ 172 ~ P o qu6 r deberia crear funciones propias? .............................................................. 173 Estructura b6sica de una funci6n ............................................................................... 173 Designaci6n de funciones ....................................................................................... 174 Parfimetros ....................................................................................................................... 175 177 Ambito .............................................................................................................................. Llamadas por referencia frente a llamadas por valor ........................................ 179 Final de las funciones .................................................................................................... 180 C6mo devolver valores desde funciones ................................................................. 182 Bloques de c6digo .................................................................................................... 182 Recursi6n ......................................................................................................................... 183 Lecturas adicionales ...................................................................................................... 185 A continuaci6n ............................................................................................................... 185

6 PHP orientado a objetos

........................................................................186

Conceptos orientados a objetos .................................................................................. 187 188 Clases y objetos ...................................................................................................... Polimorfismo ............................................................................................................. 189 Herencia ..................................................................................................................... 189 Creaci6n de clases, atributos y operaciones en PHP ........................................ 190 Estructura de una clase ........................................................................................... 190 Constructores ............................................................................................................ 191 Instanciaci6n ................................................................................................................... 191 Uso de 10s atributos de clase ....................................................................................... 192 Llamadas a operaciones de clase ............................................................................... 194 Implementaci6n de la herencia en PHP .................................................................... 195 Reemplazamientos ................................................................................................... 196 Herencia m6ltiple .................................................................................................... 197 Diseiio de clases ............................................................................................................. 198 Escritura del c6digo para nuestra clase .................................................................... 199 A continuaci6n ............................................................................................................... 207

Parte I1. Uso de MySQL ............................................................................ 209

7. Diseiio de la base de datos Web

........................................................... 210

Conceptos de base de datos relacionales ................................................................. 212 Tablas .................................................................................................................... 212 Columnas ............................................................................................................. 212 Filas ........................................................................................................................ 213 Valores .................................................................................................................. 213 Claves .................................................................................................................... 213 Esquemas .............................................................................................................. 214 Relaciones ............................................................................................................. 214 Como disefiar nuestra base de datos Web ............................................................... 215 Piense en 10s objetos del mundo real que esti modelando ............................ 215 C6mo evitar el almacenamiento de datos redundantes .................................. 216 Uso de valores de columna unicos ....................................................................... 217 Selecci6n de claves 16gicas ..................................................................................... 218 Reflexiones sobre las preguntas que desea formular a la base de datos .....218 Evite disefios con varios atributos vacios .......................................................... 219 Resumen de 10s tipos de tablas ............................................................................. 219 Arquitectura de base de datos Web ......................................................................... 220 Arquitectura .................................................................................................................... 220 Lecturas adicionales ..................................................................................................... 221 A continuaci6n ............................................................................................................... 221

8 Creaci6n de la base de datos Web

....................................................... 222

Nota sobre el uso del monitor de MySQL ................................................................ 224 C6mo registrarse en MySQL ....................................................................................... 225 Creaci6n de bases de datos y usuarios ..................................................................... 226 Creaci6n de la base de datos ................................................................................. 226 Usuarios y privilegios .................................................................................................. 227 Introduction a1 sistema de privilegios de MySQL ................................................. 227 Principio de asignaci6n del privilegio mas bajo ............................................... 227 C6mo configurar usuarios: el comando GRANT ............................................. 228 Tipos y niveles de privilegio ................................................................................. 229 El comando REVOKE .............................................................................................. 231 Ejemplos de uso de GRANT y REVOKE ............................................................. 232 C6mo configurar un usuario para la Web ............................................................... 233 C6mo cerrar la sesidn como administrador ....................................................... 233 Uso de la base de datos correcta ................................................................................ 233 Creaci6n de tablas de base de datos .......................................................................... 234 iCuil es el significado del festo de las palabras clave? .................................. 235 Tipos de columna ................................................................................................... 236 C6mo examinar la base de datos con SHOW y DESCRIBE ............................ 238 Identificadores de MySQL ........................................................................................... 239 Tipos de dato de columna ............................................................................................ 240 Tipos numericos ....................................................................................................... 241

fndice de contenidos

Tipos de fecha y hora ......................................................................................... Tipos de cadena .................................................................................................. Lecturas adicionales ...................................................................................................... A continuaci6n ..............................................................................................................

242 244 245 246

9 C6mo trabajar con la base de datos de MySQL

................................248

iQue es SQL? .................................................................................................................. 250 Inserci6n de datos en la base de datos ...................................................................... 250 Recuperaci6n de datos de la base de datos ............................................................. 252 Recuperaci6n de datos con criterios especificos ...............................................253 Recuperaci6n de datos desde varias tablas ........................................................ 256 Combinaciones sencillas de dos tablas ............................................................... 256 Combinacidn de varias tablas .......................................................................... 257 Busqueda de filas que no coincidan ............................................................... 258 Uso de otros nombres para designar tablas: 10s alias ................................ 260 Resumen de 10s tipos de combination .......................................................... 260 Recuperaci6n de datos con u n orden dado ........................................................ 261 Agrupacidn y agregaci6n de datos ...................................................................... 262 C6mo escoger las filas que recuperar .................................................................. 264 Actualizaci6n de registros en la base de datos ....................................................... 264 Alteraci6n de tablas tras su creacidn ......................................................................... 265 Eliminacidn de registros de la base de datos .......................................................... 267 Eliminaci6n de tablas .................................................................................................... 267 Eliminaci6n de una base de datos entera ................................................................. 267 Lecturas adicionales ...................................................................................................... 268 A continuaci6n ............................................................................................................... 268

10. Acceso a la base de datos de MySQL desde la Web con PHP .

Funcionamiento de las arquitecturas de base de datos ........................................ 272 Pasos bdsicos para consultar una base de datos desde la Web ........................... 275 275 Comprobaci6n y filtrado de datos entrantes ........................................................... C6mo configurar de una conexi6n ............................................................................ 277 Selecci6n de una base de datos .................................................................................. 278 Cdmo consultar la base de datos ............................................................................... 279 Recuperacidn de resultados de consulta .................................................................. 279 Desconexi6n de una base de datos ............................................................................ 281 C6mo colocar nueva informacidn en la base de datos ........................................ 281 Otras funciones utiles PHP y MySQL ....................................................................... 284 Liberaci6n de recursos ............................................................................................ 285 Creaci6n y eliminacidn de bases de datos .......................................................... 285 Otras interfaces de base de datos y PHP .................................................................. 285 Uso de una interfaz de base de datos generics: PEAR DB ................................... 286 Lecturas adicionales ...................................................................................................... 288 A continuacidn ............................................................................................................... 289

.......270

11. MySQL Avanzado

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

290

An6lisis detallado del sistema de privilegios ......................................................... 291 La tabla de usuario .................................................................................................. 292 Las tablas db y host ............................................................................................. 294 Las tablas tables-priv y columns-priv ............................................................... 295 Control de acceso: jc6m0 utiliza MySQL las tablas de concesi6n de privilegios? ..................................................................................................... 296 Actualizaci6n de privilegios: jcu6nd0 surten efecto 10s cambios? ..............297 C6mo proteger la bases de datos MySQL ................................................................ 297 MySQL desde el punto de vista del sistema operativo ...................................297 Contraseiias ......................................................................................................... 298 Privilegios de usuario ...................................................................................... 299 Aspectos relacionados con la Web ............................................................... 299 C6mo obtener m6s informaci6n sobre bases de datos ..........................................300 C6mo obtener informaci6n con SHOW ............................................................ 300 C6mo obtener informaci6n con DESCRIBE .......................................................302 Compresi6n del funcionamiento de las consultas con EXPLAIN ................303 C6mo agilizar consultas con indices .......................................................................306 Trucos de optimizaci6n general .................................................................................307 Optimizaci6n del diseiio ........................................................................................ 307 Permisos ..................................................................................................................... 307 Optimizaci6n de tablas ..................................................................................... 307 Uso de indices ........................................................................................................... 308 Uso de valores predeterminados .......................................................................... 308 Uso de conexione permanentes ............................................................................ 308 Otras sugerencias ................................................................................................. 308 Tipos diferentes de tabla ...................................................................................... 308 Carga de datos desdeun xchivo ............................................................................... 309 C6mo realizar una copia de seguridad de la base de datos MySQL .................310 Restablecimiento de la base de datos MySQL ........................................................ 310 Lecturas adicionales ...................................................................................................... 311 A continuaci6n ............................................................................................................... 311

Parte I11 Comercio electrbnico y seguridad

........................................313 12. Creacibn de un sitio Web de comercio electrbnico ......................... 314


jC~61 es nuestro objetivo? ........................................................................................... 315 Tipos de sitios Web comerciales ................................................................................ 316 Medios publicitarios en linea ................................................................................ 316 No suministrar informaci6n importante ....................................................... 317 Mala presentaci6n .............................................................................................. 317 No responder a la informaci6n generada por el sitio Web ....................... 317 No actualizar el sitio .......................................................................................... 318

fndice de contenidos

No realizar el seguimiento del 6xito del sitio .............................................. 318 Recogida de pedidos de articulos y servicios .................................................... 319 Preguntas sin respuesta .................................................................................... 321 Confianza ............................................................................................................. 321 Facilidad de uso .................................................................................................. 322 Compatibilidad ................................................................................................... 323 Suministro de servicios y articulos digitales ..................................................... 323 C6mo afiadir valor a 10s articulos y servicios ................................................... 324 Recorte de costes ...................................................................................................... 324 Riesgos y amenazas ....................................................................................................... 325 Piratas informfiticos ................................................................................................. 325 Fracaso en la atraccidn de suficiente negocio .................................................... 326 Fallos de hardware ................................................................................................... 326 Fallos de alimentacih. comunicaci6n1 red y distribuci6n ............................. 327 Competencia .............................................................................................................. 327 Errores de software .................................................................................................. 327 Cambios en las politicas e impuestos gubernamentales ................................. 328 Limites de la capacidad del sistema .................................................................... 328 Por qu6 estrategia optar ............................................................................................... 328 A continuaci6n ............................................................................................................... 329

13 Aspectos de seguridad relacionados con el comercio electr6nico 330


Importancia de la informaci6n ................................................................................... 332 Amenazas contra la seguridad ................................................................................... 332 Exposici6n de datos confidenciales ..................................................................... 333 P6rdida o destrucci6n de datos ............................................................................. 335 Modificaci6n de 10s datos ...................................................................................... 335 Errores en el software ...... ...................................................................................... 336 Malas especificaciones t6cnicas ...................................................................... 337 Suposiciones err6neas hechas por 10s desarrolladores ............................. 337 Pruebas incompletas .......................................................................................... 337 Repudio ...................................................................................................................... 338 Equilibrio entre usabilidad. rendimiento. coste y seguridad .............................. 339 Creaci6n de una politica de seguridad ..................................................................... 340 Principios de autenticaci6n .................................................................................... 340 Uso de la autenticaci6n ................................................................................................ 341 Fundamentos de la encriptaci6n ................................................................................ 342 Encriptacih de clave privada ............................................................................... 343 Encriptaci6n de clave publica ..................................................................................... 344 Firmas digitales .............................................................................................................. 344 Certificados digitales .................................................................................................... 345 Servidores Web seguros ............................................................................................... 347 Auditorias y registros ................................................................................................... 348 Cortafuegos ..................................................................................................................... 349

Desarrollo W e b con PHP y MySQL

Copia de seguridad de 10s datos ................................................................................ 349 Copia de seguridad de 10s archivos generales .................................................. 350 Copia de seguridad y restauraci6n de bases de datos MySQL .....................350 Seguridad fisica .............................................................................................................. 350 A continuaci6n ............................................................................................................... 351

14 Implementaci6n de la autenticacibn con PHP y MySQL ...............352


Identificaci61-1 de visitantes .......................................................................................... 353 Implementaci6n del control de acceso ...................................................................... 355 Almacenamiento de contraseiias ......................................................................357 Cifrado de contraseiias ........................................................................................... 360 Protecci6n de piginas multiples ...........................................................................361 Autenticaci6n bisica .....................................................................................................362 Uso de la autenticacidn bisica en PHP ..................................................................... 363 Uso de la autenticaci6n bisica con 10s archivos .htaccess de Apache ..............365 Autenticaci6n b k i c a con IIS ................................................................................. 368 Uso de la autenticacibn mod-auth-mysql ...............................................................371 Instalaci6n de mod-auth-mysql ...................................................................... 371 ................................................................................................................. 372 ~Funcionb? Uso de mod-auth-mysql ........................................................................................ 372 Creaci6n de su propio sistema de autenticaci6n .................................................... 373 Lecturas adicionales ...................................................................................................... 374 A continuation ............................................................................................................... 374

15 Implementaci6n de transacciones seguras con PHP y MySQL

.... 376

Como suministrar transacciones seguras ................................................................377 El equipo del usuario ..............................................................................................378 . Internet ....................................................................................................................... 380 Su sistema ............................................................................................................... 381 Us0 SSL .........................................................................................................:............382 Filtrado de la entrada de 10s usuarios .....................................................................385 Suministro de un almacenamiento seguro .............................................................. 386 LPor quk almacenar numeros de tarjeta de crkdito? .............................................. 387 Uso de encriptaci6n en PHP ........................................................................................ 388 Instalaci6n de GPG ..........................................................................................388 C6mo probar GPG ..............................................................................................391 Lecturas adicionales ....................................................................................................396 A continuaci6n ............................................................................................................396

Parte IV TCcnicas avanzadas de PHP

.....................................................397 16. Interacci6n con el sistema de archivos y el servidor ....................... 398


Introducci6n a la carga de archivos ........................................................................... 400

fndice d e contenidos

HTML para la carga de archivos .......................................................................... 400 Un inciso sobre seguridad .................................................................................. 401 C6digo PHP para procesar la tarea de carga del archivo ...............................402 Problemas habituales .............................................................................................. 407 Uso de las funciones de directorio ............................................................................. 407 Lectura desde directorios ....................................................................................... 408 C6mo obtener informaci6n sobre el directorio actual ..................................... 409 Creaci6n y eliminaci6n de directorios ................................................................. 409 Interaction con el sistema de archivos ..................................................................... 410 C6mo obtener informaci6n de archivo ............................................................... 410 Cdmo cambiar las propiedades de archivo ........................................................ 413 Creaci6n. eliminaci6n y desplazamiento de archivos ..................................... 413 Uso de funciones de ejecuci6n de programas ......................................................... 414 Interacci6n con el entorno: getenv() y putenv() ..................................................... 417 Lecturas adicionales ...................................................................................................... 418 A continuaci6n ............................................................................................................... 418

17. Uso de funciones de red y de protocolo ........................................420


Descripci6n general de protocolos ............................................................................ 421 Envio y recepci6n de correos electr6nicos ...............................................................422 Uso de otro sitio Web .................................................................................................... 423 Uso de funciones de busqueda de red ...................................................................... 426 Uso de FTP ....................................................................................................................... 430 Uso de FTP para realizar una copia o reproducir un archivo ........................430 Conexi6n a1 servidor FTP remoto ................................................................... 433 Inicio de sesi6n en el servidor FTP ................................................................. 433 Comprobaci6n del momento temporal de la actualizaci6n .............................................................. 434 de archivos ....,....... .....................: Descarga del archivo ......................................................................................... 435 Cierre de la conexi6n ......................................................................................... 436 Carga de archivos ..................................................................................................... 436 Como evitar 10s tiempos de espera ...................................................................... 437 Uso de otras funciones de FTP .............................................................................. 437 Comunicaciones de red genbricas con CURL...........................................................438 Lecturas adicionales .................................................................................................... 440 A continuation ............................................................................................................... 441

18 Administracih de la fecha y la hora

................................................ 442

C6mo obtener la fecha y la hora en PHP .................................................................. 443 Uso de la funci6n date()..........................................................................................443 445 Marcas de tiempo de Unix ..................................................................................... Uso de la funci6n getdate() .................................................................................... 446 Validaci6n de fechas ................................................................................................ 447 Conversi6n entre formatos de fecha de PHP y MySQL ........................................ 447

Desarrollo W e b colt PHP y MySQL

Cilculos de fecha ........................................................................................................... 449 Uso de funciones de calendario .................................................................................. 450 Lecturas adicionales ...................................................................................................... 451 A continuacidn ............................................................................................................... 451

19 Creacion de imiigenes

..........................................................................452

Configuraci6n de compatibilidad de imigenes en PHP .......................................453 Formatos de imagen ...................................................................................................... 454 JPEG ............................................................................................................................ 455 PNG .............................................................................................................................455 WBMP ....................................................................................................................... 455 GIF ............................................................................................................................... 455 Creaci6n de imigenes ................................................................................................... 456 Creacion de un lienzo .............................................................................................. 458 Dibujo o impresi6n de texto en la imagen .......................................................... 458 Generaci6n del grafico final ................................................................................. 460 Liberaci6n de recursos ............................................................................................461 Uso de imigenes generadas automiticamente en otras piginas .......................462 Uso de texto y fuentes para crear imigenes ............................................................463 Lienzo base ................................................................................................................466 C6mo ajustar el texto sobre el b o t h ................................................................... 466 Colocaci6n del texto ................................................................................................470 C6mo escribir el texto en el b o t h ...................... ................................................. 470 Para terminar .......................................................................................................... 471 Dibujo de figuras y representaci6n grifica de datos ........................................ 471 Otras funciones de imagen .......................................................................................... 478 Lecturas adicionales ..................................................................................................479 A continuaci6n ................... ........................................................................................479
;

20 Uso del control de sesi6n en PHP

.......................................................480

Qu6 es el control de sesi6n ..........................................................................................481 482 Funcionalidad de sesi6n bisica .................................................................................. Qu6 es una cookie .................................................................................................... 482 Configuraci6n de cookies desde HTTP ...............................................................483 Uso de cookies con sesiones ...........................................................................483 Almacenamiento del Id . de sesi6n ...................................................................484 Implementaci6n de sesiones simples ........................................................................484 Inicio de sesion ....................................................................................................... 484 Registro de variables de sesi6n ............................................................................. 485 Uso de variables de sesi6n ..................................................................................... 485 Anulaci6n del registro de variables y eliminaci6n de la sesi6n .................... 486 Ejemplo de sesi6n sencilla ........................................................................................ 487 489 Configuraci6n del control de sesi6n ......................................................................... Implementaci6n de autenticaci6n con el control de sesi6n .................................490

fndice de contenidos

Lecturas adicionales ...................................................................................................... 496 A continuaci6n ............................................................................................................... 497

21 . Otras caracteristicas utiles ..................................................................498


Uso de comillas migicas .............................................................................................. 499 EvaluaciBn de cadenas: eval()..................................................................................... 500 Finalizaci6n de ejecuci6n: die y exit .......................................................................... 501 Serializaci6n .................................................................................................................... 502 C6mo obtener informaci6n sobre el entorno PHP ................................................. 503 C6mo saber qu6 extensiones se han cargado .................................................... 503 Identificaci6n del propietario de la secuencia de comandos .........................504 C6mo saber cuindo se ha modificado una secuencia de comandos .................................................................................................. 504 Carga dinimica de extensiones .................................................................................. 504 Modificacih temporal del entorno de ejecuci6n .................................................. 505 C6mo resaltar fuentes ................................................................................................... 506 A continuaci6n ............................................................................................................... 506

Parte V. Creaci6n de proyectos PHP y MySQL practicos

...................509

22. Uso de PHP y MySQL en grandes proyectos ................................... 510


Aplicaci6n de ingenieria de software a1 desarrollo Web ...................................... 512 Planificaci6n y ejecuci6n de un proyecto de aplicaci6n Web .............................. 513 Reutilizaci6n de c6digo ................................................................................................ 514 C6mo escribir c6digo mantenible .............................................................................. 514 Estindares de codificaci6n ..................................................................................... 515 Convenciones de-nompnclatura ...................................................................... 515 Comentarios de c6digo ..................................................................................... 516 Sangrados ............................................................................................................. 517 Divisi6n del c6digo .................................................................................................. 518 Uso de una estructura de directorios estindar .................................................518 C6mo documentar y compartir funciones internas ......................................... 519 Implementaci6n del control de versi6n .................................................................... 519 Selecci6n de un entorno de desarrollo ...................................................................... 520 Documentaci6n de nuestros proyectos ..................................................................... 521 Prototipos ........................................................................................................................ 521 SeparaciBn de 16gica y contenido ............................................................................... 522 Optimizaci6n de c6digo ............................................................................................... 523 Uso de optimizaci6n sencilla ................................................................................. 523 Uso de productos Zend ........................................................................................... 524 Comprobaciones ............................................................................................................ 524 Lecturas adicionales ...................................................................................................... 526 A continuaci6n ............................................................................................................... 526

Desarrollo Web con P H P y M y S Q L

Errores de programacibn ............................................................................................. 530 Errores sinticticos .................................................................................................... 530 Errores de ejecuci6n ................................................................................................. 531 Llamadas a funciones que no existen ............................................................ 533 Lectura o escritura de archivos .................................................................... 533 Interacci6n con MySQL u otras bases de datos ........................................... 534 Conexiones a redes de servicios ..................................................................... 535 Comprobaci6n de entrada de datos incorrecta ........................................... 536 Errores 16gicos .......................................................................................................... 537 Ayuda de depuraci6n de variables ............................................................................ 538 Niveles de informes de errores ................................................................................... 540 Modificaci6n de 10s parimetros de informes de error .......................................... 541 C6mo desencadenar nuestros propios errores ........................................................ 543 Procesamiento correct0 de errores ............................................................................ 543 A continuaci6n ............................................................................................................... 546

24 C6mo generar autenticacihn y personalizaci6n de usuarios 548 El problema ................................................................................................................... 550 Componentes de la solucion ....................................................................................... 550 Identificaci6n y personalizaci6n de usuarios .................................................... 550 551 Almacenamiento de marcadores .......................................................................... Recomendaci61-1 de marcadores ............................................................................ 551 Presentaci6n de la soluci6n ......................................................................................... 551 Implementaci6n de la base de datos ......................................................................... 554 Implementaci6n del sitio bisico ................................................................................. 555 Implementaci6n de la aut~nticaci6n de usuarios ................................................... 558 .................................................................................................... 558 Registro ..................: Conexi6n .................................................................................................................... 563 Desconexi6n .............................................................................................................. 567 Modificaci6n de contrasefias ................................................................................. 568 Restablecimiento de contrasefias olvidadas ...................................................... 570 Implementaci6n del almacenamiento y recuperaci6n de marcadores .............. 575 C6mo afiadir marcadores ....................................................................................... 575 C6mo mostrar marcadores .................................................................................... 578 Eliminaci6n de marcadores .................................................................................. 579 Implementaci6n de recomendaciones ...................................................................... 581 Conclusi6n y posibles ampl'iaciones ......................................................................... 585 A continuaci6n .............................................................................................................. 585 25. Construcci6n de un carro de la compra 586 El problema .................................................................................................................... 588 Componentes de la soluci6n ....................................................................................... 588

.........

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

fndice de contenidos

Generaci6n de un catdogo en linea ..................................................................... 588 C6mo realizar el seguimiento de las compras de un usuario mientras compra ............................................................................................................. 588 Pagos ........................................................................................................................... 589 Interfaz de administracibn ..................................................................................... 589 Presentaci6n de la soluci6n ......................................................................................... 590 Implementaci6n de la base de datos ......................................................................... 594 Implementaci6n del catdogo en linea ...................................................................... 596 Enumeraci6n de categorias .................................................................................... 598 Enumeraci6n de libros en una categoria ............................................................. 601 C6mo mostrar detalles sobre un libro ................................................................. 602 Implementaci6n del carro de la compra ................................................................. 604 Uso de la secuencia de comandos show-cart.php ...........................................604 C6mo ver el carro ................................................................................................... 607 C6mo afiadir articulos a1 carro ............................................................................. 610 C6mo guardar el carro actualizado ..................................................................... 611 Impresi6n de un resumen en la barra de encabezado ..................................... 612 C6mo salir ................................................................................................................. 613 Implementaci6n del pago ............................................................................................ 618 Implementacidn de una interfaz de administracibn .............................................. 620 Ampliaci6n del proyecto .............................................................................................. 628 Uso de un sistema existente ........................................................................................ 628 A continuaci6n ............................................................................................................... 628

26 Creaci6n de un sistema de administraci6n de contenidos

............. 630

El problema ..................................................................................................................... 631 Requisitos de la soluci6n ..............................................................................................632 Modificaci6n del contenido ........................................................................................ 632 Introducci6n de contenido en el sistema ............................................................ 632 FTP ......................................................................................................................... 632 Metodo de carga de archivos ...........................................................................633 633 Cambios en linea ................................................................................................ Bases de datos frente a almacenamiento en archivos ......................................633 Estructura de documentos ..................................................................................... 634 Uso de metadatos .......................................................................................................... 635 Formato del resultado ................................................................................................... 635 637 Manipulaci6n de imigenes .......................................................................................... Disefio y presentaci6n de la soluci6n ........................................................................639 Disefio de la base de datos ...........................................................................................640 Implementaci6n ............................................................................................................. 642 Interfaz de usuario ................................................................................................... 642 Sistema ........................................................................................................................ 646 Busquedas .................................................................................................................. 654 Pantalla del editor .................................................................................................... 657

Desarrollo W e b con PHP y MySQL

Ampliaci6n del proyecto .............................................................................................. 658 A continuaci6n .............................................................................................................. 659

27. Creacibn de un servicio de correo electronic0 basado en la Web ... 660


El problema ..................................................................................................................... 661 Componentes de la soluci6n ....................................................................................... 662 Presentaci6n de la soluci6n ......................................................................................... 663 Configuraci6n de la base de datos ............................................................................. 665 Arquitectura de secuencias de comandos ................................................................667 Conexi6n y desconexi6n .............................................................................................. 673 Configuraci6n de cuentas ............................................................................................ 676 Creaci6n de una nueva cuenta .............................................................................. 678 Modificaci6n de una cuenta existente ................................................................ 680 Eliminaci6n de una cuenta ..................................................................................... 680 Lectura de correo ........................................................................................................ 681 Selecci6n de una cuenta ......................................................................................... 681 C6mo ver 10s contenidos del buz6n de correo ................................................ 684 Lectura de un mensaje de correo .......................................................................... 687 C6mo ver encabezados de mensaje ..................................................................... 690 Eliminaci6n de correo ............................................................................................. 691 Envio de correo ............................................................................................................... 692 Envio de un nuevo mensaje ................................................................................... 692 C6mo responder o reenviar correo ...................................................................... 694 Ampliaci6n del proyecto .............................................................................................. 695 A continuaci6n ............................................................................................................... 696

28. Creaci6n de un gestor de listas de correo

699 Componentes de la soluci6n ....................................................................................... 700 Definici6n de una base de datos de listas y suscriptores ............................... 700 Carga de archivos ..................................................................................................... 701 Envio de correo con archivos adjuntos ...............................................................701 Presentaci6n de la soluci6n ........................................................................................ 702 Definici6n de la base de datos .................................................................................... 704 Arquitectura de la secuencia de comandos ............................................................. 706 714 Implementaci6n del inicio de sesi6n ......................................................................... Creaci6n de una nueva cuenta .............................................................................. 715 Conexi6n .................................................................................................................... 717 Implementaci6n de funciones de usuario ................................................................ 720 C6mo ver las listas ................................................................................................... 720 C6mo ver informadm de listas .......................................................................... 725 C6mo ver archivos de listas ................................................................................... 727 Suscripciones y anulaci6n de suscripciones ...................................................... 728 Modificaci6n de la configuraci6n de una cuenta .............................................. 729

. El problema .....................................................................................................................

........................................ 698

fndice de contenidos

Modificaci6n de contraseiias ................................................................................. 730 Desconexidn .............................................................................................................. 732 Implementacidn de funciones administrativas ...................................................... 732 Creaci6n de una nueva lista .................................................................................. 733 Carga de un nuevo boletin informativo ............................................................. 735 Procesamiento de la carga de varios archivos ................................................... 737 Vista previa del boletin informativo ................................................................... 742 Envio del mensaje .................................................................................................... 743 Ampliaci6n del proyecto .............................................................................................. 749 A continuaci6n ........................................................................................................... 749

29 Creaci6n de foros Web

....................................................................750
752 752 754 755 758 760 763 764 770 772 778 779 779

El problema ..................................................................................................................... Componentes de la soluci6n ....................................................................................... Presentaci6n de la soluci6n ......................................................................................... Diseiio de la base de datos ........................................................................................... C6mo ver el Arb01 de articulos .................................................................................... Despliegue y repliegue ........................................................................................... C6mo mostrar 10s articulos .................................................................................... Uso de la clase treenode ......................................................................................... Cdmo ver articulos individuales ................................................................................ Cdmo afiadir nuevos articulos .................................................................................... Ampliaciones .................................................................................................................. Uso de un sistema existente ........................................................................................ A continuacidn ...............................................................................................................

30 Generaci6n de documentos personalizados en PDF 780 El problema ................................................................................................................... 781

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

Evaluacidn de formatos de documento .................................................................... 782 Papel ............................................................................................................................ 782 ASCII ........................................................................................................................... 783 HTML .......................................................................................................................... 783 Formatos de procesadores de texto ..................................................................... 783 Formato de texto enriquecido ............................................................................... 784 Postscript ................................................................................................................... 785 Formato de documento portable .......................................................................... 785 Componentes de la soluci6n ....................................................................................... 786 Sistema de preguntas y respuestas ...................................................................... 786 Software de generaci6n de documentos ............................................................. 787 Software para crear una plantilla RTF ........................................................... 787 Software para crear una plantilla PDF .......................................................... 787 Software para crear PDF mediante programaci6n ..................................... 788 Presentaci6n de la solucion ......................................................................................... 788 C6mo responder a las preguntas .......................................................................... 790

Desarrollo Web con P H P y MySQL

Cdmo calificar las respuestas ................................................................................ 792 Generacidn de un certificado RTF ........................................................................ 794 Generacidn de un certificado PDF a partir de una plantilla .......................... 797 Generacidn de un documento PDF por medio de PDFlib ............................... 801 Una secuencia de comandos Hello World para PDFlib ..................................801 Generacidn de nuestro certificado con PDFlib .................................................. 805 Problemas con 10s encabezados ................................................................................. 812 Ampliacidn del proyecto .............................................................................................. 813 Lecturas adicionales ...................................................................................................... 813

31 Conexibn a servicios Web con XML y SOAP

..................................814

El problema ..................................................................................................................... 815 Cdmo entender XML ..................................................................................................... 816 Servicios Web ................................................................................................................. 820 SOAP ........................................................................................................................... 820 WSDL .......................................................................................................................... 821 Componentes de la solucidn ..................................................................................... 822 Creacidn de un carro de la compra ...................................................................... 822 Uso de las interfaces de servicios Web de Amazon ........................................ 822 Andisis de XML ................................................................................................. 823 Uso de SOAP con PHP ............................................................................................ 823 Almacenamiento en cache ...................................................................................... 824 Presentacidn de la solucidn ........................................................................................ 824 Aplicacidn principal .............................................................................................. 828 Cdmo mostrar 10s libros de una categoria ......................................................... 834 Obtencidn de un AmazonResultSet .................................................................. 836 Uso de XML sobre HTTP ........................................................................................ 844 Uso de SOAP ........,....... .......................................................................................... 850 Almacenamiento de datos en cache ..................................................................... 852 Creacidn del carro de la compra ........................................................................... 854 Cdmo salir a Amazon .............................................................................................. 857 Instalacidn del cddigo del proyecto ........................................................................... 858 Ampliacidn del proyecto .............................................................................................. 859 Lecturas adicionales ...................................................................................................... 859

.................................................................................... 861 A . Instalacibn de PHP y MySQL .............................................................. 862


Parte VI . ApCndices
Ejecucidn de PHP como interprete CGI o como mddulo ..................................... 864 Instalacidn de Apache. PHP y MySQL en Unix ...................................................... 864 Instalacidn binaria .................................................................................................. 865 Instalacidn desde cddigo fuente ...................................................................... 8 6 5 Instalacidn de MySQL ...................................................................................... 866 Instalacidn de PDFlib ......................................................................................... 868

fndice de contenidos

Instalaci6n de CURL........................................................................................... 869 Instalacion de PHP ............................................................................................. 869 Fragmentos de c6digo de httpd.conf ................................................................... 872 ~Funciona la compatibilidad con PHP? .............................................................. 873 ~Funciona SSL? ......................................................................................................... 874 ...................................................................................................... 875 ~ l t i m o pasos s Instalaci6n de Apache. PHP y MySQL en Windows ........................................ 875 Instalaci6n d e MySQL en Windows ..................................................................... 876 Definici6n de la ruta .......................................................................................... 878 Eliminaci6n del usuario an6nimo ................................................................... 878 Definici6n de la contraseiia raiz ...................................................................... 879 Instalaci6n de Apache en Windows ..................................................................... 879 Instalaci6n de PHP en Windows .......................................................................... 881 Uso de Installshield ........................................................................................... 881 Instalacion.manual ............................................................................................. 881 Como aiiadir PHP a su configuraci6n de Apache ....................................... 883 C6mo aiiadir PHP y MySQL a Microsoft IIS y PWS .................................. 883 Pruebas .................................................................................................................. 884 Instalaci6n de PEAR ...................................................................................................... 884 Configuraciones adicionales ....................................................................................... 885

B Recursos Web

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

886
887 889 889 890

Recursos PHP .................................................................................................................. Recursos especificos de MySQL y SQL ..................................................................... Recursos para Apache ................................................................................................. Desarrollo Web ...............................................................................................................

C Contenido del C D - R O N

.......................................................................892

Contenido del CD-ROM ............................................................................................. 893 Windows .................................................................................................................... 893 Linux / Unix ................................................................................................................ 894 L6alo antes de abrirlo ....................................................................................... 894

Indice alfabdtico

..........................................................................................895

Bienvenidos a Desarrollo Web con PHP y MySQL. Estas piginas recogen 10s conocimientos fruto de nuestras experiencias con PHP y MySQL, dos de las herramientas de desarrollo Web rnis actuales. En esta introduccidn, trataremos 10s siguientes aspectos: Razones para leer este libro Objetivos que se pueden akanzar utilizando este libro Qu6 es PHP y MySQL y por qu6 son unas herramientas geniales Una repaso general a las ultimas funciones de PHP 4 Cdmo esti organizado este libro Empecemos.

Razones para leer este libro


En este libro se explica cdmo crear sitios Web interactivos, desde 10s formularios de pedidos rnis sencillos hasta 10s sitios de comercio electr6nico rnis complejos y seguros, y lo que es mis, con ayuda de tecnologias de cddigo abierto. Este libro va dirigido a lectores con un conocimiento bisico de HMTL y con cierta experiencia de programacidn con lenguajes actuales, aunque no es necesario

que hayan programado para Internet o utilizado una base de datos relacional. Los lectores con menos experiencia en programaci6n tambien podrin aprovechar este libro aunque tardarin un poco mas en digerir sus conceptos. Hemos intentado tratar 10s conceptos bisicos, aunque se aborden ripidamente. Este libro va dirigido a personas que deseen dominar PHP y MySQL para crear un sitio Web comercial o de gran tamafio. Puede que tenga experiencia con otros lenguajes de desarrollo Web. Si asi fuera, este libro le ayudari a ponerse a1 dia ripidamente. La raz6n que nos ha animado a escribir este libro es que todos 10s manuales sobre PHP que conociamos eran bisicamente guias de referencia de funciones. Estos libros resultan utiles pero no sirven para mucho cuando nuestro jefe o un cliente nos piden crear un carro de la compra para un sitio Web. Hemos intentado que 10s ejemplos resulten iitiles. De hecho, gran parte de su c6digo se puede utilizar directamente en un sitio Web o bastaria con pequefias modificaciones para hacerlo.

Objetivos que puede alcanzar con este libro


La lectura de este libro le permitiri crear sitios Web reales y dinAmicos. Si ha desarrollado sitios Web utilizando simple HTML, ya conoceri las limitaciones de este enfoque. El contenido estitico de 10s sitios desarrollados unicamente con HTML es exactamente eso, estitico. Estos sitios no varian a menos que se actualicen fisicamente. Los usuarios no pueden interactuar con el sitio de forma significativa. El uso de un lenguaje como PHP y una base de datos como MySQL permite crear sitios Web dinimicos, es decir, susceptibles de personalizaci6n y dotados de informaci6n en tiempo real. En este libro nos hemos centrado deliberadamente en aplicaciones del mundo real, incluso en 10s capitulos introductorios. Comenzamos por analizar un sencillo sistema de pedidos en linea y aprovecharemos para examinar 10s distintos componentes de PHP y MySQL. Abordaremos aspectos relacionados con el comercio electr6nico y la seguridad mientras desarrollamos un sitio Web real y le mostraremos c6mo implementarlos en PHP y MySQL. En la secci6n final del libro, comentaremos c6mo abordar proyectos del mundo real y le guiaremos a travks del disefio, planificaci6n y construcci6n de 10s siguientes ocho proyectos: Autenticaci6n d e usuario y personalizaci6n Carros de la compra Sistemas de administracidn de contenido Correo electr6nico basado en la Web Administradores de listas d e correo Foros Web

Desarrollo W e b con PHP y MySQL

Generacidn de documentos. Conexidn a servicios Web con XML. Puede utilizar estos proyectos directamente o modificarlos para ajustarlos a sus necesidades. Se han seleccionado porque creemos que representan las ocho aplicaciones Web mhs comunes desarrolladas por programadores. Si sus necesidades son distintas, este libro deberia servirle de ayuda para lograr sus objetivos.

Concepto de PHP
PHP es u n lenguaje d e secuencia d e comandos d e servidor diseiiado especificamente para la Web. Dentro de una phgina Web puede incrustar cddigo PHP que se ejecutarh cada vez que se visite una pdgina. El cddigo PHP es interpretado en el servidor Web y genera cddigo HTML y otro contenido que el visitante verh. PHP fue concebido en 1994 y es fruto del trabajo d e un hombre, Rasmus Lerdorf. Ha sido adoptado por otras personas d e talent0 y ha experimentado tres trasformaciones importantes hasta convertirse en el producto actual. En octubre de 2002, era utilizado por mhs de nueve millones de dominios de todo el mundo y su numero crece rhpidamente. Si desea conocer el numero actual de sitios que utilizan este lenguaje, visite el sitio h t t p : //www.p h p . net/usage. php. PHP es un producto de cddigo abierto, lo que quiere decir que puede acceder a su cddigo. Puede utilizarlo, modificarlo y redistribuirlo sin coste alguno. Las siglas PHP equivalian inicialmente a Personal Home Page (PBgina de inicio personal) pero se modificaron de acuerdo con la convencidn de designacidn de GNU (del ingles, Gnu's Not Unix, Gnu no es Unix) y ahora equivale a PHP Hipertext Preprocessor (PreprocesZdor a e hipertexto PHP). En la actualidad, PHP esth en su versidn 4. Esta versidn incorpora mejoras importantes a1 lenguaje que comentaremos en la siguiente seccidn. La direccidn Web de la phgina de PHP esth disponible es http: / / www.php.net. La direccidn de la pdgina de Zend (la compafiia cuyos fundadores disefiaron PHP4) se encuentra en http: / / www.zend.com.

Novedades de la versi6n 4.3 de PHP


Si ha utilizado PHP anteriormente, observar6 una serie de mejoras importantes en la version 4.3. La mayor parte de las funciones de entrada y salida utilizan ahora un enfoque de secuencias unificado, lo que significa que se pueden abrir archivos fhcilmente, asi como conexiones HTTP, HTTPS y FTP.

Introduccidn

PEAR ya ha salido de su versi6n beta y dispone de un instalador sencillo. La biblioteca gr6fica GD se ha incorporado a PHP La compatibilidad con Apache se sigue considerando como experimental, per0 mejora constantemente. Un ejecutable pensado para su uso con secuencias de linea de comandos que se incorpora de manera predeterminada a1 instalar PHP.

Concepto de MySQL
MySQL es un sistema para la administracidn de bases de datos relacional (RDBMS) r6pido y d i d o . Las bases de datos permiten almacenar, buscar, ordenar y recuperar datos de forma eficiente. El servidor de MySQL controla el acceso a 10s datos para garantizar el uso simult6neo de varios usuarios, para proporcionar acceso a dichos datos y para asegurarse de que s610 obtienen acceso a ellos 10s usuarios con autorizacidn. Por lo tanto, MySQL es un servidor multiusuario y d e subprocesamiento mdtiple. Utiliza SQL (del ingles Structured Query Language, Lenguaje de consulta estructurado), el lenguaje est6ndar para la consulta de bases de datos utilizado en todo el mundo. MySQL lleva disponible desde 1996 per0 su nacimiento se remonta a 1979. Ha obtenido el galard6n Choice Award del Linux Journal Readers en varias ocasiones. MySQL se distribuye bajo una licencia de cddigo abierto en la actualidad, per0 tambikn existen licencias comerciales.

Razones para u t i l ~ a r PHP y MySQL


A1 desarrollar un sitio de comercio electrbnico, se pueden utilizar una gran cantidad de productos diferentes: Hardware para el servidor Web Un sistema operativo Software de servidor Web Un sistema de administraci6n de base de datos Un lenguaje de secuencia de comandos o de programaci6n Algunas de estas opciones dependen de otras. Por ejemplo, no todos 10s sistemas operativos se ejecutan sobre todo el hardware ni todos 10s lenguajes de secuencia de comandos se pueden conectar a bases de datos, etc. En este libro no vamos a prestar mucha atencidn a1 hardware, ni a 10s sistemas operativos ni a1 software de servidor Web. No ser6 necesario. Una de las ventajas

Desarrollo W e b con P H P y MySQL

de PHP es que estti disponible para Microsoft Windows, para muchas versiones de Unix y para cualquier servidor Web completamente funcional. MySQL resulta igualmente verstitil. Para demostrarlo, 10s ejemplos de este libro se han escrito y probado en dos configuraciones muy utilizadas: Linux con el servidor Web Apache Microsoft Windows 2000 con Microsoft Internet Information Server (11s) Sea cual sea el hardware, sistema operativo y servidor Web que elija, le recomendamos que considere seriamente la opci6n de utilizar PHP y MySQL.

Akuna de las cualidades de PHP


Entre 10s competidores principales de PHP se puede citar a Perl, Microsoft Active Server Pages (ASP), Java Server Pages (JSP) y Allaire ColdFusion. En comparaci6n con estos productos, PHP cuenta con muchas ventajas, entre las que se encuentran las siguientes: Alto rendimiento Interfaces para una gran cantidad de sistemas de base de datos diferentes Bibliotecas incorporadas para muchas tareas Web habituales Bajo coste Facilidad de aprendizaje y uso Portabilidad Acceso a1 c6digo abierto A continuaci6n se comentan en mtis detalle estas cualidades.
. L

Rendimiento
PHP es muy eficiente. Mediante el uso de un unico servidor, puede servir millones de acceso a1 dia. Los indicadores comparativos de rendimiento publicados por Zend Technologies (http: / / www.zend.com) muestran que PHP supera ampliamente a sus competidores en esta faceta.

Integracion de base de datos


PHP dispone de una conexi6n propia a todos 10s sistemas de base de datos. Ademtis de MySQL, puede conectarse directamente a las bases de datos de

lntroduccidn

PostgreSQL, mSQL, Oracle, dbm, filepro, Hyperwave, Informix, InterBase y Sybase, entre otras. El uso de ODBC (del inglbs Open Database Connectivity Standard, Est6ndar de conectividad abierta de base de datos) permite establecer una conexi6n a cualquier base de datos que suministre un controlador ODBC. Entre ellas, se incluyen 10s productos de Microsoft, y muchos otros.

Bi bliotecas incorporadas
Como se ha diseiiado para su uso en la Web, PHP incorpora una gran cantidad de funciones integradas para realizar utiles tareas relacionadas con la Web. Puede generar im6genes GIF a1 instante, establecer conexiones a otros servicios de red, enviar correos electr6nicos, trabajar con cookies y generar documentos PDF, todo con unas pocas lineas de c6digo.

Coste
PHP es gratuito. Puede descargar la ultima versi6n de http:/ /www.php.net cuando lo desee sin coste alguno.

Aprendizaje de PHP
La sintaxis de PHP se basa en otros lenguajes de programaci61-1,principalmente en C y Perl. Si ya conoce C o Perl, o u n lenguaje d e tip0 C como C++ o Java, no tardar6 nada en utilizar PHP de manera productiva.

Portabilidad
PHP estd disponible para una gran cantidad de sistemas operativos diferentes. Puede escribir c6digo PHP en todos 10s sistemas operativos gratuitos del tip0 Unix, como Linux y FreeBSD, versiones comerciales de Unix, como Solaris y IRIX o en las diferentes versiones de Microsoft Windows. Su c6digo funcionar6 sin necesidad de aplicar ninguna modificaci6n a 10s diferentes sistemas que ejecute PHP.

C6digo fuente
Dispone de acceso a1 c6digo fuente de PHP. A diferencia de 10s productos comerciales y de c6digo cerrado, si desea modificar algo o agregar un elemento al programa, puede hacerlo con total libertad. No necesitara esperar a que el fabricante publique parches, ni tendr6 que preocuparse porque el fabricante cierre sus puertas o decida abandonar el producto.

Desarrollo W e b con PHP y MySQL

Algunas de las ventajas de MySQL


Entre 10s competidores principales de MySQL, se puede citar a PostgreSQL, Microsoft SQL Server y Oracle. MySQL cuenta con muchas ventajas, entre las que se encuentran las siguientes: Alto rendimiento Bajo coste Facilidad de configuraci6n y aprendizaje Portabilidad Accesibilidad a c6digo fuente A continuaci6n se comentan en mds detalle estas cualidades.

Rendimiento
MySQL es muy rdpido. Si lo desea, puede consultar la pdgina de indicadores comparativos de sus desarrolladores en el sitio Web mysql.com. Estos indicadores revelan en muchos casos una diferencia de velocidad abismal con respecto a 10s productos de la competencia.

Bajo coste
MySQL estd disponible de manera gratuita, bajo una licencia de c6digo abierto, o por un precio reducido en forma de licencia comercial si resultara necesario para su aplicaci6n.

Facilidad de uso
Las bases de datos mis modernas utilizan SQL. Si ha utilizado otros RDBMS, no deberia tener problemas para adaptarse a este sistema. MySQL resulta ademds rnds sencillo de configurar que otros productos similares.

PortabiIidad
MySQL se puede utilizar en una gran cantidad de sistemas Unix diferentes asi como bajo Microsoft Windows.

C6digo fuente
Como en el caso de PHP, puede obtener y modificar el c6digo fuente de MySQL.

lntroduccidn

C6mo estd organizado este libro


Este libro se divide en cinco partes principales. La parte I, "Uso de PHP", proporciona una visi6n general de las partes fundamentales del lenguaje PHP. Los ejemplos escogidos son ejemplos del mundo real utilizados para desarrollar un sitio de comercio electr6nico y no c6digo sin utilidad priictica. Esta secci6n se inicia con el capitulo "Curso acelerado". Si ya tiene experiencia en programaci6n con PHP, puede repasar riipidamente esta secci6n. Si ha trabajado antes con PHP o acaba de llegar a1 mundo de la programaci611, conviene que se detenga un poco m6s sobre ella. La parte 11, "Uso de MySQL" aborda 10s conceptos y el disefio implicado en el uso de sistemas de bases de datos relacionales como MySQL, el uso de SQL, la conexi6n de la base de datos MySQL a1 mundo con PHP y temas avanzados sobre MySQL, como la seguridad y la optimizaci6n. La parte 111, "Comercio electr6nico y seguridad" trata alguno de 10s temas generales implicados en el desarrollo de un sitio de comercio electr6nico utilizando cualquier lenguaje. El aspect0 m b importante es la seguridad. Seguidamente, explicaremos c6mo utilizar PHP y MySQL para autenticar usuarios y recoger, transmitir y almacenar datos de manera segura. La parte IV, "Tkcnicas avanzadas de PHP", trata de manera detallada alguna de las funciones principales que integra PHP. Se han seleccionado aquellos grupos de funciones que tienen una mayor probabilidad de aparici6n a1 crear un sitio de comercio electr6nico. Aprenderii a interactuar con el servidor, a interactuar con la red, a generar imiigenes, a manipular fechas y horas y variables de sesibn. En la parte V, "Construcci6n de proyectos pricticos con PHP y MySQL", trata temas del mundo real como la gesti6n de proyectos de gran tamafio y funciones de depuraci6n. Se incluyen proyecos de ejemplo que muestran el potencial y la versatilidad de PHP y MySQL. -

Finalmente
Esperamos que disfrute de este libro y que se lo pase tan bien aprendiendo a utilizar PHP y MySQL como lo hicimos nosotros cuando empezamos a utilizar estos productos. Es un placer trabajar con ellos. En poco tiempo, podrii unirse a 10s miles de desarrolladores que utilizan potentes y robustas herramientas para desarrollar sitios Web din6micos y en tiempo real.

En este capitulo se realiza un ripido repaso de la sintaxis y de las estructuras de lenguaje de PHP. Si ya programa en PHP, puede utilizar este capitulo para colmar sus lagunas de conocimientos. Si tiene experiencia en programaci6n con C, ASP u otro lenguaje de programaci611, este capitulo le ayudari a ponerse a1 dia riipidamente. En este libro aprender5 a utilizar PHP a travks de una serie de ejemplos del mundo real, tornados de nwstr-xperiencia en el desarrollo de sitios de comercio electr6nico. Por regla general, 10s textos sobre programaci6n utilizan ejemplos muy simples para explicar elementos de sintaxis. Nosotros hemos decidido no seguir esta prictica. Nos hemos dado cuenta de que lo que el lector quiere con frecuencia es poder ver un sitio ya creado y operativo, para entender c6mo se utiliza el lenguaje, en lugar de otra guia de sintaxis y funciones sin mayor inter& que un manual en linea. Pruebe 10s ejemplos, introddzcalos y ciirguelos desde el CD-ROM, modifiquelos, dividalos en partes y aprenda a unirlas de nuevo. En este capitulo comenzaremos por presentar un ejemplo de un formulario de product0 en linea para aprender a utilizar las variables, operadores y expresiones en PHP. Tambien analizaremos 10s tipos de variables y el orden de precedencia de 10s operadores. Le ensefiaremos a acceder a variables de formulario y a manipularlas para calcular 10s totales y 10s impuestos correspondientes en un pedido de cliente. Seguidamente, desarrollaremos un ejemplo de formulario de pedido en linea utilizando nuestra secuencia de comandos de PHP para validar 10s datos. Examina-

remos el concept0 de valores booleanos y presentaremos ejemplos de uso de if, else, del operador ? : y de la instruction s w i t c h . Por ultimo, analizaremos el tema de 10s bucles para lo cual escribiremos c6digo de PHP con el que generar tablas HTML repetitivas. Entre 10s temas clave que se analizarrin estan 10s siguientes: Como incrustar PHP en HTML Como agregar contenido dinrimico C6mo acceder a variables de formulario Identificadores Variables declaradas por el usuario Tipos de variables Asignacion de valores a variables Constantes Ambito de variables Operadores y su prioridad Expresiones Funciones de variables Toma de decisiones con i f , e l s e y s w i t c h

Uso de PHP
Para realizar 10s ejemplos dk ese capitulo, asi como 10s del resto del libro, necesitar6 disponer de acceso a un servidor Web con PHP instalado. Para sacar el mriximo partido a 10s ejemplos y casos prricticos que se presentarrin, deberia ejecutarlos e intentar modificarlos. Para ello, necesitar6 un banco de pruebas sobre el que experimentar. Si no tiene PHP en su equipo, deberri instalarlo o pedirle a su administrador del sistema que lo haga en su lugar. En el apkndice A encontrarri las instrucciones y en el CD-ROM se incluye todo lo necesario para instalar PHP en UNIX y Windows NT.

Aplicacion de eiemplo: Bob's Auto Parts


Una de las aplicaciones mris comunes de cualquier lenguaje de secuencia de comandos de servidor es el procesamiento de formularios Web. Empezaremos nuestro estudio de PHP implementando un formulario para Bob's Auto Parts, una compafiia

Desnrrollo Web corz P H P y MySQL

d e repuestos d e coches. El ccidigo utilizado para este ejemplo se incluye en el directorio correspondiente del CD.

5y~Ldu-k c'p l qqc4$f3s

Por el momento, el programador de HTML d e la empresa d e Bob ha creado un formulario d e pedido para los repuestos que vende la empresa. En la figura 1.1 se ilustra el aspecto del formulario. Resulta bastante sencillo y es muy parecido a 10s que se pueden encontrar e n Internet. Lo primero clue Bob quiere saber es qu6 pide el cliente, obtener el total del pedido e incluir 10s impuestos que se deben pagar. En el listado 1.1se recoge parte del codigo HTML asociado a esta pigina. En este ccidigo debe fijarse en dos &as importantes.

I1

BOWS

~Parts t o
Quantity

Order Form
Item Tires

oil
Spark Plu~,s

rI r-

Figura 1.1. El formulario inicial d e pedido d e B o b solo registra productos y cantidades

Listado 1.1, orderform.html. Codigo HTML correspondiente al formulario basico de pedido de Bob

1 . Curso acelerado de P H P

En primer lugar, hemos establecido la accibn del formulario en el nombre de la secuencia de comandos PHP que procesard el pedido del cliente. (Escribiremos esta secuencia de comandos a continuacibn.)Por regla general, el valor del atributo ACTION es el URL que se cargari cuando el usuario pulse el botbn de envio. Los datos indicados por el usuario en el formulario se enviarin a este URL a traves del metodo especificado en el a t r i b u t o ~ ~ya ~ sea ~ o GET ~ , (ajuntado al final del URL) o POST (enviado como un paquete diferente). En segundo lugar, deberia fijarse en 10s nombre s de 10s formularios t i r e q t y, o i l q t y Y s p a r k q t y . Utilizaremos estos nombres de nuevo en nuestra secuencia de comandos de PHP. Por ello, resulta importante asignar nombres significativos a 10s campos de formulario que Sean sencillos de recordar a1 escribir la secuencia de comandos de PHP. Algunos editores de PHP generan nombres de campo del tip0 camp02 3 de manera predeterminada. Estos campos resultan dificiles de recordar. Su vida como programador de PHP resultari mucho m i s sencilla si estos nombres reflejan 10s datos que se introducen en el campo. Es aconsejable adoptar un estindar de codificacibn para nombres de campos de manera que todos 10s nomljres $el sitio utilicen el mismo formato. De esta forma le resultar6 m6s sencillo recordar, por ejemplo, si abrevib una palabra en el nombre de un campo o si utilizb guiones bajos para representar espacios.

Procesamiento del formulario


Para procesar el formulario, tendremos que crear la secuencia de comandos mencionada en el atributo A C T I O N de la etiqueta FORM llamada p r o c e s s o r d e r php. Abra su editor de texto y Cree este archivo. Escriba el siguiente cbdigo:

<head> < t i t l e > B o b l s Auto P a r t s </head> <body> < h l > B o b t s Auto P a r t s < / h l > <h2>0rder Results</h2> </body> </html>

Order

Results</title>

Desnrrollo We6 con P H P !I MySQL

Como observar6, todo lo que hemos escrito hasta ahora es simple c6digo HTML. Ha llegado el momento de agregar algo de c6digo PHP a nuestra secuencia de comandos.

Agregue las siguientes lineas debajo del encabezado < h 2 > :

Guarde el archivo y cfirguelo en el navegador. Para ello, rellene el formulario de Bob y haga clic sobre el b o t h Submit Order. El resultado deberia parecerse a1 ilustra-

Bob's Auto Parts


Order Results
Order processetl.

F i g u r a 1.2. El texto pasado a la instruccion echo de PHP se refleja en el navegador

Fijese en c6mo se incrust6 el codigo de PHP que escribimos dentro de un archivo HTML de aspecto normal. Intente visualizar el c6digo fuente en su navegador. Deberia mostrarse la siguiente secuencia:

No se ve ninguna secuencia de PHP ya que el intbrprete de PHP ha recorrido la secuencia de comandos y la ha sustituido con su resultado. Por lo tanto, se puede generar c6digo HTML limpio y visible a partir de PHP desde cualquier navegador. En otras palabras, el navegador del usuario no necesita entender PHP. Este hecho ilustra de forma resumida el concept0 de secuencias de comandos del lado del servidor. El c6digo PHP se ha interpretado y ejecutado en el servidor Web, lo que difiere de JavaScript y de otras tecnologias de cliente que se interpretan dentro del navegador Web del equipo de un usuario. El c6digo de archivo se compone de cuatro elementos: HTML Etiquetas PHP Instrucciones PHP Espacios en blanco Tambibn podemos agregar Comentarios La mayor parte de las lineas de este ejemplo son sencillo c6digo HTML.

Estilos de etiquetas P H P
En PHP existen cuatro estilos diferentes de etiquetas que podemos utilizar. Los siguientes fragmentos de c6digo son equivalentes: Estilo XML
<?php echo '<p>Order- prdessed.</p>';
?>

~ s t es e el tip0 de etiqueta que utilizaremos en el libro. Se trata del estilo de etiqueta preferido que usar con PHP 3 y 4. El administrador del servidor no puede desactivarlo lo que garantiza su disponibilidad para todos 10s servidores. Este estilo de etiqueta se puede utilizar con documentos XML (del inglbs Extensible Markup Language, Lenguaje de marcado extensible). Si tiene previsto utilizar XML en su sitio, deberia utilizar este estilo de etiqueta. Estilo corto
<?

echo

'<p>Order processed.</p>';

?>

Este estilo de etiqueta es el mAs simple y sigue el estilo de una instrucci6n de procesamiento SGML (del inglbs Standard Generalized Markup Language, Lenguaje de marcado generalizado estAndar).Para utilizar este tip0 de etiqueta (la mAs corta), debe habilitar el padmetro s h o r t t a g s en el archivo de configuraci6n o compilar PHP para que utilice este tipode etiquetas. En el aphdice A encontrarA mAs informaci6n sobre su instalaci6n.

Desarrollo Web con PUP y MySQL

Estilo SCRIPT
<script language='php'> echo '<p>Order processed.</p>'; </script>

Este estilo de etiqueta es la mis larga y le resultari familiar si conoce JavaScript o VBScript. Puede utilizarla si estA usando un editor HTML que d6 problemas con otros estilos de etiquetas. Estilo ASP
<%

echo '<p>Order processed.</p>'; % >

Este estilo de etiqueta es el que utilizan las PAginas activas de servidor (ASP). Se puede utilizar si ha activado el parimetro asp tags. Puede recurrir a este estilo de etiquetas si est6 utilizando un editor diseiiado para ASP o si ya ha programado en ASP.

lnstrucciones de PHP
Para indicarle a1 interprete de PHP qu6 hacer, se introducen instrucciones de PHP entre las etiquetas de cierre y las etiquetas de apertura. En este ejemplo, s610 utilizamos un tip0 de instrucci6n:
echo '<p>Order processed.</p>';

Como habri supuesto, la funci6n de la instrucci6n echo es muy sencilla: imprime (o repite) la cadena pasada en el navegador. Si examina la figura 1.2, el resultado devuelto es la cadena "Order processed" en el ventana del navegador. Como observark a1 final de la instrucci6n echo aparece un punto y coma. Este signo se utiliza para separar instrucciones en PHP como si se tratara de un punto a1 escribir frases en espaiiol. Si ha programado antes en C o en Java, estarA familiarizado con el uso del punto y coma con dicha funci6n. Uno de 10s errores de sintaxis m i s comunes a1 programar es olvidarse de introducir 10s puntos y comas. Sin embargo, resulta igualmente sencillo descubrir el error y corregirlo.

Espacios en blanco
Los caracteres de espaciado como las lineas nuevas (retornos del carro), 10s espacios y 10s tabuladores se conocen como espacios en blanco. Como probablemente sepa, 10s navegadores ignoran 10s espacios en blanco en HTML. Y otro tanto hace el motor de PHP. Examine 10s siguientes dos fragmentos de HTML:
<hl>Welcome to Bob's Auto Parts!</hl><p>What w ~ u l dyou llke to order today?</p>

Y
<hl>Welcome Autc Parts!</hl> to Bob's

1 . Curso acelerado de P H P

<p>What would you like to order today?</p>

Estos dos fragmentos de HTML devuelven el mismo resultado a1 representarlos en el navegador. Sin embargo, conviene utilizar espacios en blanco en HTML para mejorar la legibilidad del c6digo. Y otro tanto se puede decir de PHP. El uso de espacios en blanco no es obligatorio per0 facilita la lectura del c6digo si colocamos cada instrucci6n en una linea separada. Por ejemplo:
echo 'hello ' echo 'world';
;

echo 'hello ';echo 'world';

son equivalentes, pero la primera versi6n resulta m6s sencilla de leer.

Comentarios
Los comentarios son exactamente eso, comentarios. Su funci6n es la de proporcionar indicaciones para aqu6llos que leen el c6digo. Los comentarios se pueden utilizar para explicar el objetivo de la secuencia de comandos, qui6n la escribi6, por qu6 se escribi6 de esa forma, cuando se modifico por ultima vez, etc. Por regla general, todas las secuencias de comandos de PHP incluyen comentarios, salvo las m8s sencillas. El intbrprete de PHP ignorar6 cualquier texto de un comentario. En concreto, el analizador de PHP omite 10s comentarios que equivalen a espacios en blanco. PHP admite el uso de comentarios del estilo de C, C++ y secuencias de comandos del nucleo. A continuaci6n se recoge un-comentario del estilo de C multilinea que puede aparecer a1 inicio de una se?uencia de comandos de PHP:
/ * Autor: Bob Smith
Modificado por ultima vez: 10 d e Abril Esta secuencia d e comandos procesa pedidos d e clientes

*/

Los comentarios multilinea deben empezar y acabar con el simbolo I*. Como ocurre en C, 10s comentarios en linea no se pueden anidar. T a m b i h se pueden utilizar comentarios de una sola linea, bien en estilo de C++:
echo '<p>Order processed.</p>'; / / Empezar a imprirnir el pedido

o en estilo de secuencia de comandos del nucleo:


echo '<p>Order processed.</p>';
#

Ernpezar

imprirnir

el

pedido

En ambos casos, todo lo que venga despu6s del simbolo de comentario (# o / / ) se considera con un comentario hasta el final de la linea y el final de la etiqueta de PHP, segun qu6 ocurra primero.

Desnrrollo Web corr P H P y MySQL

Hasta ahora, no hemos utilizado PHP para hacer algo que no pudiesemos conseguir con HTML. La raz6n principal para utilizar un leguaje de secuencia de comandos d e servidor es suministrar contenido dindmico a 10s usuarios de un sitio. Se trata d e una aplicaci6n importante porque el contenido que cambia e n funci6n d e las necesidades del usuario o con el tiempo garantiza la vuelta d e 10s visitantes. PHP nos permite realizar esta tarea d e manera sencilla. Vamos a empezar por un ejemplo sencillo. Sustituya el c6digo d e PHP del archivo p r o c e s s o r d e r . php por el siguiente c6digo:

En este fragmento, se utiliza la funci6n d a t e ( ) integrada en PHP para indicar a1 cliente la fecha y la ahora a la que procesar el pedido. Esta informacion serA diferente cada vez que se ejecute la secuencia d e comandos. En la figura 1.3 se ilustra el resultado d e ejecutar la secuencia d e comandos en una ocasi6n:
-1iYlx
D1rem6n[I hnp /I #ebsewef/drapleflIprocessorder php

- 88
(3 11

Bob's Auto Parts


order Gesults
Order processed al04:11. 3 1st Januay

Figura 1.3. La funcion date() devuelve una cadena de fecha con formato

Llamada cle FIJ nciones


Examine la llamada a la funci6n date ( ) . Se trata de la forma general que adoptan las llamadas d e funci6n. PHP incorpora una extensa biblioteca d e funciones que puede utilizar para desarrollar aplicaciones Web. La mayor parte d e estas funciones pasan y devuelven datos.

1 . Curso acelerado de P H P

Examine la siguiente llamada de funci6n:

Fijese en que estamos pasando una cadena (datos de texto) a la funci6n dentro de un par de parhtesis. Esta operaci6n se conoce como llamar a1 argumento o parhmetro de la funci6n. Estos argumentos son 10s datos de entrada utilizados por la funci6n para devolver resultados especificos.

La funci6n d a t e ( ) espera a que el argumento que se le pase sea una cadena de formato, que represente el estilo que se desea utilizar para devolver 10s datos. Cada una de las letras de la cadena representa una parte de la fecha y la hora. H es la hora en formato 24 horas, i son 10s minutos precedidos de un cero cuando resulte necesario, j es el dia del mes sin utilizar un cero inicial, s representa el sufijo ordinal (en este caso "th" del ingles) y F es el nombre completo del mes. (En un capitulo posterior se incluye una lista completa de 10s formatos que admite la funci6n d a t e ( ) ).

Como acceder a las variables de formulario


El 6nico objetivo de utilizar el formulario de pedido es recoger el pedido del cliente. Con PHP resulta muy sencillo obtener 10s detalles de lo que acaba de escribir el cliente, per0 el metodo exacto depende de la versi6n del lenguaje que est4 utilizando y de un parhmetro del archivo php.ini.

Variables de formulario
Dentro de una secuencia de comandos de PHP, podemos acceder a cada uno de 10s campos del formulario como una variable de PHP cuyo nombre se relaciona con el nombre del campo del formulario. En PHP 10s nombres de variables se reconocen porque comienzan con el signo del d6lar ($). Un error habitual es olvidarse de incluir este simbolo. Puede acceder a 10s contenidos del t i r e q t y de las siguientes formas:
Stireqty $-POST[ 'tireqty'] $HTTPPPOSTPVARS['tireqtyq]
/ / estilo corto / / estilo intermedio / / estilo largo

En este ejemplo, y a lo largo del libro, se utiliza el estilo largo para hacer referencia a las variables de formulario per0 puede crear versiones cortas de las variables para facilitar su uso. Se trata de una opci6n prhctica y segura de procesar 10s datos que funcionarh en todos 10s sistemas sea cual se su versi6n o configuraci6n.

Desarrollo Web con P H P y MySQL

En su c6dig0, puede utilizar otro enfoque, per0 para ello deberia conocer las diferentes opciones. En resumen: El estilo corto es prictico, per0 requiere activar el parimetro de configuraci6n register global s.(El valor predeterminado varia de una versi6n a otra de PHP.) En eGe estilo resulta sencillo cometer errores que podrian convertir a su c6digo en inseguro. El estilo intermedio resulta bastante prictico, per0 hizo su aparici6n en la versi6n PHP 4.1.0, por lo que no funcionari en las versiones antiguas. El estilo largo es el estilo que incluye m i s detalles, per0 es el unico que garantiza el funcionamiento del c6digo en todos 10s servidores, con independencia de su configuraci6n. Sin embargo, tenga en cuenta que se considera como obsoleto y que es probable que con el tiempo acabe desapareciendo. Nuestra intenci6n es que el codigo de ejemplo utilizado en el libro funcione sin necesidad de ninguna modificaci6n en la mayor cantidad de sistemas posibles. Por esta raz6n, hemos optado por el estilo largo, per0 puede escoger otro mbtodo. En el estilo corto, 10s nombres de las variables utilizadas en la secuencia de comandos son iguales a 10s nombres de 10s campos del formulario HTML. No es necesario declarar las variables en la secuencia de comandos o adoptar ninguna medida para crear dichas variables. Se pasan en la secuencia de comandos bisicamente de la misma forma que se pasan argumentos a una funcion. Si ha escogido este estilo, puede utilizar una variable como $tireqty. El campo ti rdqty del formulario crea la variable $tireqt y en la secuencia de comandos de procesamiento. El uso del estilo corto exige la activaci6n de un comando llamado register gl oba 1s en el archivo de configuracion php .ini.En PHP, desde la versi6n 4.2.0 en adelante, este parimetro esti desactivado de manera predeterminada. Por el contrario, en las versiones anterioreS'est6 activado. Resulta prictico disponer de este tip0 de acceso a las variables, per0 antes de activar el parimetro register global s conviene conocer las razones que han llevado a1 equipo de desarrollo de PHP a dejarlo desactivado. Como hemos dicho, este tip0 de acceso a las variables resulta practico, per0 es proclive a cometer errores de programaci6n que podrian comprometer la seguridad d e las secuencias d e comandos. Si las variables d e funci6n se convierten automiticamente en variables globales, no existiri una diferencia clara entre las variables creadas por nosotros y las variables no fiables procedentes directamente del usuario. Si no asignamos un valor inicial a nuestras variables, 10s usuarios de las secuencias de comandos pueden pasar variables y valores en forma de variables de formulario que se mezclarin con las nuestras. Si se opta por utilizar el estilo corto para acceder a las variables, es aconsejable asignar un valor inicial a las variables. El estilo medio implica la recuperaci6n de variables de formulario de una de las matrices $ POST, $ GET y $ REQUEST.Una de estas matrices contendra 10s detalles de tod& las variables de formulario. La variable utilizada dependeri del mbtodo

1. Curso acelerado de P H P

utilizado para enviar el formulario, POST o GET, respectivamente. Ademds, todos 10s datos enviados a trav6s de 10s m6todos POST y GET estardn disponibles a trav6s de $-REQUEST. Si el formulario se envia por el metodo POST, 10s datos introducidos en el camPO ti reqty se almacenardn en $ POST [ ' ti reqty ' ] . Si el formulario se envia utilizando GET, 10s datos se almacenarin en $ GET [ ' tireqt y 1 . En cualquiera de 10s dos casos, 10s datos estardn disponibles e i $ REQUEST [ ' tireqty ' 1 . Estas matrices se incluyen dentro de 10s conocido; conjuntos superglobales. Volveremos sobre ellos a1 examinar el dmbito de las variables. Si estd utilizando una versi6n antigua de PHP, puede que no disponga de acceso a $ POST o $ GET. En las versiones anteriores a la 4.1.0, esta informaci6n se almacenaba enlas matrices SHTTP POST VARS y SHTTP GET VARS.Este estilo es el que llamaremos estilo largo y sFpuedFutilizar con vewione; antiguas y nuevas de PHP, per0 ha sido considerado como obsoleto por lo que es probable que no funcione en las versiones futuras. En este estilo no existe un equivalente de $-REQUEST. Si estd utilizando el estilo largo, puede acceder a la respuesta del usuario a trav6s d e $ ~ T T pPOST VARS['tireqtyl] o$HTTP GET VARS['tireqtyl]. A lo largo deeste libro, hemos intentado indicar a6nde no funcionard el c6digo con las versiones antiguas de PHP. Los ejemplos utilizados se han probado con la versi6n 4.3 de PHP, por lo que es posible que a veces resulten incompatibles con versiones anteriores a la 4.1.0. Por lo tanto, le recomendamos que utilice la versi6n actual. Como habrd observado, en el c6digo no se comprueba el contenido de las variables para garantizar que se introducen datos correctos en 10s campos del formulario. Intente introducir datos err6neos deliberadamente para observar qu6 ocurre. Cuando termine de leer este capitulo, es probable que desee agregar algun tip0 de validaci6n de datos a la secuencia de comandos. Vamos a examinar el ejemplo. Como 10s nombres de v'ariable resultan un tanto pesados en el estilo lago y nos vamos a basar en un tip0 de variables conocidas como matrices, que no se analizardn de lleno hasta un capitulo posterior, comenzaremos por crear copias que resulten sencillas de utilizar. Para copiar el valor de una variable en otra, puede utilizar el operador de asignaci6n, que en PHP es el signo igual (=). La siguiente linea de c6digo crea una nueva variable denominada $ t i re q t y y copia. 10s contenidos d e $ HTT P- PO STVARS [ ' tireqt y ' 1 dentro de la nueva variable: Coloque el siguiente bloque de c6digo a1 inicio de la secuencia de comandos de procesamiento. El resto de secuencias de comandos de este libro que procesen datos desde un formulario contendrdn un bloque similar a1 inicio. Como no se generard ningun resultado, no importa si se coloca por encima o por debajo de la etiqueta <html> ni de otras etiquetas de HTML con las que se inicie la pdgina. En nuestro caso, solemos colocar este bloque a1 inicio de la secuencia de comandos para asegurarnos de que resulta fdcil de encontrar.

Desarrollo W e b con P H P y MySQL


<?php //Cree nombres de variables cortos Stireqty = SHTTP-POST-VARS['tireqty~; Scilqty = SHTTP-POST VARS['oilqty']; Ssparkqty = SHTTP-POST-VARS['sparkqtyv];
-

?>

El c6digo crea tres nuevas variables $ t i r e q t y , $ o i l q t y y $ s p a r k q t y y las configura para que contengan 10s datos enviados a traves del metodo POST desde el formulario. Para que la secuencia de comandos haga algo visible, agregue las siguientes lineas a la parte final de la secuencia de comandos de PHP:
echo '<p>Your order is as follows: < / p > ' ; echo Stireqty.' tires<br / > I ; echr Soilqty.' bottles of oil<br echc Ssparkqty. ' spark plugs<br /,' ;
/,I;

Si carga ahora este archivo en el navegador, el resultado de la secuencia de comandos se pareceri a1 ilustrado en la figura 1.4. Los valores reales se mostraran en funci6n de lo que escriba en el formulario. En las siguientes secciones se comentan un par de cosas interesantes sobre este ejemplo.

aci6n de cade

-----

En la secuencia de comandos, utilizamos e c h o para imprimir el valor que escribe el usuario en cada uno de 10s campos de formulario, seguido por texto explicativo. Si examina de cerca las instrucciones e c h o , veri que el nombre de la variable y que el texto que sigue estin separados por un punto (.), como se puede ver a continuaci6n: -

echo

Stireqty. '

tires<br

/> '

~ s t es e el operador de concatenacidn de cadenas y se utiliza para unir cadenas (secciones de texto). Lo utilizari con frecuencia con e c h o para mostrar informaci6n en pantalla. Se suele recurrir a 61 para no tener que escribir varios comandos e c h o . Para las variables que no Sean matrices, puede encerrarlas entre comillas dobles para su representacibn en el navegador. (El estudio de las matrices se aborda en un capitulo posterior.) Por ejemplo:
echo "Stireqty tires<br
/,";

Esta secuencia es equivalente a la primera. Los dos formatos son vilidos y la elecci6n de uno u otro es una cuesti6n personal. Fijese en que no es lo mismo utilizar comillas dobles que utilizar comillas simples para encerrar nombres de variables. Si se ejecuta la siguiente linea de c6digo:
echo 'Stireqty tires<br
/ > I ;

1 . Curso rrcelerrrdo de P H P

Bob's Auto Parts


Order Results
Order procesaetl at 21.09.9th April Your order is as follows: 2 lires I bonks o f oil 2 spwk p h g

Figura 1.4. Las variables de formulario introducidas por el usuario resultan de facil acceso en processorder.php enviar6 la secuencia " S t i r e q t y t i r e s < b r / > " al navegador. Si se utilizan comillas dobles, el nombre d e la variable se sustituira por SLI valor. Si se utilizan comillas simples se enviara el nombre d e la variable, o cualquier otro texto, sin alterar.

La variable y la cadena q u e concatenamos e n cada una d e las i n s t r ~ ~ c c i o ne ec sh o son cosas diferentes. Las variables son u n simbolo para sustituir a 10s datos. Las cadenas son datos e n si mismas. C u a n d o se utiliza u n segment0 d e datos como tal e n u n programa como este, se designa como literal para distinguirlo d e las variables. $ t i r e q t y es una variable,un simbolo clue representa 10s datos escritos por el cliente. Por el contrario, ' t i r e s < b r / > ' es u n literal. Se p ~ ~ e d tomar e por su valor literal. Bueno, casi. ~ R e c u e r d a el segundo ejemplo anterior? PHP sustituye el noinbre d e la variable $ t i r e q t y e n la cadena por el valor almacenado e n la variable. Recuerde q u e existen d o s tipos d e cadenas e n PHP, unas encerradas entre comillas dobles p otras entre comillas simples. P H P intentar6 evaluar las cadenas con comillas dobles, lo q u e dara como resultado el comportamiento visto anteriormente. Las cadenas con comillas simples se trataran como verdaderos literales.

Los identificadores son nombres d e variables. (Los nombres d e funciones y clases son tambien identificadores. Los nombres y las clases se examinar6n e n capitulos posteriores.) Los identificadores s i g ~ ~ algunas en reglas sencillas: Los identificadores puede tener cualquier longitud y pueden incluir letras, nlimeros, guiones bajos y signos d e d6lar. Sin embargo, conviene poner

Desarrollo W e b con P H P y MySQL

cuidado a1 utilizar 10s signos de d6lar en 10s identificadores. En una secci6n posterior explicaremos por qu6. Los identificadores no pueden comenzar por un numero. En PHP, 10s identificadores discriminan entre mayusculas y minusculas. Stireqty no es lo mismo que STireQty. Un error comun en programaci6n consiste en intentar utilizarlos indistintamente. Los nombres de las funciones son una excepci6n a esta regla (el uso de mayusculas y minusculas es indiferente). ~ n lariable a puede tener el mismo nombre que una funcibn. Este hecho puede dar lugar a confusiones por lo que conviene evitarlos. Asi mismo, no se pueden crear dos funciones con el mismo nombre.

Variables declaradas por el usuario


Puede declarar y utilizar sus propias variables adem6s de las variables que se pasan desde el formulario HTML. Uno de 10s rasgos de PHP es que no requiere declarar variables antes de utilizarlas. Las variables se crean a1 asignarles u n valor (v6ase la siguiente seccion para conocer 10s detalles).

Asignacion de valores a variables


Para asignar valores a las variables se utiliza el operador de asignaci6n, =, como hicimos a1 copiar el valor de una variable en otra. En el sitio de Bob, queremos obtener el numero total de articubs p d i d o s y la cantidad total que se debe abonar. Podemos crear dos variables para almacenar estos valores. En primer lugar, inicializamos cada una de estas variables en cero. Agregue las siguientes lineas a1 final de la secuencia de comandos de PHP:
Stotalqty = 0; $totalamount = 0.00;

Cada una de estas lineas crea una variable y le asigna u n valor literal. Tambien puede asignar valores de variables a las variables, por ejemplo:
Stotalqty = 0; $totalamount = Stotal~qty;

Tipos de variables
Un tip0 de variable hace referencia a1 tip0 de datos que se almacenan en ella.

1. Curso acelerado de P H P

Tipos de datos de PHP


PHP admite 10s siguientes tipos de datos Entero: utilizado para numeros enteros Doble: utilizado para numeros reales Cadena: utilizado para cadenas de caracteres Booleano: utilizado para valores verdaderos o falsos Matriz: utilizados para almacenar conjuntos de datos del mismo tip0 Objeto: utilizado para almacenar instancias de clases PHP 4 agreg6 tres tipos de variables adicionales: booleanas, NULL y de recurso. Las variables a las que no se les ha asignado un valor, no esttin definidas o se les ha asignado el valor NULL son de tip0 NULL. Algunas funciones incorporadas (como las funciones de base de datos) devuelven variables con tip0 de recurso. Es muy poco probable que necesite manipular directamente este tip0 de variables. PHP tambikn admite 10s tipos pdf doc y pdf info si se ha instalado con compatibilidad para PDF (del inglks, Portable Document Format, Formato de documento portable). Este aspect0 se tratarti en un capitulo posterior.

Control de tipos
PHP es un lenguaje con un control de tipos muy dkbil. En la mayoria de 10s lenguajes, las variables s610 pueden ccmtener un tip0 de datos y dicho tip0 de datos debe declararse antes de poder utilizar la variable, con ocurre en C. En PHP, el tip0 de variable viene determinado por el valor que se le asigne. Por ejemplo, a1 crear tota 1qt y y $tot a1amount,deben determinarse sus tipos iniciales, de la siguiente forma:

Como hemos asignado 0, un valor entero, a $totalqt y, se tratarti de una variable de tip0 entero. De manera similar, $ totalamount es de tip0 doble. Pero, por extrafio que pueda parecer, podemos agregar una linea a nuestra secuencia de guiones de la siguiente forma:
Stotalarnount
=

'Hello';

La variable $total amount serti entonces de tip0 cadena. PHP cambia el tip0 de la variable en funci6n del valor almacenado en ella en cualquier momento dado.

Desarrollo Web con PHP y MySQL

Esta capacidad para cambiar 10s tipos de manera transparente a1 instante puede resultar extremadamente util. Recuerde que PHP sabe "automiiticamente" quk tip0 de datos se estii colocando en una variable y devolverii 10s datos con el mismo tip0 tras recuperarlos de la variable.

Conversio
Puede simular que un tip0 de variable o valor sea de un tip0 diferente utilizando una conversi6n de tipo. Este recurso funciona de la misma forma que en C. Basta con colocar el tip0 temporal entre corchetes delante de la variable que se desea convertir. Por ejemplo, podriamos haber declarado las dos variables anteriores utilizando una conversibn.

La segunda linea indica "toma el valor almacenado en $ totalqty, interprktalo como doble y almac6nalo como $ totalamount".La variable $ totalamount serii de tip0 doble. La variable de conversi6n no cambia de tip0 por lo que $ totalqty seguirii siendo de tip0 entero.

Variables de tipo variable


PHP proporciona otro tip0 de variable: la variable de tip0 variable. Las variables de tip0 variable permiten cambiar el nombre de una variable diniimicamente. (Como puede observar, PHP proporciona una gran libertad en este sentido: todos 10s lenguajes permiten2ambiar el valor de la variable, per0 no hay muchos que permitan cambiar eT tip0 de variable y menos aun que permitan cambiar su nombre.) Su funcionamiento consiste en utilizar el valor de una variable como nombre de otra. Por ejemplo, podemos establecer

A continuaci6n podemos utilizar $$varname en lugar de $tireqty.Por ejemplo, podemos establecer el valor de $tireqty :

Esto equivale a
Stireqty
=

5;

Puede que parezca un poco confuso, per0 no se preocupe porque volveremos sobre uso posteriormente. En lugar de tener que enumerar y utilizar cada variable de formulario por separado, podemos utilizar un bucle y una variable para proce-

1. Curso acelerado de PHP

sarlas todas automiticamente. En la secci6n dedicada a 10s bucles se incluye un ejemplo que ilustra este hecho.

Constantes
Como vimos anteriormente, podemos cambiar el valor almacenado en una variable. Tambien podemos declarar constantes. Una constante almacena un valor como una variable con la diferencia de que se establece una vez y no se puede cambiar en ningGn otro punto de la secuencia de comandos. En nuestra aplicaci6n de ejemplo, podriamos almacenar 10s precios de 10s articulos de venta en forma de constantes. Para definir constantes puede utilizar la funci6n d e f i n i t i o n :

Agregue estas lineas de c6digo a la secuencia de comandos. Los nombres de las constantes utilizan siempre mayusculas. Se trata de una convenci6n tomada de C que facilita su distinci6n de las variables. Esta convenci6n no es obligatoria per0 contribuye a que la lectura y el mantenimiento del c6digo resulten m i s sencillos. Tenemos tres constantes que se pueden utilizar para calcular el total del pedido del cliente. Una diferencia importante entre las constantes y las variables es que cuando hacemos referencia a una constante, no lleva antepuesto el simbolo del d6lar. Si desea utilizar el valor de una constante, utilice Gnicamente su nombre. Por ejemplo, para utilizar una de las constantes que acabamos de crear, podemos escribir: e c h o TIREPRICE; * Ademis de las constantes definidas, PHP establece un gran nLimero de constantes propias. Una forma sencilla de verlas consiste en ejecutar el comando p h p i n f o ( ) :

phpinfo( ) ;

Este comando devuelve una lista de variables y constantes predefinidas de PHP, ademis de otra informacidn Gtil. Iremos comentindola a medida que vayamos avanzando.

Ambito de variables
El termino imbito hace referencia a 10s lugares dentro de las secuencias de comandos en 10s que resulta visible una variable dada. A continuaci6n se describen 10s cuatro tipos de imbitos de PHP: Las variables superglobales incorporadas resultan siempre visibles dentro de una secuencia de comandos.

Desarrollo W e b con P H P y MySQL

Las variables globales declaradas en una secuencia de comandos resultan visibles a lo largo de la secuencia de comandos per0 no dentro de las funciones. Las variables utilizadas dentro de funciones tienen restringido su rimbito a la funci6n. Las variables utilizadas dentro de funciones que se declaran como globales hacen referencia a la variable global del mismo nombre. A partir de la versi6n 4.2 de PHP, las matrices $ GET y $ POST asi como otras variables especiales llevan asignadas sus propias reglas de cmbito. st as se conocen como superglobables y se pueden ver en todas partes, tanto dentro como fuera de las funciones. A continuaci6n se recoge la lista completa de variables globales:
$GLOBALS, una matriz con todas las variables globales
$ -SERVER,una matriz con las variables de entorno del servidor
$ GET, una matriz con las variables pasadas a la secuencia de comandos a tr&s del metodo GET

$ POST, una matriz con las variables pasadas a la secuencia de comandos a tr&s del metodo POST $ -COOKIE,una matriz con las variables de cookies $ -FILES,una matriz con las variables relacionadas con las cargas de archiVOS

$ -ENV,una

matriz de variables de entorno matrk con todas las variables de entrada de usuario

$ -REQUEST,una

$ -SESSION,una matriz con las variables de sesi6n

Volveremos sobre cada uno de estos tipos a medida que vayamos avanzando. Analizaremos el rimbito de las variables a1 estudiar las funciones. Por el momento, todas las variables que utilicemos serrin globales de manera predeterminada.

Operadores
Los operadores son simbolos que se pueden utilizar para manipular valores y variables realizando una operaci6n sobre ellos. Tendremos que utilizar algunos para calcular 10s totales y 10s impuestos que aplicar a1 pedido del cliente. Ya hemos mencionado dos operadores: el operador de asignacidn, =, y .,el operador de concatenaci6n. A continuaci6n examinemos la lista completa. En general, 10s operadores pueden tomar dos o tres argumentos (aunque la mayoria toman dos). Por ejemplo, el operador de asignaci6n toma dos argumentos:

la ubicaci6n d e almacenaniiento en la parte izquierda del simbolo = y una expresi6n en la parte derecha. Estos argumentos se conocen como operandos, e s decir, 10s elementos sobre 10s que se opera.

Los operadores aritmeticos son bastantes claros: se trata de 10s operadores matemiticos de uso mAs comiln. En la tabla 1.1 se recogen 10s operadores aritm6ticos.
Tabla 1.1. Operadores aritmeticos de PHP

Suma Resta

$a

$b

$a - $b
$ a * $b

Multiplication
Division Modulo

$a / $ b $a % $b

Con todos estos operadores podemos guardar el resultado d e la operaci6n. Por ejemplo:

La suma y la resta funcionan como se esperaria. Estas operaciones suman o restan, respectivamente, 10s valores almacenados en las variables $a y $b. Tambibn puede utilizar el siflbolo de resta, -,como operador unitario (es decir, u n operador que toma un argumento u operando) para indicar valores negativos; por ejemplo:

La multiplicaci6n y la division t a m b i h funcionan d e la forma esperada. Tenga e n cuenta que se usa el asterisco como operador d e rnultiplicacion e n lugar d e simbolo habitual d e multiplicaci6n y la barra inclinada como simbolo d e la division. El operador d e modulo devuelve el resto d e la divisi6n d e la variable $ a por la variable Sb. Considere el siguiente fragmento de c6digo:

El valor almacenado e n la variable $ r e s u l t es el resto de dividir 27 por 10, es decir, 7.

Tenga en cuenta que 10s operadores aritmkticos se suelen aplicar a las variables enteras o dobles. Si se aplican a cadenas, PHP intentari convertir la cadena en un numero. Si contiene una "e" o una "EM, la convertiri en una variable doble, de lo contrario la convertiri en un entero. PHP busca numeros a1 principio de la cadena y 10s utiliza como valores (si no hubiera ninguno, el valor de la cadena seria cero).

Operadores de cadena
Ya hemos visto y utilizado el unico operador de cadena. Puede utilizar el operador de concatenaci6n de cadenas para agregar dos cadenas, y que genere y almacene un resultado como hariamos si utiliziramos el operador de suma para sumar dos numeros.
S a = "Bob's " . S b = ' A u t o Parts'; S r e s u l t = Sa.Sb;

La variable $result contendri la cadena "Bob's Auto Parts".

Operadores de asignacion
Ya hemos visto el operador de asignaci6n bisico =. A este operador se hari siempre referencia como operador de asignaci6n y se lee como "establecer en". Por ejemplo:

Esta secuencia se lee como "$totalqty se establece en cero". Ya explicaremos por quk a1 hablar de 10s operadores de comparaci6n en una secci6n posterior.

Devolucicin de valores d@asinnacicin


El uso del operador de asignaci6n devuelve siempre un valor general similar a otros operadores. Si escribe
Sa + Sb

el valor de la expresi6n es el resultado de agregar las variables $a y $b. De manera aniloga, puede escribir:

El valor de toda la expresi6n es cero. Esta secuencia permite realizar operaciones como

Esta secuencia establece el valor de la variable $b en 11.Por regla general, el valor de toda la instrucci6n de asignaci6n es el valor que se asigna en el operando de la izquierda.

Al calcular el valor d e una expresi61-1,se pueden utilizar 10s parentesis para asignar prioridad a una subexpresicin como hemos hecho en el ejemplo. Su funcionamiento es el mismo que en matemziticas.

Ademas de la asignaci6n simple, existe un conjunto d e operadores d e asignaci6n combinados. Se trata de formas abreviadas d e realizar otra operacicin sobre una variable y d e asignarle el resultado. Por ejemplo:

Esta secuencia equivale a escribir:

Existen operadores d e asignacicin combinados para cada uno d e 10s operadores aritm6ticos asi como para el operador d e concatenaci6n d e cadenas. En la tabla 1.2 se recoge un resumen d e todos 10s operadores d e asignaci6n combinados y su efecto.
Tabla 1.2. Operadores de asignacion combinados de PHP

Operador

Equivale a

In( vvnlc-rifu v c ' e t r . c m ~ ~ n yrr-vvio lo ) I po\lcrinr


Los operadores d e incremento (++) y decremento (-) previo y posterior son similares a 10s operadores += y -=, per0 con un par de vnriaciones. Los operadores d e increment0 presentan dos efectos: incrementan un valor y lo asignan. Considere la siguiente secuencia:

La segunda linea utiliza el operador d e incremento previo, denominado asi porque ++ aparece delante d e $ a . Este operador tiene dos efectos: e n primer lugar incrementa $a en una unidad y en segundo lugar devuelve el valor incrementado. En este caso, $a se incrementa en 5 y se devuelve e imprime dicho valor. El resultado d e

Desarrollo W e b con PHP y MySQL

toda la expresi6n es 5. (Fijese en que el valor que se almacena en realidad en $a se ha variado: no estamos devolviendo simplemente $a + 1 .) Sin embargo, si colocamos ++ despues de $a,utilizamos el operador de incremento posterior. Su efecto es diferente a1 anterior. Considere la siguiente secuencia:
$a=4; echo $a++;

En este caso, 10s efectos se invierten. En primer lugar, se devuelve e imprime el valor de $a y en segundo lugar se incrementa. El resultado de toda la expresi6n es 4. gste es el valor que se imprimiri. Sin embargo, el valor de $a tras ejecutar esta instrucci6n seri 5. Como probablemente habri adivinado, el comportamiento es similar para el operador -, con la diferencia de que el valor de $ a se reduce en lugar de incrementarse.

Referencias
Una novedad de PHP 4 es el operador de referencia, & (ampersand), que se utiliza en combinacidn con el operador de asignaci6n. Por regla general, cuando una variable se asigna a otra, se realiza una copia de la primera y se almacena en memoria. Por ejemplo:

Estas lineas de c6digo realizan una segunda copia del valor almacenado en $a y lo guardan en $b.Si cambiamos el valor de $a en un momento posterior, $b no variari:
$a
=

7;

/ / $b s e g u i r 6 s i e n d o 5

Para evitar que se haga l a ~ o p i a y que se guarde en memoria puede utilizar el operador de referencia, &: Por ejemplo:
$a $b
= =

5;
&$a;

$a = 7 ;

/ / $a y $ b s o n a h o r a 7 l a s d o s

Operadores de comparaci6n
Los operadores de comparaci6n se utilizan para comparar dos valores. Las expresiones que utilizan estos operadores devuelven el valor 16gico t r u e o el valor 16gico f a1 s e en funcidn del resultado de la comparaci6n.

El operador iguales
El operador de comparaci6n iguales, == (dos signos iguales), permite determinar si dos valores son iguales. Por ejemplo, podemos utilizar la expresidn

7. Curso acelerndo de PHP

para determinar si 10s valores almacenados en $ a y en $ b son iguales. El resultado devuelto por esta expresicin serS t r u e si son iguales o f a l s e si no lo son. Resulta sencillo confundir este operador con el operador de asignacion (=). Esta confusion no generarci un error per0 impedirA que se obtengan 10s valores deseados. En general, 10s valores distintos a cero se eval6an como t r u e y 10s valores iguales a cero se evaluan como f a l s e . Suponga que hemos inicializado dos variables d e la siguiente forma:

Si prueba $ a = $b, el resultado seri t r u e . iPor q d ? El valor d e $ a = $ b es el valor asignado a la parte izquierda d e la expresion, que en este caso es 7. Se trata d e un valor distinto a cero, por lo que la expresion se eval~ia como t r u e . Si su intencidn es probar $a == $b,que devuelve f a l s e , habrS introducido un error de 16gica en su codigo que puede resultar extremadamente dificil de detectar. Compruebe siempre el uso de estos dos operadores y verifique si ha utilizado el que tenia previsto. Se trata de un error muy sencillo d e cometer y es muy probable que caiga en 61 muchas veces a lo largo de su carrera como programador.

PHP admite otros operadores de comparacicin, que se recogen en la tabla 1.3. Uno de 10s m6s destacados es el nuevo operador de identidad, ===, introducido en PHP, que devuelve t r u e so10 si 10s dos operadores son iguales y del mismo tipo.
Tabla 1.3. Operadores de comparacion de PHP -.- - -... --Nombre Us0

--

,.,

- --

Operador

igual

distinto
c> c

$a != $b $a <> $b $a < $b $a > $b

distinto menor que mayor que menor o igual que mayor o igual que

> <=

$a <= $b
$a >= $b

>=

Los operadores 16gicos se utilizan para combinar 10s resultados de condiciones 16gicas. Por ejemplo, puede que nos interese que el valor de una variable, $ a , se

Desnrrollo W e b con P H P y MySQL

encuentre entre 0 y 100. Para ello tendriamos que probar las condiciones $ a >= 0 y $a <= 100,utilizando el operador AND, como se indica a continuaci6n:

PHP admite el uso de 10s operadores logicos AND, OR, XOR (o exclusivo) y NOT. En la tabla 1.4 se resumen 10s operadores 16gicos y su uso.
Tabla 1.4. Operadores logicos de PHP

Operador

Nombre NOT AND

Us0 !$b $a && $b $a

Resultado Devuelve t r u e si Sb es f a l s e y viceversa Devuelve t r u e si $ a y Sb son t r u e ; de lo contrario devuelve f a l s e Devuelve t r u e si $ a o $ b o ambas son t r u e ; de lo contrario devuelve f a l s e lgual que baja
&&,

II
and or

OR

11 $b

AND
OR

$a and $b $a or $b

per0 con prioridad mas

lgual que I I , per0 con prioridad mas baja

Los operadores a n d y o r tienen una prioridad inferior a la de 10s operadores L L y I I . En una secci6n posterior se analizar6 el terna de la prioridad.

Operadores bit a

bit

Los operadores bit a bit permiten tratar un entero corno una serie de bits utilizados para representarlos. Estos operadores no se utilizan dernasiado en PHP. En la tabla 1.5 se recoge un resurnen de 10s operadores bit a bit.
Tabla 1.5. Operadores bit a bit de PHP

-- ---. Operador

-.

- -- Nombre

Uso

--

- - -. . Resultado

AND bit a bit

$a & $b $a I $b -$a

Los bits asignados en $ a y $ b se establecen en el resultado Los bits asignados en $ a o $ b se establecen en el resultado Los bits asignados en $ a no se establecen en el resultado y viceversa

OR bit a bit NOT bit a bit

I . Curso ncclr~rndodc PHP

Operador
A

Us0 $a

Resultado $b

- -

Nombre XOR bit a bit desplazamiento a la izquierda desplazamiento a la derecha

Los bits asignados en $ a o $ b per0 no en ambos se establecen en el resultado Mueve $ a a la izquierda en funcion de 10s bits de $ b Mueve $ a a la derecha en funcion de 10s bits de $ b

<< >>

$a << $ b $a >> $ b

A d e m i s d e 10s operadores vistos hasta ahora, existen otros. El operador coma, ,, se utiliza para separar argumentos d e funci6n y otros elementos d e lista. Se suele utilizar d e manera ocasional. Los operadores new y - > se utilizan para instanciar una clase y para acceder a 10s miembros d e clase, respectivamente. Estos operadores se analizarin detalladamente e n u n capitulo posterior. Los operadores d e elementos d e matrices, [ 1 , se utilizan para acceder a elementos d e matrices. Tambien utilizaremos el operador => en algunos contextos d e matrices. ~ s t o se s analizarin e n u n capitulo posterior. Existen otros tres operadores q u e se examinan brevemente a continuacion.

Este operador, ? :, funciona d e la misma forma q u e en C. Adopta la siguiente forma:

El operador ternario es similar a la version d e la expresi6n d e una instruccion


i f - e l s e , q u e se analizari m i s adelante en este capitulo.

Vemos un sencillo ejemplo:

Esta expresi6n evalua la nota del estudiante como 'Aprobado' o 'Suspenso'.

Operador d e qupresi5n dc t r r o r El operador d e supresion d e error, @, se puede utilizar por delante d e cualquier expresion, es decir, d e todos aquellos elementos q u e generen o tengan un valor. Por ejemplo: Sin el operador @, esta linea generari un aviso d e division por cero (intentelo). Si se incluye el operador, se suprimiri el error.

Desarrollo W e b con PHP y MySQL

Si tiene previsto suprimir advertencias de esta forma, deberia escribir c6digo de control de errores que compruebe curindo tiene lugar una advertencia. Si ha configurado PHP con la funci6n t r a c k e r r o r s activada, el mensaje de error se alrnacenarri en la variable global S p h p-e r r o r r n s g .

Operador de ejecucion
En realidad el operador de ejecuci6n estri formado por un par de operadores: dos acentos graves ("). Este simbolo es diferente a la comilla simple (en el teclado se sit6a en la tecla con el simbolo de dieresis). PHP intentarri ejecutar todo lo que se incluya entre estos simbolos como un comando en la linea de comandos del servidor. El valor de la expresi6n es el resultado del comando. Por ejemplo, en sistemas operativos del tipo UNIX, puede utilizar:
$out echo
=

'1s -la'; '<pre>'.$out.'</pre>';

0 el equivalente en un servidor Windows:


$out = 'dir c:'; echo 'cpre>'.Sout.'</pre>';

Cualquiera de estas versiones devolverri un listado de directorio y lo almacenarri en $ o u t . A continuaci6n se puede imprimir en el navegador o manipular de otra forma. Existen otras formas de ejecutar comandos en el servidor, como veremos en un capitulo posterior.

Uso de operadores: calcular 10s totales de 10s formularios


Ahora que ya sabemos c6mo utilizar operadores de PHP, podemos calcular 10s totales y 10s impuestos en el formulario de pedido de Bob. Para ello agregue el siguiente c6digo a1 final de la secuencia de comandos de PHP:
Stotalqty = 0; Stotalqty = Stireqty + Soilqty + Ssparkqty; echo 'Items ordered: '.$totalqty.'<br / > I ; Stotalamount
=

0.00;

define('TIREPRICE', 100); define( 'OILPRICE', 10); define ( 'SPARKPRICE', 4 ) ; Stotalamount


=

Stireqty

TIREPRICE

Si actualiza la pigina en la ventana del navegador, veri un resultado similar a1 ilustrado en la figura 1.5.

Bob's Auto Parts


Order Results
Order processed at 07:47, 10th April Your order is as follows: 1 tires I bottles of oil I spark plugs Items ordered: 3 Subtotal: $114.00 Total including tw: $125.40

Figura 1.5. Se han calculado 12s totales del pedido de clientes, se les ha aplicado

forrnato y s e ha rnostrado Como puede observar, en esta secuencia de codigo hemos utilizado varios operadores. El operador de suma (+) y de multiplicacion (*) se encargan de calcular las cantidades y el operador de concatenation (.) establece el resultado en el navegador. T a m b i h hemos utilizado la funci6n number f o r m a t ( ) para aplicar formato a 10s totales como cadenas con dos decimales. Se trata de una funci6n de la biblioteca de matemsticas de PHP. Si se detiene a examinar 10s cdculos, es posible que se pregunte por qu6 se realizaron en ese orden. Por ejemplo, considere esta instruction:

La cantidad total parece correcta, per0 ipor qu6 realizar las multiplicaciones antes que las sumas? La respuesta reside en la precedencia de 10s operadores, es decir, en el orden en el que se calculan.

Desarrollo Web con P H P y M!ySQL

Precedencia cxpresiones

y asociatividad: evaluation de

Por regla general, 10s operadores se evaluan siguiendo una precedencia ti orden d e prioridad fijado. Los operadores llevan asignada una asociatividad, que es el orden en el que se evaluan 10s operadores con el mismo orden d e prioridad. Suele ser de izquierda a derecha (o izquierda simplemente), de derecha a izquierda (o derecha simplemente) o no resulta relevante. En la tabla 1.6 se recoge la precedencia d e operadores y la asociatividad en PHP. En esta tabla, se incluyen 10s operadores d e prioridad m6s baja en la parte superior y la precedencia va aumentado seg6n se desciende por ella.
Tabla 1.6. Precedencia de operadores en PHP

Asociatividad izquierda izquierda izquierda izquierda derecha izquierda izquierda izquierda izquierda izquierda izquierda izquierda nla izquierda izquierda izquierda derecha derecha

Operadores

or xor and print

< <= > >= << >>

+-.

*I%
-!

- ++ - (entero) (doble) (cadena) (matriz) (objeto) @


1

n la

new

1 . Curso acelerado de P H P

Fijese en que el operador con mayor prioridad no se ha analizado todavia: 10s parhtesis. El efecto de 10s parentesis consiste en incrementar la prioridad de todos 10s elementos incluidos en su interior. Esto simbolos permiten alterar las reglas de prioridad cuando resulte necesario. Recuerde la siguiente seccibn del 6ltimo ejemplo:
Stotalamount
=

Stotalamount

(1

Staxrate);

Si hubieramos escrito
Stotalamount
=

Stotalamount

Staxrate;

el operador de multiplicaci6n, que tiene precedencia sobre el operador de suma, se aplicaria en primer lugar, lo que nos daria un resultado incorrecto. El uso de 10s parentesis permite forzar el calculo de la subexpres i o n 1 + $ taxra te en primer lugar. Puede utilizar tantos parentesis como desee en una expresibn. En primer lugar se calcular6n 10s mas internos.

Funciones de variables
Antes de abandonar el mundo de las variables y de 10s operadores, vamos a examinar las funciones de variables de PHP. Se trata de una biblioteca de funciones que permite manipular y probar variables de distintas formas.

Como probar y establecer tipos de variables


La mayor parte de estas-fundones se utilizan para probar el tip0 de una variable. Las dos mas generales son gett ype ( ) y settype ( ) . Estas tienen 10s siguientes prototipos de funciones; es decir, lo que esperan 10s argumentos y lo que devuelven.
string gettypeimixed var); boo1 settype (mixed var, string type);

Para utilizar gett ype ( ) , la pasamos en una variable. Determinara su tipo y devolvera una cadena que contenga el tip0 de nombre o "tipo desconocido" si no es uno de 10s tipos estandar, es decir, entero, doble, cadena, matriz u objeto. Para utilizar sett ype ( ) , le pasamos una variable cuyo tip0 deseemos modificar y una cadena que contenga un nuevo tip0 para dicha variable a partir de la lista anterior. Podemos utilizarla de la siguiente forma:
$a = 56; echo gettype($a).'<br / > I ; settype($a, 'double'); echo gettype($a).'<br / > I ;

Desarrollo Web con PHP y MySQL

Cuando se llama a g e t t y p e ( ) por primera vez, $ a es de tip0 entero. Tras llamar a s e t t y p e ( ) , el tip0 se convierte en doble. PHP tambien incorpora funciones para probar tipos. Cada una de estas toma s e . Las funciones son: una variable como argument0 y devuelve t r u e o f a 1 is-array() is-double(), is-float(), is-real() (Toda la misma funci6n) is-long(), is-into, is-integer() (Toda la misma funci6n)

Como probar el estado de las variables


PHP dispone de varias formas de probar el estado de una variable. La primera de estas formas es i s s e t ( ) , que consta del siguiente prototipo:
boo1 isset(rnixed var);

Esta funci6n toma el nombre de una variable y devuelve t r u e si existe y f a 1 s e en caso contrario. Puede eliminar una variable utilizando u n s e t ( ) . Este es su prototipo:
void unsetirnixed var);

Esta funci6n suprime la variable si se pasa y devuelve t r u e . Por ultimo, tenemos la funci6n e m p t y ( ) . Esta funci6n comprueba si existe una variable y si contiene un valor no vacio o distinto a cero y devuelve t r u e o f a l s e segun el caso. Su sintaxis es lasiguiente:
boolean emptyimixed var);

Vamos a examinar un ejemplo del uso de estas funciones. Intente agregar el siguiente cddigo a su secuencia de comandos temporalmente:
echo echo echo echo isset($tireqty); issetisnothere); empty($tireqty); ernpty($nothere);

Actualice la pigina para ver 10s resultados. La variable $ t i r e q t y deberia devolver t r u e de i s s e t ( ) con independencia del valor introducido o de si se introdujo algun valor en el campo del formulario. Que sea e m p t y ( ) o no depende del valor introducido. La variable $ n o t h e r e no existe, por lo que generard f a l s e desde i s s e t ( ) y t r u e desdeempty ( ) . Estas funciones pueden resultar utiles para asegurarnos de que el usuario rellen6 10s campos apropiados del formulario.

1 . Curso acelerado de PHP

Reinterpretacion de variables
Puede lograr el equivalente de convertir una variable llamando a una funcibn. En este sentido, existen tres funciones utiles:
int intval(mixed var); float doubleval(mixed var); string strvalimixed var);

Cada una de &as acepta una variable como entrada y devuelve el valor de la variable convertida en el tip0 apropiado. En este libro, y en la documentaci6n de php.net, se utiliza el tip0 de datos mixed. Este tip0 de datos no existe, per0 como PHP es tan flexible en materia de procesamiento de tipos, gran parte de las funciones pueden tomar muchos (o todos) 10s tipos de datos como argumento. Para identificar 10s argumentos en 10s que se permiten utilizar muchos tipos se utiliza mixed.

Estructuras de control
Las estructuras de control de un lenguaje permiten controlar el flujo de la ejecuci6n de un programa o secuencia de comandos. Las estructuras de control se pueden agrupar en estructuras condicionales (o de bifurcaci6n) y en estructuras de repeticibn, o bucles. En las siguientes secciones se examinarhn las implementaciones especificas de cada una de ellas en PHP.

Toma de decisiones'con estructuras condicionales


Si deseamos responder 16gicamente a las entradas de nuestros usuarios, nuestro c6digo debe ser capaz de tomar decisiones. Esta funci6n recae sobre las estructuras condicionales.

Las instrucciones if
Podemos utilizar una instrucci6n if para tomar una decisi6n. Debemos darle una condici6n a la instrucci6n if para que la utilice. Si la condicidn fuera t r u e , se ejecutar6 el siguiente bloque de c6digo. Las condiciones de las instrucciones if deben ir incluidas entre parhtesis. Por ejemplo, si mandamos un pedido en el que no se incluyan neumriticos, latas de aceite ni bujias en el sitio de Bob, probablemente se deber6 a que se ha pulsado accidentalmente el b o t h Submit En lugar de indicarnos "Order processed", la pigina podria devolver un mensaje mucho m6s util.

Desnrrollo Web con P H P y MySQL

Cuando el visitante realiza un pedido sin n i n g h articulo, podriamos indic5rselo. Para ello podemos utilizar la siguiente instrucci6n i f :

La condici6n que estamos utilizando es S t o t a l q t y == 0. Recuerde que el operador iguales (==) se comporta d e manera distinta a1 operador d e asignacion (=). L a c o n d i c i 6 n $ t o t a l q t y == 0 ser6 trueporloque$totalqtyesigualacero. Si $ t o t a l q t y no es igual a cero, la condici6n s e r i fa 1 s e . Cuando la condici6n sea t r u e , la instruccidn e c h o se ejecutari.

A menudo necesitaremos ejecutar m5s d e una instrucci6n dentro de una secuencia condicional como i f . No es necesario colocar una nueva instrucci6n i f para cada una de ellas. En su lugar, podemos agrupar un nGmero de instrucciones en un bloque. Para declarar un bloque, encigrrelo entre llaves:
if4

Stotalqry

==

i
echo ' < f o n t c o l o r = r e d > '; echcs 'You rlisl n n t o r d e r ; i n y t h i r l q echc~ f,)nt.>' ;
'%'/

t h e previous p a g e ! ' k : r

/:.I;

Las tres lineas d e c6digo encerradas entre llaves forman ahora un bloque d e codigo. Si la condici6n es t r u e , se ejecutar5n las tres lineas. Si la condici6n es f a l s e , se ignorarin las tres lineas.

Como se menciono anteriormente, en PHP no es importante la disposicion del codigo. Sin embargo, conviene sangrarlo por cuestiones de legibilidad. Las sangrias nos permiten distinguirde un vistazo que lineasse ejecutaran solo si se cumplen una condicion, que instruccionesse agrupan en bloques yque instrucciones forman parte de bucles o funciones. En 10s ejemplos anteriores, se ha sangrado la instruccion que depende de la instruccionif y las instruccionesque forman el bloque.

lnstrucciones else
Con frecuencia no s610 querra decidir si desea que se ejecute una acci6n sin0 seleccionar una entre un conjunto d e ellas. Las instrucciones e l s e permiten establecer la adopci6n de una accion alternativa cuando la condicidn de una instrucci6n i f resulte f a l s e . Queren~os avisar a 10s

1. Curso acelerado de PHP

clientes de Bob si envian una pedido sin ningtin articulo. Por otra parte, si realizan un pedido, en lugar de una advertencia, queremos mostrarles lo que han pedido. Si reorganizamos nuestro c6digo y agregamos una instrucci6n e l s e , podemos mostrar un aviso o un resumen de 10s articulos solicitados.
if ( Stotalqty
==

I
e c h o 'You d i d n o t o r d e r a n y t h i n g o n t h e p r e v i o u s p a g e ! < b r
/ > I ;

I
else

I
echo S t i r e q t y . ' t i r e s < b r / > I ; echo S o i l q t y . ' b o t t l e s of o i l < b r / > I ; echo S s p a r k q t y . ' s p a r k plugs<br / > I ;

Podemos desarrollar procesos 16gicos mds complejos anidando instrucciones


i f . En el siguiente c6dig0, no s610 se mostrard el resumen si la condici6n $ t o t a l q t y
== 0 resulta ser cierta, sin0 que ademds cada linea del resumen s610 se mostrar6 si se cumple su propia condici6n.
i f ( Stotalqty
==

0)
/ > I ;

i
e c h o 'You d i d n o t o r d e r a n y t h i n g on t h e p r e v i o u s p a g e ! < b r t else

i
if
( $tireqty>O ) echo S t i r e q t y . ' t i r e s < b r / > I ; i f ( $oilqty>O ) echo S o i l q t y . ' b o t t l e s of o i l < b r i f ( Ssparkqty>O ) echo S s p a r k q t y . ' s p a r k p l u g s < b r /

/ > I ;

> I ;

lnstrucciones elseif
Para muchas de las decisiones que tomamos suele haber mds de dos opciones. Podemos crear una secuencia de varias opciones utilizando la instrucci6n e 1s e i f . Esta instrucci6n es una combinaci6n de e l s e e i f . A1 suministrar una secuencia de condiciones, el programa puede comprobar cada una de ellas hasta que encuentre una que sea t r u e . Bob ofrece un descuento por grandes pedidos de neum6ticos. La oferta se articula de la siguiente forma: Menos de 10 neumdticos, sin descuento De 10 a 49,5% de descuento De 50 a 99,10% de descuento 100 o mds de 100,15% de descuento

Desarrollo W e b con PHP y MySQL

Podemos crear cddigo para calcular el descuento utilizando condiciones e instrucciones i f y e 1 s e i f . Necesitamos utilizar el operador AND ( & &) para combinar las dos instrucciones en una.
S t i r e q t y < 10 $ d i s c o u n t = 0; e l s e i f ( S t i r e q t y >= $ d i s c o u n t = 5; e l s e i f ( S t i r e q t y >= $discount = 10; e l s e i f ( S t i r e q t y >= $discount = 15; i f (

i
1 0 & & S t i r e q t y <= 4 9 ) 5 0 & & S t i r e q t y <= 9 9 ) 100 )

Fijese en que da lo mismo escribir e l s e i f o e l s e i f, ya que ambas son correctas. Si va a escribir un conjunto de instrucciones i f en cascada, deberia se consciente de que s610 se ejecutarfi uno de 10s bloques o instrucciones. En este ejemplo no importa porque todas las condiciones son mutuamente excluyentes, s610 una puede ser verdadera a la vez. Si escribi6ramos las condiciones de forma que mfis de una pueda ser verdadera, s610 se ejecutaria el bloque o instruccidn situada a continuacidn de la primera condicidn cierta.

Instruccion switch
La instruccidn s w i t c h funciona de una forma similar a la instrucci6n i f , per0 permite que la condicidn tome mfis de dos valores. En una instruccidn i f , la condicidn puede ser t r u e o f a l s e . En una instruccidn s w i t c h , la condicidn puede tomar cualquier n6mero de valores diferentes, siempre y cuando se eval6e en un tip0 6nico (entero, cadena o doble). Es necesario incluir una instruccidn c a s e para cada valor a1 que desee reaccionar y, opcionalmente, una instruccidn c a s e predeterminada para procesar aquellos valores para 10s que no se hayan incluido una instruccidn c a s e especifica. Bob quiere saber qu6 tip0 de publicidad atrae visitantes a su sitio. Para ello podemos agregar una pregunta a nuestro formulario de pedidos. Inserte el siguiente cddigo HTML dentro del formulario de pedidos y el formulario presentarfi un aspect0 parecido a1 ilustrado en la figura 1.6.

<tr> <td>How d i d you f i n d B o b l s < / t d > < t d > < s e l e c t name="findM> <option value = "a">I1m a r e g u l a r customer < o p t i o n v a l u e = "bM.>TV a d v e r t i s i n g < o p t i o n v a l u e = " c M > P h o n ed i r e c t o r y < o p t i o n v a l u e = " d M > W o r d o f mouth </select> </ t d > </tr>

I . Curso ncelerndo de P H P

k c h m Edlabn Ver Fmntos Henam~entas Ayuda


Dtrembn

I& hnp Ilwebserverlcheplerl lordedorm2 hlml

Bob's Auto Parts


Order Form
Item
Tires

Quantity

oil
Spark Plugs

r r r

How did you find Bob's Il'rn a regular customer3


Phone directory

Figura 1.6. El formulario de pedidos pregunta a 10s visitantes como encontraron el sitio Bob's Auto Parts

Este c6digo d e HTML agrega una nueva variable de formulario cuyo valor ser6
"a", "b", " c " , o " d " . Podriamos procesar esta nueva variable con una serie d e instrucciones i f y e l s e i f como la siguiente:

Como alternativa podriamos utilizar una instrucci6n switch:

Desarrollo Web corl P H P y MySQL

La instruccion s w i t c h se cornporta d e una forma ligeramente diferente a una instrucci6n i f o e l s e i f.Una instruccion i f afecta s610 a una instruccidn a menos clue se utilicen llaves de manera deliberada para crear bloques d e instrucciones. Una instruccion s w i t c h se cornporta d e fornia contraria. Cuando se activa un caso en una instruccion s w i t c h , PHP ejecutara las instrucciones hasta que alcance una instrucci6n b r e a k . Sin una instrucci6n b r e a k, la instrucci6n s w i t c h ejecutaria todo el ccidigo situad o detris del caso que resultara ser cierto. A1 alcanzar la instrucci6n b r e a k, se ejecutara la linea de c6digo situada tras la instruccion s w i t c h .

Si no estci familiarizado con estas instrucciones, es probable que se este preguntando c u d es la mejor. Sin embargo, no podemos d a r una respuesta exacta a esta pregunta. No hay nada que pueda hacer con una o varias instrucciones e l s e , e l s e i f o s w i t c h que no puede hacerse con un conjunto de instrucciones i f . Deberia intentar utilizar aquella opci6n que le resulte m i s sencilla de leer Con el tiempo ir6 aprendiendo a seleccionar una u otra.

'teraci6n: rcpctici6n d e acciones


Una de las cosas para las que 10s ordenadores han demostrado siempre ser buenos es automatizar tareas repetitivas. Si hay algo que necesite hacer d e la misma forma una serie d e veces, puede utilizar un bucle para repetir partes d e un programa. Bob quiere una tabla que muestre el coste d e envio en funcion d e la distancia a la que se estA enviando el pPtquefe. El coste se puede calcular con una sencilla f6rmula. Queremos clue la tabla d e costes d e envio se parezca a la ilustrada en la figura 1.7.

Distance Cost

Figura 1.7. Esta tabla muestra el coste de envio en funcion de la distancia

1. Curso acelerado de PHP

El listado 1.2 incluye el c6digo HTML utilizado para mostrar esta tabla. Como observarfi, el c6digo es largo y repetitivo.
Listado 1.2.freight.htrnl: la tabla de costes de envio de Bob

Convendria delegar en un ordenador barato e incansable la tarea de escribir este c6digo de HTML en lugar de recurrir a un humano que se aburriria con facilidad (y a1 que habria que pagar). Las instrucciones de bucle hacen que PHP ejecute una instrucci6n o un bloque de manera repetida.

Bucles while
El tip0 de bucle mfis sencillo en PHP es el bucle w h i l e . Como en el caso de las instrucciones i f , se basan en una condici6n. La diferencia entre un bucle w h i l e y una instrucci6n i f es que &ta ejecuta el siguiente bloque de c6digo si la condici6n resulta ser t r u e . Un bucle w h i l e ejecuta el bloque repetidamente mientras la condici6n sea t r u e . Los bucles w h i l e se utilizan cuando no se sabe cufintas iteraciones resultarfin necesarias para que la condici6n resulte cierta. Si el nfimero de iteraciones debe ser fijo, considere la posibilidad de utilizar el bucle f o r .

Desarrollo Web con PHP y MySQL

La estructura b6sica de un bucle while es la siguiente:

El siguiente bucle mostrar6 10s n6meros d e l l a1 5.


Snum = 1; while (Snum <= 5
(
)

echo Snum."<br / > " ; Snurntt;

A1 principio de cada operacibn, se prueba la condicibn. Si es falsa, el bloque no se ejecuta y el bucle finaliza. A continuacibn, se ejecutar6 la instruccibn situada por detr6s del bucle. Podemos utilizar un bucle while para realizar algo m6s 6til como mostrar la tabla de costes de envio repetitivos de la figura 1.7. El listado 1.3 utiliza un bucle while para generar la tabla de gastos de envio.
Listado 1.3. freightphp. Generacion de la tabla de gastos de envio de Bob en PHP
<body> <table border="On cellpadding="3"> <tr> <td bgcolor="#CCCCCC" align="center">Distance</td> <t3 bgcolor="#CCCCCC" align="center">Cost</td> </tr>
<?

Sdistance = 50; while ($distance <=

echo "<tr>\n <td echo " <td align="rightW>". Sdistance / 1 0 ."</td>\n</tr>\nW; $distance t= 50;

align"="right">$distance</td>\n";

250

Para que el cbdigo HTML generado por nuestra secuencia de comandos resulte legible, debe incluir nuevas lineas y espacios. Como se indicb anteriormente, 10s navegadores ignoran estos elementos per0 resultan importantes para facilitar la lectura de 10s humanos. Con frecuencia necesitari examinar el c6digo HMTL si el resultado obtenido no es el esperado. En el listado 1.3 ver6 que algunas cadenas incluyen 10s caracteres \ n . Si se incluye dentro de una cadena encerrada entre comillas dobles, representa un car6cter de nueva linea.

1. Curso acelerado de PHP

10s bucles for y foreach


La forma en la que utilizamos 10s bucles while anteriormente resulta muy comun. En primer lugar establecimos u n contador. Antes de cada interaccidn, probamos el contador en una condicidn. A1 final de cada iteracidn, modificamos el contador. Podemos escribir este estilo de bucle de forma mds compacta utilizando un bucle for. La estructura bdsica de 10s contadores for es la siguiente:
for( expresihnl; expresi6n3; condicihn; expresi6n2)

La expresidnl se ejecuta una vez a1 principio. En este pardmetro se suele establecer el valor inicial de un contador. La condicidn se prueba antes de cada iteracidn. Si la expresidn devuelve fa1s e, la iteracidn se detendrd. En este pardmetro se suele probar el contador con respecto a un limite. La expresidn2 se ejecuta a1 final de cada iteracidn. En este pardmetro se suele ajustar el valor del contador. La expresidn3 se ejecuta una vez por iteracidn. Esta expresidn suele ser un bloque de cddigo y contendrd el grueso del cddigo de bucle. Podemos rescribir el ejemplo del bucle whi 1e del listado 1.3como un bucle for. El cddigo PHP se convertird en
<?

for(Sdistar1ce

50;

$distance

<-

250;

$distance

+=

50)

i
echo "<tr>\n <td a l i q m = ' r i g h t ' > $ d i s t a n c e < / t d > \ n " ; echo " <td align='rightl>". $distance / 1 0 ."</td>\r,</tr>\nm;

I
?>

Tanto la versidn while como la versidn for funcionan de manera idhtica. El bucle for resulta un poco mds compacto y ahorra dos lineas. Ambos tipos de bucles son equivalentes. Ninguno de 10s dos es mejor o peor que el otro. En una situacidn dada, puede utilizar el que le resulte mds intuitivo. Como comentario a1 margen, hay que decir que se puede combinar una variable de tip0 variable con un bucle for para procesar una iteracidn a travds de una serie de campos de formulario repetitivos. Si, por ejemplo, tiene campos de formulario con nombres como name 1,nam2,name3,etc. puede procesarlos de la siguiente forma:
for (Si=l; Si

<=

Snumnames;

$i++)

i
temp= "name$iN; cho $$temp.'<br
/ > I ;

/ / o cualquier procesamiento que desee realizar

Desarrollo W e b con PHP y MySQL

A1 crear didmicamente 10s nombres de las variables, podemos acceder a cada campo uno por uno. Adem6s del bucle f o r existe el bucle f o r e a ch, disefiado especificamente para su uso con matrices. En un capitulo posterior comentaremos c6mo utilizarlo.

Bucles d o while
El tip0 final de bucle que mencionaremos se comporta de mod0 ligeramente diferente. La estructura general de una instrucci6n do. . w h i l e es la siguiente:

...

Un bucle d o . .w h i l e se diferencia de un bucle w h i l e en que la condici6n se prueba a1 final. Por lo tanto en un bucle do. . w h i l e , la instrucci6n o el bloque incluido en el bucle se ejecuta siempre una vez a1 menos. Incluso si tomamos un ejemplo en el que la condicidn ser6 f a 1 s e a1 principio y nunca puede ser t r u e , el bucle se ejecutar6 una vez antes de comprobar la condici6n y el final.

Snum d0
(

100;

echo $num.'<br
I

/ > I ;

while

(Snum < 1

i;

Como salir de- una estructura de control o una secuencia de comandos


Si desea detener la ejecuci6n de un fragment0 de c6dig0, existen tres opciones que dependen del efecto que est6 persiguiendo. Si desea detener la ejecucidn de un bucle, puede utilizar la instrucci6n b r e a k como se coment6 anteriormente en la seccion sobre s w i t c h . Si utiliza esta instrucci6n en un bucle, la ejecucidn de la secuencia de comandos continuard en la linea situada tras el bucle. Si desea saltar hasta la siguiente iteraci6n de bucle, puede utilizar la instrucci6n continue. Si desea terminar de ejecutar la secuencia de comandos PHP entera, puede utilizar la instrucci6n e x i t . Esta opci6n resulta util a1 realizar tareas de comprobaci6n de errores. Por ejemplo, podemos modificar nuestro ejemplo anterior de la siguiente forma:

1. Curso acelerado de P H P

I
e c h o 'You exit; did not order anything on the previous page!<br
/ > I ;

La llamada a exit impide que PHP ejecute el resto de la secuencia de comandos.

Siguiente paso: guardar el pedido del cliente


Ahora ya sabe c6mo recibir y manipular pedidos de un cliente. En el siguiente capitulo examinaremos c6mo almacenar el pedido para poder recuperarlo y servirlo.

Ahora que ya sabemos cdmo acceder y manipular datos introducidos en un formulario HTML, podemos pasar a examinar variar formas de almacenar dicha informacidn para su uso posterior. En la mayor parte de 10s casos, incluido el ejemplo examinado en el capitulo anterior, querri almacenar 10s datos y cargarlos en un momento posterior. En nuestro caso, necesitamos escribir pedidos de cliente para almacenarlos y poder servirlos despuds. En este capitulo vamos a expkcar cdmo podemos escribir el pedido del cliente del ejemplo anterior en un archivo y cdmo volverlo a leer. Tambikn veremos por qud esta solucidn no es siempre la mejor. Si tenemos un gran numero de pedidos, deberiamos utilizar un sistema de administracidn de base de datos como MySQL. Entre 10s temas clave que trataremos en este capitulo se incluyen 10s siguientes: Cdmo guardar datos para su uso posterior Cdmo abrir un archivo C6mo crear y escribir en un archivo Cdmo cerrar un archivo Lectura de un archivo Bloqueo de un archivo Eliminacidn de archivos Otras funciones utiles con archivos

2. Almacerrnrrlierrto

!j

rec~~yerncio de r ~datos

Una opci6n inejor: 10s sistemas de administraci6n de bases de datos Lecturas adicionales

Bdsicamente existen dos formas d e almacenar datos: en archivos planos o e n una base d e datos. Los archivos planos pueden tener multiples formatos pero, e n general, cuando hacemos referencia a un archivo plano, nos estamos refiriendo a un archivo simple d e texto. En este ejemplo, vamos a escribir 10s pedidos d e 10s clientes en un archivo d e texto, uno en cad a 1'inea. Este rn4todo es muy sencillo, per0 resulta a la vez muy restrictivo, como veremos en una secci6n posterior. Si esta tratando con informacion de un volumen significative es probable que prefiera utilizar una base d e datos. Sin embargo, 10s archivos planos se utilizan en determinadas ocasiones y hay situaciones en las que necesitara saber c6mo hacerlo. Las operaciones d e lectura y escritura d e archivos en PHP se realizan priicticamente d e la misma forma que e n C. Si ha programado alguna vez en C o ha desarrollado secuencias d e comandos d e nucleo para sistemas UNIX, la mecinica le resultara bastante familiar.

En este capitulo, utilizaremo? una versi6n modificada del formulario d e pedido visto en el 6ltimo capitulo: Comenzaremos por este formulario y por el c6digo d e PHP que escribimos para procesar 10s datos del pedido.
I

Nota
Las secuenciasde comandosde HTMLy de PHP que se utilizan en este capitulo se pueden encontrar en la carpeta correspondiente del CD-ROM.

Hemos modificado el formulario para incluir un metodo rapido para obtener la direccion d e envio del cliente. En la figura 2.1 se ilustra s u aspecto. El campo del formulario en el que se recoge la direccion d e envio del cliente se denomina address.Este campo nos da una variable a la que podemos acceder como $address a1 procesar el formulario e n PHP, si hemos activado el parimetro register-globals o como $ -POST [ 'address ' ] o $ GET [ 'address ' ] si el parametro register-globals n o est6 activado (consu~te el capitulo 1 si desea obtener mAs detalles).

Dcsnrrollo Wch con P H P y MySQL

1 Order Form
Item
Tires

I
Quantity

oil
Spark Plugs

l i -

1 6

Sllipp~ng Address 11 Smith Strecl. Nowlieresv~lle

Figura 2.1. Esta version del pedido obtiene la direccion de envio del cliente

Escribiremos cada pedido que entre en el mismo archivo. Seguidamente, construiremos una interfaz Web para permitir que la plantilla d e Bob pueda ver 10s pedidos que entran.

Introducci~n al procesamiento c'e arcliivos


La operaci6n d e escribir datos en u n archivo incluye 10s siguientes pasos:

1. Abrir el archivo. Siel a r h i v o no existiese, tendriamos que crearlo.


2. Escribir 10s datos en el archivo.

3. Cerrar el archivo.
La operation d e lectura d e 10s d a t o s d e u n archivo t a m b i h incluye d e tres pasos:

1. Abrir el archivo. Si no se puede abrir (por ejemplo, si no existiese), tendriamos que reorganizar el proceso y salir con elegancia. 2. Leer 10s datos del archivo.

3. Cerrar el archivo.
Cuando queremos leer 10sdatos d e u n archivo, podemos determinar qu6 cantidad d e elementos del archivo leer cada vez. En una secci6n posterior examinaremos dichas opciones. En primer lugar vamos a comenzar por abrir un archivo.

2. Almacenamiento y recuperacidn de datos

Como abrir un archivo


Para abrir un archivo en PHP, se utiliza la funci6n f open ( ) . A1 abrir un archivo, tenemos que especificar para qud tenemos pensado utilizarlo. Es lo que se conoce como 10s modos de archivo.

Modos de archivo
El sistema operativo del servidor necesita saber qud queremos hacer con el archivo que vamos a abrir. Necesitamos saber si otra secuencia de comandos puede abrir el archivo que ya tenemos abierto y determinar si el titular de la secuencia de comandos dispone de permiso para utilizarlo de esa forma. Bfisicamente, 10s modos de archivo ofrecen a1 sistema operativo un mecanismo para determinar la forma de procesar las peticiones de acceso procedentes de otras personas o secuencias de comandos, y un mdtodo para comprobar si dispone de acceso y permiso para utilizar el archivo. A1 abrir un archivo dispone de tres opciones:
1. Puede abrir un archivo para leerlo para escribir en dl o para ambas acciones. 2. Si estfi escribiendo en un archivo, puede sobrescribir 10s contenidos existentes o adjuntar nuevos datos a1 final del archivo.

3. Si est6 intentando escribir en un archivo sobre un sistema operativo que diferencie entre archivos binarios y archivos de texto, puede que desee especificar esta circunstancia.
La funci6n f open ( ) admite combinar estas tres opciones.

Uso de fopen() para abrir un archivo


Supongamos que desea escribir el pedido de un cliente en el archivo de pedidos de Bob. Puede abrir el archivo para escribir el pedido con siguiente secuencia:

A1 llamar a f open, se esperan dos o tres parfimetros. Por regla general se utilizarfin dos, como se muestra en la linea de c6digo. El primer0 deberia ser el archivo que queremos abrir. Puede especificar una ruta hasta este archivo como hemos hecho en el c6digo anterior; nuestro archivo o r d e r s . t x t se encuentra dentro del directorio de pedidos. Hemos utilizado la variable incorporada SHTTP SERVER VARS [ ' DOCUMENT ROOT ' 1 pero, como ocurre con 10s inc6modos nombre; comple<os de las variables de formulario, le hemos asignado un nombre mfis corto. Esta variable apunta a la base del firbol de documentos de su servidor Web. Hemos utilizado " " para indicar "el directorio superior del directorio raiz del documento".

..

Desnrrollo W e b con PHP y MySQL

Este directorio se encuentra fuera del arb01 de directorios, por razones de seguridad. No queremos que este archivo resulte accesible desde la Web salvo a trav6s de una interfaz que proporcionaremos nosotros. Esta ruta se conoce como ruta relativa ya que describe una posici6n en el sistema de archivos en relaci6n a1 directorio del documento. Como ocurre con 10s nombres cortos que asignamos a las variables de formulario, si no activamos el padmetro register global s, necesitamos incluir la siguiente linea a1 principio de la secuencia de comandos:

para copiar 10s contenidos de la variable de estilo largo a la variable de estilo corto. A1 igual que existen varias formas de acceder a 10s datos de formulario, existen varias formas de acceder a las variables de servidor predefinidas. En funci6n de la configuraci6n del servidor puede acceder a la raiz del documento a traves de:

Como en el caso de 10s datos de formulario, el primer estilo, que hemos llamado estilo corto, est6 disponible autom6ticamente si ha activado el partimetro register globals. El segundo estilo (el estilo intermedio) no se puede desactivar, pero s610 ;st6 disponible en PHP 4.1 y versiones posteriores. El estilo largo est6 disponible para todos 10s sistemas, pero se considera obsoleto por lo que es posible que desaparezca en un futuro. T a m b i h se especifica una ruta absoluta a1 archivo. Esta es la ruta desde el directorio raiz ( / en 10s sistemas UNIX y, por regla general, c : \ en Windows). En nuestro servidor UNIX, ~ e r i a Jhome / boo k / o rde r s . El problema de utilizar este m6todo es que si alojamos el sitio en el servidor de un tercero, la ruta absoluta podria variar. A nosotros nos toc6 aprenderlo de la forma dificil ya que tuvimos que modificar las rutas absolutas de una gran cantidad de secuencias de comandos cuando 10s administradores del sistema decidieron cambiar la estructura de directorios sin previo aviso. Si no se especifica la ruta, el archivo se crear6 o se buscar6 en el mismo directorio que la propia secuencia de comandos. Esta ser6 diferente si estd ejecutando PHP a traves de algiin tip0 de contenedor CGI y ello depender6 de la configuraci6n del servidor. En un entorno UNIX, las barras de 10s directorios son las barras est6ndar (/). Si estd utilizando la plataforma Windows, puede usar estas barras o las barras invertidas (\). Si utiliza estas iiltimas, debe marcarlas como caracteres de escape para que fopen puede entenderlas correctamente. Para marcar un car6cter como car6cter especial, basta con agregar otra barra invertida delante, como se muestra a continuaci6n:

2. Almncetrntr~ierrtoy recrrperncidw dp dntos

Las barras invertidas no se suelen utilizar para indicar rutas e n P H P porque el codigo solo funcionaria e n Windows. El uso d e la barra estandar permite mover codig o entre equipos Windows y UNIX sin variaciones. El segundo par6metro d e f o p e n ( ) es el m o d o d e archivo, q u e deberia ser una cadena. ~ s t especifica a qu4 hacer con el archivo. En este caso vamos a pasar ' w ' a f o p e n ( ) , q u e significa abrir el archivo para escritura. En la tabla 2.1 se describen 10s distintos modos d e archivo.
Tabla 2.1. Resumen de 10s modos de archivo de fopen
7-

--Significado

--

--.

Modo

Modo de lectura: abre el archivo para la lectura, empezando por la parte inicial del archivo. Modo de lectura: abre el archivo para lectura y escritura, empezando por la parte inicial del archivo. Modo de escritura: abre el archivo para escritura, empezando por la parte inicial del archivo. Si el archivo ya existiese, elimina sus contenidos. Si no existiese, intenta crearlo. Modo de escritura: abre el archivo para escritura y lectura. Si el archivo ya existiese, elimina sus contenidos. Si no existiese, intenta crearlo. Modo de adjuncion: abre el archivo para adjuntar (escribir) unicamente, empezando por la parte final de 10s contenidos existentes. Si no existiese, intenta crearlo. Modo de adjuncion: abre el archivo para adjuntar (escribir) -y l e a , empezando por la parte final de 10s contenidos existentes. Si no existiese, intenta crearlo. Modo binario: se utiliza en combinacion con uno de 10s otros modos. Puede utilizarlo si su sistema de archivos distingue entre archivos binarios y archivos de texto. Los sistemas Windows hacen esta diferencia al contrario que 10s sistemas UNIX.

El modo d e archivo para nuestro ejemplo d e p e n d e d e como s e utilice el sistema. En nuestro caso, hemos utilizado 'w', q u e solo permite almacenar u n pedido e n el archivo. Cada vez que s e tome u n nuevo pedido, s e sobrescribira el anterior. Esta opci6n no parece m u y adecuada por lo que haremos mejor e n seleccionar el m o d o d e adjuncion. La funcion f o p e n ( ) consta d e u n tercer parametro opcional. Puede utilizarlo si desea buscar el par6metro i n c l u d e p a t h (establecido e n la configuration d e PHP; a este respecto consulte el a p 4 n d i c e i ) d e u n archivo. Si desea activar esta opcicin,

Desarrollo Web con P H P y MySQL

asigne 1 a1 parfimetro. De esta forma no tendr6 que suministrar un nombre o una ruta de directorio:
Sfp
=

fopenilorders.txt', 'a', 1);

Si f o p e n ( ) se abre satisfactoriamente, se devolverfi un puntero a1 archivo que deberia guardarse en una variable, en este caso $ f p . Esta variable se utiliza para acceder a1 archivo cuando se desee leer o escribir en el.

Como abrir archivos a trav6s de FTP o HTTP


Ademfis de abrir archivos locales para su lectura o escritura, puede abrir archivos a traves de FTP y HTTP utilizando f o p e n ( ) . Si el nombre del archivo utilizado comienza por f t p : / /, se abrirfi una conexi6n FTP en mod0 pasivo a1 servidor especificado y se devolverfi un puntero a1 inicio del archivo. Si el nombre del archivo utilizado comienza por h t t p : //, se abrir6 una conexi6n HTTP al servidor especificado y se devolverri un puntero a la respuesta. A1 utilizar el mod0 HTTP, debe especificar las barras situadas a1 final de 10s nombres de directorios, como se muestra a continuaci6n:

Cuando se especifica la iiltima forma de direcci6n (sin la barra), el servidor Web suele utilizar una redirecci6n HTTP para enviarle a la primera direcci6n (con barra). Pruebe en su navegqdor., En las versiones de PHP anteriores a la 4.0.5, la funci6n f o p e n ( ) no admitia redirecciones HTTP, por lo que debe especificar 10s URL a 10s que hacen referencia 10s directorios con una barra final. A partir de la versi6n 4.3.0 tambien puede abrir archivos sobre SSL siempre y cuando se haya compilado o habilitado la compatibilidad para OpenSSL y utilice la secuencia h t t p s : / / delante del nombre del archivo. Recuerde que 10s nombres de dominio de su URL no discriminan entre mayiisculas y minfisculas per0 que la ruta y el nombre del archivo puede que si lo hagan.

Problemas al abrir el archivo


Un error que suele producirse de manera habitual es intentar abrir un archivo para el que no se disponga de permiso de lectura o escritura. PHP generar6 un aviso similar a1 que se ilustra en la figura 2.2. Si recibe este error, debe asegurarse de que el usuario utilizado para ejecutar la secuencia de comandos dispone de permiso para acceder a1 archivo que est6 inten-

tando utilizar. En funcion d e c6mo se configure el servidor, la secuencia d e comandos puede clue se ejecute como el usuario de servidor Web o como el propietario del directorio e n el clue s e incluye la secuencia d e comandos.

Order Results
Order processed at 16:36, 20th April Your order is as follorva: 4 spark plugs Told of order is 16.00

.4ddre~.s to ship lo is 200 Interciiy Hny, Counhytorvn


WHII~I foper~("../../ordera/o~'de~_~~tx-t",) ~: - Pem~issiondenied in /home/bookipubtic~1111nl/cl1apte1'2~~1roce~~0rd~r.~1h~1 011 line 54

Figura 2.2. PHP le avisa especificarnente cuando no puede abrir

u n archivo

En la mayor parte d e 10s sistemas, la secuencia d e comandos se ejecuta como el usuario d e servidor Web. Si SLI secuencia d e comandos estuviera e n u n sistema UNIX dentro del directorio -/public html/chapter2/, se crearia u n directorio sobre el clue todo el rnundo podria escribir y almacenar el pedido mediante la siguiente secuencia:

Tenga e n cuenta q u e 10s directorios y 10s archivos sobre 10s q u e puede escribir todo el m u n d o son peligrosos. No deberia utilizar directorios susceptibles d e escritura clue resulten accesibles desde la Web. Por esta razcin, nuestro directorio orders se encuentra d o s subdirectorios m i s atras, por encima del directorio public html.El tema d e la seguridad se comentari e n m i s profundidad e n u n capitulo Uno d e 10s elementos clue suele d a r errores a1 abrir u n archivo es el uso d e permisos incorrectos, a u n q u e no es el ilnico problema. Si el archivo n o se puede abrir, necesitari saberlo para n o intentar leer o escribir datos e n 41. Si la llamada a fopen ( ) falla, la funci6n devolveri false.Puede tratar el error d e forma clue resulte m i s significative sustituyendo el mensaje d e PHP por otro.

Desnrrollo Wtb con P H P

!j

M!ySQL

El simbolo @ situado delante d e la llamada a fo p e n { ) indica a P H P clue suprima todos 10s errores producidos por la llamada d e funci6n. Por regla general, conviene saber c u i n d o ocurre alglin error, per0 en este caso vamos a tratar el problema en otro lugar. Esta linea t a m b i h s e puede escribir d e la siguiente forma:

Sin embargo, con esta secuencia resulta menos obvio que se esta utilizando el operador d e supresion d e errores. En un capitulo posterior se tratari el tema de la generacidn de informes de error d e manera m i s detallada. La instruccidn i f comprueba la variable $ f p para determinar si se ha devuelto un punter0 v d i d o d e archivo desde la llamada f o p e n . En caso negativo, imprime u n mensaje d e error y concluye la ejecucidn d e la secuencia d e comandos. Como la pigina termina aqui, se ha utilizado etiqueta HTML d e cierre para que cddigo HTML resulte correcto. En la figura 2.3 se ilustra el resultado d e este enfoque.

A r ~ h m Edta6n Ver F m n l a s Henam~enlas b d a

1 Dlrernbn la t np I

BR CI/

tT

c I

rtl

J '2

II

Order Results
Order processed a l 16:41,20th April

I1
1
11

You- order is a s follows: I spark plugs Total oforder is 16.00 Address to ship to is 200 Jntercity Hwy, C o u n ~ o w n Your order could not be yrocesacd at U~is t h e . Plense t ~ y a g h later.

Figura 2 . 3 . El uso de propios mensajes de error propios en lugar de 10s de PHP puede mejorar la comprension de 10s errores

C6mo escribir en un archivo


La operacidn d e escribir en u n archivo e n PHP resulta relativamente sencilla. Puede utilizar la funci6n fwri t e ( ) (escribir archivo) o la funci6n f p u t s ( ) (cadena

2. Almacenamiento y recuperacidn de datos

de archivo); f p u t s ( ) es un alias de f w r i t e la funci6n f w r i t e ( ) :


fwrite($fp, Soutputstring);

()

. En el siguiente ejemplo llamamos a

Esta linea indica a PHP que escriba la cadena almacenada en $ o u t p u t s t r i n g en el archivo a1 que apunta $ f p . Antes d e analizar 10s contenidos d e $ o u t p u t s t r i n g , vamos a comentar la funci6n f w r i t e ( ) . Parametros

de fwrite()

La funci6n f w r i t e ( ) toma tres parimetros aunque el tercero es opcional. Su sintaxis es la siguiente:


int fwrite
(

int

fp, string

cadena

[,

int

longitud])

El tercer parimetro, longitud, es el niimero miximo de bytes que escribir. Si se incluye este parimetro, f w r i t e ( ) escribiri la cadena en el archivo a1 que apunte el parimetro fp hasta que alcance el final de la cadena o haya escrito la longitud de bytes, dependiendo de qu6 venga primero.

Formatos de archivo
A1 crear un archivo de datos como el utilizado en el ejemplo, la decisi6n sobre el formato en el que almacenar 10s datos seri nuestra. (Sin embargo, si tiene previsto utilizar el archivo de datos en otra aplicacGn, puede que necesite seguir las reglas de dicha aplicaci6n.) Vamos a crear una cadena que represente un registro en nuestro archivo de datos. Para ello, podemos utilizar el siguiente c6digo:
Soutputstring = $date."\tW .$tireqty." tires .$sparkqty." spark plugs\t\$".$total \ t u . $address."\rr";
M

\t".$oilqty."

oil\tM

En nuestro sencillo ejemplo, estamos almacenando cada registro de pedido en una linea separada del archivo. Hemos optado por escribir un registro por linea porque de esta forma obtenemos un separador de registros sencillo en forma del caricter de nueva linea. Como las nuevas lineas son invisibles, las representamos con la secuencia de control " \ n u . Escribiremos 10s campos de datos en el mismo orden y utilizaremos el caricter de tabulaci6n para separar 10s campos. De nuevo, como el caricter de tabulaci6n es invisible, se representa mediante la secuencia de control " \ t " . Puede seleccionar cualquier delimitador 16gico que resulte sencillo de distinguir. El separador o delimitador no debe ser un caricter que se utilice como entrada ya que deberia procesarse para eliminar o utilizar caracteres de escape en todas las instancias del limitador. En un capitulo posterior se analizari c6mo procesar las entradas del usuario. Por el momento asumiremos que no se van a introducir tabuladores en un formulario de pedido. Aunque resulta dificil, no es imposible que un usuario introduzca un tabulador o un caricter de nueva linea en un campo de entrada HTML de una sola linea.

Desarrollo Web con P H P y MySQL

El uso de un separador especial de campo nos permitira dividir 10s datos en variables distintas de manera mas sencilla a1 leer 10s datos, como veremos en capitulos posteriores. Por el momento, trataremos cada pedido como una unica cadena. Tras procesar varios pedidos, 10s contenidos del archivo se parecertin a1 ejemplo ilustrado en el listado 2.1.
Listado 2.1. Ejemplo de lo que podria contener el archivo de pedidos
15:42, 20th April 15:43, 20th April 15:43, 20th April 4 tires 1 ail 6 spark plugs $434.00 22 Short St, Smalltown 1 tires 0 oil 0 spark plugs $100.00 33 Mairl Rd, Newtown 0 tires 1 oil 4 spark plugs $26.00 127 Acacia St, Springfield

Como cerrar un archivo


Cuando se termina de utilizar un archivo, es necesario cerrarlo. Deberia hacerlo utilizando la funci6n f clos e ( ) de la siguiente forma:

Esta funci6n devolverti t r u e si el archivo se cerr6 satisfactoriamente o f a 1s e en caso contrario. Como la probabilidad de que surja un problema con esta funcion es muy inferior a la operaci6n de apertura, no procederemos a probarla.

Lectura desde un archivo


Llegados a este punto, 10s clientes de Bob pueden remitir sus pedidos a travks de la Web, pero si 10s empleados de Bob quieren examinar 10s pedidos, tendr6n que abrir 10s archivos manualmente. Vamos a crear una interfaz Web para permitir que 10s empleados de Bob puedan leer 10s archivos de manera sencilla. El c6digo correspondiente a esta interfaz se incluye en el listado 2.2.
Listado 2.2. vieworders.php. lnterfaz para leer el archivo de pedidos
<?php //cree un nombre de variable corto $DOCUMENTpROOT = SHTTP-SERVER-VARS['DOiJJMENTTROOT'];
?>

<html> <head> <title>Bobls Auto Parts - Customer Orders</title> </head> <body>

2. Alrnacennrniento y recuperncidn de datos

Esta secuencia d e comandos sigue el orden expuesto anteriorinente: abre el archivo, lee el archivo y cierra el archivo. En la figura 2.4 se ilustra el resultado de esta secuencia d e comandos utilizando el archivo d e datos del listado 2.1.

I 4rhr.o
Dlr-~bo

E ~ , c I c Ver ~ FwarPre H ~ r w m e ~ 1 m Amda


il] Ihap //rr,,,b;awl
,/ri ~
~ ~ p ~ r ? x.2 / . . .I, , ,;

~ h n

. . . .

...

J ' 'lr . .

Bob's Auto Parts

il

Customer 0 r d &
15:42,20th April 4 tires 1 oil 6 spark plugs $434.00 22 Short St. Smalltown 15:43.20& April 1 tires 0 oil 0 spark plugs $100.00 33 Main Rd, Newtown 15:43, 20lh April 0 tires 1 oil 4 spark plugs $26.00 127 Acacia St, Springiield

Figura 2.4. La secuencia de comandos vieworders.php muestra todos 10s pedidos

actuales del archivo orders.txt en la ventana del navegador Vamos a examinar las funciones d e esta secuencia d e comandos en detalle.

Apertura de un archivo para s u lectura: fopen0


De nuevo, abrimos el archivo utilizando fo p e n ( ) . En este caso abrimos el archivo para su lectura unicamente, por lo que utilizamos el mod0 de archivo ' r ' :

Desarrollo Web con P H P y MySQL

C6mo saber cuiindo parar: feof()


En este ejemplo, utilizamos el bucle w h i l e para leer el archivo hasta alcanzar el final del archivo. El bucle w h i l e busca el final del archivo utilizando la funci6n
feof
while

0:
( ! f e o f ( S f p ))

La funci6n f e o f ( ) toma un puntero de archivo como su unico parimetro. Devuelve t r u e si el puntero de archivo se encuentra al final del archivo. En este caso (y en general a1 leer desde un archivo), leemos desde el archivo hasta que alcanzamos EOF.

Cdmo leer linea a linea: fgets(), fgetss() y fgetcsv()


En nuestro ejemplo, utilizamos la funci6n f g e t s
$order= fyets (Sfp,
999) ;

()

para leer desde un archivo:

Esta funci6n se utiliza para leer, linea a linea, un archivo. En este caso, leer5 hasta que encuentre un nuevo cardcter de linea (\n), un EOF o haya leido 998 bytes del archivo. La longitud de lectura es la longitud menos un byte. Se pueden utilizar muchas funciones diferentes para leer archivos. La funci6n f g e t s ( ) resulta util para tratar con archivos que contengan texto plano con el que queramos trabajar en grupos. Una variacion interesante de esta funcion es la funcion f g e t s s ( ) ,cuya sintaxis es la siguiente:
s t r i n g fgetss ( i n t fp, i n t l o z g i tud, s t r i n g [etiquetas-permi t i d a s ] ) ;

Esta funci6n es muy parecida a la funci6n f g e t s ( ) con la salvedad de que elimina todas las etiquetas PHP y HTML que encuentra. Si desea dejar alguna etiqueta en particular, puede incluirlas en la cadena etiquetas-permitidas. Se utiliza f g e t s s ( ) por seguridad a1 leer un archivo escrito por otra persona o que contenga entradas de usuario. La inclusion de codigo HTML sin restricciones en el archivo puede estropear el formato atentamente organizado y la inclusion de c6digo PHP podria ofrecer rienda suelta a un usuario malintencionado sobre su servidor. La funcidn f g e t c s v ( ) es otra variacion sobre f g e t s ( ) . Su sintaxis es la siguiente:
array fgetcsv contenedorl 1 )
(

int

fp,

int

longitud

[,

string

delimitador

[,

string

Se utiliza para dividir las lineas del archivo si se ha utilizado un caracter de delimitacion, como el caracter de tabulacion sugerido antes o una coma como se suele hacer en las hojas de c~lculo y otras aplicaciones. Si desea reconstruir las variables del pedido de manera individual en lugar de en forma de linea de texto, f g e t c s v ( )

2 . Almacenamiento y recuperacio'n de datos

nos permite hacerlo con facilidad. Se invoca de la misma forma que f g e t s se le pasa el delimitador utilizado para separar campos. Por ejemplo:

( ) ,per0

recupera una linea desde el archivo y la divide a1 encontrar un tabulador ( \ t ) . Los resultados se devuelven en una matriz ( $ o r d e r en el ejemplo de c6digo). En un capitulo posterior examinaremos las matrices. El pardmetro de longitud deberia ser mayor que la longitud en caracteres de la linea m i s larga que incluya el archivo que este intentando leer. El pardmetro contenedor se utiliza para especificar por qu6 estd encerrado cada campo en una linea. Si no se especifica, se tomardn las comillas dobles (") como elemento predeterminado. Este pardmetro se agreg6 en PHP 4.3.0.

Lectura de todo el archivo: readfile(), fpassthruo, file()


En lugar de leer un archivo linea a linea, podemos leer todo el archivo de una vez. Esta operaci6n se puede realizar de cuatro maneras. La primera utiliza la funci6n r e a d f i l e ( ) . Podemos sustituir la secuencia de comandos entera que escribimos anteriormente por una linea: Una llamada a la funci6n r e a d f i l e ( ) abre el archivo, imprime el contenido de manera esthndar (en el navegador) y cierra el archivo. Su sintaxis es la siguiente:
int readfile (string nornbre d? a r c h l v o , int [ u s a r p l n i - l u d e - p a t h ] )
;

El segundo pardmetro ppcimal especifica si PHP deberia buscar el archivo en


i n c l u d e p a t h y funciona de la misma forma que f open ( ) . La funci6n devuelve el

numero total de bytes leidos desde el archivo. En segundo lugar, puede utilizar f p a s s t h r u ( ) . Necesitari abrir el archivo utilizando f o p e n ( ) primero. A continuaci6n puede utilizar el puntero del archivo como argument0 hasta f p a s s t h r u ( ) , que eliminard 10s contenidos del. archivo desde la posici6n del puntero hasta la salida e s t h d a r . Cierra el archivo cuando termina. Podemos sustituir la secuencia de comandos anterior por f p a s s t h r u ( ) de la siguiente forma:

La funci6n f p a s s t h r u ( ) devuelve t r u e si la lectura resulta satisfactoria y f a 1 s e en caso contrario. La tercera opci6n para leer el archivo entero consiste en utilizar la funci6n f i l e ( ) . Esta funci6n es idhtica a r e a d f i l e ( ) con la salvedad de que en lugar de imprimir el archivo en la aplicaci6n esthdar, lo convierte en una matriz. Examinaremos esta

Desarrollo Web con PHP y MySQL

opci6n de manera m i s detallada en un capitulo posterior. Simplemente como referencia, se invoca utilizando el siguiente c6digo: Esta linea de c6digo lee el archivo entero en una matriz llamada $ f i l e a r r a y . Cada linea del archivo se almacena en un elemento separado de una matriz. Esta funci6n no es segura para datos binarios. Por ultimo, desde la versi6n PHP 4.3.0 puede utilizar la funcidn f i l e -g e t c o n t e n t s ( ) . Esta funci6n es identica a r e a d f i l e ( ) con la salvedad de que devuelve el contenido de un archivo en forma de cadena en lugar de dirigir la salida al navegador. La ventaja de esta nueva funci6n es que ofrece seguridad binaria, a diferencia de la funci6n file().

Lectura de un car6cter: fget()+


Otra opci6n para procesar un archivo consiste en leerlo caricter a caricter. Para ello, se puede utilizar la funci6n f g e t c ( ) . Esta funci6n toma un punter0 de archivo como dnico parimetro y devuelve el siguiente caracter de un archivo. Podemos sustituir el bucle w h i l e en nuestra secuencia de comandos original por una que utilice f g e t c ( ) :
while
( !

f e o f ( $ f p ))

i
$char = fgetc($fp); ) if (!feof($fp) echo ($char=-"\nu ? '<br $char);

/ > I :

Este codigo lee un solo caricter del archivo a la vez utilizando f g e t c ( ) y lo almacena en la variable $_chal;hasta que se alcanza el final del archivo. A continuacibn, sustituimos 10s caracteres de final de linea del texto, /n, por saltos de linea, < b r />. El unico objetivo es limpiar el formato. Como 10s navegadores no representan una linea nueva en HTML como tal sin este c6dig0, todo el archivo se imprimiri en una linea (pruebelo). Utilizaremos el operador ternario para realizar esta operaci6n de manera satisfactoria. Un pequefio efecto secundario product0 del uso de f g e t c ( ) en lugar de f g e t s ( ) es que devolveri el caricter E O F mientras que f g e t s ( ) no lo hari. Es necesario probar f e o f ( ) de nuevo tras la lectura del caricter para evitar que se imprima EOF en el navegador. No resulta normal leer un archivo caricter a caricter a menos que queramos procesar cada uno de ellos por alguna raz6n concreta.

Lectura de una longitud arbitraria de bytes: fread()


Por ultimo, podemos utilizar la funci6n f r e a d ( ) para leer un numero arbitrario de bytes de un archivo.

2. Almacenamiento y recuperacidn de datos

Su sintaxis es la siguiente:
string freadiint
fp, int l o n g i tud);

Funciona de la siguiente forma: lee la longitud de bytes que se especifique o hasta llegar a1 final del archivo, segun qu6 sea lo primero.

Otras funciones de archivo utiles


Existen otra serie de funciones de archivo que resultan titiles de vez en cuando.

Comprobacidn de la existencia de un archivo: file exists0


Si desea comprobar si un archivo existe sin abrirlo, puede utilizar la funci6n
f i1 e-e x i s t s ( ) como se indica a continuaci6n:
if [fiLe-exists("$DOCUMENTpROOT/../orders/orders.txt")) echo 'There are orders waiting to be processed.'; e 1s e echo 'There are currently no orders.';

Como averiguar el tamaAo de un archivo: filesize()


La funci6n f i l e s i z e ( ) p e r m i t e comprobar el tamafio de un archivo. Esta funci6n devuelve el tamafio del un archivo en bytes:
echo
filesi~e("$DOCUMENT~ROOT/../~rders/orders.txt");

Se puede utilizar en combinaci6n con f r e a d ( ) para leer todo un archivo (o parte de un archivo). Podemos sustituir toda nuestra secuencia de comandos por
Sfp = fopen("$DOCUMENT ROOT/../orders/orders.txt", 'r'); echo fread ( $fp, filesize i "$DOCUMENT~ROOT/. . /orders/orders.txt" fclose( Sfp ) ;
) ) ;

Eliminacion de un archivo: unlink()


Si desea eliminar un archivo tras procesar 10s pedidos, puede hacerlo con ayuda de la funci6n u n l i n k ( ) . (No existe una funci6n llamada d e 1e t e.) Por ejemplo: Esta funci6n devuelve f a 1 s e si el archivo no se puede eliminar, lo que suele ocurrir si 10s permisos asociados a1 archivo no resultan suficientes o si no existe el archivo.

Dc.snrrollo Web corz P H P y MySQL

Navegaci6n dentro de un archivo: rewind(), fseeko y dtell()


Puede manipular y descubrir la ubicacion del puntero del archivo dentro d e un archivoutilizandorewind~), fseek ( ) y f t e l l ( ) . La funcion r e w i n d ( ) restablece el puntero del archivo a1 comienzo del archivo. La funci6n f t e l l ( ) indica la distancia a la que se encuetra el puntero dentro del archivo en bytes. Por ejemplo, podemos agregar las siguientes lineas a la parte final de nuestra secuencia de comandos (antes del comando f c l o s e ( ) ).

1
I

Customer Orders
15:42, 20th April 4 tires 1 oil 6 spark plugs $434.00 22 Short St, S~nalllowm 15:43,20th April 1 tires 0 oil 0 spark plugs $100.00 33 Main Rd, Newtown 15:43,20th April 0 tires I oil 4 spark plug $26.00 127 Acacia St, Springiield

Final position of Ihe file poinicr is 234 ABcr rewind, the position is 0

Figura 2.5. Tras leer 10s pedidos, el puntero apunta al final del archivo, una distancia de 234 bytes. La llamada de retroceso lo establece a la posicion 0, es decir al principio del archivo

La funcion f seek ( ) se puede utilizar para establecer el puntero del archivo en otro punto dentro del archivo. Su sintaxis es la siguiente: Una llamada a f s e e k ( ) establece el puntero f p en un punto desde 10s que desplaza 10s bytes indicados. El parimetro punto de parfida se agreg6 en PHP 4.0.0. Su valor predeterminado es SEEK S E T que es en principio del archivo. Los otros valores posibles son SEEK-CUR (la ubi&ci6n actual del punter0 del archivo) y SEEK-END (el final del archivo). La funcion r e w i n d equivale a llamar a la funcion f s e e k con un desplazamiento 0. Por ejemplo, podemos utilizar f seek ( ) para buscar el registro intermedio de un archivo o para realizar una b k q u e d a binaria. A menudo, si alcanza el nivel de complejidad d e un archivo d e datos en el que necesite realizar este tip0 d e tareas, le resultarii mucho m i s sencillo utilizar una base de datos.

2 . Alrrrncennrnierrto y recuperncidn de dntos

Rlocweo de archivos
Imagine una situaci6n en la que dos clientes intenten realizar un pedido d e un prodrrcto a la vez. (Algo que no resulta extrafio, en especial si el volumen d e trifico del sitio Web comienza a tener cierta importancia.) Piense en qu6 ocurriria si LIII cliente llama a la funcion f o p e n ( ) y comienza a escribir, y entonces otro cliente llama a la misma funci6n y t a n ~ b i h escribe. iQu6 contendri a1 final el archivo? i S e r i uno d e 10s pedidos o el otro? 0 algo menos util, como dos pedidos entremezclados. La respuesta depende del sistema operativo, per0 a menudo resulta imposible d e saber. Para evitar problemas como este, se puede utilizar el bloqueo d e archivos. Para implementar este recurso en PHP se utiliza la funci6n f l o c k ( ) . Esta funci611 deberia invocarse tras abrir u n archivo, per0 antes d e que se lea o escriba ningGn dato. Su sintaxis es la siguiente:

Es necesario pasarle un punter0 a1 archivo abierto y un numero que represente el tipo d e bloqueo deseado. Devuelve true si el bloqueo se logra satisfactoriamente y false si no es asi. En la tabla 2.2 se recoge un resumen con 10s valores posibles del parimetro operaciidn. Estos valores cambiaron en la versi6n 4.0.1 d e PHP. En la tabla se recopilan ambos conjuntos d e valores.
Tabla 2.2. Valores de operacion de la funcion flock()

Valor de operacibn LOCK-SH (antes 1) LOCK-EX (antes 2) LOCK-UN (antes 3) LOCK-NB (antes 4)

SignJficado Bloqueo de lectura. El archivo se puede compartir con otros lectores. Bloqueo de escritura. Es exclusive. El archivo no se puede compartir. Liberar bloqueo existente. Si se agrega el numero 4 a la operacion, se impide que el bloqueo al intentar obtener uno.

Si va a utilizar f l o c k ( ) , tendri que agregarlo a todas las secuencias d e comandos que utilicen el archivo ya que d e lo contrario carecer6 d e valor. f l o c k ( ) no funciona con el sistema d e archivos NFS ni con otros sistemas d e archivos d e red. Tampoco se puede utilizar con sistemas d e archivos antiguos que no admitan bloqueos como FAT. En algunos sistemas operativos se implementa en el nivel d e proceso y n o funcionari correctamente si utiliza un API d e servidor multiproceso.

Desarrollo W e b con PHP y MySQL

Para utilizarlo en el ejemplo, es necesario modificar p r o c e s s o r d e r .p h p de la siguiente forma:


Sfp
= fopen("SD0CUMENT-ROOT/../orders/orders.txt", 'a'); flock(Sfp, LOCK-EX); / / bioquee el archivo para su escritura fwriteiSfp, $outputstring); flock($fp, LOCK-UNI; / / desactive el bloqueo d e escritura f c l o s e ( S f p );

Tambi6n deberia agregar bloqueos a v i e w o r d e r s p hp:


Sfp
= fopen("SD0CUMENT-ROOT /../orders/orders.txt", Ir1); / / bloquee el archjvo para lectura flock($fp, LOCK-SH); / / lee desde el archivo flockiSfp, LOCK-UN); / / desactive el bloqueo d e lectura fclose1Sfp);

Nuestro c6digo resulta ahora mas s6lido per0 no es perfecto. iQu6 ocurrira si dos secuencias de comandos intentan obtener un bloqueo a la vez? Que se crearh una carrera en la que 10s procesos competirhn por conseguir bloqueos sin saber qui6n lo lograrh primero, lo que puede ser fuente de mas problemas. Lo mejor es un utilizar un DBMS.

La opcion mas acertada: 10s sistemas de adrninistracion de base de datos


Hasta el momento todos 10s ejemplos vistos utilizan archivos planos. En la siguiente secci6n examinaremos c6mo utilizar MySQL, un sistema de administraci6n de bases de dafos raacional. Es posible que se est6 preguntando por qu6 molestarse en recurrir a este sistema.

Problemas con el uso de archivos planos


El uso de archivos planos plantea una serie de problemas: Cuando un archivo supera un determinado tamaiio, el trabajo se ralentiza. La busqueda de un determinado registro o de un grupo de ellos resulta dificil dentro de un archivo plano. Si 10s registros estan ordenados, puede utilizar algun tip0 de busqueda binaria en combinaci6n con un registro de ancho fijo para buscar sobre un campo clave. Si desea buscar patrones de informaci6n (por ejemplo, para extraer todos 10s clientes que viven en una determinada ciudad), tendrh que leer cada registro y comprobarlo de manera individual.

2 . Alrnacenamiento y recuperacidn de datos

Los accesos simultdneos pueden resultar dificiles de solucionar. Ya hemos visto cdmo bloquear archivos, pero este mecanismo puede dar lugar a una carrera entre procesos. Tambi6n pueden dar lugar a cuellos de botella. En determinados niveles de trdfico, puede ocurrir que un grupo grande de usuarios tenga que esperar a que se desbloquee el archivo para poder realizar.un pedido. Si la espera es muy larga, se irdn a comprar a otra parte. El procesamiento de archivos que hemos visto hasta el momento es de tip0 secuencial, es decir, partimos del principio del archivo y lo leemos progresivamente hasta llegar a1 final. Si queremos insertar o eliminar registros de la parte central del archivo (acceso aleatorio), la operacidn resultard complicada ya que serd necesario leer todo el archivo en memoria, realizar 10s cambios y volver a escribir el archivo completo. Si el archivo de datos es grande, la carga serd significativa. Aparte de las funciones que ofrecen de 10s permisos de archivos, no existe una forma sencilla de aplicar diferentes niveles de acceso a datos.

Como resolver estos problemas


Los sistemas de administracidn de bases de datos dan una respuesta a todos estos problemas: Los RDBMS proporcionan acceso mds rdpido a 10s datos que 10s archivos planos. MySQL, el sistema de base de datos que utilizaremos en este libro, es uno de 10s mds rdpidos. Resulta sencillo consultar 10s RDBMS para extraer conjuntos de datos que se correspondan con deterGnados criterios. Los RDBMS incorporan mecanismos integrados para resolver el problema de 10s accesos simultdneos para que 10s programadores no tengan que preocuparse. Los RDBMS proporcionan acceso aleatorio a 10s datos. Los RDBMS incorporan sistemas de privilegios. MySQL dispone de funciones especiales en este sentido. Probablemente, la razdn principal para utilizar un RDBMS es que implementan todas las funciones (o a1 menos la mayor parte de ellas) que se desean para un sistema de almacenamiento. Puede escribir su propia biblioteca de funciones de PHP, per0 ipor qu6 tomarse esa molestia? En la segunda parte de este libro, se analizard el funcionamiento general de las bases de datos y cdmo configurar MySQL para crear sitios Web dotados debases de datos.

Desarrollo Web con P H P y MySQL

Lecturas adicionales
En un capitulo posterior veremos c6mo interactuar con 10s sistemas de archivos. En concreto, se indicari c6mo cambiar permisos, derechos y nombres de archivos, c6mo trabajar con directorios y c6mo interactuar con el entorno del sistema de archiV O S . Tambih puede consultar la secci6n dedicada a1 sistema de archivos del manual enlinea de P H P e n h t t p : //www.php. n e t / f i l e s y s t e m .

A continuacion
En el siguiente capitulo, analizaremos las matrices y c6mo utilizarlas para procesar datos en secuencias de comandos PHP.

En este capitulo se explica c6mo utilizar una importante estructura de programaci6n: las matrices. Las variables que hemos visto en 10s capitulos anteriores s610 almacenan un valor. Una matriz es una variable capaz de almacenar un conjunto o secuencia de valores. Una matriz puede constar de una gran cantidad de elementos. Cada elemento puede albergar un unico valor, como texto o numeros, u otra matriz. Las matrices que contienen otras matrices se conocen como matrices multidimensio-nales. PHP admite matrices indexadas numericamente y matrices asociativas. Es probable que este familiarizado con las matrices indexadas numericamente si ha utilizado algun lenguaje de programaci6n, pero si no ha programado nunca en PHP o en Per1 es muy probable que no conozca las matrices asociativas. Estas matrices permiten utilizar valores mfis 6tiles como indice. Las matrices asociativas permiten asociar a cada elemento palabras u otro tip0 de informaci6n con significado en lugar de indices numericos. En este capitulo retomaremos el ejemplo de la aplicaci6n Bob's Auto Parts y utilizaremos matrices para facilitar el trabajo con informaci6n repetitiva como 10s pedidos de 10s clientes. Asi mismo, escribiremos c6digo mfis breve y claro para realizar parte de las tareas desarrolladas en el capitulo anterior. Nos centraremos en 10s siguientes aspectos: Matrices indexadas numericamente Matrices asociativas Matrices multidimensionales Ordenaci6n de matrices

3 . Uso de matrices

iQuC es una matriz?


En un capitulo anterior vimos las variables escalares. Una variable escalar es una ubicaci6n con nombre en la que se almacena una variable; de manera similar, un matriz es una ubicaci6n con nombre para almacenar un conjunto de valores, que, por tanto, permite agrupar variables escalares. Utilizaremos la lista de productos de Bob para crear la matriz de nuestro ejemplo. En la figura 3.1 se puede ver una lista de tres productos almacenados en formato de matriz y una variable, denominada $ p r o d u c t s , que contiene tres valores. (En un instante explicaremos cdmo crear un variable como &a).

Tires

Oil

Spark Plugs

product0

Figura 3.1. Los productos de Bob se pueden almacenar en una matriz

Tras colocar la informaci6n en una matriz, podemos trabajar con ella de varias formas utiles. Si utilizamos la estructura de bucle vista en un capitulo anterior, podemos ahorrar trabajo aplicando las mismas acciones a cada valor de la matriz. Podemos trasladar todo el conjunto de informaci6n de un sitio a otro como si se tratara de una unidad. De esta forma, bastari con una sola linea de c6digo para pasar todos 10s valores a una funci6n. Por ejemplo, podriamos ordenar todos 10s productos alfabeticamente pasindoselos a la funci6n s o r t ( ) de PHP. Los valores almacenado? en ups matriz se denominan elementos de matriz. Cada elemento de matriz lleva asociado un indice (tambien denominado clave) que se utiliza para acceder a1 elemento. Las matrices de la mayor parte de 10s lenguajes de programaci6n constan de indices numericos que suelen comenzar en cero o en uno. PHP admite este tip0 de matrices. PHP tambidn admite matrices asociativas con las que estarin familiarizados 10s programadores de Perl. Estas matrices pueden utilizar pricticamente cualquier valor como indice de matriz, sobre todo cadenas. Comenzaremos por examinar las matrices indexadas numericamente.

Matrices indexadas numericamente


La mayor parte de 10s lenguajes de programaci6n permite el uso de las matrices indexadas numericamente. En PHP, 10s indices comienzan en cero de manera predeterminada per0 se puede variar este parimetro.

Desarrollo W e b con P H P y MySQL

Inicializacion de matrices indexadas numkricamente


Para crear la matriz ilustrada en la figura 3.1, utilice la siguiente linea de c6digo de PHP:
$products
=

array(

'Tires',

O i l ,

'Spark

Plugs'

);

Esta linea de c6digo crea una matriz llamada p r o d u c t s que contiene 10s tres valores dados 'Tires', 'Oil' y 'Spark Plugs'. Como en el caso de la instruction e c h o , a r r a y ( ) es miis una unidad estructural del lenguaje que una funci6n. Puede que no necesite inicializar manualmente 10s elementos de una matriz como en el siguiente ejemplo. Todo depende de 10s contenidos de la matriz. Si tiene 10s datos que necesita en otra matriz, puede copiarlos utilizando el operador =. Si quiere almacenar una secuencia ascendente de numeros en una matriz, puede utilizar la funci6n r a n g e ( ) para crear la matriz automiiticamente. La siguiente linea de c6digo crearii una matriz denominada n u m b e r s cuyos elementos son 10s 10 primeros numeros.
$numbers
=

r a n g e ( 1 , l O );

Si tiene la information almacenada en un archivo del disco duro, puede cargar 10s contenidos directamente del archivo, como veremos en un secci6n posterior. Si 10s datos destinados a la matriz se almacenan en una base de datos, puede cargar sus contenidos directamente desde la base de datos, como veremos en un capitulo posterior. T a m b i h puede utilizar varias funciones para extraer parte de una matriz o para volver a ordenarla. En una secci6n posterior veremos parte de estas funciones.

Acceso a 10s coplteiiidos de matrices


Para acceder a 10s contenidos de una matriz, utilice su nombre. Si la variable es una matriz, utilice el nombre de variable o el indice para acceder a 10s contenidos. La clave o el indice indican a qu6 valores almacenados accedemos. El indice se coloca entre corchetes tras el nombre. Escriba $ p r o d u c t s [ O ] , $ p r o d u c t s [I]y $ p r o d u c t s [ 2 I para utilizar 10s contenidos de la matriz de productos. El primer elemento de la matriz es el elemento cero. Se trata del mismo sistema de numeraci6n utilizado en C, C++, Java y otros lenguajes, per0 puede que a1 principio le cueste acostumbrarse a 61. Como ocurre con otras variables, para cambiar 10s contenidos de 10s elementos de matriz se utiliza el operador =. La siguiente linea sustituirii el primer elemento de la matriz, ' T i r e s I, por
F u s e s I.
$products [0]
=

'Fuses';

3. Uso de matrices

La linea que se incluye a continuaci6n podria utilizarse para agregar un nuevo elemento ( ' FUS e s ' ) a1 final de la matriz, lo que nos da un total de cuatro elementos:
$products[3]
=

'Fuses';

Para mostrar 10s contenidos, podriamos escribir:


echo "$products[O] $products[l] $products[2] $products[3]";

Tenga en cuenta que aunque el an6lisis de cadenas que realiza PHP es bastante inteligente, puede que resulte un poco confuso. Si tiene problemas porque las matrices u otras variables no se interpretan correctamente a1 encerrarlas entre comillas dobles, puede colocarlas fuera de las comillas. La instrucci6n e c h o anterior funcionar6 correctamente, per0 en gran parte de 10s ejemplos posteriores, de mayor complejidad, no se utilizan cadenas con comillas. Como ocurre con otras variables de PHP, no es necesario inicializar las matrices o crearlas por adelantado ya que se crean automtiticamente la primera vez que se utilizan. El siguiente c6digo crear6 la misma matriz $ p r o d u c t s :
$products [O] $products[l] $products[2]
= = =

'Tires'; 'Oil'; 'Spark Plugs';

Si la matriz $ p r o d u c t s no existiera todavia, la primera linea crearia una nueva matriz con un ~ n i c o elemento y las siguientes lineas agregarian valores a la matriz.

Uso de bucles para acceder a la matriz


Como la matriz se indexa a partir de una secuencia de n ~ m e r o spodemos , utilizar un bucle f o r para mostrar las contenidos de manera m6s sencilla.
for
( $i = 0; $i<3; $it+ ) echo "$products [$i] ";

Este bucle produce resultados similares a1 c6digo anterior, per0 exige menos trabajo ya que no es necesario escribir c6digo para trabajar con cada elemento de una matriz. Una de las caracteristicas destacadas de las matrices indexadas es la posibilidad de utilizar un sencillo bucle para acceder a cada uno de sus elementos. En el caso de matrices asociativas no resulta tan sencillo utilizar bucles para recorrerlas, per0 permiten usar indices con valores significativos. Tambien podemos recurrir el bucle f o r e a c h que estd especialmente disefiado para su uso con matrices. En este ejemplo podemos utilizarlo de la siguiente forma:
foreach ($products as $current) echo $current.' ' ;

Este c6digo almacena elemento a elemento en la variable $ c u r r e n t y 10s imprime.

Matrices asociativas
En la matriz de productos, permitimos que PHP asigne a cada elemento el indice predeterminado. Esto significa que el primer elemento que agregamos se convierte en 0, el segundo en 1y asi sucesivamente. PHP admite el uso de matrices asociativas. En una matriz asociativa, podemos asociar cualquier clave o indice que deseemos a un valor.

Inicializacion de una matriz asociativa


El siguiente c6digo crea una matriz asociativa utilizando 10s nombres de productos y 10s precios como valores.
$prices
=

array( 'Tires'=>100, 'Oil'=>10, 'Spark Plugs1==>41 ;

Como acceder a elementos de matriz


De nuevo, utilizamos el nombre de la variable y una clave para acceder a 10s contenidos. De esta forma podemos acceder a la informaci6n almacenada en la matriz de precios como $ p r i c e s [ ' T i r e s ' 1, $ p r i c e s [ ' O i l ' ] y $ p r i c e s [

' Spark

Plugs

' 1.

Como en el caso de las matrices indexadas, las matrices asociativas se pueden crear e inicializar elemento a elemento. El siguiente fragment0 de c6digo crea la misma matriz $ p r i c e s . En lugar de crear una matriz con tres elementos, esta versi6n crea una matriz con un unico elemento y, a continuaci611, crea dos m6s.
$prices = array( 'TireC'=>100 $prices['Oil'] = 10; $prices['Spark Plugs'] = 4;

);

Aqui tambien existe una pequeiia diferencia, aunque el c6digo sea equivalente. En esta versi611, no creamos una matriz de manera explicita sin0 que se crea automdticamente a1 agregarle el primer elemento.
$prices ['Tires'] = 100; $prices ['Oil'] = 10; $prices['Spark Plugs'] = 4;

Uso de bucles con matrices asociativas


Como 10s indices de esta matriz asociativa no est6n formados por ntimeros, no podemos incluir u n simple contador dentro de bucle f o r para que funcione con la matriz. Podemos utilizar el bucle f o r e a ch o las instrucciones 1i s t ( ) y e a c h ( ) . El bucle f o r e a c h presenta una estructura ligeramente diferente cuando se utiliza

3 . Uso de rnntrices

con matrices asociativas. Podemos usarlo tal y como hicimos en el ejemplo anterior o incorporar las claves:
foreach echo
( S p r i c e s as $ k e y =) $value) $ k e y . '=-,' . $ v a l u e . ' i b r / > I ;

El siguiente c6digo devuelve 10s contenidos d e la matriz $ p r i c e s utilizando Ia instruccion e a c h ( ) :

El resultado de este fragment0 de c6digo se muestra en la figura 3.2. En un capitulo anterior, vimos 10s bucles w h i l e y la instrucci6n e c h o . El c6digo anterior utiliza la funci6n e a c h ( ) ,que no se ha visto todavia. Como estamos llamand o a e a c h ( ) dentro de un bucle w h i l e , 10s elementos de la matriz se devolverAn uno a uno y se detendri a1 alcanzar el final d e la matriz.

Tires 100 Oil - 10 Spark Plugs - 4

Figura 3.2. Se puede utilizar una instruccion each() para recorrer matrices

En este codigo, la variable $ e l e m e n t es una matriz. A1 llamar a e a c h ( ), nos devuelve una matriz con cuatro valores y 10s cuatro indices hasta las ubicaciones d e matriz. Las ubicaciones k e y y 0 contienen la clave del elemento actual y las ubicaciones v a l u e y 1contienen el valor del elemento actual. Aunque da igual cuAl se escoja, en nuestro ejemplo hemos optado por utilizar las ubicaciones con nombre en lugar de las ubicaciones con n ~ m e r o . Existe una forma mAs habitual y elegante de realizar esta tarea. Podemos utilizar la funci6n l i s t ( ) para dividir una matriz en un ndmero de valores y separar 10s dos valores que nos proporciona la funci6n e a c h ( ) de la siguiente forma:
Slistl $product,

$price

eachl

Sprices

i;

Esta linea utiliza e a c h ( ) para tomar el elemento actual desde $ p r i c e s , lo devuelve en forma d e una matriz y convierte al siguiente elemento en el actual.

Dcsarrolln Web coil P H P y MySQL

Tambi6n utiliza la funci6n l i s t ( ) para convertir 10s elementos 0 y 1de la matriz devueltos por each ( ) en dos nuevas variables llamadas $ p r o d u c t y $ p r i c e . Podemos utilizar u n bucle para recorrer la matriz $ p r i c e s entera y mostrar 10s resultados utilizando esta breve secuencia d e comandos.
w h i l e ( l i s t ( Sprnduct, S p r i c e ~ c h u "$product - $pric?.:.hr
)
=

each(

Sprices

/'i";

El resultado de este codigo es el mismo que el generado por la secuencia de comandos anterior, per0 resulta m6s sencilla d e leer porque la instrucci6n l i s t ( ) permite asignar nombres a las variables. Una cosa en la que fijarse a1 utilizar e a c h ( ) es que la matriz realiza el seguimiento el elemento actual. Si queremos utilizar la matriz dos veces en la misina secuencia d e comandos, debemos reestablecer el elemento actual a1 principio d e la matriz utilizando la funci6n r e s e t ( ) . Para recorrer la matriz de precios de nuevo con ayuda de un bucle, utilice el siguiente cbdigo:

Este codigo restablece el elemento actual a1 principio d e la matriz y nos permite recorrerla d e nuevo.

Matrices muitidimensiona~es
Las matrices no tienen por qu6 estar formadas por una simple lista d e claves y valores ya que cada ubicaci6n de la matriz puede contener otra matriz. De esta forma podemos crear una matriz de dos dimeiisiones. Para hacerse una idea del concept0 d e las matrices bidimensionales, piense en ellas como una tabla, o cuadricula, con altura y anchura o con filas y columnas. Si queremos almacenar mi5s de un dato de cada producto de Bob, podemos utilizar una matriz bidimensional. La figura 3.3 muestra 10s productos d e Bob en una matriz bidimensional en la que cada fila representa un producto y cada columna un atributo de producto.

Code TIR OIL SPK

Description Tires Oil Spark Plugs

Price
100

10
4
r

atributo de producto

Figura 3.3. Podemos almacenar mas informacion sobre 10s productos de Bob en una matriz bidimensional

3. Uso de matrices

Utilizando PHP podriamos escribir el siguiente c6digo para configurar 10s datos de la matriz que se muestra en la figura 3.3.
$products
=

a r r a y ( a r r a y ( 'TIR', a r r a y ( 'OIL', a r r a y ( 'SPK',

' T l r e s ' , 100 ) , 'Oil', 10 ), 'Spark Plugs', 4

);

En esta definici6n puede ver que la matriz de productos contiene ahora tres matrices. Para acceder a 10s datos de una matriz unidimensional, recuerde que necesitamos el nombre de la matriz y el indice del elemento. En una matriz bidimensional la operaci6n es similar con la salvedad de que cada elemento consta de dos indices, una fila y una columna. La fila superior es la fila 0 y la columna situada m i s a la izquierda es la columna 0. Para visualizar 10s contenidos de esta matriz, podriamos acceder manualmente a cada elemento de la siguiente forma:
echo echo echo

I ' .$products ' I ' .$products I ' .$products


1

[ O ] [O]

.' I ' .$products [Ol


' '

[ l ][ O ] . ' 1 [2] [0] .' I

[I].' 1 .$products [ l l I l l . ' l . $ p r o d u c t s [ 2 ] [ I ] .' 1

' . S p r o d u c t s I01 ' .$products [ l l

'

121 . ' l < b r I>'; [21. ' l <br / > I ; . $ p r o d u c t s [ 2 1 [21 . ' l < b r / > I ;

Tambien podemos colocar un bucle for dentro de otro bucle for para obtener el mismo resultado.
for
(

$row
(

0;

$row
=

< 3; S r o w t t
$column

) )

t
for $column 0;

< 3; $column++

i
echo

' I ' .$products [$row] [$column];


/ > I ;

I
echo ' < b r

Ambas versiones generan el mismo resultado en el navegador.

La Linica diferencia entre 10s dos ejemplos es que el c6digo seri m i s breve si utiliza la segunda versi6n con una matriz de gran tamaiio. Si lo prefiere puede crear nombres de columna en lugar de nLimeros, como se ilustra en la figura 3.3. Para ello, puede utilizar matrices asociativas. Para almacenar el mismo conjunto de productos, con columnas con nombre como las de la figura 3.3, se utiliza el siguiente c6digo:
$products
=

a r r a y ( a r r a y ( C o d e => ' T I R ' , D e s c r i p t i o n => P r i c e => 1 0 0


r

'Tires',

Desarrollo W e b con PHP y MySQL


array( Code => 'OIL', Description => 'Oil', Price => 10
)
I

array ( Code => 'SPK', Description => 'Spark Plugs', Price = > 4
)
);

Resulta mds sencillo trabajar con esta matriz si s610 se desea recuperar un valor

y es mds sencillo recordar que la descripci6n almacenada e n la columna


D e s c r i p t i o n que recordar que estd almacenada en la columna 1. El uso de matrices asociativas evita tener que memorizar que se ha almacenado un articulo en [x][y]. Es f6cil encontrar 10s datos utilizando la referencia a una ubicaci6n utilizando nombres de fila y columna significativos. Sin embargo, perderemos la posibilidad de utilizar un sencillo bucle f o r para recorrer cada columna. Una forma de escribir c6digo para mostrar esta matriz es la siguiente:
for
I (

$row

0; $row c 3; $row++

echo 'I'.$products[$row! ['Code'l.'~'.$products[$raw]['Description']. '.$pruducts[$row]['Price'].'l<br / > I ;

El uso de un bucle f o r permite recorrer la matriz externa $ p r o d u c t s , numkricamente indexada. Cada fila de la matriz $ p r o d u c t s es un matriz asociativa. Podemos utilizar las funciones e a c h ( ) y li s t ( ) en un bucle w h i l e para recorrer matrices asociativas. Por lo tanto, necesitamos utilizar u n bucle w h i l e dentro de un bucle f o r :
for
I

$row

0; $raw < 3;-$row++


)
=

while i list( $key, $value


I

each( $products[ $row

echo "I$value"; echo 'l<br


/ > I ;

No tenemos por qu6 limitarnos a dos dimensiones. De la misma forma que 10s elementos de las matrices pueden contener otras matrices, esas nuevas matrices pueden contener a su vez otras. Una matriz tridimensional tiene altura, anchura y fondo. Si el simil de las matrices bidimensionales como tablas con filas y columnas le ayud6 a imaginarselas, piense en las matrices tridimensionales como un conjunto apilado de tablas. Para hacer referencia a cada elemento, se utilizard la capa, la fila y la columna. Si Bob dividiera sus productos en categorias, podriamos utilizar una matriz tridimensional para almacenarlos. La figura 3.4 muestra 10s productos de Bob en una matriz tridimensional.

.?

710d,
g'
Car Parts
Code

L-

Description

Price
100
10

CAR-TIR
CARglL

011 Spark Plugs

T~res

CAR-SPK

Figura 3.4. Esta rnatriz tridimensional nos perrnite dividir 10s productos en categorias

Si examina el c 6 d i g o q u e define esta matriz, o b s e r v a r 5 q u e u n a m a t r i z tridimensional es una matriz q u e contiene matrices d e matrices.
TIR', ' CAF: - 01 L ' ,
'CfiR

, i,.h -,, ,

SFK',

ti,^?,<*,
'Oil',

] V

j,

35 1 , ,> r . . y ' Fl r k F 1 I . (;I : :'

Como esta matriz s610 consta d e indices numkricos, podemos utilizar bucles for anidados para mostrar sus contenidos.

Debido a la forma e n la q u e se crean las matrices multidimensionales, podriamos crear matrices d e cuatro, cinco o seis dimensiones. El lenguaje no tiene limites a este

Desarrollo W e b con P H P y MySQL


'

respecto, per0 resulta dificil visualizar estructuras con m i s de tres dimensiones. La mayor parte de 10s problemas del mundo real se corresponden 16gicamente con estructuras de tres o menos dimensiones.

Como ordenar matrices


A menudo resulta util ordenar datos relacionados que estkn almacenados en una matriz. Es sencillo tomar un matriz unidimensional y ordenarla.

Uso de sort()
El siguiente c6digo da como resultado una matriz que se ordena en orden alfabktico ascendente:
$products = a r r a y ( s o r t ( $ p r o d u c t s ); 'Tires', O i l , 'Spark Plugs'
);

Los elementos de nuestra matriz quedardn ordenados de la siguiente forma: oil,


S p a r k Plugs, T i r e s .

Tambikn podemos ordenar 10s valores numkricamente. Si tenemos una matriz con 10s precios de 10s productos de Bob, podemos ordenarla en sentido ascendente como se muestra a continuation:

Los precios se ordenarin ahora de la siguiente forma: 4,10,100. Tenga en cuenta que la fu?ci6n de ordenaci6n discrimina entre mayusculas y minusculas, y que las letras mayusculas van delante de las minusculas. Por lo tanto, la "A"va antes que "Z", per0 la "Z" va antes que la "a".

Uso de asorto y ksort() para ordenar matrices asociativas


Si quisikramos utilizar una matriz asociativa para almacenar articulos y sus precios, necesitariamos utilizar diferentes tipos de funciones de ordenaci6n para mantener agrupadas las claves y su valores a1 ordenarlos. El siguiente c6digo crea una matriz asociativa en la que se incluyen tres productos y sus precios asociados, y ordena la matriz en orden ascendente por 10s precios.
Sprizes = array( a s o r t ( $ p r i c e s ); 'Tiresl=>lOO, 'Oil'=>10, 'Spark Plugsf=>3
);

La funci6n a s o r t ( ) ordena la matriz en funci6n del valor de cada elemento. En la matriz, 10s valores son 10s precios y las claves son las descripciones textuales. Si

en lugar de o r d e n a ~ la matriz por el precio, queremos hacerlo por la descripcidn, se utilizard la funcidn k s o r t ( ) , que ordena la matriz por la clave y no por su valor. Como resultado se ordenardn las claves de la matriz alfabkticamente: Oil, Spark Plugs, Tires.
$prices = array( 'Tires'=>100, 'Oil'=>10, 'Spark Plugs1=>4 ksort($prices);
);

Inversion del orden


Hemos visto las funciones s o r t ( ) , a s o r t ( ) y k s o r t ( ) . Estas tres funciones ordenan las matrices en orden ascendente. Pero cada una de ellas tiene una funcidn correspondiente para ordenar las matrices en orden descendente. Estas funciones inversas son r s o r t ( ) , a r s o r t ( ) y k r s o r t ( ) . Las funciones de ordenacidn inversa se utilizan de la misma forma que las funciones d e ordenacidn normales. La funcidn r s o r t ( ) ordena u n matriz unidimensional indexada numkricamente en orden descendente. La funcidn a r s o r t ( ) ordena una matriz asociativa unidimensional en sentido descendente utilizando el valor de cada elemento. La funcidn k r s o r t ( ) ordena una matriz asociativa unidimensional en orden descendente utilizando la clave de cada elemento.

Ordenacion de matrices multidimensionales


La ordenacidn de matrices con m6s de una dimensidn o aplicando un orden distinto a1 alfabetico o numkrico resulta m6s complicado. PHP sabe cdmo comparar dos nLimeros o dos cadenas de texto,gero en una matriz multidimensional cada elemento de una matriz es otra matriz. PHP no sabe cdmo comparar dos matrices, por lo que es necesario crear un metodo para compararlas. En la mayor parte de las ocasiones, el orden de las palabras o nLimeros resulta bastante obvio per0 en el caso de objetos complicados, se convierte en una operacidn m6s problemdtica.

Ordenaciones definidas por el usuario


A continuacidn se repite la definicidn de una matriz bidimensional utilizada anteriormente. Esta matriz almacena 10s tres productos que comercializa Bob con un cddigo, una descripcidn y un precio.
$products
=

array( array( 'TIR', 'Tires', 100 ) , array( 'OIL', 'Oil', 1 0 ) , array( 'SPK', 'Spark Plugs', 4

);

Si ordenamos esta matriz, ique orden se aplicar6 finalmente a 10s valores? Como sabemos que contenidos representan, existen dos posibilidades a1 menos. Podemos

Desarrollo Web con PHP y MySQL

ordenar 10s productos en orden alfabetico utilizando su descripci6n o hacerlo numericamente por su precio. Ambas opciones son posibles, pero necesitamos utilizar la funci6n u s o r t ( ) y decirle a PHP c6mo comparar 10s articulos. Para ello tenemos que escribir nuestra propia funci6n de comparacion. El siguiente c6digo ordena esta matriz en orden alfabetico utilizando la segunda columna de la matriz: la descripci6n.
function compare($x, $y)

i
( $ x [ l l == S y l l l I r e t u r n 0; else i f ( Sxlll < $y[ll r e t u r n -1; else r e t u r n 1;

i f

Hasta el momento, hemos utilizado varias funciones incorporadas en PHP. Para ordenar esta matriz, hemos definido una funci6n propia. En un capitulo posterior se analizari en detalle la creaci6n de funciones. Las funciones se definen utilizando la palabra clave f u n c t i o n . Es necesario asignar un nombre a la funci6n. Los nombres deberian ser descriptivos. Muchas funciones toman parimetros o argumentos. Nuestra funci6n c o m p a r e ( ) toma dos, uno llamado x y otra llamado y. El objetivo de esta funci6n es tomar dos valores y determinar su orden. En este ejemplo, 10s parametros x e y serin dos matrices dentro de la matriz principal y cada una representari un producto. Para acceder a la descripci6n de la matriz x, escribimos $ x [ 1] porque se trata del segundo elemento de estas matrices y la numeraci6n comienza ensero. Utilizamos $ x [ 1] y $ y [ 1] para comparar las descripciones de las matiices pasadas en la funci6n. A1 final de la funcibn, se puede devolver una respuesta a1 c6digo de llamada. Para devolver un valor, utilizamos la palabra clave r e t u r n . Por ejemplo, la linea r e t u r n 1; devuelve el valor 1 a1 c6digo que invoc6 la funci6n. Para utilizar la funci6n c o m p a r e ( ) con u s o r t ( ) , debemos comparar x e y. La funci6n debe devolver 0 si x es igual a y, un numero negativo si es menor y un numero positivo si es mayor. La funci6n devolveri 0,1, o - 1, segun 10s valores de x e Y. La linea final del c6digo llama a la funci6n incorporada de PHP u s o r t ( ) dentro de la matriz que queremos ordenar ( $ p r o d u c t s ) y el nombre de la funci6n de comparaci6n ( c o m p a r e ( ) ). Si quisikramos ordenar la matriz de otra forma, bastaria con escribir una funci6n de comparaci6n diferente. Para ordenar la matriz por el precio, debemos examinar la tercera columna de la matriz y crear la siguiente funci6n de comparaci6n
function c o m p a r e ($x, $y)

3 . Uso de matrices

if ( $x[21 == Sy121 ) return 0; else i f ( $x[21 < Sy[2] return -1; else return 1;

A l l l a m a r a u s o r t ( $ p r o d u c t s , compare),lamatrizseordenardenordenascendente por el precio. La "u" de u s o r t ( ) equivale a "usuario" porque requiere una funci6n de comparaci6n definida por el usuario. Las versiones u a s o r t ( ) y u k s o r t ( ) de a s o r t y k s o r t tambien requieren una funci6n definida por el usuario. A 1 igual que a s o r t ( ) , la funci6n u a s o r t ( ) deberia utilizarse a1 ordenar una matriz asociativa por su valor. Utilice a s o r t si 10s valores son numeros o texto. Defina una funci6n de comparaci6n y utilice u a s o r t ( ) si 10s valores son objetos mds complicados que las matrices. A1 igual que k s o r t ( ) , u k s o r t ( ) deberia utilizarse para ordenar una matriz asociativa por su clave. Utilice k s o r t ( ) si sus claves son numeros o texto. Defina una funcion de comparacidn y utilice u k s o r t ( ) si sus claves son objetos m6s complicados que matrices.

Ordenaciones de usuario inversas


s o r t ( ) ,a s o r t ( ) y k s o r t ( ) tienen funciones inversas que se establecen colocando una "r" delante del nombre de la funci6n. Las ordenacionei definidas por el usuario no disponen de variantes inversas, per0 se puede ordenar una matriz multidimensional en orden inverso. Para ello, bastard con escribir una funci6n de comparaci6n que devuelva 10s valores al reves. Para ordenar una matriz en orden inverso, la funcion tendra que devolver 1 si x es menor que y y - 1 si x es mayor que y. Por ejemplo:
function
{
( $x[2] == $y[2] ) return 0; else if ( $x[21 < $y[21 return 1; else returrt -1;

reverseCompare($x,

$y)

if

La funci6n u s o r t ( $ p r o d u c t s , r e v e r s e c o m p a r e ) dard como resultado una matriz en orden descendente por el precio.

Reordenacion de matrices
En algunas aplicaciones puede que necesitemos manipular el orden de las matrices de varias formas. La funci6n s h u f f l e ( ) reordena de manera aleatoria 10s

Desarrollo W e b con P H P y MySQL

elementos de la matriz. La funcidn array reverse ( ) devuelve una copia de la matriz con todos 10s elementos en brden inverso.

Uso de shuffle()
Bob quiere destacar un n6mero reducido de sus productos en la pfigina principal del sitio. El ntimero de productos que comercializa es grande, per0 quiere seleccionar tres productos de manera aleatoria para que aparezcan en la pfigina principal. Su intencidn es que 10s visitantes que vuelvan a1 sitio vean algo diferente en cada visita y no se aburran. Resultaria muy sencillo conseguir este objetivo si todos 10s productos se incluyeran en una matriz. El listado 3.1 muestra tres imfigenes seleccionadas de manera aleatoria. Para ello, se aplica un orden aleatorio a 10s elementos de la matriz y se muestra el primer0 de 10s tres articulos.
Listado 3.1. bobs-front-page.php. Uso de PHP para generar una pagina principal dinamica en el sitio Bob's Auto Parts
<?php $pictures

a r r a y ( ' t i r e . j p g l , ' o i l . j p g V , 'sparkPplug.jpgl, 'daar.jpg', 'steering-wheel. jpg', 'thermostat.jpg', 'wiper blade. jpg', 'gasket.jpq', 'brake pad. jpg');

srand ( (float)microtime()*l000000); shuffle($pictures);


?>

<html> <head> <title>Bobls Auto Parts</title> </head> <body> <center> <hl>Bobls Auto Parts</hl> <table width = loo%> <tr> <?php for [ $i = 0; $i < 3; $it+ )

i
echo '<td align="center"><img src="'; echo $pictures[$i]; echo '"width="100" height="10OW></td\';

1
?\

</tr> </table> </center> </body> </html>

Como el cddigo selecciona imfigenes aleatorias, genera una pagina diferente prficticamente cada vez que se carga, como se muestra en la figura 3.5.

3. Uso de watrices

Figura 3.5. La funcion shuffle() nos permite mostrar tres productos seleccionados de

manera aleatoria Para que las funciones d e nLimeros aleatorios realicen s u trabajo, es necesario suministrar el generador d e nLimeros primero, llamando a la funcion s r a n d ( ) , como puede apreciar en el listado 3.1. La funci6n s h u f f l e ( ) n o se distingue por s u pasado. En las versiones mcis antiguas d e PHP, n o mezclaba m u y bien 10s resultados aleatoriamente. En la version 4.2.x para Windows n o funcionaba en absoluto (devolvia el inismo resultado inicial). Nuestro consejo es probarla en el servidor para comprobar s u s resultados.

La funcion a r r a y - r e v e r s e ( ) toma una matriz y crea una nueva invirtiendo el orden d e 10s elementos. Por ejemplo, existen varias formas d e crear una matriz que incluya una cuenta a t r . 5 ~ d e d i e c a uno. Si utilizamos r a n g e ( ) iinicamente s e crearci u n a secuencia ascendente. Por ello, debemos utilizar r s o r t ( ) para ordenar 10s nfimeros e n o r d e n descendente. Opcionalmente, podemos crear la matriz elemento a elemento escribiendo u n bucle for:

Los bucles f o r ( ) pueden tener orden descendente como 6ste. Establecemos u n valor alto como valor inicial y a1 final d e cada bucle utilizamos - para reducir el contador a uno. Creamos una matriz vacia y utilizamos a r r a y p u s h ( ) para q u e cada elemento agregue u n o nuevo al final d e una matriz. La f u n z 6 n contraria d e a r r a y p u s h ( ) es a r r a y-p o p ( ) . Esta funcicin elimina y devuelve un elemento desde e l final d e una matriz. Tambien podemos utilizar la funci6n a r r a y-r e v e r s e ( ) para invertir la matriz creada por r a n g e ( ) .

Desarrollo W e b con P H P y MySQL


$numbers $numbers
=

range(1,lO); array reverse($numbers);


-

Recuerde que array r e v e r s e ( ) devuelve una copia modificada de la matriz. Como no queremos la matriz original, almacenamos la nueva matriz sobre el original.

Carga de matrices desde archivos


En un capitulo anterior, almacenamos 10s pedidos de 10s clientes en un archivo. Cada linea del archivo presenta un aspect0 parecido a 6ste:
15:42, 20th April S m a l l t-own 4 tires

1 oil

6 spark

plugs

$434.00 22 Short

St,

Para procesar o servir este pedido, podemos volver a cargarlo en una matriz. El listado 3.2 muestra el archivo actual de pedidos.
Listado 3.2. vieworders.php. Uso de PHP para rnostrar 10s pedidos de Bob
<?php //cree u n nombre d e variable corto $DOCUMENT-ROOT = $HTTP-SERVER-VARS[~DOCIJMENT_ROOT'];

$number -of orders = count ($orders); if [$number-of-orders = = 0 )


-

i
echo

' <p><strong>No o r d e ~ spendinq.


Fiease try ag5in later.i/strong></p>'; $it+)

I
for ($i=O; $i<$nurnber-of-orders;

t
echo $orders[$i].'<br
I
/ > I ;

Esta secuencia de comandos genera pricticamente el mismo resultado que el listado 2.2 del capitulo anterior, que se muestra en la figura 2.4. Esta vez vamos a utilizar la funci6n f i l e ( ) que carga el archivo entero en una matriz. Cada linea del archivo se convierte en un elemento de una matriz. Este c6digo tambikn utiliza la funci6n c o u n t ( ) para comprobar el numero de elementos que contiene una matriz. Adicionalmente, podriamos cargar cada secci6n del pedido en elementos de matriz separados para procesar las secciones de manera independiente o para aplicarles un formato m i s llamativo. Eso es lo que hace el listado 3.3 exactamente.

3. Uso de matrices
<?php //cree un nombre d e variable corto $DOCUMENTPROOT = SHTTP-SERVERPVARS['DOCUMENT-ROOT'];
?>

<html> <head> <title>BoD1s Auto Parts - Customer Orders</title> </head> <body> < h l > B o b l s Auto Fartsc/hl> <h2>Customer Orders</h2> <?php //Lea el archivo completo. //Cada pedido se convierte en ur~ elemento d e la matriz ; $orders= file ( "$DOCUMENTPROOT/. . /circiers.txtT') / / cuerlte el nhmero d e pedidos de la matriz SnunberPof-orders = count($ordersj; if (Srjurnber of-orders == 0 )
P

i
echo '<p><strong>No orders pending. Flease try again later.</strong></p>';

1
echo "<table border=l->\nu; echo '<tr><th bgcolor="#CCCCFF">Order Date</th> <th bgcolor="#CCCCFF">Tires</th> <th bgcolor="#CCCCFF">Oil</th> <th bgcolor=" #CCCCFF">Spark PI ugs</th> <th bgcolor="#CCCCFF">Total</th> <th b g c o l o r = " # C C C C F F " > A d d r e s s . : / t h > <tr>'; for i $ 1 = 0 ; SiiSnumber-of-orders; $it+)

i
//divida cada linea $1 ine = explode ( "\tn , $orders [$i] ) ; / / Mantenga ordenado ~Gr~Lcamente el nhmero d e articulos $line [l] = intvai ( $line [l] ) ; $line [2] = intval ( $line [2] ) ; $line [3] = intval ( $line [3] ) ; / / muestre cada pedido echo "<tr><td>$line[O]</td> i/td> <td align="right">$line [1] <td align="right">$lir~e[2] i/td> <td align="right">$lir~e[3]i/td> <td align="rightV>$line[4].:/td> <td>$line [5] </td> .:/tr>";

I
echo "</table>";
?>

</body> </html>

El codigo del listado 3.3 carga el archivo completo en una matriz per0 a diferencia del ejemplo del listado 3.2, aqui utilizamos la funcion e x p l o d e ( ) para dividir cada linea para poder procesar y aplicar formato antes de impresi6n.

Desarrollo Web coil P H P y MySQL

En la figura 3.6 se ilustra el resultado d e esta secuencia d e coniandos. La funcion


e x p l o d e tiene la siguiente sintaxis:

& c h w Ed#u&n Ver Famdas Herramtentas A y d a

I/Customer Orders
r -

Order Date

-- - -

~ire;,%

i$GiZii&i r T z !

Address

-I

15 42, 20lh ApllI '15 43,201h April

1 6 $434 00 22 Shod St, Smalltown 1 -0 - - 0 $100 00 33 M& Rd. ~ e S & v n 115.43,2 0 1 h ~ ~ 1 l l ~ 6 r l 4 826 00 127 AcactaSI, Springfield -

--

Figura 3.6. Tras dividir 10s registros del pedido con la funcion explode, podemos colocar cada seccion del pedido en una celda de tabla diferente para mejorar su aspect0

En el capitulo anterior, utilizamos el carficter d e tabulacidn como delimitador a1 almacenar estos datos. Por ello, aqui llamanios a: Este cddigo divide las cadenas pasada en partes. Cada cariicter d e tabulacion separa 10s elementos. Por ejemplo, la cadena

se divide en "15:42, 20th April", "4 tires", "1 oil", "6 spark plugs", "$434.00" y "22 Short St, Smalltown". Fijese eg que el parimetro opcional liruite se puede utilizar para restringir el nlimero mfiximo d e partes devueltas. En este cddigo no se ha realizado una gran cantidad de operaciones de procesamiento. En lugar d e devolver 10s articulos en cada linea, s610 mostramos el numero de cada uno y agregamos una fila de encabezados para mostrar qu6 representan. Existen varias formas de extraer numeros de estas cadenas. En este caso, hemos utilizado la funcidn i n t v a l ( ) . Como se menciono en un capitulo anterior, i n t v a l ( ) convierte una cadena en un entero. El proceso d e conversi6n resulta razonablemente inteligente e ignorarfi partes, como la etiqueta d e este ejemplo, que no se pueden convertir en un entero. En el siguiente capitulo abordaremos varias formas de procesar cadenas.

Hasta el momento, s610 hemos analizado aproximadamente la mitad d e las funciones disponibles para el procesamiento d e matrices. Existen otras muchas que resultarin d e utilidad de vez en cuando.

3. Uso de matrices

Navegacion dentro de una matriz con each(),


Ya mencionamos anteriormente que todas las matrices constan de un puntero interno que apunta a1 elemento actual de la matriz. Ya se utilizd antes este puntero indirectamente con la funcidn e a c h ( ) ,per0 podemos utilizarlo directamente y manipularlo. Si crea una nueva matriz, el puntero actual se inicializarii con el puntero a1 primer elemento de la matriz. Si llamamos a c u r r e n t ( Snombre -m a t r i z ) se devolverii la primer elemento. Si llamamos a n e x t ( ) o a e a c h ( ) , el puntero avanzard un elemento. Si llamamos a e a c h ( Snombre mat r i z ) , se devuelve el elemento actual antes de que el puntero avance. La fun& n e x t ( ) se comporta de manera ligeramente diferente: si llamamos a n e x t ( Snombre -mat r i z ) ,el punter0 avanzarii y devolverii el nuevo elemento actual. Ya hemos visto que r e s e t ( ) devuelve el puntero a1 primer elemento de la matriz. De manera similar, si llamamos a e n d ( $nomb re-ma t r i z ) ,el puntero se enviarii a1 final de la matriz. r e s e t ( ) y end ( ) devuelven el primer y el dtimo elemento de la matriz, respectivamente. Para recorrer una matriz en orden inverso, podemos utilizar e n d ( ) y p r e v ( ) . La funcidn p r e v ( ) es la opuesta a la funcidn n e x t ( ) . Mueve el puntero actual un puesto hacia atriis y devuelve el elemento actual. Por ejemplo, el siguiente cddigo muestra una matriz en orden inverso:
$value = end ($array); while ($value)

t
echo "Svaluecbr / > " ; Svalue = prev($array);

Si $ a r r a y se declararade laiguiente forma:


$array
=

arrayil, 2, 3);

El resultado se mostraria en el navegador de la siguiente forma:

Eluso d e e a c h ( ) , c u r r e n t ( ) , r e s e t ( ) , e n d ( ) , n e x t ( ) , p o s ( ) y p r e v ( ) nos permite escribir nuestro propio cddigo para navegar a traves de una matriz en cualquier orden.

Aplicacidn de cualquier funcion a cada elemento de una matriz: array-walk()


En ocasiones, puede que necesitemos trabajar o modificar cada elemento de un matriz de la misma forma. Para ello, podemos utilizar la funcidn a r r a y-walk:

Desarrollo W e b con PHP y MySQL

La sintaxis de esta funci6n es la siguiente:


int array-walkiarray mat, st ring func, [mixed datos-de
-

usuario] )

De manera similar a como hicimos anteriormente a1 llamar a u s o r t ( ) , la funci6n a r r a y walk ( ) espera que declaremos una funci6n propia. Como pu<de apreciar, a r r a y walk ( ) toma tres pardmetros. El primero, mat,es la matriz que se procesard. El seiundo, func, es el nombre de una funci6n definida por el usuario que se aplicard a cada elemento de la matriz. El tercer parametro, dafos-de-usuario, es opcional. Si lo utiliza, se pasard a trav6s de su funci6n como pardmetro. En un instante veremos como funciona. Podriamos crear una funci6n prdctica definida por el usuario que muestre cada elemento con opciones de formato diferentes. El siguiente c6digo visualiza cada elemento en una linea llamando a la funci6n definida por el usuariomyprint ( ) con cada elemento de $ a r r a y :
function myPrint($value)

t
echo "$value<br / > " ;

1
array-walkisarray, 'myprint');

La funci6n debe tener una firma especial. Para cada elemento de la matriz la funcion a r r a y wa 1k toma la clave y el valor almacenado en la matriz y todo lo que pase como datoxde-usuario, y llama a la funci6n de la siguiente forma:
Sufunci6n(valor, clave, d a t o s-d e u s u a r i o )
-

En la mayor parte de 10s casos, la funci6n so10 utilizard 10s valores de la matriz. En algunos casos, puede que tambi6n necesite pasar un pardmetro a la funci6n utilizando el pardmetro datos-de-usuario. En ocasiones puede que est6 interesado en la clave de cada elemento asi como en'su valor. Como en el caso de M y P r i n t ( ) ,la funcidn puede optar por ignorar la clave y el pardmetro datos-de-usuario. Podemos escribir un ejemplo un poco mds complicado, en el que una funcidn modifique 10s valores de las matrices y necesite un pardmetro. Fijese en que a pesar de no estar interesados en la clave, tenemos que aceptarla para poder aceptar el tercer pardmetro.
function myMultiply(&$value, $key, Sfactor)

$value * = Sfactor;

En este ejemplo, se define una funcibn, myMultiply ( ) , que multiplicard cada elemento de la matriz por un factor suministrado. Necesitamos utilizar el tercer pariimetro opcional de array-wal k ( ) para tomar un pardmetro que pasar a nuestra funci6n y utilizarlo como factor por el que multiplicar. Como necesitamos este pardmetro, podemos definir la funci6n myMu 1t i p 1y ( ) para que tome tres

3. Uso d t nzntriccs

parimetros: u n valor d e elemento d e matriz ( $ v a l u e ) , una clave d e elemento d e matriz ( $ k e y ) y otro parimetro ( S f a c t o r ) . Vamos a optar por ignorar la clave. Un punto sutil en el que fijarse es la forma d e pasar $ v a l u e . El simbolo & colocado delante del nombre d e la variable en la definici6n d e m y M u l t i p l y ( ) significa que $ v a l u e se pasar6 por referencia. Este modo d e pasar variables permite que la funci6n modifique 10s contenidos d e la matriz. Analizaremos este mod0 en un capitulo posterior. Por el momento, fijese simplemente en que a1 pasar por referencia se utiliza un simbolo & delante del nombre d e la variable.

C6mo comhr elememtos de una matriz: count(), sizeof(), and arrav , -count-values()
En u n ejemplo anterior utilizamos la funci6n c o u n t ( ) para contar la cantidad d e elementos d e una matriz d e pedidos. La funci6n s i z e o f ( ) tiene el mismo objetivo. Ambas funciones devuelven el numero d e elementos d e una matriz que se le han pasado. Obtendremos 1para el n6mero d e elementos e n una variable escalar normal y 0 si pasamos una matriz vacia o una variable que no se haya establecido. La funcion a r r a y - c o u n t - v a 1 u e s ( ) e s m6s compleja. Si llama a a r r a y - c o u n t - v a l u e s ( $ a r r a y ) , esta funci6n contar6 el numero d e veces que tiene lugar cada valor unico en la matriz $ a r r a y . (Se determina por la cardinalidad d e la matriz). La funcion devuelve una matriz asociativa que contiene una tabla d e frecuencia. Esta matriz contiene 10s valores exclusivos d e S a r r a y como claves. Cada clave tiene un valor numeric0 que indica las veces que tiene lugar la clave correspondiente en $ a r r a y . Por ejemplo, el siguiente c6digo:
3 d r r ; i y = a r r a y ( 4 , 5 , 1, 2 ,
$,I,-:
=

3, 1, 2, 1 ) ;

a r r a y - c c , u n t -v a l u e s ( S a r r a y ) ;

crea una matriz llamada S a c que contiene


- ---

--

clave

valor

Esto indica q u e 4,5 y 3 ocurren una vez en $ a r r y, 1 ocurre tres veces y 2 ocurre dos veces.

Desnrrollo Web con P H P IJ MIJSQL

C o n v e r s i h de matrices en variables escalares: wtract()


Si tenemos una matriz asociativa con una serie d e pares d e valor y clave, podemos convertirlas e n u n conjunto d e variables escalares utilizando la funcion
extract ().

Esta funcidn tiene la siguiente sintaxis:

El objetivo d e e x t r a c t

()

es tomar una matriz y crear variables escalares con

10s nombres d e las claves d e la matriz. Los valores d e estas variables se establecen en funcidn d e 10s valores d e la matriz. A continuacidn se incluye un ejemplo:

Este c6digo genera el siguiente resultado:

La matriz tiene tres elementos con claves: k e y l , k e y 2 y k e y 3 . La funci6n e x t r a c t ( ) nos permite crear tres variables escalares, $ k e y l , $ k e y 2 y $ k e y 3 . Por el resultado podemos ver que 10s valores d e $ k e y l , $ k e y 2 y $ k e y 3 son 'valuel', 'value2' y 'value3', respectivamente. Estos valores proceden de la matriz original. La funcion e x t r a c t ( ) consta d e dos parametros opcionales: tipo-extraccidn y prefijo. La variable t i p 0 e x t ~ a c c i o n indica a e x t r a c t ( ) c6mo resolver las colisiones. st as tienen lugar cuando ya existe una variable con el mismo nombre que una clave. La respuesta predeterminada consiste en sobrescribir la variable existente. En la tabla 3.1 se recogen 10s valores posibles de este parimetro.

.Tabla 3.1. Valores permitidos del parametro tipos-extraccion de la funcion extract()

r--Tipo
EXTR-OVERWRITE
EXTR-SKIP

Significado
Sobrescribe la variable existente cuando tiene lugar una colision. Salta un elemento cuando tiene lugar una colision. Crea una variable denominada $ p r e f ix-key cuando tiene lugar una colision. Se debe incluir el parametro pref ij0 . Coloca delante de todos 10s nombres de variables el valor del p r e f i j o. Se debe incluir el parametro p r e f i j o.

EXTR-PREFIX-SAME EXTR-PREFIX-ALL

Tipo
EXTR-IF-EXISTS

Significado Extrae solamente variables que ya existen (es decir, rellena las variables existentes con valores procedentes de la matriz). Esta opcion s e agrego a la version 4.2.0 y resulta ~itil para convertir, por ejemplo, $-REQUEST en u n conjunto de variables validas.
i ya existiese una version Solo crea una version con prefijo s sin prefijo. Esta opcion s e agrego en la version 4.2.0.

EXTR-PREFIX-IF-EXISTS

EXTR-REFS

Extrae variables como referencia. Esta opcion s e agrego en la version 4.3.0.

Las opciones m i s Gtiles son las predeterminada, EXTR OVERWRITE, y EXTR PREFIX-ALL. Las otras funciones pueden resultar de uclidad si sabemos que s e v a a producir una colisi6n y queremos saltarla o utilizar prefijos. A continuaci6n se recoge u n sencillo ejemplo utilizando EXTR P R E F I X ALL. Como puede observar, las variables creadas se denominan prefix-fui6n bajoInombre d e clave.

Este c6digo devolvera d e nuevo v a l u e 1 v a l u e 2 v a l u e 3 . Tenga en cuenta que para que e x t r a c t ( ) extraiga u n elemento, la clave d e dicho elemento debe ser un nombre vilido d e variable, lo que significa que se no se tendrsn en cuenta las claves que comiencen por n6meros o que incluyan espacios.

En este capitulo se trata lo que e n nuestra opini6n son las funciones d e matriz mfis utiles d e PHP, per0 no se han estudiado todas. En el manual en linea d e PHP, disponible en h t t p : / /www p h p n e t / a r r a y , encontrari una breve descripci6n d e todas ellas.

En el siguiente capitulo se analizarin las funciones d e procesamiento. Veremos c6mo realizar operaciones d e busqueda, sustitucion, divisi6n y combinaci6n d e cadenas. Asi mismo, se examinarin las potentes funciones d e expresiones regulares capaces de realizar pricticamente cualquier operaci6n sobre una cadena.

En este capitulo, veremos c6mo puede utilizar las funciones de cadena de PHP para aplicar formato y manipular texto. Tambikn veremos c6mo utilizar funciones de cadena o funciones de expresiones regulares para buscar (y reemplazar) palabras, frases y otros patrones dentro de una cadena. Estas funciones resultan utiles en muchos contextos. Con frecuencia se suele limpiar o modificar el formato de 10s datos recibidos de 10s usuarios para almacenarlos en una base dedatm. Las funciones de busqueda son magnificas para crear motores de busqueda (entre otras cosas). En este capitulo, analizaremos 10s siguientes aspectos: Formato de cadenas Combinaci6n y divisi6n de cadenas Comparaci6n de cadenas Coincidencia y sustituci6n de subcadenas con funciones de cadena Uso de expresiones regulares

Aplicaci6n de ejemplo: Smart Form Mail


En este capitulo, vamos a examinar las funciones de cadena y de expresiones regulares en el context0 de la aplicaci6n Smart Form Mail. Agregaremos estas se-

cuencias d e comandos a1 sitio Bob's Autor Parts que hemos desarrollado en 10s 61timos capitulos. E n concreto, varnos a crear un sencillo torrnulario para que 10s clientes d e Bob expsesen sus quejas y agradecirnientos, corno se ilustra en la figura 4.1. Sin embargo, nuestra aplicaci6n incorporarci una mejora con respecto a 10s forrnularios d e este tiyo que se incluyen e n la Web. En lugar d e remitir el formulario For correo electr6nico a una direcci6n gen6rica corno i n f o r m a c i o n @ e j e m p l o com, intentaremos que s u procesamiento resulte mas avanzado. Para ello, se analizara el texto en busca d e palabras clave y frases, y se rernitirci el correo electr6nico a1 ernpleado apropiado d e la compariia d e Bob. Por ejemplo, si el correo contiene la palabra "avertising", el formulario podria dirigirse a1 departarnento d e marketing - Si el correo procede d e un cliente importante, se &rigi& dirictamente a Bob.

1 Customer Feedback
Your name:
Your email address

RI
feedback:

~end?eedback

Figura 4.1. El formulario para comentarios de Bob pregunta a 10s clientes su nombre, direccion de correo electronico y comentarios

Cornenzarernos por la sencilla secuencia d e cornandos que se rnuestra en el listado 4.1 e iremos agregando elementos progresivarnente.
Listado 4.1. processfeedback.php: secuencia de comandos basica de Email Forms Contents

Desarrollo Web con PHP y MySQL


Srnailcontent 'Customer name: '.$name."\n" .'Customer ernail: '.Semail."\n" ."Customer commerits: \n".Sfeedback."\n"; 'From: webserver@example.corn';

Sfromaddress

mail [Stoaddress, Ssubj ect, Smailcontent, Sfromaddress) ;


?>

<html> <head> < t i t l e > B o b l s Auto Parts - Feedback Submitted</title> </head> <body> <hl>Feedback submitted</hl> <p>Your feedback has been sent.</p> </body> < / html>

Por regla general, deberia comprobar si 10s usuarios han rellenado todos 10s campos obligatorios del formulario con ayuda de isset ( ) ,por ejemplo. Hemos omitido esta operaci6n en la secuencia de comandos asi como en otros ejemplos para no alargar el andlisis. En esta secuencia de comandos, hemos concatenado 10s campos del formulario y hemos utilizado la funci6n mail ( ) de PHP para enviar un correo electronic0 a informaci6nee j emplo .com.A continuaci6n, analizaremos la funci6n mail ( ) . La funci6n mai 1 ( ) envia correos electrbnicos. Su sintaxis es la siguiente:
boo1 mail (string to, string t e m a , string m e n s a j e , string [ e n c a b e z a d o s a d i c i o n a l e s [ , string p a r i r n e t r ~ s ~ a d i c i o n a i e ]s )] ;

Los primeros tres parbmetros son obligatorios y representan la direcci6n a la que dirigir el correo electr6nic0, la linea de asunto y 10s contenidos del mensaje, respectivamente. El cuarto pardmetro se puede utilizar para enviar otros encabezados vblidos. Los encabezados vdlidos de correo electr6nicos se describen en el documento RFC822, que estd &sponible en linea si desea obtener mds detalles. (Los RFC o Solicitudes de comentarios son la fuente de una gran cantidad de estdndares de Internet, como se comentard en un capitulo posterior.) Aqui hemos utilizado el cuarto pardmetro para agregar una direccidn "From: " a1 correo electrbnico. Tambi6n puede utilizarlo para agregar campos "Reply-To: " y "Cc:",entre otros. Si desea incluir mbs de un encabezado, s610 serb necesario separarlos mediante caracteres de nueva linea (\n)en la cadena, de la siguiente forma:

El quinto parbmetro se puede utilizar para pasar otro argument0 a1 programa que tenga configurado para enviar correo. Para poder utilizar la funci6n ema il ( ) ,configure su instalaci6n de PHP para que apunte a1 programa utilizado para enviar correos electr6nicos. Si la secuencia de comandos no funciona correctamente, consulte el apendice A. A lo largo de este capitulo, optimizaremos esta secuencia de comandos bdsica utilizando funciones de procesamiento de cadenas y expresiones regulares de PHP.

4 . Manipulacio'n de cadenas y expresiones regulares

Aplicacion de formato a cadenas


A menudo es necesario limpiar las cadenas que envian 10s usuarios (por regla general procedentes de una interfaz de formulario HTML) para poder utilizarlas.

Limpieza de cadenas: chop(), Itrim() y trim()


El primer paso del proceso de limpieza consiste en quitar todos 10s espacios en blanco no necesarios de la cadena. Aunque no resulta obligatorio, puede resultar util si se va a almacenar la cadena en un archivo o base de datos, o si vamos a compararla con otras cadenas. PHP incorpora tres funciones que resultan de utilidad en este sentido. Utilizaremos la funci6n t r i m ( ) para limpiar 10s datos de entrada de la siguiente forma:

La funci6n t r i m ( ) elimina 10s espacios en blanco desde a1 principio a1 final de una cadena, y devuelve la cadena resultante. De manera predeterminada, limpia 10s caracteres de nueva linea y retorno del carro ( \ n y \ r), tabuladores horizontales y verticales ( \ t y \v), caracteres de final de cadena ( \ 0 ) y espacios. Tambikn permite pasar un segundo parimetro para incorporar otros caracteres que eliminar a la lista predeterminada. Existen otras funciones l t r i m ( ) o chop ( ) que puede utilizar. Ambas son similares a t r i m ( ) :toman la cadena en cuesti6n como parimetro y devuelven la cadena con formato. La diferencia entre estas tres es que t r i m ( ) elimina 10s espacios en blanco desde el principio a1 final de la cadena, 1t r i m ( ) elimina 10s espacios en blanco desde el principio (.o desde la izquierda) unicamente y c h o p ( ) elimina 10s espacios en blanco desde el final (o desde la derecha) Gnicamente.

Aplicaci6n de formato a cadenas para presentaciones


PHP consta de un conjunto de funciones que permiten volver a aplicar formato a una cadena de diferentes formas. Uso

de formato HTML: la funcion nl2br()

La funcidn n l 2 b r ( ) toma una cadena como pardmetro y sustituye todas las lineas nuevas con la etiqueta XHTML < b r / > (o la etiqueta < b r > en las versiones anteriores a la 4.0.5). Esta funci6n resulta util para imprimir una cadena de gran tamaiio en el navegador. Por ejemplo, hemos utilizado esta funci6n para aplicar formato a la informaci6n recibida del cliente y devolverla:
<p>Your feedback (shown below) has been <p><? echo nl2br($rnailcontent); ?> </p> sent.</p>

Desarrollo Wcb con P H P y MySQL

Recuerde que HTML no tiene e n cuenta 10s espacios en blanco sin procesar, por lo que si 11o filtramos este resultado a travgs de n l 2 b r ( ) , aparecerin en una sola linea (a excepcion d e las lineas nuevas forzadas por la ventana del navegador), como se ilustra e n la figura 4.2.

Aplicacicin cle frwtnnho a una cadena para c u irnprcsion


Hasta el momento, hemos utilizado la instrucci6n echo para mostrar cadenas en el navegador. PHP tambien incluye la instrucci6n print ( ) , que realiza la misma funci6n que echo, per0 devuelve un valor ( t r u e o f a l s e , para denotar el resultado d e la operaci6n).

Customer name: Jane Smith Customer m a i l : jane@somewhere Customer conunenls: Thank you for provicling elech.ouic ordering on your websitc. With nlZbr: Customer name: Jane Smith Customer email: jane@somewhere Customer comuenls: Thank you for providing elecbotlic ordering on y o w website.

Figura 4.2. El uso de la funcion nl2br() rnejora la representacion de cadenas largas dentro de HTML

Estas dos t6cnicas imprimen una cadena sin mfis. Puede aplicar formato mAs sofisticado utilizando las.funoiones p r i n t f ( ) y s p r i n t f ( ) . st as funcionan bssicamente d e la misma forma, con la excepcion d e que la primera imprime una cadena con formato en el navegador y la segunda devuelve una cadena con formato. Si ha programado previamente en C, observarfi que estas funciones son iguales que sus versiones d e C. Si no lo ha hecho, lleva cierto tiempo acostumbrarse per0 resultan fitiles y potentes. Las sintaxis d e estas funciones es la siguiente:

El primer parsmetro pasado a ambas funciones es una cadena d e formato que describe la forma b6sica del resultado con c6digo d e formato e n lugar d e variables. Los demds par6metros son variables que se sustituirsn e n la cadena d e formato. Por ejemplo, con echo,utilizamos las variables deseadas para imprimir en linea. Por ejemplo:

4 , Mnt~ip~rlacibtr de mdenns y a p r e s i o n e s regrrlnres

Para obtener el mismo resultado con p r i n t f ( ) ,se utilizari:

La secuencia Gs utilizada en la cadena de formato se denomina especificaci6n d e conversi6n. Su objetivo es "ser reemplazada por una cadena". En este caso, s e r i sustituida con $ t o t a l , interpretada como una cadena. Si el valor almacenado en $ t o t a l fuera 12.4, ambas instrucciones imprimirian 12.4. La ventaja d e p r i n t f ( ) es que podemos utilizar una especificaci6n d e conversi6n m i s util para especificar que $ t o t a l es un numero d e coma flotante y que deberia constar d e dos decimales tras el punto, como se indica a continuation:

La cadena d e formato puede incluir varias especificaciones d e conversi6n. Si tenemos n especificaciones d e conversi6n, tendri n argumentos tras la cadena d e formato. Cada especificaci6n d e conversi6n s e r i reemplazada por un argument0 con nuevo formato en el orden e n el que se liste. Por ejemplo:

Las especificaciones de conversi6n utilizarin la variable $ t o t a l per0 en la segunda se utilizarii la variable $ t o t a l s h i p p i n g . Cada especificaci6n d e conversi6n s&ue el mismo formato, a saber:

Todas las especificaciones d e conversi6n comienzan por un siinbolo % .Si desea imprimir un simbolo 3, necesitari utilizar 9, A . El caricter de rellcno es opcional. Se utilizari para rellenar 10s espacios de la variable con la anchura especifirada. Por ejemplo, podemos agregar ceros iniciales a un n6mero en un contador. El simbolo - es opcional. Especifica que 10s datos del campo se justificarin a la izquierda, en lugar d e a la derecha (opci6n predeterminada). El especificadoramhura indica a p r i n t f ( ) el espacio (en caracteres) que se debe dejar para que la variable se sustituya. El especificador precisidiz deberia comenzar por una coma decimal. Deberia contener el nilmero d e espacios deseados tras la coma decimal. La parte final d e la especificaci6n es un c6digo d e tipo. En la tabla 4.1 se recoge un resumen.
Tabla 4.1. Codigos de tipo de especificacion de conversion

Se interpreta carno u n entero y se imprime como u n numero binario. Se interpreta como u n entero y se imprime como u n caracter.

Desnrrollo W e b con P H P y MySQL

S e interpreta como u n entero y s e imprime como u n numero decimal. S e interpreta como u n doble y s e imprime como u n numero con coma flotante. S e interpreta como u n entero y s e imprime como u n numero octal. s Se interpreta como una cadena y se imprime como una cadena S e interpreta como u n entero y s e imprime como u n numero decimal con minusculas para 10s digitos a-f. S e interpreta como u n entero y s e imprime como u n numero hexadecimal con mayusculas para 10s digitos A-F. Desde la versicin 4.0.6 se puede utilizar la numeraci6n d e argumentos, lo clue significa que no es necesario utilizar el mismo orden que las especificaciones d e conversion. Por ejemplo:

Basta con agregar la posicion del argument0 directamente tras el simbolo E, seguido por el cariicter d e escape $. En este caso, 2\$ significa "sustituir con el segundo argumento d e la lista". Este m6todo tambien se puede utilizar para repetir argumentos.
~ ~ , i , - ~r ~ ' d > ~ i , ,

vi,i\,t,\,

3 ,

rnin(r\,.t~l,>c

$\rj I J ~ , >

--

~ . , : d ~ ~ t ~ ~

Podemos modificar el uso & mayusculas y minlisculas en una cadena. Este recurs o n o resulta especialmente util en nuestra aplicacion, pero examinaremos algunos ejemplos. Si comenzamos por la cadena del tema, $ s u b j e c t , que vamos a utilizar e n nuestro correo electr6nic0, podemos cambiar el formato d e mayusculas y m i n ~ s c u l a s con ayuda d e varias funciones. El efecto d e estas funciones se resume e n la tabla 4.2. La primera columna muestra el nombre d e la funcion, la segunda describe s u efecto, la tercera muestra c6mo se aplicara a la cadena $ s u b J e c t y la ultima indica que valor se devolverii d e la funci6n.
Tabla 4.2. Funciones para la aplicacion de mayusculas y minusculas a cadenas y sus

efectos

$subject

Information procedente del sitio Web

Funcion
strtoupper ( )

escripci6n Convierte la cadena en rnayusculas Convierte la cadena en rninusculas Pone en rnayusculas el primer caracter de la cadena si es un caracter alfabetico

Us0
strtoupper ($subject) strtolower ($subject) ucf irst ($subject)

Valor INFORMACION PROCEDENTE DEL SlTlO WEB Inforrnacion procedente del sitio W e b inforrnacion procedente del sitio W e b

strtolower ( )

ucfirst ( )

ucwords ( )

Pone en rnaylisculas ucwords ($subject) la prirnera letra de cada palabra de la cadena que cornience por un caracter alfabetico

Inforrnacion Procedente Del Sitio W e b

Adem6s d e utilizar funciones d e cadena para modificar el formato d e las cadenas visualmente, podemos utilizar parte d e estas funciones para variar el formato d e cadenas para SLI almacenamiento en una base d e datos. Aunque el tema d e la escritura d e cadenas en bases de datos no se examinari hasta la segunda parte de este libro, seguidamente analizaremos c6mo aplicar formato a cadenas para su almacenamiento en bases d e datos. Determinados caracteres s o p perfectamente vtilidos como parte d e una cadena per0 pueden originar problemas, en especial a1 insertar datos en una base d e datos ya que esta podria interpretarlos como caracteres d e control. Los caracteres problerniticos son las comillas (simples o dobles), las barras invertidas y el car6cter NUL. Debemos buscar una forma d e marcar estos caracteres para indicar a las bases d e datos, como MySQL, que se trata d e caracteres especiales y no d e una secuencia d e control. Para marcar estos caracteres corno caracteres especiales, se agrega una barra invertida delante de ellos. Por ejemplo, las comillas dobles ( " ) se convertirtin en \ " (barra invertida seguida de las comillas dobles) y la barra invertida ( \ ) se convierte en \ \ (doble barra invertida). (Esta regla se aplica universalmrnte 10s caracteres especiales, d e manera que si tiene \ \ en una cadena, debera sustituirla por \ \ \ \ . ) PHP incorpora dos funciones especificamente disefiadas para marcar caracteres especiales. Antes d e escribir cadenas en una base d e datos, deberia modificar SLI formato con la funci6n AddSlas hes ( ), por ejemplo:

Drstrvrollo W e b con P H P y M!ySQL


~ ~ ~~

Como muchas otras funciones d e c a d e n a , ~ d d ~ lh aess ( ) toma una cadena con10 pardmetro y devuelve la cadena con formato nuevo. A1 utilizar A d d s l a s h e s ( ) , la cadena se almacenari e n la base d e datos con las barras. Al recuperar la cadena, deberci acordarse de quitar dichas barras. Para ello puede utilizar la funci6n S t r i p s l a s h e s ( ) :
:fc.~dk.?,:~
=

St:ipSl,~~t~r~!?(::fe+?.:ik~a::l:;;

La figura 4.3 muestra 10s efectos d e utilizar estas funciones e n la cadena.

Customer feedhack hefore AddSlnshes: Your customer service I-epresentalive told me. "We don't give any g~nrantees." What kind of service is hat?

I
I

Customer feedback after AddSIashes: Your customer senice I-epreserilalive told me, \"We dorr\'t give my gunranlnlecs.\" R%atkind of sewice is that'?

Your custorner service repl-esentative told me, 'We don't give any guamlees." What kind orscn,ice is hat?

Figura 4.3. Tras llamar a la funcion AddSlashesO, se colocaran barras delante de todas las comillas. La funcion StripSlashes() quitara las barras

Tambien puede configurar PHP para agregar y quitar barras automiticamente. Esta funci6n se conoce como_comillas migicas y cornentar6 en mayor detalle en u n capitulo posterior.

A menudo, necesitamos examinar partes d e una cadena por separado. Por ejemplo, puede que necesitemos examinar las palabras d e una frase (para cornprobar s u ortografia, por ejemplo) o dividir u n nombre o una direccidn d e correo electrdnico en sus componentes. PHP incorpora varias funciones d e cadena (y una funcion d e expresi6n regular) que nos permite realizar esta tarea. En nuestro ejemplo, Bob quiere recibir todos 10s comentarios procedentes de b i g c u s t o m e r . comdirectamente, por lo que dividiremos la direcci6n d e correo electr6nica escrita por el cliente e n partes para determinar si se trata d e clientes importantes d e Bob.

4. Manipulacidn de cadenas y expresiones regulares

Uso de explode(), implode() y ioin()


La primera funci6n que podriamos utilizar para este objetivo es explode ( ) cuya sintaxis es la siguiente:
array explode (string separador, string en trada
[,

int

1 imi te] ) ;

Esta funci6n toma una entrada de cadena y la divide en partes en una cadena de separador especificada. Las partes se reunen en una matriz. Puede limitar el numero de partes con el parfimetro opcional de limitacibn, agregado en PHP 4.0.1. Para obtener un nombre de dominio de la direcci6n de correo electr6nico del cliente en su secuencia de comandos, podemos utilizar el siguiente c6digo:

Esta llamada a la funci6n explode ( ) divide la direcci6n de correo electr6nico del cliente en dos partes: el nombre de usuario, que se puede almacenar en $email a rra y [ 0 ] y el nombre de dominio en $ ema i1 array [ 1] . Ahora ya podemos bar el nombre de dominio para determinar el orTgen del cliente y enviar sus comentarios a la persona apropiada.
(Semall array[l]=='b~gcustomer.com') Stoaddress = 'bob@example.com'; else Stoaddress = 'feedback@example.c n m ' ;
lf
-

Si el dominio estuviera en mayusculas, la operaci6n no funcionaria. Podemos evitar este problema convirtiendo el dominio a todo maydsculas o todo minusculas y realizar la comprobaci6n seguidamente:
$email-array[ll
=

strtoupper ($email-array[ll);

Puede invertir 10s efectos de explode ( ) utilizando las funciones implode ( ) o join ( ) ,que son idbnticas. Por ejemplo:

Este c6digo toma 10s elementos de la matriz $ email array y 10s combina con la cadena pasada en el primer parfimetro. La llamada a l a funci6n es muy similar a explode ( ) , per0 el efecto es el contrario.

Uso de strtok()
A diferencia de explode ( ) ,que divide una cadena en pequefias partes de una sola vez, strto k ( ) va extrayendo partes (llamadas simbolos) de la cadena una a una. Esta funci6n es una alternativa util a la'funci6n explode ( ) para procesar una cadena palabra a palabra. La sintaxis d e la propiedad strto k ( ) es la siguiente:
string strtok (string entrada, string separador) ;

Desarrollo Web con PHP y MySQL

El separador puede ser un cardcter o una cadena de caracteres pero la cadena de entrada se dividird en cada uno de 10s caracteres de la cadena del separador en lugar de en toda la cadena (como ocurria con e x p l o d e ) . La tarea de llamar a la funci6n s t r t o k ( ) no resulta tan sencilla como pudiera parecer por su sintaxis. Para obtener el primer simbolo de una cadena, se invoca s t r t o k ( ) con la cadena divida en las partes deseadas y un separador. Para obtener las siguientes partes de la cadena, se pasa u n 6nico pardmetro: el separador. La funci6n mantiene su propio puntero interno dentro de la cadena. Si desea restablecer el puntero, puede pasarle la cadena de nuevo. La funci6n s t r t o k ( ) se suele utilizar de la siguiente forma:
$token = strtok ($feedback, ' echo $token.'<br / > I ; while ($token!='')

' );

I
$token = strtoki' echo $token.'<br /
');
> I ;

i;

Como de costumbre, conviene comprobar que el cliente ha escrito alg6n comentario en el formulario, utilizando la funci6n e m p t y ( ) . En nuestro caso se ha omitido para no alargar el ejemplo. Este c6digo imprime cada simbolo del comentario del cliente en una linea distinta y recorre en bucle el comentario hasta que no quedan m6s simbolos. En las versiones de PHP anteriores a la 4.1.0, s t r t o k ( ) no funcionaba de forma exactamente igual a como lo hace en C. Si una cadena de destino contiene dos instancias de un separador seguidas (en este caso dos espacios), s t r t o k ( ) devuelve una cadena vacia. Este resultado no se puede diferenciar de la cadena vacia que se devuelve a1 llegar a1 final de la cadena de destino. Asi mismo, si uno de 10s simbolos es 0, se devolverd la cadena vacia. Esto convierte a la funci6n s t r t o k ( ) de PHP en algo menos util que la de C. La nueva versi6n funciona correptamente ya que salta las cadenas vacias.

Uso de su bstr()
La funci6n s u b s t r ( ) permite acceder a una subcadena situada entre el punto inicial y el punto final de una cadena. En nuestro ejemplo no resulta apropiado pero puede ser util si intenta acceder a partes de cadenas con formato fijo. La funci6n s u b s t r ( ) tiene la siguiente sintaxis:
string substr (string cadena, int ~ n i c i o [ , int lonyi t u d ]
) ;

Esta funci6n devuelve una subcadena copiada de cadena. Si se llama a esta funci6n con un n6mero positive desde el par6metro inicio (6nicamente), se obtendr6 la cadena desde la posici6n inicio hasta el final de la cadena. Por ejemplo:

4 . Manipulacidn de cadenas y expresiones regulares

devuelve our customer service is excellent. Tenga en cuenta que la , como ocurre con las matrices. posici6n inicial es 0 Si llama a la funci6n subst r ( ) con un valor inicio negativo (Gnicamente), obtendrii la cadena desde su final menos 10s caracteres inicio hasta el final de la cadena. Por ejemplo:

En este caso se devuelve exce 11en t. El pariimetro de longitud se puede utilizar para especificar un nGmero de caracteres que devolver (si es positivo) o el cariicter final de la secuencia de retorno (si es negativo). Por ejemplo:
s u b s t r ( $ t e s t , 0,
4 ;

devuelve 10s primeros cuatro caracteres de la cadena, en concreto, Your. El siguiente c6digo:
echo substr($test,
4,

-13);

devuelve 10s caracteres situados entre el cuarto y el cariicter decimotercero, es decir, customer service.

Hasta el momento s610 hemos utilizado el operador == para comparar si dos cadenas son iguales. Pero PHP permite realizar comparaciones un poco miis avanzadas. Las hemos dividido en dos categorias: coincidencias parciales y otras. En primer lugar estudiaremos las demiis y 2eguidamente pasaremos a estudiar las coincidencias parciales, para lo cual atanzaremos en el desarrollo del ejemplo Smart Form.

Estas funciones se pueden utilizar para ordenar cadenas y, por tanto, para ordenar datos. La sintaxis de la funci6n st rcmp ( ) es la siguiente:
i n t strcrnpistring strl, s t r i n g str2);

La funci6n espera recibir dos cadenas, que compararii. Si son iguales, devolverii
0. Si la cadena st rl viene tras (o es mayor que) str2 en orden lexicogriifico, st rcmp ( ) devolverii un nGmero mayor que cero. Si str 1 es menor que str 2 , strcmp ( ) devolverii un nGmero menor que cero. Esta funci6n discrimina entre ma-

yGsculas y minGsculas.

La funci6n strcasecmp ( ) es idkntica con la diferencia de que no discrimina entre mayusculas y minusculas. La funcion strcasecmp ( ) y su pareja strnatcasecmp ( ) , que no discrimina entre mayusculas y minusculas, se agregaron en PHP 4. Estas funciones comparan cadenas en funci6n de un "orden natural", que se parece mtis a la forma en la que lo hace un humano. Por ejemplo, st rcmp ( ) ordenarti la cadena " 2 " como mayor que la cadena " 12 " porque lexicogrtificamente resulta mayor. strcasecmp ( ) hace exactamente lo contrario. Si desea saber mtis sobre el orden natural, dirijase a http: //www.naturalordersort. org/.

Comprobacion de la longitud de una cadena con strlen()


Podemos comprobar la longitud de una cadena con la funci6n strlen ( ) . Si se pasa en una cadena, devolverti su longitud. Por ejemplo, strlen ( ' hello ' ) devuelve 5. Esta funci6n se puede utilizar para validar datos de entrada. Considere la direcci6n de correo electr6nico de nuestro formulario, almacenada en $email.Una forma elemental de validar una direcci6n de correo electr6nico almacenada en $email consiste en comprobar su longitud. Si partimos de unos ctilculos aproximados, la longitud minima de una direcci6n de correo electr6nico es de seis caracteres, por ejemplo a @a.to (suponiendo que el c6digo del pais no tiene dominios de segundo nivel, y que el nombre del servidor y la direcci6n s610 tienen una letra respectivamente). Por lo tanto, si la direcci6n no tiene esta longitud minima, se generarti un error:
I
I

echo 'That email address is not valld'; exit; / / fir~alice la ejecuci6n d e la secuencia d e comandos d e P H E

Obviamente, se trata de una forma muy simple de validar la informaci6n. En la siguiente secci6n examinaremos formas mejores.

Como buscar subcadenas y reemplazarlas con funciones de cadena


Resulta habitual comprobar si una subcadena dada estti presente en una cadena de mayor tamafio. Esta coincidencia parcial suele ser mtis util que comprobar la igualdad entre cadenas. En nuestro ejemplo Smart Form, queremos buscar determinadas frases clave dentro de 10s comentarios de 10s clientes y enviar el correo a1 departamento adecuado. Si

4. Manipulacidn de cadenas y expresiones regulares

queremos enviar correos electr6nicos relacionados con las tiendas de Bob a1 encargado del departamentos de ventas, tendremos que saber si aparece la palabra "shop" (o alguna variaci6n) en el mensaje. Podriamos utilizar funciones ya vistas, como e x p l o d e ( ) o s t r t o k ( ) para recuperar palabras individuales del mensaje y compararlas utilizando el operador == o s t r c m p 0 . Sin embargo, podemos hacer lo mismo con una unica llamada de funci6n a una de las funciones de comparacidn de cadenas o de expresiones regulares. h t a s se utilizan para buscar un patr6n dentro de una cadena. Examinaremos cada conjunto de funciones por separado.

Busqueda de cadenas en cadenas: strstro, strchr(), strrchr(), stristro


Para buscar una cadena dentro de una cadena, podemos utilizar cualquiera de las funcionesstrstr ( ) , s t r c h r ( ) , s t r r c h r ( ) o s t r i s t r 0. La funci6n s t r s t r ( ) es la mhs generica y se puede utilizar para buscar una cadena o caracter dentro de una cadena d e mayor tamafio. Tenga en cuenta que en PHP, la funci6n s t r c h r ( ) es exactamente igual que la funci6n s t rs t r ( ) ,aunque su nombre implique que se utiliza para buscar un carhcter en una cadena, de manera similar a la versi6n de C de esta funci6n. En PHP, se pueden utilizar las dos funciones para buscar una cadena dentro de otra cadena, incluyendo la posiblidad de buscar una cadena que contenga un solo carhcter. La sintaxis de s t r s t r ( ) es la siguiente:
string strstr(string pajar, string aguja);

En la funci6n se pasa el parhpetro pajar sobre el que buscar y un parhmetro aguja que encontrar. Si se encuedra una coincidencia exacta de aguja, la funcidn devolverh el pajar desde la aguja en adelante o, de lo contrario, devolverh f a 1 s e . Si la aguja tiene lugar en mhs de una ocasibn, la cadena devuelta comenzarh desde la primera ocurrencia de aguja. Por ejemplo, en la aplicaci6n Smart Form, podemos decidir d6nde enviar el correo electr6nico d e la siguiente forma:
Stoaddress
=

'feedback@exarnple.cornl;

/ / el valor predeterninado

/ / Cambie Stoaddress si s e curnple el criterio if (strstrisfeedback, 'shop')) Stoaddress = 'retail@exarnple.cornl; else if (strstriSfeedback, 'delivery')) Stoaddress = 'fulfilment@example.corn'; else if (strstrisfeedback, 'bill')) 'accounts@example.corn'; Stoaddress =

Este c6digo busca determinadas palabras claves en el comentario del usuario y envia el correo a la persona adecuada. Por ejemplo, si el cliente escribe "I still haven't

Desarrollo W e b con P H P y MySQL


received delivery of my last order" (todavia no he recibido mi tiltimo pedido), se detectar6 la cadena "delivery" (entrega) y el comentario se e n v i a r i a fulfilment@example.com. Existen dos variantes de st rstr ( ) . La primera es stri st r ( ) , que es pricticamente idbntica con la salvedad de que no distingue entre maytisculas y mintisculas. Esta funci6n resulta titil en nuestra aplicaci6n ya que el cliente podria escribir 'delivery', 'Delivery' o 'DELIVERY'. La segunda variante es st rrchr ( ) , que es, de nuevo, pricticamente idhtica, per0 devuelve pajar desde la tiltima ocurrencia de la aguja en adelante.

usqueda de la posicion de una subcadena: str


Las funciones st rpos ( ) y st rrpos ( ) funcionan de la misma forma que st rs t r ( ) , con la diferencia de que en lugar de devolver una subcadena, devuelven la posici6n numbrica de una aguja en un pajar. La funci6n st rpos ( ) tiene la siguiente sintaxis:
i r ~ t s t r p o s ( s t r i r ~ y pajar-, s t r i n g

ayuja,

int

[desplazamienrsl

) ;

El valor entero devuelto representa la posici6n de la primera ocurrencia de aguja dentro de pajar. El primer caricter es la posici6n 0 como de costumbre. Por ejemplo, el siguiente c6digo imprimiri el valor 4 en el navegador:
$ t e s t = 'Hello w ~ ~ r l d ' ; e c h o s t r p o s ( $ t ~ s t ,' 0 ' 1 ;

En este caso, s610 hemos pasado un caricter como aguja, per0 puede ser una cadena de cualquier longitud., El parimetro opcionai de desplazamiento se utiliza para especificar un punto dentro de pajar a partir del cual iniciar la btisqueda. Por ejemplo:

Este c6digo imprimiri 7 en el navegador porque PHP ha comenzado a buscar el caricter o en la posici6n 5 y, por lo tanto, no veri el situado en la posici6n 4. La funci6n st rrpos ( ) es pricticamente idbntica, per0 no devuelve la posici6n de la ultima ocurrencia de aguja en pajar. A diferencia de s t r p o s o , s610 funciona con un unico caricter aguja. Por lo tanto, si la pasamos en una cadena como aguja, s610 utilizari el primer caricter de la cadena para establecer la coincidencia. En cualquiera de estos casos, si aguja no esti en la cadena, s t rpos ( ) o st rrpos ( ) devolveri fa1se,lo cual puede plantear un problema porque fa1se en un lenguaje con control debil de tipos como PHP equivale a 0, es decir, a1 primer caricter de una cadena. Para evitar este problema podemos utilizar el operador === y probar 10s valores devueltos:
Sresult
=

strpos($test,

'HI);

Tenga en cuenta que solo funcionara en PHP 4 ya que en las versiones anteriores puede probar si es f a l s e examinando el valor devuelto para determinar si se trata d e una cadena (es decir, fa 1 s e ) .

La funcion d e buscar y reemplazar cadenas puede resultor extremadamente Litil con cadenas. Se puede utilizar para personalizar documentos generados por PHP (por ejemplo, sustituyendo < < n o m b r e > >con el nombre de una persona y < < d l r e c c i o n > > con SLI direcci6n). T a m b i h puede utilizarla para censurar el uso d e determinados tckminos, por ejemplo en u n foro o incluso e n la aplicacion Smart Form. De nuevo, puede utilizar funciones d e cadena o funciones d e expresion regular con este fin. La funci6n d e cadena que m i s se suele utilizar para realizar s ~ ~ s t i t u c i o n e es s s t r -r e p l a c e ( ) . A continuaci6n se recoge su sintaxis:

Esta funci6n sustituira todas las instancias d e nguja en pajar por izueua-aguja y devolvera la nueva version d e yajar.

Nota

Desde PHP 4.0.5 puede pasar todos 10s parametros como matrices y la funcion se comportara de manera bastante inteligente. Puede pasar una matriz de palabras para su sustitucion, una matriz de palabras con la que sustituirlas (respectivamente) y una matriz de cadenas a las que aplicar estas reglas. La funci6n devolvera una matriz de cadenas revisadas.
En el formulario Smart Form podrian aparecer palabras malsonantes incluidas por los usuarios al manifestar sus quejas. Como programadores, podemos evitar que 10s distintos departainentos d e Bob reciban los insultos:

La funcion s u b s t r r e p l a c e ( ) se utiliza para buscar y reemplazar una determinada subcadena d e k a cadena en funci6n d e su posici6n. SLIsintaxis es la siguiente:

Esta funci6n sustituird parte d e la cadena cadel~ncon la cadena sustrtrrc~cirz.La parte quc se sust~tuirci depende d e 10s valores d e 10s parimetros ~ n i c i o y lorzcyltlid. El valor irliclo representa el desplazamiento dentro d e la cadena en el que comenzard la sustitucicin. Si el valor fuera 0 o positivo, el desplazamiento se estableceria con respecto al principio d e la cadena; si fuera negativo, el desplazamiento se estableceria con resyecto al final d e la cadena. Por ejemplo, esta linea d e c6digo sust ~ t u i rel i ~ltimo cardcter d e $test con "x":

El valor l o l ~ g i t u d es opcional y representa el punto en el clue PHP dejar6 d e realizar sustituciones. Si n o se indica este pardmetro, la cadena scrd sustituida desde el irricio hasta el final dc. la cadena. Si el valor del pardmetro l o ~ g i t ~ es i d cero, la cadena d e sustituci6n se i ~ ~ s e r t a r ~ i dentro d e la cadena sin sobrescribir la cadena existente. Una l o r r ~ i t u dpositiva representa el nrjmero d e caracteres q u e se sustituiran con la nueva cadena. Una lorlgitrd negativa representa el punto en el que le gustaria detener la sustituci6n d e caracteres, contados desde el final d e la cadena.

PHP admite d m estilos d e sintaxis d e expresicin regular: POSIX y Pcrl. El estilo POSIX d e expresi6n regular sc compila en PHP d e manera predeterminada, pero se puede utilizar el estilo Perl compilando en biblioteca PCRE (Expresi6n regular y compatible con Perl). . En nuestro caso, utilizaremos el estilo POSIX q u e e s 1116s sencillo, pero si es programador d e Perl o desea saber m& sobre la biblioteca PCIIE, consulte el manual en linea d i r i g i h d o s e a h t t p : / / p h p . n e t .

Nota
Las expresiones regulares de POSlX resultan mas sencillas de aprender y se ejecutan con mas rapidez, per0 no son seguras para datos binarios.
Por lo tanto, las coincidencias d e patrcin rcalizadas hasta ahora utilizaban funciones d e cadena. Nos hemos limitado a las coincidencias exactas o a la coincidencia exacta d e subcadenas. Si desea establecer coincidencias m6s coniplejas, deberia utilizar expresiones regulares. El uso d e las expresiones regulares resulta dificil d e comprender a1 principio pero pueden llegar a ser extremadamente Citiles.

4 . Manipulacidn de cadenas y expresiones regulares

10s fundamentos
Una expresi6n regular es una forma de describir un patr6n en un texto. La coincidencia exacta (o literal) que hemos realizado hasta el momento es una forma de expresi6n regular. Por ejemplo, en una secci6n anterior buscamos las expresiones regulares
"shop" y " d e l i v e r y " .

En PHP, el establecimiento de coincidencias con expresiones regulares se parece m i s a utilizar la funci6n s t r s t r ( ) que a realizar una comparaci6n de igualdad, porque se hace coincidir una cadena con alguna parte de otra cadena (puede ser cualquier parte de la cadena a menos que se especifique otra cosa.) Por ejemplo, la cadena "shop" coincide con la expresi6n regular "shop". Pero tambien con las expresiones regulares "h", "ho" etc. Podemos utilizar caracteres especiales para indicar un metasignificado ademis de hacer coincidir caracteres de forma exacta. Por ejemplo, mediante el uso de caracteres especiales se puede indicar que ocurra un patr6n a1 inicio o a1 final de una cadena, que parte de un patr6n se pueda repetir o que 10s caracteres de un patr6n Sean de un tip0 dado. Tambien podemos buscar coincidencias literales de caracteres especiales. Examinaremos todas estas posibilidades.

Conjuntos y clases de caracteres


El uso de conjuntos de caracteres aumenta el potencial de las expresiones regulares con respecto a las expresiones de coincidencia exacta. Los conjuntos de caracteres se pueden utilizar para hacer coincidir cualquier caricter de un tip0 dado (en realidad son un tip0 de comodin). En primer lugar, puede-utilkar el caricter como comodin para sustituir cualquier otro caricter individual a excepci6n del caricter de nueva linea ( \ n ) . Por ejemplo, la expresi6n regular

coincide con las cadenas ' c a t ' , ' s a t ' y ' mat I , entre otras. Este tip0 de comodin de coincidencia se suele utilizar para bkquedas de nombres de archivo en sistemas operativos. Sin embargo, las expresiones regulares permiten especificar el tip0 de caricter que se desea buscar y, de hecho, se puede especificar un conjunto a1 que pertenezca un caricter. En el ejemplo anterior, las expresiones regulares coinciden con ' c a t ' y ' mat ' per0 tambien con ' # a t ' . Si desea limitar el rango de coincidencias a un caricter entre la a y la z, puede hacerlo de la siguiente forma:

Todo aquello que quede encerrado entre 10s corchetes ( [ I ) se considerari una clase de caricter (un conjunto de caracteres a 10s que debe pertenecer un carficter

D t s a r r o / / o Wcb rorl PHP y MySQL

coincidente). Tenga en cuenta que la expresion incluida entre 10s corchetes coincide con un 6nico car6cter. Puede incluir u n conjunto d e caracteres; por ejemplo:

significa cualquier vocal. Tambien puede describir un rango, como hicimos anteriormente utilizando un guion o un conjunto d e rangos.

Este conjunto d e rangos equivale a cualquier carscter alfabetico ya sea may6sculas o minLisculas. Tambien puede utilizar conjuntos para excluir un caracter del conjunto. Por ejemplo:

equivale a cualquier caracter que no est6 entre la a y la z. El simbolo de acento circunflejo significa rzo cuando se coloca dentro d e corchetes. Si se utiliza fuera d e 10s corchetes tiene otro significado, que examinaremos e n breve. A d e m i s d e enumerar conjuntos y rangos, se pueden utilizar varias clases de caracter predefinido en una expresi6n regular, que se recogen en la tabla 4.3.
Tabla 4.3. Clases de caracteres para su uso en expresiones regulares de estilo de POSIX.

-.Clase
[[:alnum:]] [[:alpha:]]

--

* * -

Coincidencia ~ g r a c t e r e salfanumericos Caracteres alfabeticos Letras en minusculas Letras en mayusculas Digitos decimates Digitos hexadecimales Puntuacion Tabuladores y espacios Espacios en blanco Caracteres de control Todos 10s caracteres imprimibtes

[[:graph:]

Todos 10s caracteres imprimibles a excepcion del espacio

Repeticion
Con frecuencia necesitamos especificar que se van a dar varias ocurrencias de una cadena o clase de caricter concreta. Para ello, podemos utilizar dos caracteres especiales dentro de una expresi6n regular. El simbolo * significa que el patr6n se puede repetir cero o m i s veces y el simbolo + indica que el patr6n se puede repetir una o varias veces. El simbolo puede aparecer directamente tras la parte de la expresi6n a la que se aplique. Por ejemplo:
[ [ :alnurn: ]

1+

significa "a1menos un caricter alfanum6rico".

Su bexpresiones
Suele resultar util poder dividir una expresi6n en subexpresiones para representar, por ejemplo, "a1 menos una de estas cadenas seguidas exactamente por una de esas otras". Para ello, se pueden utilizar 10s parkntesis, exactamente de la misma forma que haria en una expresi6n aritmetica. Por ejemplo:
(very )*large

equivale a ' l a r g e ' , ' v e r y l a r g e ' , ' v e r y v e r y l a r g e ' , etc.

Recuento de s bexpresiones
Podemos especificar cuintas veces se repite un elemento utilizando expresiones numericas entre llaves ( { 1 ). Podemos mostrar el numero exacto de repeticiones ( { 3 ) significa exactamented repticiones), un rango de repeticiones ( { 2 , 4 ) significa de 2 a 4 repeticiones) o un rango sin cerrar de repeticiones ( I 2 , ) significa a1 menos dos repeticiones). Por ejemplo, equivale a ' v e r y ' , ' v e r y v e r y ' y ' v e r y v e r y v e r y '

Anclajes al principio o al final de una ca


Podemos especificar si una subexpresi6n dada deberia aparecer a1 final, a1 principio o en ambos lugares. Esta opci6n resulta bastante util cuando queremos estar seguros de que en la cadena s610 aparece el t6rmino de busqueda y nada mis. Se utiliza el acento circunflejo ( ^ ) a1 principio de una expresi6n regular para indicar que debe aparecer a1 principio de una cadena buscada. El simbolo $ se utiliza a1 final de una expresi6n regular para indicar que debe aparecer a1 final.

Por ejemplo, la siguiente expresi6n busca coincidencias con b o b al principio d e una cadena:

La siguiente expresi6n busca coincidencias con corn a1 final d e u n a cadena:

Por ultimo, la siguiente expresi6n busca coincidencias con cualquier caricter u n co d e la a la z, en s u propia cadena:

Puede representar una opci6n en una expresi6n regular utilizado una bnrra vertical. Por ejemplo, si deseamos buscar coincidencias con corn, e d u o n e t , podemos utilizar la siguiente expresi6n:

Si desea buscar coincidencias con 10s caracteres especiales mencionados como ., o $, debe anteponerles una barra invertida ( \ ) . Si desea representar una barrn invertida, debe sustituirla por d o s barras inversas, \ \ .
(

En las t a b l a ~ 4.4 y 4.5 se recogen un resumen d e todos los caracteres especiales. La tabla 4.4 muestra el significado d e 10s caracteres especiales fuera d e corchetes y la tabla 4.5 muestra s u significado cuando se ~ ~ t i l i z a dentro n ellos.
Tabla 4.4. Resurnen de caracteres especiales utilizados en expresiones regulares POSlX

fuera de corchetes Significado Caracter de escape Coincidencia al principio de la cadena Coincidencia al final de la cadena Coincidencia de cualquier caracter a excepcion del caracter de nueva linea (\n)

Carhcter I

Significado lnicio de una opcion alternativa (como OR) lnicio de un subpatron Final de un subpatron Repetir 0 o mas veces Repetir 1 o mas veces lnicio del cuantificador rninlmax lnicio del cuantificador minlmax

Tabla 4.5. Resumen de caracteres especiales utilizados en expresiones regulares POSlX dentro de corchetes

Caracter

\
h

Caracter d e escape

NO, solamente si se utiliza en una posicion inicial


Usado para especificar rangos de caracter

En la aplicacion Smart Form, las expresiones regulares se pueden utilizar con dos fines. El primer0 consiste en.dete?tar terminos concretos e n 10s comentarios enviados por 10s clientes. Podemos utilizar expresiones regulares para ahorrarnos trabajo. Si utilizamos funciones de cadena, tendremos que realizar tres blisquedas si queremos encontrar ' s h o p I , ' customer s e r v i c e ' o ' retail ' cuando bastaria con una expresion regular para realizar la misma operacion:

El segundo uso consiste e n validar las direcciones d e correo electronic0 del cliente en nuestra aplicaci6n codificando el formato estandarizado d e una direction d e correo electronic0 en una expresi6n regular. El formato incluye varios caracteres alfanumdricos o d e ptintuaci6n, seguidos por el simbolo @, por una cndena alfanumdrica y guiones, seguidos por un punto, por m i s caracteres alfanum6ricos y guiones, y posiblemente por m6s puntos, hasta llegar al final d e la cadena, que se codifica d e la siguiente forma:

Desarrollo W e b con PHP y MySQL

La subexpresi6n [ a- zA-z0- 9 \ - \ . ] t significa "la cadena debe comenzar con una letra, un numero, un gui6n bajG u n gui6n medio o un punto o una combinaci6n de estos caracteres". El simbolo @ equivale a1 literal @. La subexpresi6n [ a-ZA-z0-9\ - ] + equivale a la primera parte del nombre del host incluyendo caracteres alfanum6ricos y guiones. Como puede observar se ha quitad0 la barra invertida delante del gui6n dado que se trata de un caracter especial cuando va entre corchetes. La combinaci6n \ . equivale a1 literal .. La subexpresi6n [ a-ZA-z0- 9\ - \ . ] t $ equivale a1 resto del nombre del dominio, incluyendo letras, numeros, guiones y m i s puntos si fueran necesarios, hasta el final de la cadena. Si analiza esta expresion, descubriri que es posible crear direcciones no vilidas equivalentes a la expresibn regular. Resulta pricticamente imposible capturar todos 10s casos, per0 hemos logrado mejorar bastante la situacibn. Puede volver a definir esta expresi6n de muchas formas. Por ejemplo, puede enumerar todos 10s TDL vilidos. Ahora bien, es necesario tener cuidado a la hora de restringir elementos ya que una funci6n de validaci6n que rechace un 1%de 10s datos v6lidos resulta mucho m i s molesta que una que permita un 10% de datos no vilidos.
A

Busqueda de subcadenas con expresiones regulares


La busqueda de subcadenas es la aplicaci6n principal de las expresiones regulares que acabamos de desarrollar. Las dos funciones disponibles en PHP para buscar coincidencias con expresjoneoregulares son e r e g ( ) y e r e g i ( ) .
int ereg (string p a t r d n , string b6squeda, array [ c o i n c i d e n c i a s ] )
;

Esta funcibn busca la cadena bu'squeda para encontrar coincidencias con la expresi6n regular patrdn. Si se encuentran coincidencias para las subexpresiones de patrdn, se almacenar6n en la matriz coincidencias, u n subexpresih por cada elemento de matriz. La funci6n e r e g i ( ) es identica con la salvedad de que no discrimina entre mayusculas y min6sculas. Podemos adaptar el ejemplo Smart Form para utilizar expresiones regulares de la siguiente forma:
if (!eregi(IA[a-zA-Z3-9 - \-\.]+@[a-zA-50-9\-]+\.[a-zA-ZO-9\-\.I+$', Semail i ) t echo 'That is not a valld email address. Please return t o the' . ' previous page and try again.'; exit;

4. Manipulacidn de cadenas y expresiones regulares

Stoaddress = ' f e e d b a c k @ e x a m p l e . i o r n ' ; / / e l v a l o r predeterrninado if (ereqii'shoplcustorner servlieretail', $feedback)) = 'retail@example.iorn'; $toaildress e l - e i f (ereqi('deliver.*fulfil.*', $ f e e d b a c k ) ) Sraaililress = ' f u l f i l r n e n t @ e x a m p l ~ . ~ n r n ' ; e l s e i f i e r e g i ( ' b i l l a c c o u r ~ t ' ,$ f e e d b a c k ) ) Stoaddress = 'accounts@exarnple.corn'; i f ( e r e g i ( ' b i q c u r t . i m e r \ . corn', $ernail) = 'hnb@exarnple.corn'; $toaddress

Tambien podemos utilizar expresiones regulares para buscar y reemplazar subcadenas de la misma forma que utilizamos s t r r e p l a c e ( ) . Las dos funciones disponibles para realizar esta operaci6n son e r e g -r e p l a c e ( ) y e r e g i -r e p l a c e ( ) . Lafunci6nereg-r e p l a c e ( ) tienelasiguientesintaxis:
s t r i n g e r e g -r e p l a c e ( s t r i n q hbsqueda); patrbn, string s u s t i tucibn, string

Esta funci6n busca la expresi6n regular patrdn en la cadena bu'squeda y la reemplaza con la cadena sustitucidn. La funci6n e r e g i -r e p l a c e ( ) es id4ntica con la diferencia de que no discrimina entre mayusculas y minusculas.

Otra funci6n de expresi6n regular util es s p l i t te:


array split(string patrdn, strinq hbsqueda,

()

,cuya sintaxis es la siguien[rndx] ) ;

int

Esta funci6n divide la cadena busqueda en subcadenas en la expresi6n regular patrdn y devuelve subcadenas en una matriz. El valor entero m i x limita el numero de elementos que puede incluir la matriz. Esta funci6n resulta util para dividir nombres de dominio o fechas. Por ejemplo,
$domain = 'yal1ara.cs.rrnit.elu.a~'; S a r r = s p l i t ( ' \ . ', Sdc~main); while ( l i s t ( $ k e y , $value) = each ( S a r r ) ) ?tho ' < b r / > ' . $ v a l u e ;

Esta funci6n divide el nombre del host en cinco componentes e imprime cada uno en una linea distinta.

Comparacion de funciones de cadenas y funciones de expresiones regulares


En general, la ejecuci6n de funciones de expresiones regulares resulta menos eficaz que las funciones de cadena con funcionalidad similar. Si su aplicaci6n es sencilla, utilice expresiones de cadena.

Lecturas adicionales
PHP consta de una gran cantidad de funciones de cadena. En este capitulo hemos visto las m6s sencillas, per0 si tiene una necesidad concreta (como la traduccidn d e caracteres a1 cirilico), consulte el manual en linea d e PHP para averiguar si dispone de ella. La cantidad de material disponible sobre expresiones regulares es ingente. Puede comenzar por la p6gina man de la funcidn r e g e x p si est6 utilizando UNIX. Tambien encontrar6 articulos muy buenos en d e v s h e d . corny p h p b u i l d e r corn. En el sitio Web de Zend, se incluye una funci6n de validacidn para correos electr6nicos m6s compleja y potente que la desarrollada en este capitulo. Se denom i n a M a i l V a l ( ) y est6 disponible en h t t p : / / w w w . zend. com/codex p h p ? i d = 88&single=l. La correcta comprensi6n de las expresiones regulares lleva cierto tiempo. Cuanto m6s ejemplos examine y ejecute, m6s seguro se sentir6 utiliz6ndolas.

A continuacion

En el siguiente capitulo, veremos varias formas de utilizar PHP para ahorrar tiempo y esfuerzos de programaci611, y evitar la redundancia a1 utilizar c6digo preexistente.

En este capitulo explicaremos cdmo la reutilizaci6n del cddigo permite desarrollar codigo mds coherente, fiable y sencillo de mantener con menos esfuerzo. Mostraremos thcnicas para dividir el c6digo en m6dulos y reutilizarlo. Para ello, comenzaremos por explicar el sencillo uso de las instrucciones r e q u i r e ( ) e i n c l u d e ( ) que permiten utilizar el mismo cddigo en varias pdginas. Explicaremos por qu6 resultan preferibles a las inclusiones en el lado del servidor. En el ejemplo que presentaremos se recclrre a archivos de inclusidn para lograr un aspecto visual y operativo uniforme en todo el sitio. Explicaremos cdmo escribir funciones propias y llamarlas utilizando funciones de generacidn de pdginas y formularios como ejemplos. En este capitulo abordaremos 10s siguientes aspectos: Reutilizacidn del cddigo Utilizacidnde r e q u i r e
()

e include

()

Introducci6n a las funciones Definicidn de funciones Pardmetros Recuperacidn de valores Llamadas por referencias frente a llamadas por valor Ambito Recursidn

5. Reutilizacidn de cddigo y creacidn de funciones

iPor quC reutilizar cbdigo?


Uno de 10s objetivos de 10s ingenieros informiticos consiste en reutilizar c6digo para no tener que escribirlo de nuevo. No porque se trate de un grupo especialmente vago sin0 porque la reutilizaci6n de c6digo contribuye a reducir 10s costes, a aumentar la fiabilidad del c6digo y a mejorar la uniformidad de 10s resultados. Lo ideal seria que 10s nuevos proyectos se crearan combinando componentes de c6digo ya existentes, con un minimo de desarrollo desde cero.

Costes
Durante la vida util de un fragment0 de c6dig0, se invierte mis tiempo en modificarlo, probarlo y documentarlo que en crearlo. Si esti escribiendo c6digo comercial, deberia intentar limitar el numero de lineas que se utilizan dentro de la organizaci6n. Una forma prictica de lograrlo consiste en volver a utilizar c6digo ya creado en lugar de escribir versiones ligeramente diferentes del mismo c6digo para realizar una nueva tarea. Menos c6digo significa menos costes. Si ya existe software que satisface sus necesidades para un proyecto, adqui6ralo. El coste de comprar software existente es siempre inferior a1 coste de desarrollar un product0 equivalente. Ponga mucha atenci6n si el software existente no cubre exactamente sus necesidades ya que su modificaci6n podria resultar mis dificil que su creaci6n desde cero.

Legibi lidad
Si un m6dulo de c6digo se utiliza en otra parte de la organizaci611, es muy probable que se haya probado exhaustivamente. Aunque se trata de un5s p&as lineas, si se vuelve a escribir, es probable que pasemos algun elemento por alto incorporado por su autor original o que se agreg6 a1 c6digo tras descubrir un fa110 durante la fase de prueba. El c6digo existente suele ser mis fiable que el c6digo reci6n creado.

Uniformidad
Las interfaces externas de nuestro sistema, incluidas las interfaces de usuario y las interfaces para 10s sistemas externos, deben ser uniformes. Para escribir c6digo nuevo que resulte uniforme con respecto a la forma en la que funcionan el resto de las partes del sistema se necesita una voluntad y un esfuerzo deliberado. Si reutilizamos c6digo ejecutado en otra parte del sistema, la uniformidad quedari garantizada automiticamente. Sobre todas estas ventajas, la reutilizaci6n del c6digo significa menos trabajo, siempre y cuando dicho c6digo sea modular y est6 bien escrito. A1 trabajar, intente reconocer secciones de su c6digo a las que pueda llamar en el futuro.

Desarrollo Wcb con PHP y MySQL

Uso d e require() e include()


PHP incorpora dos instrucciones muy sencillas per0 d e gran utilidad para permitir la reutilizaci6n d e cualquier tip0 de ccidigo. Mediante el uso de las instrucciones r e q u i e r e ( ) o i n c l u d e ( ) puede cargar u n archivo en su secuencia d e comandos de PHP. El archivo puede contener todos aquellos elementos que se incluirian por regla general e n una secuencia d e comandos, incluidas instrucciones d e PHP, etiquetas HTML, funciones d e PHP o clases d e PHP. Estas instrucciones funcionan d e manera similar a las inclusiones del lado del servidor que ofrecen muchos servidores Web y a las instrucciones # i n c l u d e d e C o C++.

El siguiente c6digo se almacena en u n archivo llamado r e u s a b l e . php:

El siguiente c6digo se almacena en un archivo llamado m a i n . php:

Si carga r e s u a b l e . php, es probable que no le sorprenda ver aparecer la secuencia "Here is a very simple PHP statement." en el navegador. Si carga el archivo m a i n . p h p ocurrir5 algo u n tanto mas interesante. El resultado d e esta secuencia d e comandos se ilustra en la figura 5.1.

This is the main file.


Here is a very simple PHI' stderncnt. ?he script will end now.

Figura 5.1. El resultado de main.php muestra el resultado de la instruccion require()

Se necesita un archivo para utilizar la instrucci6n r e q u i r e ( ) . En el ejemplo anterior, utilizamos el archivo r e u s a b l e . p h p . A1 ejecutar nuestra secuencia d e comandos, la instruccidn r e q u i r e ( )

se sustituye por 10s contenidos del archivo solicitado y, a continuaci611, se ejecuta la secuencia de comandos. Esto implica que a1 cargar m a i n . php, se ejecuta como si la secuencia de comandos estuviera escrita de la siguiente forma:
<?php echo 'This is the main file.<br / > I ; echo 'Here is a very simple PHP statement.<br echo 'The script will end now.<br / > I ; ?>

/ > I ;

A1 utilizar r e q u i r e ( ) es necesario tener en cuenta las diferentes formas en las que se procesan las extensiones de nombre de archivo y las etiquetas de PHP.

Extensiones de nombre de archivo y require()


PHP no examina la extensi6n del nombre de archivo en el archivo requerido. Esto significa que puede asignar el nombre que desee a su archivo siempre y cuando no tenga previsto llamarlo directamente. A1 utilizar r e q u i r e ( ) para cargar el archivo, se convertiri de manera efectiva en parte de un archivo de PHP y se ejecutari como tal. Por regla general, las instrucciones de PHP no se procesarin si estuvieran en un archivo llamado, por ejemplo, p a g e . h t m l . S610 se llama a PHP para analizar archivos a1 definir extensiones como php. Sin embargo, si carga la pigina p a g e . h t m l a traves de una instrucci6n r e q u i r e ( ) , se procesarin todas las instrucciones de PHP incluidas en su interior. Por lo tanto, puede utilizar cualquier extensi6n que desee para archivos de inclusibn, per0 conviene utilizar una convenci6n 16gica, como i n c . Recuerde que si almacena 10s archivos que terminan en . i n c o alguna otra extensi6n no estindaron ekirbol de documentos Web y 10s usuarios 10s cargan directamente en el navegador, podran ver el c6digo en forma de texto sin procesar, incluidas las contraseiias. Por lo tanto, es importante almacenar 10s archivos de inclusi6n fuera del arb01 de documentos o utilizar extensiones estandar.

Etiquetas de PHP y require()


En nuestro ejemplo, el archivo reutilizable ( r e u s a b l e . php) se escribe de la siguiente forma:
<?php echo 'Here is a very simple PHP statement.<br
?>
/ > I ;

El c6digo de PHP se coloca dentro del archivo en etiquetas de PHP. Necesitari realizar esta operaci6n si desea que el c6digo PHP incluido en el archivo requerido sea tratado como c6digo de PHP. Si no abre una etiqueta de PHP, su c6digo seri tratado como texto o cddigo HTML y no se ejecutari.

Desnrrollo Web con PHP y MySQL

!)so do require0 para olantillas de sitios Web


Si las piginas Web d e su compaiiia presentan un aspecto visual y operativo uniforrne, puede utilizar PHP para agregar la plantilla y 10s elernentos estindar utilizandorequire ( ) . Por ejernplo, las p6ginas del sitio Web de la compafiia TLA Consulting presentan la apariencia que se muestra en la figura 5.2. Cuando se necesita crear una nueva psgina, el desarrollador puede abrir una existente, recortar el texto del archivo e introducir el nuevo texto, y guardar el archivo con otro nornbre.

Archrm EdlaOn Ver Favorlloa Henam~enlas Ayuda

.I

. 4 I ,

Welcome to the home of TLA Consulting. Please take some time to get to know us.

Ii

W e specialiie in s e ~ n g your business needs and hope to hear from you soon.

Figura 5.2. El sitio W e b de T L I A Consulting presenta un aspecto visual y operativo ' estandar en todas sus paginas

Considere la siguiente situaci6n: imagine un sitio Web que lleva rnucho tiernpo activo y consta d e decenas, centenas o miles d e piiginas con un estilo corntin. Entonces se toma la decision d e cambiar parte d e s u aspecto. Puede tratase d e un cambio pequefio, corno agregar una direction d e correo electronic0 a1 pie d e pigina d e todas las pAginas o incluir una nueva entrada en el menu d e navegacion. Seguro clue n o le apetece aplicar este pequefio cambio a todas las p6ginas. La posibilidad de reutilizar secciones de c6digo HTML comunes a todas las piginas es una opcion mucho m$s prActica que cortar y pegar 10s cambios e n decenas, centenas o miles piginas. En el listado 5.1 se recoge el codigo fuente d e la pigina d e inicio (home. h t m l ) ilustrada en la figura 5.2.
Listado 5.1. home.html. Codigo HTML de la pagina de inicio de TLA Consulting

5. Reutilizacidn de cddigo y creacidn de funciones


<title>TLA Consultinq Pty Ltd</title> <style> hl {color:white; font-size:24pt; text-aliqr1:centel-; font-family: arial, sans-se~-if] .mer~u (co1or:white; font-size:lZpt; text-a1ign:center; font-family:arial,sans-serif; font-weight:bold] td {backgl-ound: black] p {color:black; font-size:12pt; text-a1ign:justify; font-family:arial,sans-se~ifj p.foot {color:white; font-size:9pt; text-aligr1:center; font-family:arial,sans-serif; font-weight:bold] a:link,a:visited,a:active {color:white] </style> </head>

< ! page header -> <table width="100%" cellpadding="12" cellspacing="O" border="O"> <tr bgcolor="black"i <td align="left"><img src="logo.gif"></td> <td> <:hl>TLA Consulting</hl> </td> <:td aliqn="riqht"><img src="logo.gifN></td> </ t r> </table> < ! - menu -> <table width="lOO%" bgcalor="white" cellpadding="4" cellspacing="4"> <tr > <td width="25%"> <img src="s-loqo.gif"> ispan c l a s s = " m e n u " > H o m e < / s p a r ~ > < / t d > <td width="i5%"> <img src="s-logo.gif"> <span c l a s s = = " m e n u " > C o n t a c t < / s p a r ~ > < / t d > <td width="25%"> <img src="s-logo.gif"> <span class="menu">Services</span></td> <td width="25?zW> <img src="s-logo.qif"> <span class="menu">Site Map</span></td> </tr> </table>

! page content -> <piwelcome to the home of TLA Consulting. Please take some time to get to know us.</p> <p>We specialize in serving your busir~ess needs and hope to hear from you soon.</p> <

< ! - page footer -> <table width="100%" bgcolor="black" cellpadding="12" border="O"> <tr> <td> <p class-"foot">scopy; TLA Consulting Pty Ltd.</p> < p class="foot">Please see our <a href="legal.php">legal information page</a><:/p> <:/ td> </tr>

Desarrollo W e b con PHP y MySQL

En el listado 5.1 puede ver que el archivo consta de un numero de secciones distintas. El encabezado contiene las definiciones CSS (del ingles, Cascading Style Sheet, Hoja de estilo en cascada) utilizada por esta pdgina. La secci6n titulada "page header" (encabezado de pigina) muestra el nombre de la compaiiia y el logotipo, la secci6n "menu bar" (barra de menus) crea la barra de navegaci6n de la pdgina y la secci6n "page content" (contenido de pdgina) integra el texto exclusivo de esta pdgina. A continuacibn, aparece el pie de pdgina. Podemos dividir este archivo y designar las distintas partes como h e a d e r . i n c , home. p h p y f oo t e r .i n c . Las secciones h e a d e r . i n c y f o o t e r .i n c contendrdn c6digo que se reutilizard en otras pdginas. El archivo home. p h p sustituye a home. h t m l y contiene el texto exclusivo de esta pdgina y dos instrucciones r e q u i r e ( ) como se muestra en el listado 5.2.
Listado 5.2. horne.php. El codigo PHP que produce la pagina de inicio de TLA
<?php require('header.incl);
?\

! page cc,ntent -> cpjwelcome to the home of TLA Consultinq. Please take some time to get to know us.</p\ <p>We specialize in serving your business needs and hope to hear from you soon.</p> <?php require('footer.incl); <
?>

La instrucci6n r e q u i r e ( ) de home. p h p carga 10s archivos h e a d e r . i n c y


footer. inc.

Como se mencion6, el nombre asignado a estos archivos no afecta a la forma en la que se procesan a1 llamarlos con r e q u i r e ( ) . Una convenci6n habitual, aunque del todo opcional, consiste en llamar a archivos parciales que terminardn incluidos en otros archivos a l g o .i n c (aqui i n c equivale a incluir). Tambien resulta habitual, ademds de conveniente, colocar 10s archivos que se incluirdn dentro de un directorio a1 que puedan acceder sus secuencias de comandos per0 no permitir que se carguen individualmente a traves del servidor Web. De esta forma impediremos su carga, lo que dard lugar a a) que se produzcan errores si la extensi6n del archivo es .p h p per0 s610 contienen una pdgina o secuencia de comandos parcial o b) permitir que se pueda leer el c6digo fuente si ha utilizado otra extensi6n. El archivo h e a d e r . i n c contiene las definiciones de CSS utilizadas por la pdgina, las tablas que muestran el nombre de la compaiiia y 10s menus de navegaci6n como se ilustran en el listado 5.3. El archivo f o o t e r . i n c contiene la tabla que muestra el pie de pdgina en la parte inferior de cada pdgina. Este archivo se muestra en el listado 5.4.

5. Reutilizacidn de cddigo y creacidn defunciones


Listado 5.3. header.inc. El encabezado reutilizable para todas las paginas Web de TLA
<html> <head> <title>TLA Consulting Pty Ltd</title> <style> hl {color:white; font-size:24pt; text-a1ign:center; font-family:arial,sans-serif) .menu [color:white; font-size:12pt; text-a1ign:center; font-famiLy:arial,sans-serif; font-weight:bold] td [background:black] p {color:black; font-size:12pt; text-a1ign:justify; font-farnily:arial,sans-serif) p.foot (co1'or:white; font-size:9pt; text-a1ign:center; font-family:arial,sans-serif; font-weight:bold] a:link,a:visited,a:active {color:white] </style>

< ! page header > <table width="100%" cellpadding="12" cellspaclnq="@" border="O"> <tr bgcolor="black"> ctd align="left"><img src="logo.gif"></td> <td> <hl>TLA Consultlng</hl> < / td> <td align="right"><irng src="logo.gif"></td> </tr> </table> < ! - menu

-> <table width="100%" bgcolor="white" cel:padding="4" cellspacinq="4"> <tr > itd width="25%"> r <img src="s-logo.gif"> <span class="menu">Home</span></td, <td width="25%"> <img src="s-logo.gifn> <span c l a s s = " m e n u " > C o n t a c t < / s p a r ~ > < / t d > <td width="25%"> <img src="s-logo.gifW> <span class="menu">Services</span></td> <td width="25%"> <img src="s-logo.gifM> <span class="menu">Site Map</span></td> </tr> </table>

Listado 5.4. footer.inc. El pie de pagina reutilizable para todas las paginas Web de TLA
< ! page footer -> <table width="100%" bgcolor="black" cellpadding="12" border="OW> <tr> <td> <p class="foot">hcopy; TLA Consulting Pty Ltd.</p> <p class="foot">Please see our <a href="legal.php">legal information page</a></p> < / td>

Este enfoque facilita la tarea de lograr una apariencia uniforme en un sitio Web y permite crear una pigina Web con el mismo etilo escribiendo algo asi como:
<?php require('header.incl); ? > Here is the corltent for this page <?php require('footer.inc'); ?,

Pero incluso tras crear una gran cantidad de piginas utilizando este encabezado
y este pie de pigina, resulta sencillo modificar sus respectivos archivos. Con inde-

pendencia del tip0 de carnbio que desee realizar (una pequefia variacidn o modificar el disefio completo del sitio), s610 necesitarfi realizar el carnbio una vez. No tendri que variar cada pigina del sitio porque todas ellas se cargan en 10s archivos de encabezado y pie de pigina. El ejemplo visto utiliza unicamente HTML en el cuerpo, en el encabezado y en el pie de pigina. Pero no tiene por qu6 ser asi. Dentro de estos archivos, podriamos utilizar instrucciones de PHP para generar dinfimicamente partes de las piginas.

Uso de auto-prepend-file y auto-append-file


Si queremos utilizar la instruccidn r e q u i r e ( ) para agregar el encabezado y el pie de pigina de todas las piginas, existe otra forma de hacerlo. Dos de las opciones deconfiguraci6ndelarchivophp.incsonauto -p r e p e n d -f i l e y a u t o -a p p e n dfile.

Si asignamos estas opciones a 10s archivos de encabezado y pie de pigina, estaremos seguros de que se cargarfin antes y despu6s de cada pigina. En Windows, la configuraci6n presentari este aspecto:
a u t o prepend-file = "c:/inetpub/include/header.incCC auto append-file = "c:/inetpub/include/footer.inc"
--

En UNIX, la configuraci6n presentari este aspecto:


a u t o prepend-file = "/horne/username/include/header.inc" auto-append-file = "/horne/usernarne/include/footer.inc"
-

Si utiliza estas directivas no necesitari escribir las instrucciones r e q u i r e ( ), per0 10s encabezados y pies de pigina dejarin de ser opcionales. Si esti utilizando un servidor Web Apache, puede cambiar varias opciones de configuraci6n como 6stas en directorios individuales. Para ello, debe configurar el servidor para permitir que el archivo o archivos de configuraci6n principales Sean sustituidos.

5. Reutilizacidn de cddigo y creacidn de funciones

Para configurar las funciones de anexi6n a1 principio o a1 final de un directorio, Cree un archivo llamado .h t a c c e s s en el directorio. Este archivo debe contener las siguientes dos lineas:
p h p -v a l u e p h p -v a l u e a u t o prepend-file a u t o append file
-

"/horne/usernarne/include/header.inc" "/horne/usernarne/include/footer.inc"

Fijese en que la sintaxis resulta ligeramente diferente con respecto a la misma opci6n en php.ini asi como el elemento p h p v a l u e situado a1 principio de la linea. No hay signo igual. Tambih puede alterar-otra serie de pardmetros de configuraci6n de esta forma. La sintaxis ha cambiado desde PHP 3. Si estd utilizando una versi6n antigua de PHP, las lineas del archivo h t a c c e s s presentardn este aspecto:

php3-auto-prepend-file php? a u t o a p p e n d f i l e
-

/horne/username/include/header.inc /horne/username/include/footer.inc

La posibilidad de establecer opciones en el archivo . h t a c c e s s en lugar de hacerlo en el archivo php.ini o en 10s archivos de configuraci6n de su servidor Web brindan una gran versatilidad. Puede alterar 10s pardmetros en un equipo compartido que s610 afecte a sus directorios. No es necesario reiniciar el servidor Web ni disponer de acceso de administrador. Una de las desventajas del metodo . h t a c c e s s es que 10s archivos se leen y se analizan cada vez que se solicita un archivo de dicho directorio en lugar de uno a1 inicio, lo que afecta a1 rendimiento.

Uso de include()
Las instrucciones r e q u i r e ( ) y i n c l u d e ( ) son pricticamente identicas. La unica diferencia entre ambas es que cuando fallan, la instrucci6n r e q u i r e ( ) devuelve i instrucci6n i n c l u d e ( ) devuelve una advertencia. un error terminal, mientrasque k Existe un cambio en cuanto a1 funcionamiento de estas instrucciones. En las versiones de PHP anteriores a la 4.0.2, existian diferencias importantes en su funcionamiento. Si estd utilizando una versi6n antigua de PHP, lea las siguientes lineas. La instrucci6n i n c l u d e ( ) se evalua cada vez que se ejecuta y no se evalua si no se ejecuta. La instrucci6n r e q u i r e ( ) se ejecuta la primera vez que se analiza la instrucci6n, independientemente de si el bloque de c6digo que la contiene se ejecuta. Este hecho no tiene mucha importancia si el trdfico del servidor es reducido per0 implica que el c6digo que incluya instrucciones r e q u i r e ( ) dentro de estructuras condicionales resultarii ineficaz.
if ($variable
==

true)

i
require('filel.incl); else

I
require('file2.inc1);

Desnrrollo Web con PHP y MySQL

Este codigo cargari innecesariamente ambos archivos cada vez que se cargue la secuencia de comandos, per0 s610 utilizari una en funci6n del valor de $ v a r i a b l e . Sin embargo, si el c6digo se ha escrito utilizando dos instrucciones i n c l u d e ( ) , s610 se cargari uno de 10s archivos y se utilizard como en la siguiente versi6n:
ifi$variable
==

true)

1
include('filel.inc');

I
else

1
include('file2.inc');

A diferencia de 10s archivos cargados a traves de una instrucci6n r e q u i r e ( ) , aquellos cargados con i n c l u d e ( ) pueden devolver un valor. Por lo tanto, podemos indicar a otras partes del programa sobre el &xitoo el fa110 del archivo incluido o devolver una respuesta o resultado. Si vamos a abrir archivos muchas veces, podemos encargar la tarea a un archivo de inclusi6n en lugar de volver a escribir las mismas lineas de codigo en cada ocasi6n. Este archivo podria llamarse "openf i l e . i n c " y presentaria un aspect0 parecido a1 siguiente:
<?php @ $fp = fopen($name, $mode); if (!$fp)

1
echo '<p><strong> Oh No! I could not open the file.</strong></p>'; return 0 ;
1

else
[

return 1;

I
?>

Este archivo intentari abrir el archivo $name utilizando el mod0 indicado en $mode. Si fallara, devolveria un mensaje de error y un 0. Si tuviera &xito,devolveria un 1y no generaria ningun mensaje. Puede llamar a este archivo en una secuencia de comandos de la siguiente forma:
$name = 'file.t.xt ' ; $mode 'r'; $result = include('openfile.phpl); if ( $result == 1 )

/ / haga l o que desee hacer curl el archivo / / haga referencia a $fp creado en el archivo d e
1

inclusidn

Tenga en cuenta que podemos crear variables en el archivo principal o en el de inclusi6n u obligatorio, y que la variable existird en ambos.

Este comportamiento es el mismo para las instrucciones r e q u i r e ( ) y i n c l u d e ( ) . No puede utilizar r e q u i r e ( ) de la misma forma que se ha mostrado aqui porque no es posible devolver valores desde esta instrucci6n. La devolution de valores puede resultar util porque nos permite notificar a otras partes del programa sobre un fallo, realizar procesamientos independientes o devolver una respuesta. Las funciones proporcionan un mecanismo que resulta incluso mejor para dividir el c6digo en m6dulos aut6nomos, como veremos en la siguiente secci6n. Si se estii preguntando por qu4 deberia utilizar r e q u i r e ( ) ,dadas las ventajas de la instruccidn i n c l u d e ( ) sobre r e q u i r e ( ) ,la respuesta que es que resulta ligeramente mfis rfipida. Como se mencion6 anteriormente, este comportamiento ha cambiado, por lo que puede evitar el problema actualizando su versi6n de PHP.

Uso de las funciones de PHP


La mayoria de 10s lenguajes de programaci6n constan de funciones. 6stas se utilizan para separar el c6digo que realiza una tarea simple y bien definida. Las funciones facilitan la lectura del c6digo y nos permiten volver a utilizarlo cuando necesitamos realizar la misma tarea. Una funci6n es un m6dulo de c6digo aut6nomo que establece una interfaz de llamada, realiza alguna tarea y, opcionalmente, devuelve un resultado. Ya hemos visto una serie de funciones. En 10s capitulos anteriores, hemos llamado a varias funciones integradas en PHP. Tambien hemos creado algunas funciones sencillas y se han comentado. En esta secci6n vamos a analizar en mayor detalle las operaciones de llamar y desarrollar funciones.

Llamada de funciones
La siguiente linea representa la llamada miis sencilla a una funci6n:
nornbre f u n c i 6 n O ;
-

Esta linea llama a una funci6n denominada nornb r e f u n c i 6 n ( ) que no requiere pariimetros. Esta linea de c6digo ignora cualquier valor que pudiera devolver la funci6n. Existen varias funciones que se llaman de la misma forma. La funci6n p h p i n f ( ) suele resultar util para realizar pruebas porque muestra la versi6n de PHP instalada, informaci6n sobre PHP, la configuraci6n del servidor y valores sobre varias variables de PHP y de servidor. Esta funci6n no toma parfimetros y por regla general ignora el valor devuelto. Las llamadas a p h p i n f o ( ) presentan este aspecto:

La mayor parte de las funciones requieren uno o miis parfimetros: informaci6n que se le da a una funci6n a1 llamarla y que influye sobre el resultado de la ejecucion de la

Desarrollo Web con PHP y MySQL

funci6n. Los pardmetros se pasan colocando 10s datos o el nombre de una variable con 10s datos incluidos dentro del parhtesis tras su nombre. La llamada a una funci6n con un parfimetro presenta este aspecto:
nombre funci5n('par6metro');
-

En ese caso, el parfimetro utilizado es una cadena que contiene unicamente la palabra p a r a m e t r o , per0 las siguientes llamadas tambikn son correctas segun la funcidn:
nornbre funcibn(2); nornbre-funci6n (7.893); nornbre-funcihn(Svariab1e);
-

En la ultima linea, $ v a r i a b l e puede ser cualquier tip0 de variable de PHP, incluso una matriz. Un parfimetro puede ser cualquier tip0 de datos per0 las funciones concretas suelen necesitar tipos de datos dados. Para saber cufintos parfimetros tom6 una funcibn, qu6 representa cada uno de ellos y el tip0 que necesitan, basta con consultar su sintaxis. A1 describir las funciones solemos incluir su sintaxis. A continuacibn, se recoge la sintaxis de la funcidn f o p e n ( ) :
int fopen ( string n o m b r c d z - a r c h i vo, u s a r r u t a-i n z l u s i d n ] ) ;
-

string

modo,

[ int

Esta sintaxis nos indica varias cosas y es importante saber interpretarlas. En concreto, el termino i n t que aparece delante del nombre de la funci6n indica que devolver6 un valor entero. Los parfimetros de la funcidn se incluyen dentro de 10s par6ntesis. En el caso de f o p e n ( ) tenemos tres. El nombre del archivo y el mod0 son cadenas y el parfimetro es un entero. Los corchetes que rodean a la expresidn usar-ruta-inclusidn indican que se trata de un parfimetro opcional. Po<emos incluir valores o ignorar el par6metr0, en cuyo caso se utilizar6 el predeferminado. Tras examinar la sintaxis de esta funcibn, sabemos que el siguiente fragment0 de cddigo es una llamada vfilida a fo p e n ( ) :
$name = 'myfile.txtl; Sopenmode = ' r ' ; S f p = fopenisname, Scpenmode)

Este cddigo llama a la funci6n f o p e n ( ) . El valor devuelto se almacenarfi en la variable $ f p. Hemos optado por pasarle una variable llamada $name que contiene una cadena que representa el archivo que queremos abrir y una variable llamada $openmode que contiene una cadena que representa el mod0 en el que queremos abrir el archivo. En cuanto a1 tercer parfimetro opcional, hemos decidido no utilizarlo.

C6mo llamar a una funci6n no definida


Si intenta llamar a una funci6n que no existe, obtendrfi un mensaje de error como el ilustrado en la figura 5.3.

5. Retrtilizncidr~de c6digo y creacidn d e funciones

Fatal error: Call to unsupported or undefined function functionname() in /hon1e/hoolrlpublic~htnd/chnpter5!m1delimedphp on line 6

1
.

Figura 5.3. Este mensaje de error es el resultado de llamar a una funcion que no existe

Los mensajes de error que PHP devuelve suelen ser d e gran utilidad. ~ s t nos e indica exactamente en qu6 archivo tuvo lugar el error, en qu6 linea d e la secuencia d e comandos y el nombre d e la funci6n que intentamos llainar. De esta forma resultarri muy sencillo buscar error y corregirlo. Si se recibe este mensaje d e error, hay que comprobar dos cosas:

1. i E s t i escrita correctamente la funcibn? 2. ~ E x i s t e la funci6n e n la versi6n d e PHP que e s t i utilizando?


No siempre resulta sencillo recordar como se escribe una funci6n. Por ejemplo, algunos nombres d e funci6n formados por dos palabras utilizan un p i o n bajo para separarlas y otras no. La funci6n stripslashes ( ) se compone d e dos palabras juntas mientras que la funci6n strip tags ( ) utiliza un gui6n bajo para separar sus dos palabras. Si se escribe incorrectamente el nombre d e una funci6n en una llamada se devolveri el error ilustrado en la figura 5.3. Muchas d e las funciones que utilizamos en este libro n o existen en PHP 3.0 ya que asumimos que est6 utilizando la version PHP 4.0. En cada nueva version se definen nuevas funciones por lo que las nuevas funcionalidades y el mayor rendimiento justifican la actualizaci6n. Si desea saber cuando se ha agregado una funci6n concreta, puede consular el manual en linea. Si intenta llamar a una funci6n no declarada en la versi6n que est6 ejecutando obtendrfi como resultado un error como el que se ilustra en la figura 5.3.

Funciones y el uso de mavusculas y minusculas


Recuerde que las llamadas a funciones n o discriminan entre maytisculas y minilsculas por lo que las secuencias function name ( ) , Func t ion-Name ( ) o FUNCTION NAME ( ) son igualmente vilidas y devuelven el mismo resultado. Pued e utilizar el patr6n que le resulte m i s sencillo d e leer pero debe intentar mantener cierta uniformidad. En este libro, asi como en la mayor parte d e la documentation d e PHP, se utilizan las minusculas como convention. Es importante recordar que 10s nombres d e funcion se comportan d e manera diferente a 10s nombres d e variable. Los nombres d e variable discriminan entre maylisculas y minhculas, por lo que $ ~ a m y e $name serin dos variables diferentes mientras q u e Name ( ) y name ( ) identifican la misma funci6n.

Desarrollo W e b con PHP y MySQL

En 10s capitulos anteriores se ha incluido una gran cantidad de ejemplos sobre el uso d e las funciones que incorpora PHP. Sin embargo, el verdadero potencial de un lenguaje de programacidn se mide por su capacidad para crear funciones propias.

#or quC deberia crear funciones propias?


Las funciones incorporadas de PHP nos permiten interactuar con archivos, utilizar una base de datos, crear grificos y establecer conexiones a otros servidores. Sin embargo, a lo largo de su vida profesional descubrird muchas veces que necesita realizar una operacidn no prevista por 10s creadores del lenguaje. Afortunadamente, PHP permite crear funciones para realizar cualquier tarea deseada. Con toda probabilidad, su cddigo combinari funciones existentes con ldgica propia desarrollada para realizar una tarea. Si esti escribiendo un bloque de cddigo que probablemente desee utilizar de nuevo en varios puntos de una secuencia de comandos o en varias secuencias de comandos, es aconsejable que declare dicho bloque en forma de funcidn. La declaracidn de una funcidn permite utilizar el cddigo creado de la misma forma que las funciones incorporadas. Bastari con llamar a la funcidn y definir 10s parimetros necesarios, lo que implica que puede llamar a la funcidn y volver a utilizarla varias veces en la secuencia de comandos.

Estructura bisica de una funcion


La declaracidn de una funcidn crea o declara una nueva funcidn. La declaracidn comienza con la palabra clave function, incluye el nombre de la funcidn, 10s pardmetros obligatorios y conJiene el cddigo que se ejecutard cada vez que se llame a la funcidn. A continuacio'n, se recoge el ejemplo de una funcidn trivial:

I
echo ' M y function was called';

Esta declaracidn de funcidn comienza con el t6rmino function, para que 10s lectores humanos y el analizador de PHP sepan que lo que viene a continuaci6n es una funcidn definida por el usuario. El nombre de la funcidn es m y -function. Podemos llamar a nuestra nueva funcidn con la siguiente instruccidn:
my-function
( ) ;

Como habri supuesto, la llamada a esta funci6n devolveri la frase "My function was called" en el navegador. Las funciones integradas estin disponibles para su uso en todas las secuencias de comandos de PHP, per0 si declara sus propias funciones, s610 estarin disponibles

5 . Reutilizacio'n de cddigo y creacio'n de funciones

para la secuencia o secuencias de comandos en las que se declaren. Conviene incluir en un archivo las funciones rnds utilizadas y recurrir a un instrucci6n r e q u i r e ( ) dentro de las secuencias de comandos para acceder a ellas. Dentro de una funci6n, las llaves encierran el c6digo que realiza la tarea requerida. En su interior se pueden incluir todos aquellos elementos vhlidos de PHP como llamadas de funci6n, declaraciones de nuevas variables o funciones, instrucciones r e q u i r e ( ) o i n c l u d e ( ) y c6digo HTML. Si queremos salir de PHP dentro de una funci6n y escribir HTML, podemos hacerlo de la misma forma que en cualquier otra parte de la secuencia de comandos: mediante una etiqueta de cierre de PHP seguida del c6digo HMTL. A continuaci6n se recoge una modificaci6n vdlida del ejemplo anterior que genera el mismo resultado:
<?php

function my_functlon()

1
?>

My function was called


<?php

1
?>

Fijese en que el c6digo de PHP aparece encerrado entre etiquetas de apertura y cierre de PHP. En la mayor parte de 10s ejemplos de c6digo utilizados en este libro se incluyen estas etiquetas. En este caso se muestran porque resultan necesarias dentro del ejemplo asi como por encima y por debajo de 61.

Designaci6n de funciones
Lo mds importante que recordar a la hora de asignar nombres a las funciones es Si su funci6n crea un encabezado de phgina, que deberian ser cortos y de_scri~tivos. e n c a b e z a d o p a g ( ) o e n c a z a d o -p a g serian buenas elecciones. A continuaci6n se indican varias limitaciones: No se puede utilizar el mismo nombre asignado a una funci6n existente. El nombre de la funci6n s610 puede contener letras, digitos y guiones bajos. El nombre de la funci6n no puede comenzar por un digito. Muchos lenguajes permiten volver a utilizar nombres de funciones. Esta opci6n se conoce como sobrecarga de funciones. Sin embargo, PHP no admite esta posibilidad por lo que sus funciones no pueden tener el mismo nombre que una funci6n incorporada o una funci6n existente definida por el usuario. Fijese en que aunque las secuencias de comando de PHP conocen las funciones integradas en el lenguaje, las funciones definidas por el usuario s610 existen en las secuencias de comandos declaradas. Por lo tanto, podemos volver a utilizar el nombre de una funci6n en un archivo diferente aunque esta prhctica genera confusi6n y deberia evitarse.

Los siguientes nombres de funci6n son vilidos:


name ( ) name2 ( ) name-three ( namefour (

) )

Estos otros no lo son:


5name [ ) name-six fopen (
( )

(El iiltimo seria vilido si no existiese una funci6n con el mismo nombre.)

Parimetros
Para poder realizar su trabajo, la mayor parte de las funciones requieren el uso de uno o varios parimetros. Un parimetro permite pasar datos dentro de una funci6n. A continuaci61-1,se recoge el ejemplo de una funci6n que requiere un parimetro. Esta funci6n toma una matriz unidimensional y la muestra en una tabla.
function create-table($data)

I
echo '<table horder="lm>'; resetisdata); / / Recuerde que se utiliza para apuntar a1 inicio $value = current($data); while ($value) i echo "<tr><td>$value</td></tr>\nn'; $value = next($data);

I
echo '</table>';

Si llamamos a la funci6n c r e a t e-t a b l e ( ) de la siguiente forma:


$myparray = array('Line one.','Line two.','Line three.'); create-table ( $my-array) ;

se generari el resultado ilustrado en la figura 5.4. Los pardmetros nos permiten obtener datos creados fuera de la funci6n (en este caso la matriz $ d a t a ) dentro de la funci6n. Como ocurre con las funciones incorporadas, las definiciones establecidas por el usuario pueden tener varios pardmetros asi como pardmetros opcionales. Podemos mejorar la funci6n c r e a t e t a b 1 e ( ) de varias formas, per0 una de ellas podria consistir en permitir que el i&ocador especifique el borde de la tabla u otros atributos. A continuaci611, se recoge una versi6n mejorada de la funci6n. Resulta muy similar, per0 nos permite establecer la anchura del borde de la tabla asi como el espacio y relleno de las celdas.

5. Reutilizacioir de co'digo y creacidn de f'uizciorzes

Line one.

Eme WO.
-

Line Lh;e<
-

Figura 5.4. Esta tabla HTML es el resultado de llarnar a la funcion create-table()

El primer parsmetro c r e a t e t a b l e 2 ( ) sigue siendo obligatorio. Los otros tres parimetros son opcionales p&pe se han definido valores predeterminados. Podemos obtener un resultado muy similar a1 ilustrado en la figura 5.4 con la siguiente llamada a c r e a t e-t a b l e 2 ( ) .

Si queremos mostrar los~misfios datos con m i s detalles, podriamos llamar a la funci6n d e la siguiente forma:

No es necesario indicar 10s valores opcionales (podemos suministrar algunos e ignorar otros). Los parimetros se a s i g n a r h de izquierda a derecha. Recuerde que no se puede dejar sin definir un parimetro opcional y definir otro situado por detris. En este ejemplo, si desea pasar un valor para c e l l s p a c i n g , tambi6n deberi pasar otro c e l l p a d d i n g . ~ s t a suele ser una fuente c o m h d e errores d e programaci6n. Tambien es la raz6n por la que 10s parimetros opcionales se especifican a1 final en cualquier lista d e parfimetros. La siguiente llamada d e funci6n:

resulta perfectamente vilida: establece $ b o r d e r en 3 y deja 10s parimetros S c e l l p a d d i n g y $ c e l l s p a c i n g en sus valores predeterminados.

Desarrollo Web con PHP y MySQL

C(FR

Es posible que se haya fijado en que cuando necesitamos utilizar variables dentro de un archivo requerido o incluido, basta con declararlo en la secuencia de comandos antes de la instruccidn r e q u i e r e ( ) o i n c l u d e ( ) , per0 a1 utilizar una funcibn, pasamos dichas variables dentro de la funci6n de manera explicita. Esto se debe en parte a que no existe ningun mecanismo para pasar variables explicitamente a u n archivo requerido o incluido y en parte a que el dmbito de las variables se comporta de forma diferente en las funciones. El Bmbito de una variable controla d6nde resulta visible y el lugar en el que se puede utilizar. Cada lenguaje de programaci6n adopta reglas diferentes a la hora de establecer el Bmbito de las variables. Las de PHP son bastantes simples: El Bmbito de variables declaradas dentro de una funci6n abarca desde la instrucci6n en la que se han declarado hasta las llaves de cierre situadas a1 final de la funci6n. ~ s t e Bmbito es el dmbito de funci6n y las variables declaradas asi se denominan variables locales. El dmbito de las variables declaradas fuera de funciones abarca desde la instrucci6n en la que se declaran hasta el final del archivo, per0 no en el interior de funciones. Este Bmbito es el Bmbito global y las variables declaradas asi se denominan variables globales. Las variables superglogales resultan visibles tanto dentro como fuera de las funciones (si desea obtener un listado de estas variables, consulte un capitulo anterior). El uso de las instrucciones r e q u i r e ( ) e i n c l u d e ( ) no afecta a1 Bmbito. Si la instrucci6n se utiliza dentro de una funci6nl se aplicard el Bmbito de la funci6n. Si no se mcue'ntra dentro de una funci6nl se aplica el dmbito de global. La palabra clave g l o b a l se puede utilizar manualmente para especificar que una variable definida o utilizada dentro de una funci6n tiene Bmbito global. Las variables se pueden eliminar manualmente llamando a u n s e t ( $ nornbrev a r i a b l e ) . Una variable deja de tener Bmbito si se elimina. Los siguientes ejemplos le ayudardn a aclarar estos conceptos. El fragment0 de c6digo que se incluye a continuacidn no genera ningun resultado. En concreto, se declara una variable llamada $ v a r dentro de la funci6n f n ( ) . Como la variable se declara dentro de una funci6n, su Bmbito es el de una funci6n y s610 existirB desde donde se declara hasta el final de la funcibn. Cuando volvamos a hacer referencia a $ va r fuera de la funci6n, se crearB una nueva funci6n llamada $ va r . Esta nueva variable tiene dmbito global y estara visible hasta el final del archivo. Por desgracia, si la unica instrucci6n que utilizamos con la nueva variable $ v a r es echo, nunca tendrd un valor.

5. Reutilizacidn d e co'digo y creacio'n defunciones


function f n 0

i
Svar
I
=

'contents';

echo

Svar;

El siguiente ejemplo muestra lo contrario. En 61 se declara una variable fuera de la funci6n y se intenta utilizar dentro de otra.
function fn() Svar Svar
=

i
echo ' i n s i d e t h e function, Svar = 'contents2'; echo ' i n s i d e t h e function, '.$var.'<br '.$var.'<br
/ > I ;

/ > I ;

Svar 'contsnts 1'; f n 0 ; e c h o ' o u t s i d ? t h e function, S v a r

'.$var.'<br

/ > I ;

El resultado de este c6digo serB el siguiente:


inside t h e function, Svar = inside t h e function, Svar = contents 2 outside t h e function, Svar = contents 1

Las funciones no se ejecutan hasta que no se llaman, por lo que la primera instrucci6n es $ va r = ' contents 1 ' ;. Csta crea una variable llamada $ va r,con Bmbito global y su contenido es "contents 1". La siguiente instrucci6n ejecutada es una llamada a la funci6n f n ( ) . Las lineas incluidas dentro de la instrucci6n se ejecutan en orden. La primera linea de la funci6n hace referencia a la variable llamada $ va r. A1 ejecutar esta linea, no se puede ver la variable $ va r creada anteriormente, por lo que crea una nueva con Bmbito de funci6n e imprime su valor. Esto crea la primera linea de 10s resultados. ' La siguiente linea de la funci6n establece el contenido de $va r en "contents 2 ". Como estamos dentro de la funcibn, esta linea cambia el valor de la variable $var local, no de la global. La segunda linea del resultado verifica que este cambio funciona. Con esto llegamos a1 final de la funci6n y se ejecuta la secuencia de comandos. La instrucci6n echo demuestra que el valor de la variable global no ha cambiado. Si queremos que una variable creada dentro de una funci6n tenga Bmbito global, podemos utilizar la palabra clave global de la siguiente forma:
function fn()

I
global Svar; Svar = 'contents'; echo ' i n s i d e t h e f u n c t i o n , Svar
=

'.Svar.'<br

/ > I ;

1
f n 0 ; echo ' o u t s l l e

the

function,

Svar

'

.$var. '<br

/ > I ;

Desarrollo Web con P H P y MySQL

En el siguiente ejemplo, la variable $var se ha definido como global lo que significa que tras llamar a la funcibn, la variable tambien saldr6 fuera de la funci6n. El resultado de esta secuencia de comandos ser6 el siguiente:
inside the function, $var outside t h e function, Svar
=
=

contents contents

El Ambito de la variable abarca desde el punto en el que se ejecuta la linea global $var ;. Podriamos haber declarado la funci6n por encima o debajo de la linea de llamada. (Como observarA, existe bastante diferencia entre el Bmbito de funci6n y el Ambito de variable.) La ubicaci6n de la declaraci6n de funci6n no tiene relevancia. Lo importante es el lugar en el que se llame a la funci6n y, por lo tanto, desde el que se ejecuta el c6digo incluido en su interior. T a m b i h puede utilizar la palabra clave global en la parte superior de una secuencia de comandos a1 utilizar por primera vez una variable para declarar que su Ambito abarca la secuencia de comandos. gste es probablemente el uso mBs comun de la palabra clave global. Como puede ver por 10s ejemplos anteriores, resulta perfectamente vBlido volver a utilizar un nombre de variable para una variable dentro y fuera de una funcidn sin que se produzcan interferencias entre ambas. Sin embargo, no conviene utilizar el mismo nombre porque sin un examen atento del c6digo y del Bmbito podria pensarse que se trata de las mismas variables.

Llamadas por referencia frente a llamadas por valor


Si desea escribir una f y n c i k llamada increment ( ) que nos permita incrementar un valor, podriamos vernos tentados a escribir lo siguiente:
f u n c t i o n i r ~ c r e m e n( t $ v a l u e , $amount
J

1)

Este c6digo no sirve de nada. El resultado del siguiente c6digo de prueba sera
"10".
$ v a l u e = 10; irlcrement ( $ v a l u e ); echo Svalue;

Los contenidos de $value no han cambiado. Esto se debe a las reglas de Bmbito. Este c6digo crea una variable llamada $value que contiene 1 0 .A continuaci6n llama a la funci6n increment ( ) . Se crea la variable $value de la funci6n a1 llamarla. Se le agrega una unidad, por lo que el valor de $value pasa a 11 dentro de la funci6n hasta que llega a su fin y volvemos a1 c6digo

5 . Reutilizacidn de cddigo y creacidn de funciones

que la llam6. En este c6dig0, la variable $ v a l u e es diferente porque tiene ambito global y no varia. Una forma de resolver este problema consiste en declarar $ v a l u e en la funci6n como global, per0 esto implica que para poder utilizarla, la variable que queremos incrementar deber6 llamarse $ v a l u e . Una solucidn mejor seria utilizar las llamadas por referencia. La forma normal de llamar a 10s parametros de una funcidn es pasindolos por valor. A1 pasar un pardmetro, se crear6 una nueva variable que contiene el valor pasado. Se trata de una copia del original. Puede modificar este valor como desee, per0 el valor original de la variable fuera de la funci6n seguir6 siendo el mismo. Una solucidn mejor es utilizar las llamadas por referencia. En este caso, cuando se pasa un par6metro a una funcidn, en lugar de crear una nueva variable, la funcidn recibe una referencia a la variable original. Esta referencia tiene un nombre de variable, que comienza por el simbolo del ddlar y se puede utilizar de la misma forma que cualquier otra variable. La diferencia est6 en que en lugar de tener un valor propio, simplemente hace referencia a1 original. Cualquier carnbio realizado a la referencia s610 afectar6 a1 original. Para indicar que un parimetro debe pasarse por referencia se coloca un simbolo & delante del nombre del par6metro en la definici6n de funci6n. No es necesario n i n g h carnbio en la llamada de funci6n. El ejemplo de funcidn anterior, i n c r e m e n t ( ) , se puede modificar para pasar un parimetro por referencia y lograr que funcione correctamente.
function increment(&$value, $amount
=

1)

Ahora ya disponemos de una funcidn operativa y podemos utilizar el nombre que deseemos para incrementar el valor que nos plazca. Como se indicd anteriormente, resulta confuso utilizar el mismo nombre fuera y dentro de una funcidn, por lo que aplicaremos un nuevo nombre a la variable en la secuencia de comandos principal. El siguiente c6digo d e prueba imprimir6 10 antes d e llamar a i n c r e m e n t ( ) y 11 despuks.
$ a = 10; echo $a.'ibr / > I ; i n c r e m e n t ( S a1 ; e c h o $a.'<br / > I ;

Final de las funciones


La palabra clave r e t u r n detiene la ejecucidn de una funci6n. Cuando una funci6n termina porque todas sus instrucciones se han ejecutado o porque se ha utilizado la palabra clave r e t u r n , la ejecucidn regresa a la llamada de la funcidn.

Desarrollo W e b con P H P y MySQL

Si llama a la siguiente funci6n, s610 se ejecutard la primera instrucci6n e c h o .


function t e s t return0

I
echo 'This statement w i l l be e x e c u t e d ' ; return; echo 'This statement w i l l never be e x e c u t e d ' ;

Obviamente, no se trata de una forma muy util de utilizar la instrucci6n r e t u r n . Por regla general, so10 querremos volver desde el centro de una funci6n en respuesta a una condicibn. Por ejemplo, una raz6n habitual para utilizar una instrucci6n r e t u r n es una condici6n de error que detenga una funci6n a1 final. Por ejemplo, si escribimos una funci6n para determinar el numero mds grande de dos especificados, podemos salir de la funcion si falta alguno de 10s numeros.
f u n c t i o n l a r g e r ( Sx, Sy )

i
if ( ! i s s e t ( $ s )I I ! i s s e t ( $ y ) ) echo 'This return; f u n c t i o n r e q u i r e s two n u m b e r s ' ;

1
(Ssi=Sy) e c h o Sx; else e c k ~ oS y ; echo ' i b r / if

> I ;

La funci6n incorporada is s e t ( ) indica si se ha creado una variable y se le ha asignado un valor. En este c6$go, devolvemos un mensaje de error y salimos de la funci6n si uno de 10s par2imetros no lleva definido un valor. Para probarla, utilizamos ! is s e t ( ) , que significa "NO isset()", de manera que la instruccion i f pueda leerse como "si x no estd establecida o si y no estd establecida". La funcion regresard si cualquiera de las dos condiciones resulta ser cierta.Si se ejecuta la instrucci6n r e t u r n , se ignorardn las siguientes lineas de la funci6n. La ejecuci6n del programa regresara a1 punto en el que se invoc6 la funci6n. Si se establecen ambos pardmetros, la funci6n imprimird el mas grande de 10s dos. El resultado del siguiente c6digo:

2.5

1.9
This function requires two numbers

5 . Reutilizacidn de cddigo y creacidn defunciones

Como devolver valores desde funciones


La salida de una funci6n no es la unica raz6n para utilizar la instrucci6n r e t u r n . Muchas funciones utilizan instrucciones r e t u r n para comunicarse con el cddigo que las llam6. En lugar de imprimir 10s resultados de la comparaci6n de la funci6n l a r g e r ( ) , puede que resulte m6s util devolver la respuesta. De esta forma, el c6digo que llame a la funcidn puede decidir si mostrar o utilizarla y c6mo. La funci6n incorporada max ( ) es equivalente y se comporta de esta forma. Podemos escribir la funci6n 1a r g e r ( ) asi:
function larger ($x, $y)
t

if (!isset($x)ll!isset($y)) return false; else if ($x>=$y) return $x; else return $y;

En este c6digo devolvemos el valor mtis grande de 10s pasados. Obviamente, el valor devuelto serti diferente en caso de error. Si uno de 10s ntimeros desaparece, devolveremos f a l s e . El 6nico pero de este enfoque es que 10s programadores que llamen a esta funcidn deben probar el tip0 de devolucidn con === para asegurarse de que f a 1s e no se confunde con 0. La funci6nmax ( ) de PHP no devuelve nada si se establecen ambas variables y si s610 se establece una, serti la que devolverti. El siguiente c6digo:
$a = echo echo echo

1; $b = 2.5; $C = 1.9; larger($a, $b)."<br j>"; larger($c, $a)."<br / > " ; larger($d, $a)."<br />";

generarti el siguiente resultado porque Sd no existe y f a l s e no estti visible:

Las funciones que realizan alguna tarea, pero que no necesitan devolver un valor, a menudo devuelven t r u e o f a 1 s e para indicar si se realizan satisfactoriamente o fallan. Los valores booleanos t r u e y fa 1 s e se pueden representar con valores 1y 0, respectivamente, aunque son de tipos diferente.

Bloques de codigo
Para declarar que un grupo de instrucciones forma un bloque las colocamos entre llaves. Esta estructura no tendrti efectos sobre el funcionamiento del c6digo pero si

Desarrollo Web con P H P y MySQL

implicaciones especificas como la forma en la que se ejecutan las estructuras de control, como 10s bucles y las estructuras~condicionales. A continuacidn se incluyen dos ejemplos que funcionan de forma muy diferente: Ejemplo sin bloque de c6digo
f o r ( S i = 0; S i < 3 ; Slit echo 'Line l < b r / > I ; echo 'Line 2<br />I;
)

Ejemplo con bloque de c6digo


for(Si
=

0;

Si

c:

3;

$i++
/ > I ; / > I ;

t
echo echo 'Line l<br 'Line 2<br

En ambos ejemplos, el bucle f o r se itera tres veces. En el primer ejemplo, el bucle f o r s610 ejecuta la linea situada inmediatamente por debajo. El resultado de este ejemplo es el siguiente:
Line Line Line Line 1 1

1 2

El segundo ejemplo utiliza un bloque de c6digo para agrupar las dos lineas. Esto implica que el bucle f o r ejecuta ambas lineas tres veces.
Line Line Line Line Line Line 1 2

1 2
1 2

Como el c6digo de estos ejemplos est6 sangrado correctamente, es probable que vea la diferencia ensepida. El sangrado del c6digo tiene el objetivo de ayudar a 10s lectores a interpretar visualmente las lineas afectadas por el bucle f o r . Sin embargo, fijese en que 10s espacios no afectan a la forma en la que PHP procesa el c6digo. En algunos lenguajes, 10s bloques de c6digo afectan a1 dmbito de las variables. 6ste no es el caso de PHP.

Recursion
PHP admite las funciones de recursi6n. Las funciones de recursi6n se llaman a si mismas. Estas funcione resultan especialmente utiles para navegar por estructuras de datos dindmicas como listas y drboles vinculados. Sin embargo, son pocas las aplicaciones basadas en Web que requieran una estructura de datos de esta comple-

5. Reutilizacidn de cddigo y creacidn de funciones

jidad por lo que el uso de esta funci6n es limitado. La recursi6n se puede utilizar en lugar de la iteraci6n en muchos casos porque ambas permiten realizar una operaci6n de manera repetida. Las funciones recursivas resultan mfis lentas y utilizan mfis memoria que la iteracibn, raz6n por la cual deberia dar prioridad a estfis dtimas. En el listado 5.5 se recoge un breve ejemplo de funci6n recursiva.
Listado 5.5. recursion.php. Resulta sencillo invertir una cadena utilizando la recursion

Tambien se muestra la version iterativa.


function reverse-r($str)

I
if (strlen($str)>O) reverse-r(substr($str, 1 ) ) ; echo substr($str, 0, 1 ) ; return;

function reverse-i($str)
{

for ($i=l; $i<=strlen($str); $i++)

I
echo substr($str, -$i, 1 ) ;
)

return;

En este listado, hemos implementado dos funciones. Ambas imprimen una cadena a1 rev&. La funci6n r e v e r s e r ( ) es recursiva y la funci6n r e v e r s e-i ( ) es iterativa. La funci6n r e v e r s e r ( l t o m a una cadena como parfimetro. A1 llamarla, se llamar6 a si misma y pasarz el pendtimo carficter de la cadena. Por ejemplo, si llama a
reverse r i l H e l l o ' ) ;
-

se llamarfi a si misma varias veces con 10s siguientes parfimetros:


reverse r ( ' e l l o l ) ; reverse-r('llol); reverse r('1o'); reverse r ( ' o l ) ; reverse-r(");
-

Cada llamada que realiza a si misma crea una nueva copia del c6digo de funci6n en la memoria del servidor per0 con un parfimetro diferente. Es como si pretend%ramos llamar a una funci6n diferente cada vez. Esto evita que las instancias de la funci6n se confundan. En cada llamada, se prueba la longitud de la cadena pasada. A1 llegar a1 final de la cadena ( s t r l e n ( ) = 0 ) falla la condici6n. La instancia mfis reciente de la funci6n ( r e v e r s e r ( ' ' ) ) seguirfi adelante y ejecutarfi la siguiente linea de c6digo que debe imprimir el primer carficter pasado de la cadena (en este caso, no hay n i n g ~ n carficter porque la cadena estfi vacia). A continuacibn, esta instancia de la funcidn devuelve el control a la instancia que la llam6, en concreto r e v e r s e -r ( ' o ' ) .

Desarrollo W e b con P H P y MySQL

Esta instruccidn imprime el primer cardcter en su cadena ("0 ") y devuelve el control a la instancia que lo llam6. El proceso continua (se imprime un carticter y se vuelve a la instancia de la funcion superior en el orden de llamada) hasta que el control vuelve a1 programa principal. Las soluciones recursivas presentan un aspect0 muy elegante y matematico. En la mayor parte de 10s casos, sin embargo, resulta mucho mejor utilizar una soluci6n iterativa. El listado 5.5 tambidn incluye la variante iterativa. Como observard, es igual de larga (aunque no siempre es asi) y realiza la misma funci6n. La diferencia principal es que la funci6n recursiva realiza copias de si misma en memoria, lo que implica la sobrecarga de varias llamadas de funci6n. La version recursiva se puede utilizar cuando el c6digo resulta mds breve y elegante que el de la version iterativa, cosa que en este dominio de aplicaciones no suele ocurrir a menudo. Aunque la recursion parece mds elegante, 10s programadores suelen olvidarse de incluir una condition de finalizacion, lo cual implica que la funcion se repetird hasta que el servidor se quede sin memoria o hasta que se exceda el tiempo de ejecucion.

Lecturas adicionales
El uso de las funciones i n c l u d e ( ) , r e q u i r e ( ) , f u n c t i o n y r e t u r n tambien se explica en el manual en linea. Si desea saber mas sobre conceptos como el de la recursion, las llamadas por valor o por referencia y el ambito de las variables que afecta a muchos lenguajes, consulte un libro de texto general sobre informdtica.

A continuacion

Ahora que ya sabemos utilizar 10s archivos de inclusion, 10s archivos requeridos y las funciones para lograr que nuestro c6digo resulte mds sencillo de mantener y susceptible de utilizar de manera repetida, en el siguiente capitulo se analizara el software orientado a objetos y la compatibilidad que ofrece PHP a1 respecto. El uso de objetos permite lograr objetivos similares a 10s conceptos presentados en este capitulo per0 con ventajas superiores para proyectos complejos.

En este capitulo se explican conceptos relacionados con el desarrollo orientado a objetos y se muestra c6mo implementarlos en PHP. Entre 10s temas clave que trataremos en este capitulo se incluyen 10s siguientes: Conceptos orientados a objetos Creaci6n de clases, atributos y operaciones Uso de atributos de chse Herencia Llamadas a mktodos de clases Disefio de clases Desarrollo de c6digo para clases Llamadas a operaciones de clase

Conceptos orientados a obietos


Los lenguajes de programaci6n modernos suelen admitir o incluso necesitan adoptar un enfoque orientado a objetos para el desarrollo de software. El desarrollo orientado a objetos (00)intenta utilizar las clasificaciones, las relaciones y las propiedades de 10s objetos del sistema para contribuir a1 desarrollo de programas.

6 . PHP orientado a objetos

Clases y obietos
En el context0 de software orientado a objetos, un objeto puede ser pricticamente cualquier elemento o concept0 (un objeto fisico como una mesa o un cliente; o un objeto conceptual que s610 existe en el software, como un campo de entrada de texto o un archivo). Por regla general, estaremos mAs interesados en objetos conceptuales, incluidos objetos del mundo real que necesitan representarse en software. El software orientado a objetos se diseiia y construye como un conjunto de objetos independientes con atributos y operaciones que interactuan para cubrir nuestras necesidades. Los atributos son propiedades o variables relacionadas con el objeto. Las operaciones son mktodos, acciones o funciones que el objeto realiza para modificarse a si mismo o para obtener algun efecto externo. La ventaja principal del software orientado a objetos es su capacidad para admitir o fomentar la encapsulaci6n, t a m b i h conocida como ocultaci6n de datos. BAsicamente, el acceso a 10s datos dentro de un objeto s610 estA disponible a travks de operaciones con objetos, conocida como la interfaz del objeto. La funcionalidad de un objeto estA vinculada a 10s datos que utiliza. Podemos alterar 10s detalles de la implementaci6n del objeto para mejorar el rendimiento, agregar nuevas funciones o resolver errores sin tener que modificar la interfaz, cuyos efectos pueden extenderse a todo el proyecto. En otras Areas del desarrollo de software, la programaci6n orientada a objetos es la norma y el software orientado a funciones se considera desfasado. Por varias razones, la mayor parte de las secuencias de comandos orientadas a objetos siguen, por desgracia, diseiiadas y escritas utilizando una metodologia orientada a funciones. Existen varias razones que explican este enfoque. La mayoria de 10s proyectos Web son relativamente pequeiios y sencillos. En la mayor parte de 10s casos, 10s proyectos Web se pueden desawollar satisfactoriamente sin planificar el enfoque debido a su tamaiio. Sin embargo, si intenta aplicar la misma t6cnica para construir algo de mayor tamaiio, la calidad de 10s resultados se verA afectada, si es que se obtiene algun resultado. Muchos proyectos evolucionan a partir de un conjunto de piginas vinculadas para convertirse en una aplicaci6n compleja. Estas aplicaciones, ya se presenten a trav4s de cuadros de dialog0 y ventanas o.pAginasHTML generadas dinAmicamente, necesitan disponer de una metodologia de desarrollo correctamente ideada. La orientaci6n a objetos puede ayudarle a gestionar la complejidad de 10s proyectos, a incrementar la reusabilidad del c6digo y, por tanto, a reducir 10s costes de mantenimiento. En el software orientado a objetos, un objeto es una colecci6n unica e identificable de datos y operaciones almacenados que operan sobre dichos datos. Por ejemplo, podemos tener dos objetos que representen botones. Aunque ambos tengan el texto "Aceptar", una anchura de 60 pixeles, una altura de 20 pixeles y otros atributos i d h ticos, necesitamos disponer de la posibilidad de trabajar con uno o con el otro. En software, existen variables independientes que actuan como identificadores unicos para dichos objetos.

Desarrollo W e b con P H P y MySQL

Los objetos se pueden agrupar en clases. Las clases representan un conjunto de objetos que puede variar, per0 que deben tener un conjunto de caracteristicas en comun. Una clase contiene objetos con operaciones que se comportan de la misma forma y atributos que representan las mismas cosas, aunque 10s valores de dichos atributos varien de objeto a objeto. Podemos imaginar el tkrmino bicicleta como una clase de objetos que describe muchas bicicletas diferentes con una gran cantidad de caracteristicas o atributos en comun; por ejemplo, que tengan dos ruedas, un color y un tamafio, y realicen operaciones, como moverse. Mi bicicleta es un ejemplo de objeto que encaja en la clase bicicleta Compartiri rasgos comunes a todas las bicicletas, incluida una operacidn de movimiento que se comporta de la misma forma en la mayoria de las bicicletas (aunque apenas la utilice). Mi bicicleta tiene atributos con valores unicos porque es verde y no todas las bicicletas tienen ese color.

Polimorfismo
Un lenguaje de programacidn orientado a objetos debe admitir el polimorfismo, lo que significa que las clases pueden tener diferentes comportamientos con respecto a la misma operaci6n. Por ejemplo, si tenemos una clase coche y una clase bicicleta, sus operaciones de desplazamiento sertin diferentes. Para 10s objetos del mundo real, este hecho no plantea un problema ya que es poco probable que se confunda el movimiento de una bicicleta con el de un coche. Sin embargo, un lenguaje de programacidn no posee el sentido comun del mundo real, por lo que el lenguaje debe admitir el polimorfismo para determinar quk operacidn de movimiento utilizar con un objeto dado. El polimorfismo es m i s una caracteristica relacionada con 10s comportamientos que con 10s objetos. En PHP, &lo las funciones de miembro de una clase puede ser polim6rficas. Una comparacidn del mundo real es la de 10s verbos en 10s lenguajes naturales, que equivalen a las funciones de miembro. Considere las formas en las que una bicicleta se puede utilizar en el mundo real. Se puede limpiar, mover, desmontar, reparar o pintar, entre otras cosas. Estos verbos describen acciones genkricas porque no se puede saber el tip0 de objeto sobre el que se actda. (Este tip0 de abstracci6n sobre objetos y acciones es una de las caracteristicas que distinguen a la inteligencia humana.) Por ejemplo, la operacidn de mover una bicicleta requiere acciones completamente diferentes a las necesarias para mover un coche, aunque 10s conceptos sean similares. El verbo mover se puede asociar a un conjunto concreto de acciones una vez que se d6 a conocer el objeto sobre el que se actua.

Herencia
La herencia nos permite crear una relaci6n jer6rquica entre clases utilizando subclases. Una subclase hereda atributos y operaciones de su superclase. Por ejem-

6. PHP orientado a objetos

plo, un coche y una bicicleta tienen elementos en comun. Podemos utilizar una clase vehiculo para incluir elementos como un atributo de color y una operaci6n de movimiento comun a todos 10s vehiculos y permitir que nuestras clases coche y bicicleta las hereden. Gracias a la herencia, podemos desarrollar y seguir agregando elementos a clases existentes. A partir de una clase bdsica se pueden derivar clases m& complejas y especializadas a medida que surja la necesidad. Como resultado, nuestro c6digo ser6 m6s reutilizable, lo cual es una de las ventajas m i s importantes de un enfoque orientado a objetos. El uso de la herencia puede ahorrarnos trabajo si las operaciones se escriben una vez en una superclase en lugar de varias veces en subclases diferentes. Tambien puede ayudarlos a modelar de manera m i s exacta relaciones del mundo real. Si se establece una relaci6n 16gica del tip0 "es un/unaVen una frase entre dos clases, es probable que la herencia resulte adecuada. La frase "un coche es un vehiculo" tiene sentido, per0 la frase "un vehiculo es un coche" no lo tiene porque no todos 10s vehiculos son coches. Por lo tanto, el coche puede derivarse desde la clase vehiculo

Creacion de clases, atributos y operaciones en PHP


Por el momento, las clases se han estudiado de forma bastante abstracta. A1 crear una clase en PHP, se utiliza la palabra clave cla s s.

Estructura de una clase


La definici6n bisica debna ?lase presenta este aspecto:
class nombreclase

Para que la clase resulte util necesita tener atributos y operaciones. Para crear atributos se declaran variables dentro de una definici6n de clase utilizando la palabra clave var. El siguiente c6digo crea una clase llamada clas sname, con dos atributos $attribute1 y Sattribute2.
class classname var Sattributel; var Sattribute2;

Las operaciones se crean declarando funciones dentro de la definici6n de clase. El siguiente c6digo crea una clase denominada classname con dos operaciones que no hacen nada.

Desarrollo Web con PHP y MySQL

La operacion o p e r a t i o n 1 ( ) no toma par6metros y la operacionoperation2 toma dos par6metros.


class classname

()

t
function operat

I
function operat

Constructores
La mayor parte de las clases constan de un tip0 especial de operacidn llamado constructor. Un constructor se llama a1 crear un objeto y suele realizar tareas utiles de inicializacih como establecer atributos con valores de inicio 16gicos o crear otros objetos necesarios. Un constructor se declara de la misma forma que otras operaciones, pero tiene el mismo nombre que la clase. Aunque podemos llamar manualmente a1 constructor, su funci6n principal es hacerlo automiticamente a1 crear un objeto. El siguiente cddigo declara una clase con un constructor:
class classname function classname($param)

i
echo "Constructor called with parameter Sparam <br / > " ;

1 1

Recuerde que PHP no admite de manera nativa la sobrecarga de funciones, lo que significa que so10 se puede proporcionar una funcion con un nombre dado, incluido el constructor. (Muchos lenguajes de programacidn orientados a objetos admiten este recurso.) Existe una extensidn experimental que permite la sobrecarga de m6todos get y set, per0 no es muy 6til.

Instanciacion
Tras declarar una clase, tenemos que crear un objeto (un elemento concreto que forme parte de una clase) con el que trabajar. Esta tarea tambi6n se conoce como crear una instancia e instanciar una clase. Para crear u n objeto se utiliza la palabra clave new. Es necesario especificar a qu6 clase pertenecer6 el objeto y suministrar todos 10s par6metros que requiera el constructor.

6. PHP orientado a objetos

El siguiente cddigo declara una clase llamada c l a s s n a m e con un constructor y crea tres objetos del tip0 c l a s s name:
class
{

classname classname ( S p a r a m )

function

echo "Constructor called with parameter Sparam <br / > " ;

1
1

$a $b $C

= = =

new classname ( 'First' ) ; new classname('Second1); new classname();

Como el constructor se llama cada vez que creamos un objeto, este c6digo genera el siguiente resultado:
Constrl~ctor called with parameter First Constrllctor called with parameter Second ConstrLctor called with parameter

Uso de 10s atributos de clase


Dentro de una clase, disponemos de acceso a una variable especial llamada
$ t h i s . Si un atributo de la clase actual se denominara $ a t t r i b u t e , se utilizaria la

secuencia $ t h i s - > a t t r i b u t e para hacer referencia a 61 a1 establecer o acceder a la variable desde una operaci6n dentro de una clase. El siguiente cddigo muestra cdmo establecer o acceder a un atributo dentro de una clase:

- -

class classname var Sattribute; function operation($param) $this->attribute = Sparam echo $this->attribute;
1

Algunos lenguajes de programacidn nos permiten limitar el acceso a atributos declarando dichos datos como privados o protegidos. PHP no admite esta funcidn, por lo que 10s atributos y operaciones que utilicemos resultardn visibles fuera de la clase (es decir, ser6n todos publicos). Podemos realizar la misma tarea como se demostrd anteriormente desde fuera de la clase, utilizando sintaxis ligeramente diferente.
class classname

Desarrollo Web con PHP y MySQL


var
1

Sattribute;

$a = new classname ( ) ; $a->attribute = 'value'; echo $a->attribute;

No es buena idea acceder directamente a 10s atributos desde fuera de una clase. Una de las ventajas de u n enfoque orientado a objetos es que fomenta la encapsulation. Aunque en PHP no se puede forzar la ocultacion de datos, con un poco de voluntad se pueden extraer ciertas ventajas. Si en lugar de acceder a 10s atributos de una clase directamente, se escriben funciones de descriptores de acceso, todos 10s accesos se realizarfin a trav6s de una unica secci6n de c6digo. Las funciones de descriptores de acceso pueden presentar el siguiente aspecto a1 principio:
class classname

i
var Sattribute; function getpattribute()

t
return Sthis->attribute;

1
function set-attribute($new-value)

I
$this->attribute
=

$new-value;

Este c6digo proporciona funciones para acceder a1 atributo denominado


S a t t r i b u t e . Tenemos una funci6n llamada g e t a t t r i b u t e ( ) que devuelve simplementeelvalor de S a t t r i b u t e y u n a f u n c i 6 ~ l l a m a d a s e t -a t t r i b u t e ( ) que asigna un valor nuevo a S a t t r i b u t e .

A primera vista, podria pacecer que este c6digo no agrega mucho valor. En su forma actual, es probablemente cierto, per0 la raz6n para suministrar las funciones de descripci6n de acceso es sencilla: s610 tendremos una secci6n de c6digo que accede a dicho atributo. Con un solo punto de acceso, podemos implementar elementos de comprobaci6n para'asegurarnos de que s610 se almacenan datos pertinentes. Si en un momento posterior necesitamos que el valor de $ a t t r i b u t e est6 entre cero y cien, bastarii con agregar unas pocas lineas de c6digo y verificar antes de permitir 10s cambios. Podemos modificar la funci6n s e t -a t t r i b u t e ( ) para que presente esta aspecto:
function set-attributeisnew-value) if( $new-value >= 0 Sthis->attribute
&&
=

$newvalue <= 100 $new-value;

Este cambio resulta sencillo, per0 si no utilizamos la funci6n de descriptor de acceso, tendremos que recorrer cada linea de c6digo y modificar cada acceso a $ a t t r i b u t e , lo cual resulta pesado y proclive a errores.

6 . P H P orientado a objetos

Con un solo punto de acceso, podemos cambiar libremente la implementacibn subyacente. Si por alguna razbn, optamos por cambiar la forma en la que se almacena $ a t t r i b u t e , las funciones de descriptor de acceso nos permitirin hacerlo variando el cbdigo en un solo punto. Puede que en lugar de almacenar $ a t t r i b u t e como variable queremos recuperarla tinicamente desde la base de datos cuando resulte necesario, calcular un valor actualizado cada vez que se solicite, inferir un valor de 10s valores de otros atributos o codificar 10s datos con un tip0 de dato m6s pequeiio. Sea cual sea el cambio que decidamos realizar, bastar6 con modificar nuestras funciones de descriptor de acceso. El resto de las secciones de cbdigo no se ver6n afectadas mientras las funciones de descriptor de acceso sigan aceptando o devolviendo 10s datos que esperan otras partes del programa.

Llamadas a operaciones de clase


Podemos llamar a operaciones de clases de la misma forma que llamamos a 10s atributos de clase. Si tenemos la siguiente clase:
class classname

t
function operatiorll (
)

I
function operatior~2(Spararnl, Spararn2)

I
1

y creamos un objeto dei tipo c l a s s name llamado $a de la siguiente forma:


$ a = new classname();

Seguidamente llamamos a las operaciones de la misma forma que a otras funciones: por su nombre y con todos 10s par6metros que se necesiten entre p a r h t e sis. Como estas operaciones pertenecen a un objeto en lugar de a funciones normales, tenemos que especificar a qut! objeto pertenecen. El nombre del objeto se utiliza de la misma forma que 10s atributos de objeto:
$a->operationl(); $a->operation2(12, 'test');

Si nuestras operaciones devuelven algo, podemos capturar 10s datos devueltos de la siguiente forma:
$x Sy
= =

$a->operationl(); $a->operation2(12,

'test');

Desarrollo W e b con PHP y MySQL

Implementation de la herencia en PHP


Si nuestra clase es una subclase de otra, podemos utilizar la palabra clave e x t e n d s para especificarlo. El siguiente c6digo crea una clase llamada B que se deriva de la clase llamada A previamente definida.
class
B

extends

1
v a r Sattribute:; funct i n n operation2 ( )

Si la clase A se declara de la siguiente forma:


class A

i
var Sattributel;

todos 10s accesos siguientes a las operaciones y atributos de un objeto de tip0 B serian vAlidos:
S b = new B O ; Sb->operation1 ( 1 ; S b - > a t t r i b u t e 1 = 10; So->operatinn2 ( ) ; Sb->attribute2 = 10;

Fijese en que como la clase B extiende la clase A, podemos hacer referencia a y $ a t t r i b u t e 1, aunque se declararon en la clase A. Como subclase d e ~B, tiene la misma funcionalidad y 10s mismos datos. Ademds, B ha declarado un atributo y una operaci6n propia. Es importante observar que la herencia s610 funciona en una direcci6n. La subclase hereda las funciones de la clase principal o superclase, per0 6sta no toma ninguna funci6n de aqu6lla. Por lo tanto, las dos siguientes lineas de c6digo serian e r r h e a s :
o p e r a t i o n 1( )
$ a = new A ( ) ; $ a - > o p e r a t i m ~ n jl ) ; $a->attribute1 = 10; $a->operation20; = 10; $a->attribute2

La c l a s e no ~ tiene una operaci6n o p e r a t i o n 2

()

ni un atributo a t t r i b u t e 2 .

6. PHP orientado a objetos

Reemplazamientos
Hemos mostrado una subclase que declara nuevos atributos y operaciones. Tam, a declarar 10s mismos atributos y operaciobi6n resulta vilido, y a veces ~ t i lvolver nes. Podemos hacerlo para asignar un atributo de la subclase, un valor diferente para el mismo atributo de su superclase o aplicar a una operaci6n de la subclase funcionalidad diferente con respecto a la misma operaci6n de su superclase. Este recurso se denomina reemplazamiento. Por ejemplo, si tenemos una clase A:
class A

i
var Sattribute = 'default value'; function o p e r a t i o n 0 i echo 'Something<br / > I ; echo "The value o f \$attribute is $this->attribute<br / > " ;

I
1

y queremos alterar el valor predeterminado de S a t t r i b u t e y suministrar nueva funcionalidad para o p e r a t i o n ( ) , podemos crear la siguiente clase B, que reemplaza S a t t r i b u t e y o p e r a t i o n ( ) :
class B extends A

t
var Sattrlbute = 'cllfferent value'; function o p e r a t i o n 0
t

echo 'Something else<br / > I ; echo "The value o f \$attribute is Sthis->attribute<br / > " ;

La declaraci6n de B no afecta a la definici6n original de A. Considere las siguientes dos lineas de c6digo:
$a = new A ( ) ; $a -> operationi);

Hemos creado un objeto de tip0 A y hemos llamado a la funci6n o p e r a t i o n ( ) . El resultado seri:


Something The value of Sattribute is default valu?

si la creaci6n de B no ha alterado a A. Si creamos un objeto de tip0 B, obtendremos un resultado diferente. El siguiente c6digo:
$b $b
=

->

new B ( ) ; operation();

Desarrollo Web con P H P y MySQL

Something The value

else of Sattribute

is

different

value

De la misma forma que el suministro de nuevos atributos y operaciones dentro de una subclase no afecta a la superclase, el reemplazamiento de atributos u operaciones dentro de una subclase no afecta a la superclase. Una subclase heredar6 todos 10s atributos y operaciones de su superclase, a menos que se suministren reemplazamientos. Si suministra una definici6n de reemplazamiento, 6sta tendr6 preferencia y reemplazar6 a la definici6n original. A diferencia de otros leguajes orientados a objetos, PHP no permite reemplazar una funci6n y a la vez llamar a la versi6n definida en la clase superior. La herencia puede tener varias capas de profundidad. Por ejemplo, podemos declarar una clase c, que extienda B y que por tanto herede las funciones desde B y desde la clase superior A. La clase C puede a su vez seleccionar atributos y operaciones de sus clases principales para anularlas y reemplazarlas.

Herencia multiple
Algunos lenguajes orientados a objetos admiten la herencia mdtiple per0 no asi PHP. Esto significa que cada clase s610 puede heredarse desde una clase superior. No existen restricciones en cuanto a la cantidad de clases secundarias que puede compartir una clase principal. Puede que este concept0 no resulte claro a1 principio. La figura 6.1 muestra tres formas diferentes de derivar las c l a s e s ~B , y C.

Herencia simple

Herencia multiple

Herencia simple
Figura 6.1. PHP no admite la herencia multiple

La combinaci6n de la izquierda muestra la clase c que se hereda de la clase B, que a su vez se hereda de la clase A. Cada clase tiene un elemento superior a1 menos, por lo que se trata de una herencia simple perfectamente factible en PHP.

6 . PHP orientado a objetos

En la combinaci6n central, la clase B y la clase c se heredan de la clase A. Cada clase tiene una clase superior como mdximo, por lo que de nuevo estamos ante una herencia permitida en PHP. ~ de la La combinaci6n de la derecha muestra la clase c que se deriva de la c l a s e y clase B. En este caso, la clase c consta de dos clases principales lo que la convierte en una clase no vdlida en PHP.

Diseno de clases
Ahora que ya conocemos algunos d e 10s conceptos en 10s que se basan 10s objetos y las clases, y la sintaxis para implementarlos en PHP, ha llegado el momento de examinar c6mo disefiar clases utiles. Muchas clases de nuestro c6digo representan clases o categorias d e objetos del mundo real. Las clases que se utilizan en el desarrollo Web pueden incluir pdginas, componentes de interfaces de usuario, carros d e la compra, resoluci6n de errores, categorias de productos y clientes. Los objetos de su c6digo tambien pueden representar instancias especificas de clases mencionadas previamente, por ejemplo, la p6gina principal, un b o t h dado o el carro de la compra utilizado por Fred Smith en un momento dado. El propio Fred Smith puede representarse mediante un objeto de tip0 cliente. Cada articulo comprado por Fred se puede representar como un objeto que pertenezca a una categoria o clase. En el capitulo anterior, utilizamos sencillos archivos de inclusi6n para proporcionar a nuestra compafiia ficticia, TLA Consulting, un aspecto visual y operativo uniforme en las diferentes pdginas del sitio Web. El uso de las clases y la herencia permite crear versiones m6s avanzadas del mismo sitio. Queremos disponer d e ia pcnibilidad de crear p6ginas riipidamente para el sitio TLA que se comporten de igual forma y presenten un aspecto semejante. Estas piginas se podr6n modificar para su adaptaci6n a diferentes partes del sitio. Vamos a crear una clase Page. El objetivo global de esta clase es limitar la cantidad de c6digo HTML necesario para crear una nueva pigina. Nos permitird alterar las partes que cambian d e una pdgina a otra adem6s d e generar autom6ticamente 10s elementos para que no varien. Las clases ofrecen un marco flexible para crear nuevas pdginas y no deberian comprometer nuestra libertad de acci6n. Como estamos generando la pagina desde una secuencia de comandos en lugar de c6digo HTML estdtico, podemos agregar cualquier elemento que resulte inteligente, incluyendo funcionalidad para: Permitirnos alterar elementos de p6gina en un lugar. Si cambiamos la advertencia sobre 10s derechos de autor o agregamos un b o t h adicional, s610 necesitaremos realizar el cambio en un punto. Disponer de contenido predeterminado para la mayor parte de las pAginas, per0 disponer de la capacidad d e modificar cada elemento donde resulte

Desarrollo W e b con PHP y MySQL

necesario y establecer valores personalizados para elementos como el titulo y las etiquetas meta. Reconocer qu4 pdgina se estd visualizando y alterar 10s elementos de navegacidn para adaptarlos (no tiene mucho sentido tener un b o t h vinculado a la pdgina principal dentro de la pdgina principal). Permitirnos sustituir elementos estandar para pdginas particulares. Por ejemplo, si queremos utilizar diferentes botones de navegacidn en las secciones del sitio, deberiamos disponer de la posibilidad de sustituir 10s estdndar.

Escritura del codigo para nuestra clase


Tras decidir el aspect0 que queremos que devuelva nuestro codigo y la aplicacidn de una serie de funciones, jcdmo lo implementamos? En una parte posterior del libro abordaremos el diseiio y la gestidn de proyectos de gran tamaiio. Por el momento, vamos a concentrarnos en las partes especificas relacionadas con la escritura de PHP orientado a objetos. Nuestra clase necesitard un nombre logico. Como representa a una pdgina, se denominard Page.Para declarar una clase llamada Page,escribimos
class Page

Esta clase necesita algunos atributos. Estableceremos 10s elementos que es probable que queramos modificar de una pdgina a otra, como 10s atributos de nuestra clase. El contenido principal de la pdgina, que sera una combinacidn de etiquetas HMTL y texto, se denorrfinarZ $content. Podemos declarar el contenido con la siguiente linea de cddigo dentro de la funcidn de clase.
var $content;

Tambien podemos establecer 10s atributos para almacenar el titulo de la pdgina. Es probable que queramos modificar este elemento para indicar con claridad la pagina que estd visualizando nuestro visitante. En lugar de incluir titulos en blanco, suministraremos un titulo predeterminado con la siguiente declaracidn:
var $title
=

'TLA Consulting Pty Ltd';

La mayor parte de las pdginas Web comerciales incluyen etiquetas meta para ayudar a 10s motores de busqueda a indexarlas. Para que resulten utiles, las etiquetas meta deberian cambiar de una pdgina a otra. De nuevo, suministramos un valor predeterminado:
var $keywords some of
=

'TLA Consulting, Three Lette~. Abbreviation, my best friends are search engines';

6 . PHP orientado a objetos

Los botones de navegaci6n que se muestran en la pagina original de la figura 5.2 (vkase capitulo anterior) deberian mantenerse entre las diferentes paginas para evitar confundir a 10s usuarios, per0 para poder cambiarlos con facilidad 10s convertiremos en un atributo. Como el numero de botones puede ser variable, utilizaremos una matriz y almacenaremos el texto del bot6n y del URL a1 que deberia apuntar.
var $buttons
=

array( 'Home' => 'Cor~tact' => 'Services' => 'Site Map' =>

'home.phpl, 'contact .phpl, 'services.phpT, 'map.phpl

Para proporcionar alguna funcionalidad, la clase tambien necesita operaciones. Podemos comenzar por suministrar funciones de descriptores de acceso para establecer y obtener valores de 10s atributos definidos. fistos suelen adoptar la siguiente forma:
function SetContent($newcontent)

t
$this->content
=

Snewcontent;

Como es poco probable que solicitemos alguno de estos valores desde fuera de la clase, hemos optado por utilizar una colecci6n de funciones Get. La funci6n principal de esta clase es mostrar una pigina de c6digo HTML, por lo que necesitaremos una funci6n. Hemos llamado a la funci6n Display ( ) y presenta de la siguiente forma:
function Display (
)

i
echo "<html>\n<head>\n"; Sthis -> DisplayTitle ( ) Sthis -> DisplayKey'words ( 1 ; $this -> Displaystyles ( ) ; echo "</head>\n<body>\nn; $this -> DisplayHeaderi ) ; $this -> DisplayMenu($this->buttons); echo $this->content; Sthis -> DisplayFooter ( ) ; echo "</body>\n</html>\n";

Esta funci6n incluye varias instrucciones echo sencillas para mostrar c6digo HTML, per0 se compone fundamentalmente de llamadas a otras funciones de la clase. Como es probable que haya supuesto por 10s nombres, dichas funciones muestran partes de la p6gina. No es obligatorio dividir las funciones de esta forma. Todas ellas podrian combinarse en una funci6n de mayor tamaiio. En nuestro caso, las hemos dividido por varias razones. Cada funci6n deberia realizar una tarea definida. Cuanto m i s sencilla sea, m i s ficil resultar5 escribirla y probarla. Tampoco conviene excederse: si divide su programa en unidades demasiado pequeiias puede resultar dificil de leer.

Desarrollo Web con P H P y MySQL

El uso de la herencia permite reemplazar operaciones. Podemos reemplazar la funci6n Display ( ) , per0 es poco probable que queramos cambiar la forma en la que se muestra toda la pigina. Resultari mucho mejor dividir la funcionalidad de visualizaci6n en unas pocas tareas independientes y disponer de la posibilidad de reemplazar s610 las partes que deseemos modificar. Nuestra funci6n Display llama a DisplayTitle ( ) , DisplayKeywords 0, Displaystyles 0, DisplayHeader 0, DisplayMenu ( ) y DisplayFooter 0. Por lo tanto, necesitamos definir estas operaciones. Una de las mejoras de PHP 4 sobre PHP 3 es que podemos escribir operaciones o funciones en orden 16gico. Para ello, se llama a la operaci6n o a la funci6n antes que a1 c6digo de la funcion. En PHP 3 y muchos otros lenguajes, necesitamos escribir la funci6n u operaci6n antes de poder llamarla. La mayor parte de nuestras operaciones son bastante simples y necesitan mostrar HTML y quizis 10s contenidos de nuestros atributos. El listado 6.1 muestra la clase completa, que hemos guardado como page. inc para incluir o exigir dentro de otros archivos.
Listado 6.1. page.inc. Nuestra clase proporciona una forrna facil y flexible de crear paginas para el sitio TLA
<?php class Page

I
/ / atributos de la clase Page var $content; var $title = 'TLA Consulting Pty Ltd'; var $keywords = 'TLA Consulting, Three Letter Abbreviation, some of my best friends are search engines'; var Sbuttoris = array ( 'Home' => 'home.phpl, 'Contact' => 'contact.php', 'Services' => 'services.php', 'Site Map' => 'map.php9 1;

/ / operaciones de Page

function SetContent($newcontent)

t
Sthis->content
=

Snewcontent;

I
function SetTitle(Snewtit1e)

I
Sthis->title
=

Snewtitle;

1
function SetKeywords(Snewkeywords)

i
Sthis->keywords
=

Snewkeywords;

1
function SetButtons(Snewbuttons)

6 . PHP orientado a objetos

1
$this->buttons
=

Snewbuttons;

I
function Display() i echo "<html>\n<head>\n"; $this -> DisplayTitle ( ) ; Sthis DisplayKeywords ( ) ; $this -> DisplayStyles ( ) ; echo "</head>\n<body>\nW; $this -> DisplayHeader ( ) ; Sthis -> DisplayMenu($this->buttons); echo $this->content; $this -> D i s p l a y F o o t e r O ; echo "</body>\n</html>\n";

I
function DisplayTitleO

1
echo '<title> $this->title </title>';

function DisplayKeywords (

I
echo "<META name=\"keywords\" c o r l t e r ~ t = \ " $ t h i s - > k e y w o r d s \ " > " ;

I
function Displaystyles (
?>
)

.menu {color:white; font-size:12pt; text-a1ign:center; font-farnily:&lal, sans-serif; font-weight:bold) td {background: black} p ico1or:black; font-size:12pt; text-a1ign:justify; font-family:arial,sans-serifi

function DisplayHeaderO

I
?>

<table width="lOO%" cellpadding ="12" cellspacing ="O" border = " O m > <tr bgcolor ="blackm> <td align ="leftW><img src = "logo.gif"></td> <td> <hl>TLA Corlsulting Pty Ltd</hl> </td> <td align ="rightM><img src = "logo.gif"></td>

Desarrollo Web con PHP y MySQL

function DisplayMenu(Sbuttons)

i
echo "ctable width='lOO%' bgcolc,r='white' cellpadding='4' cell spacing='l ' \ n W ; <tri\nW; echo " //calcular el tamafio del bot6n $width = 100/count(Sbuttons); while (list(Sname, Surl)
=

each($buttonc))

I
Sthis -> DisplayButton($width, $name, Surl, !Sthis-> lsURLCurrentPagt($url));

I
echo " </tr>\nl'; echo "//table>\nn;

1
function IsURLCurrentPage(Sur1)
I

ifistrpos( $GLOBALS['SCRIPT-NAME'], Surl )==false)

I
return false; else i return true;

if (Sactive)

function DisplayButtorl ($width, $name, Surl, $active

true)

i
echo "ctd width ='$width%'> <a href ='$urlt> <img src ='s-lrig,3.gif' alt ='$name' border = ' O 1 > < / a > 1 class= ' n l e r ~ u ' > $ r ~ a m e < / s p a r ~ > i / a > < / t d ' " ; <a liref = ' $ 1 1 ~'><span

i
else

i
echo "<td width ='$width%'> <img src ='side-logo.gifl>

function DisplayFooter ( i i

?>

<table width == "100%" bgcolor ="black" cellpadding ="12" border = " O w > <t r> <td> <p class="foot">&copy; TLA Consulting Pty Ltd.</p> <p class="foot">Please see our <a href ="">legal information page</a></p> </td> </tr> </table> <?php

I
?>

A1 leer esta clase, fijese en que Displaystyles ( ) , DisplayHeader ( ) y DisplayFooter ( ) necesitan mostrar un gran bloque de HTML estdtico sin ningun procesamiento de PHP. Por lo tanto, s610 hemos utilizado una etiqueta final de PHP (?>), hemos escrito nuestro c6digo de HTML y hemos vuelto a introducir PHP con una etiqueta de apertura de PHP (<?php)dentro de las funciones. En esta clase se definen otras dos operaciones. En concreto, la operaci6n Di splayButt on ( ) muestra un bot6n de menu. Si el bot6n va a apuntar a la pdgina en la que estamos, mostramos un bot6n inactivo que presenta un aspect0 ligeramente diferente sin vinculaci6n. De esta forma, logramos mantener la uniformidad de la pdgina y suministramos a 10s visitantes una ubicaci6n visual. La operaci6n IsURLCurrentPage ( ) determina si el URL asociado a un bot6n apunta la pdgina actual. Se pueden utilizar muchas tkcnicas para descubrirlo. En este caso, hemos utilizado la funci6n de cadena strpos ( ) para determinar si el URL dado estd contenido en una de las variables establecidas de servidor. La instrucci6n s trpos ( ) SGLOBXLS SCRIPT NAME ' I , $url ) devolverd un numero si la cadena de $url se encuentra dentro de la variable global o SCRIPT-NAME, en caso contrario. Para utilizar esta clase de pdgina necesitamos incluir page. inc en una secuencia de comandos y llamar a Display ( ) . El c6digo del listado 6.2 crear6 la p6gina de inicio de TLA Consulting y devolverd un resultado muy similar a1 que generamos previamente en la figura 5.2. El c6digo del listado 6.2 realiza las siguientes tareas:

r'

1. Utiliza require para incluir contenidos depage .inc,que contiene la definici6n de la clase Page.
2. Crea una instancia de la clase Page, denominada $homepage.

3. Llama a la operaci6n setcontent ( ) dentro del objeto $homepage y pasa texto y etiquetas HTML para que aparezcan en la p6gina.
4. Llama a la operaci6n Display ( ) dentro del objeto $homepage para obligar a la pdgina a mostrarse en el navegador del visitante.

Desarrollo Web con PHP y MySQL


Listado 6.2. home.php. Esta pagina de inicio utiliza la clase Page para realizar la mayor parte del trabajo implicado en la generacion de la pagina
<?php require ('page.inc'); Shornepage
=

new P a g e ( ) ;

Shomepage -> SetContenti'<p>Welcome to the home of TLA Consulting Please take some time to get to know us.</p> <p>We specialize in serving your business needs and hope to hear from you soon.</p>'
i;

Shomepage -> Display();


?>

Como puede observar en este listado, se necesita realizar muy poco trabajo para generar nuevas piginas utilizando la clase Page. El uso de esta clase de la forma ilustrada implica que todas nuestras piginas deben ser muy similares. Si queremos que una secci6n del sitio utilice una variante de la pagina estindar, bastard con copiar p a g e . i n c en un nuevo archivo llamado p a g e 2 . i n c y realizar algunos cambios. Como resultado, cada vez que actualicemos o modifiquemos partes de la pigina p a g e . i n c necesitaremos acordarnos de realizar 10s mismos cambios en p a g e 2 . i n c . Una opci6n mejor consiste en utilizar la herencia para crear un nueva clase que derive gran parte de su funcionalidad de Page y que reemplace las partes que necesiten ser diferentes. En el sitio de TLA, queremos que la pigina de servicios incluya una segunda barra de navegaci6n. La secuencia de comandos que se muestra en el listado 6.3 realiza esta tarea mediante la creaci6n de una nueva clase llamada S e r v i c e s Page que se deriva de Page. Suministramos una nueva matriz llamada $ r o w 2 b u t t o n s que contiene 10s botones y vinculos que queremos en la segunda fila. Como queremos que esta clase se comporte pricticamente'de la-misma manera, s610 anulamos la parte que queremos modificar: la operacidn D i s p 1a y ( ) .
Listado 6.3. services.php. La pagina de servicios se deriva de la clase Page per0 reemplaza Display() para variar el resultado
<?php require ('page.inc1); class ServicesPage extends Page

I
var Srow2buttons
=

array( 'Re-engineering' => 'reengineering.php', 'Standards Compliance' => 'standards.php1, 'Buzzword Compliance' => 'buzzword.phpl, 'Mission Statements' => 'mission.php'
1;

function Display (
{

echo "<html>\nihead>\nW; DisplayTitlei); Sthis ->

6 . P H P oricntndo n objctos

El sustituto d e D i s p l a y linea m i s

()

es m u y similar con la excepcicin d e q u e contiene una

para llamar a D i s p l a y M e n u ( ) una segunda vez y crear una segunda barra d e menu. Fuera d e la definicicin d e clase, creamos una instancia d e la clase S e r v i c e p a g e , establecemos 10s valores para 10s clue no queremos 10s predeterminados y llamamos a
Display ( )

Archm Edtuon Ver F n m t o i Herrm


D~remon
I t
A

Z~L nyvd
r 1 i'

-.x

r I

At TLA Consulting, we offer a number of services. Perhaps the productivity of your employees would improve if we re-engineered your business. Maybe all your business needs is a fresh mission statement, or a new batch of buzzwords.

Figura 6.2. La pagina de servicios se creo utilizando la herencia para volver a utilizar gran parte de nuestra pagina estandar

Desarrollo Web con P H P y MySQL

Como se ilustra en la figura 6.2, tenemos una nueva variante de la pfigina esttindar. El unico c6digo nuevo que necesitamos escribir es el que hace referencia a las partes diferentes. La creaci6n de pdginas a traves de clases PHP presenta ventajas claras. Con una clase que realice la mayor parte del trabajo por nosotros, necesitaremos realizar menos trabajo para crear una nueva pigina. Podemos actualizar todas las ptiginas de una vez actualizando la clase. La herencia nos permite derivar diferentes versiones de la clase desde el original sin perder sus ventajas. Como ocurre con casi todo en esta vida, estas ventajas tienen un coste. La creaci6n d e paginas desde una secuencia de comandos exige un mayor esfuerzo del procesador que la simple carga de una pdgina HTML estandar desde el disco y su envio a un navegador. En un sitio con trtifico este hecho resultara importante por lo que convendria utilizar ptiginas HTML esttiticas o almacenar en cache el resultado de las secuencias de comandos alli donde resulte posible para cargarlo en el servidor.

La siguiente secci6n aborda el estudio de MySQL. Explicaremos como crear y completar una base de datos de MySQL, y vincularemos lo aprendido a PHP para poder acceder a nuestra base de datos desde la Web.

Ahora que ya se ha familiarizado con 10s fundamentos de PHP, vamos a ver como integrar un base de datos en nuestras secuencias de comandos. En un capitulo anterior comentamos las ventajas de utilizar una base de datos relacional en lugar de un archivo sin procesar: Los RDBMS brindan un acceso mas rapido a 10s datos que 10s archivos sin procesar.

Los RDBMS permiten realizar consultas ficilmente para extraer conjuntos de datos que encajen con determinados criterios. Los RDBMS incorporan mecanismos para tratar con accesos simultdneos para no tener que preocuparnos de esta tarea como programadores. Los RDBMS brindan acceso aleatorio a 10s datos. Los RDBMS incorporan un sistema de privilegios. Para ser mas concretos, el uso de una base de datos relacional nos permite responder de forma rapida y sencilla a consultas sobre la procedencia de 10s clientes, 10s productos que se estdn vendiendo mejor o qu6 tip0 de clientes son 10s que mas dinero se dejan. Esta informaci6n puede ayudarle a mejorar el sitio para atraer y fidelizar a 10s clientes. En esta secci6n utilizaremos MySQL como base de datos.

Antes de profundizar en el estudio de las caracteristicas de MySQL en el siguiente capitulo, examinaremos 10s siguientes aspectos:
r Conceptos relacionados con las bases de datos relacionales y terminologia r Disefio debases de datos Web r Arquitectura debases de datos Web

Conceptos de base de datos relacionales


Las bases de datos relacionales son, con diferencia, el tip0 de base de datos mas utilizado. Estas bases de datos se basan tedricamente en el algebra relacional. No es necesario comprender la teoria para utilizar una base de datos relacional (aunque vendria bien), per0 si conviene comprender algunos conceptos basicos relacionados con las bases de datos.

Tahlas Las bases de datos relacionales se componen de relaciones, conocidas de manera mas comun como tablas. Una tabla es exactamente eso, una tabla de datos. Un ejemplo de tabla relacional es una hoja de calculo electr6nica. Vamos a examinar un ejemplo. En la figura 7.1, puede ver una tabla de ejemplo. Esta tabla contiene 10s nombres y las direcciones de 10s clientes de una libreria, Book-0-Rama.

CustomerlD Name

Address Cily 1 Julie Smith Airport West 25 Oak Street 1147 Haines Avenue Box Hill 2 Alan Wong 3 Michelle Arthur 357 North Road Yarraville

Figura 7.1. Los detalles de 10s clientes de Book-0-Rama se guardan en una tabla

La tabla tiene un nombre (Customers), varias columnas, que hacen referencia a un tip0 diferente de datos, y filas que se corresponden con 10s distintos clientes.

Columnas
Cada columna de la tabla tiene un nombre unico y diferentes datos. Cada una de ellas lleva asociado un tip0 de datos. Por ejemplo, en la tabla Customers de la figura 7.1, puede ver que el campo CustomerID es de tip0 entero y las otras tres columnas son cadenas. Las columnas a veces se llaman campos o atributos.

Desarrollo Web con PHP y MySQL

--

Cada fila de la tabla representa un cliente distinto. Debido a1 formato tabular, todos tienen 10s mismos atributos. Las filas tambikn se denominan registros.

Cada fila se compone de un conjunto de valores individuales que se corresponden con las columnas. Cada valor debe tener el tip0 de dato especificado por su columna.

Necesitamos disponer de una forma de identificar a cada cliente. Los nombres no son una buena opcion (si tiene un nombre muy utilizado, entenderd por qu6). Tomemos como ejemplo a Julie Smith de la tabla Customers. Si abre una guia de telefonos de 10s EEUU, descubrird una gran cantidad de entradas con ese nombre. Podemos distinguir a Julie de diferentes formas. Es probable que sea la unica Julie Smith que viva en la direcci6n que se indica. Sin embargo, el uso del nombre y la direcci6n en conjunto para distinguir a alguien resulta muy pesado y suena un poco a lenguaje legal. Ademds se necesita utilizar mds de una columna de la tabla. En este ejemplo, lo que hemos hecho, y es probable que se decante por la misma soluci6n en sus aplicaciones, es asignar un numero de identification de cliente exclusivo (CustomerID). Se trata del mismo principio seguido para asignar numeros de cuenta o numero de socios unicos. Esta tecnica facilita el almacenamiento de 10s detalles en una base de datos. Un numero d e identificaci61-1asignado artificialmente garantiza su exclusividad. Existen muy pocos tipos de informaci6n real que dispongan de esta propiedad, aunque se utilicen en una combinaci6n. La columna de identificaci6n de una tabla se denomina clave o clave principal. e el caso si optamos por Las claves pueden constar de varias columnas. ~ s t seria utilizar el nombre y la direccidn de un cliente, per0 su exclusividad no estd garantizada. Las bases de datos suelen constar de varias tablas y utilizan una clave para asociar una tabla a otra. En la figura 7.2, hemos agregado una segunda tabla a la base de datos. En esta tabla se almacenan 10s pedidos realizados por 10s clientes. Cada fila de la tabla Orders representa un unico pedido realizado por un unico cliente. Sabemos quien es el cliente porque almacenamos su CustomerID. Por ejemplo, si examinamos el pedido con OrderID 2, descubriremos que lo ha realizado el cliente con CustomerID 1.A continuaci6n, si examinamos la tabla Customers, veremos que el cliente con CustomerID 1es Julie Smith. El termino utilizado en las bases relacionales para designar esta relaci6n es clave secundaria. La columna CustomerIP es la clave principal de la tabla Customer, per0 cuando aparece en otra tabla, como la tabla Orders, se conoce como clave secundaria. Es posible que se est6 preguntando por qu6 hemos optado por utilizar dos tablas distintas y no almacenar la direccidn de Julie en la tabla Orders. En la siguiente secci6n intentaremos dar respuesta a esta cuesti6n.

7 . Disefio de la base de datos W e b

CUSTOMERS
CustomerlD Name 1 Julie Smith 2 Alan Wong 3 Michelle Arthur Address 25 Oak Street 1147 Haines Avenue 357 North Road City Airport West Box Hill Yarraville

ORDERS

Figura 7.2. Cada pedido de la tabla Orders hace referencia a un cliente de la tabla Customer

Esquemas
El conjunto completo de disefios de tabla de un base de datos se conoce como esquema de la base de datos. Es como el esqueleto de la base de datos. Un esquema debe mostrar las tablas con sus columnas, 10s tipos de datos de las columnas e indicar la clave principal de cada tabla y sus claves secundarias. Los esquemas no incluyen datos, per0 se puede incluir un ejemplo para explicar su objetivo. Los esquemas pueden adoptar la forma de diagramas, como 10s que estamos utilizando, diagramas de relaciones de entidad (que no se analizarin en este libro) o pueden tener forma de texto, como Customers(CustomerID, Name, Address, City) Orders(OrderID, CustomerID, Amount, Date) Los t6rminos subrayados con una linea continua en el esquema son las claves principales de la relaci6n. Los terminos subrayados con una linea discontinua son las claves secundarias de la relaci6n en la que aparecen.

Las claves secundarias representan una relaci6n entre 10s datos de dos tablas. Por ejemplo, el vinculo de Orders a Customers representa una relaci6n entre una fila de la tabla Orders y una fila de la tabla Customers. Existen tres tipos bisicos de relaciones en una base de datos relacional. Se clasifican en funci6n del n6mero de elementos que haya a cada lado de la relaci6n. Las relaciones puede ser uno a uno, uno a varios o varios a varios. Una relaci6n uno a uno significa que s610 hay un elemento a cada lado de la relaci6n. Por ejemplo, si hemos colocado direcciones en una tabla distinta a la de clientes, existiria una relaci6n uno a uno entre ambas. Podriamos tener una clave secundaria desde la tabla de direcciones a la tabla de clientes o a1 rev& (no serian obligatorias ambas).

Desarrollo W e b con PHP y MySQL

En una relaci6n uno a varios, una fila de una tabla se vincula a varias filas de otra tabla. En nuestro ejemplo, un cliente podria haber realizado varios pedidos. En estas relaciones, la tabla que contiene varias filas tendrd una clave secundaria hasta la tabla con una sola fila. En este caso, hemos incluido la columna CustomerID dentro de la tabla Order para mostrar la relaci6n. En las relaciones varios a varios, varias filas de una tabla se asocian a varias filas de otra tabla. Por ejemplo, si tememos dos tablas, L i b r o s y A u t o r e s , puede que un libro haya sido escrito por dos autores y que ambos hayan escrito otros libros, en solitario o en colaboraci6n con otros autores. En este tip0 de relaciones se crea una tabla especial para representar las relaciones, con lo que nos tendremos las siguientes: L i b r o s , A u t o r e s , L i b r o s A u t o r e s . La tercera tabla contendrii unicamente las claves de las otras tablas como claves secundarias en pares, para mostrar qu4 autores estdn relacionados con cada libro.

Como diseiiar nuestra base de datos Web


La tarea miis dificil consiste en determinar cuiindo se necesita una tabla y cud1 deberia ser la clave. Existe una ingente cantidad de material dedicado a estudiar 10s diagramas de relaci6n de entidad y de normalizaci6n de bases de datos, pero quedan fuera del iimbito de este libro. Sin embargo, en la mayor parte de 10s casos, basta con seguir unos sencillos principios b6sicos de diseiio. Vamos a analizarlos en el context0 de la aplicaci6n Book-0-Rama.

Piense en 10s objetos del mundo real que esta modelando


A1 crear una base de datos, lo que hacemos es modelar elementos y relaciones del mundo real, y almacenar la informaci6n sobre dichos objetos y relaciones. Por regla general, cada clase de objeto del mundo real que se modele necesitarii su propia tabla. Piense en ello un momento: queremos almacenar la misma informaci6n sobre todos nuestros clientes. Si existe un conjunto de datos con la misma "forma", podremos crear fiicilmente una tabla que se corresponda con dichos datos. En el ejemplo Book-0-Rama, queremos almacenar la informaci6n sobre nuestros clientes, 10s libros que vendemos y 10s detalles de 10s pedidos. Todos 10s clientes tienen un nombre y una direcci6n. Los pedidos tienen una fecha y una cantidad total, asi como 10s libros pedidos. Los libros constan de ISBN, de un autor, un titulo y un precio. Por lo tanto, parece que necesitamos a1 menos tres tablas en esta base de datos: C u s t o m e r s , O r d e r s y B o o k s . En la figura 7.3 se recoge el esquema inicial. Por el momento, no podemos determinar qu6 libros se incluyen en cada pedido a partir del modelo. Lo veremos en un instante.

7. Disefio de la base de datos Web

Como evitar el almacenamiento de datos redundantes


En una secci6n anterior ya nos planteamos por qu6 no almacenar la direcci6n de Julie Smith en la tabla de pedidos. Si Julie realiza varios pedidos a Book-0-Rama, como asi esperamos, acabaremos almacenando sus datos varias veces. Es probable que la tabla de pedidos presente un aspect0 parecido a1 ilustrado en la figura 7.4.
CUSTOMERS
CustomerlD Name 1 Julie Smith 2 Alan Wong 3 Michelle Arthur Address 25 Oak Street 1/47 Haines Avenue 357 North Road City Airport West Box Hill Yarraville

1 OrderlD

1 CustomerlD

1 Amount

1 Date

BOOKS

1 ISBN

1 Author

1 Title

Figura 7.3. El esquemahicial consta de las tablas Customers, Orders y Books

1 price Java 2 for Professional Developers 34.99 124.99 Installing Debian GNUILinux Teach Yourself GlMP in 24 Hours 24.99

ORDERS
OrderlD Amount Date 12 13 14 15 199.50 25-Apr-2000 43.00 29-Apr-2000 15.99 30-Apr-2000 23.75 01-May-2000 CustomerlD Name 1 1 1 1 Julie Smith Julie Smith Julie Smith Julie Smith Address 28 Oak Street 28 Oak Street 28 Oak Street 28 Oak Street City A~rport West Airport West Airport West Airport West

Figura 7.4. El diseiio de una base de datos que almacena datos redundantes aumenta el espacio utilizado y puede dar lugar a anomalias en 10s datos

Esto plantea dos problemas bdsicos. El primer0 supone malgastar espacio innecesariamente. iPor qu6 guardar 10s detalles de Julie en tres sitios si s610 necesitamos guardarlos en uno? El segundo problema son las anomalias que pueden surgir a1 actualizar 10s datos, es decir, situaciones en las que a1 cambiar 10s datos se producen inconsistencias. La integridad de 10s datos quedard alterada y ya no sabremos qu6 datos son correctos y

Desarrollo W e b con PHP y MySQL

qu6 datos son incorrectos. Por regla general, esta situaci6n dar6 lugar a la p6rdida de datos. Es necesario evitar tres tipos de anomalias de actualizaci6n: anomalias de modificacibn, de inserci6n y de eliminaci6n. Si Julie se muda de domicilio con pedidos todavia pendientes, tendremos que actualizar su direcci6n en tres lugares en lugar de en uno, lo que equivale a tener que realizar el trabajo tres veces. Resulta sencillo pasar por alto esta tarea y acabar realizando el cambio en un solo lugar, lo que dar6 lugar a la incoherencia de 10s datos de la base de datos (algo muy negativo). Estos problemas se conocen como anomalias de modificaci6n porque tienen lugar cuanto se intenta modificar la base de datos. En este diseiio, necesitamos insertar 10s detalles de Julie cada vez que recibimos un pedido, lo que significa que deberemos comprobar y asegurarnos de que sus datos son correctos en las filas existentes de la tabla. Si pas6ramos por alto la comprobaci6n, podriamos acabar con dos filas de datos desiguales sobre Julie. Por ejemplo, una fila podria indicar que vive en Airport West y otra en Airport. Este tip0 de anomalia se conoce como anomalia de inserci6n porque tiene lugar a1 introducir 10s datos. El tercer tip0 de anomalia se conoce como anomalia de eliminaci6n porque tiene lugar (sorpresa, sorpresa) a1 eliminar filas de la base de datos. Por ejemplo, imagine que tras enviar un pedido, lo eliminamos de la base de datos. Cuando se hayan servido todos 10s pedidos de Julie, se habrin eliminado todos de la tabla Order. Esto significa que no dispondremos de un registro sobre la direcci6n de Julie. Por tanto, no podremos enviarles ninguna oferta especial y necesitaremos tomar sus datos de nuevo cuando vuelva a realizar un pedido. Por regla general, a1 disefiar las bases de datos se intenta evitar estas anomalias.

Uso de valores de columna unicos


Cada atributo de una fila debe almacenar un solo valor. Por ejemplo, necesitamos saber qut! libros componen cada pedido. Existen varias formas de hacerlo. Podemos agregar una columna a la tabla Orders en la que se enumeren todos 10s libros que hemos pedido, como se ilustra en la figura 7.5.

ORDERS
OrderlD CustomerlD Amount Date
1 2 3 4 3 1 2 3 27.50 12.99 74.00 6.99 02-Apr-2000 15-Apr-2000 19-Apr-2000 01-May-2000

Books Ordered
0-672-31697-8 0-672-31745-1. 0-672-31509-2 0-672-31697-8 0-672-31745-1, 0-672-31 509-2. 0-672-31697-8

Figura 7.5. En este disetio, el atributo Books Ordered de cada fila incluye varios valores

No es una buena idea por varias razones. Lo que en realidad estamos haciendo es anidar una tabla dentro de una columna (una tabla que relaciona pedidos y libros). A1 hacerlo, resulta m6s dificil responder a preguntas como "iCu6ntas copias del libro

7. Diseiio de la base de datos W e b

Java 2 for Professional Developers quiere pedir?" ya que el sistema no puede contar 10s campos coincidentes. En su lugar, debe analizar cada valor de atributo y determinar si contiene una correspondencia en su interior. Como lo que estamos haciendo es crear una tabla dentro de otra, lo que deberiamos hacer es crear una nueva tabla. Esta nueva tabla, se denomina Order -1 tems y se muestra en la figura 7.6.

-ITEMS
ISBN 0-672-31697-8 0-672-31745-1 0-672-31509-2 0-672-31697-8 0-672-31745-1 0-672-31509-2 0-672-31697-8

Figura 7.6. Este diseiio facilita la bljsqueda de libros concretos pedidos

Esta tabla proporciona un vinculo entre la tabla O r d e r s y la tabla Books. Es habitual crear este tip0 de tablas en una relaci6n varios a varios entre dos objetos: en este caso, un pedido puede constar de varios libros y varias personas pueden pedir un libro.

Seleccion de claves logicas


Asegurese de que las claves seleccionadas son exclusivas. En nuestro caso, hemos creado una clave especial para 10s clientes (CustomerID) y para 10s pedidos (OrderID) porque es posible que estosobjebs del mundo real no dispongan de manera natural de un identificador con garantias de exclusividad. No necesitamos crear un identificador unico para 10s libros porque ya existe en forma de ISBN. EnOrder 1 tem, puede agregar una clave adicional si lo desea, pero la combinaci6n de 10s atributos OrderID (subrayadps???)e ISBN resultarfi exclusiva siempre y cuando se trate a cada copia de un libro dentro de un pedido como una fila. Por resta raz6n, la tabla Order-1t em incluye una columna Quantity.

Reflexiones sobre las preguntas que desea formular a la base de datos


Enlazando con la secci6n anterior, piense en las preguntas que desea que responda la base de datos. (Recuerde las preguntas que realizamos a1 principio del capitulo. Por ejemplo, jcufiles son 10s libros que mfis vende Book-0-Rama?). Asegurese de que la base de datos contiene todos 10s datos necesarios y que se han establecido 10s vinculos adecuados entre las tablas para responder a las preguntas deseadas.

Desarrollo W e b con P H P y MySQL

Evite disenos con varios atributos vacios


Si desea agregar resefias de libros a la base de datos, dispone a1 menos dos formas de hacerlo. En la figura 7.7 se recogen ambos enfoques. La primera consiste en agregar la columna Review a la tabla Books. En esta solucion se incluye un campo nuevo de resefia para cada libro. Si la base de datos consta de una gran cantidad de libros y el encargado de las resefias no tiene previsto crear una para cada libro, muchas filas quedaran vacias. Es lo que se conoce como valor nulo
BOOKS
ISBN

1 Author

1 Title

1 Price 1 Review 1

0-672-31687-8 Michael Morgan Java 2 for Professional Developers 34.99 0-672-31745-1 Thomas Down Installing Debian GNUlLinux 24.99 Teach Yourself GlMP in 24 Hours 24.99 0-672-31509-2 Pruitt, et al.

BOOK-REVIEWS
ISBN

1 Review
I

Figura 7.7. Para agregar reseiias, podemos incorporar una nueva columna a la tabla Books o aiiadir una tabla especifica para almacenar esta informacion

No conviene tener muchos valores nulos en una tabla ya que esta practica contribuye a desperdiciar espacio de almacenamiento y ocasiona problemas a1 calcular totales o a1 aplicar otras funciones a columnas num6ricas. Si un usuario ve un valor nulo en una tabla, no sabra si se debe a que el valor no resulta relevante, a que hay un error en la base de datos o a que no se han introducido 10s datos todavia. Por regla general, para evit3r 10s problemas con la inclusi61-1 de demasiados valores nulos se recurre a un disefio alternativo. En este caso, podemos utilizar el segundo diseiio ilustrado en la figura 7.7. En este caso, s610 se enumeran 10s libros con una resefia a la tabla Book Reviews, asi como sus resefias. Fijese en que este disefio se basa en la idea de tener una persona encargada de la revisi6n. Como alternativa podriamos permitir que 10s clientes se encarguen de realizar las resefias. En este caso, podriamos afiadir el campo c u s t o m e r I D a la tabla Book-Reviews.

Resumen de 10s tipos de tablas


Como tendr6 la oportunidad de comprobar, las bases de datos suelen componerse de dos tipos de tablas: Tablas sencillas que describen un objeto del mundo real. Tambien podrian contener claves a otros objetos simples en 10s que exista una relaci6n uno a uno o uno a varios. Por ejemplo, nuestro cliente podria contener varios pedidos,

7. Diseiio de la base de datos W e b

per0 cada pedido se asocia a un unico cliente. Por lo tanto, asignamos una referencia a1 cliente en el pedido. Tablas de uni6n que describen una relaci6n varios a varios entre dos objetos reales como la relaci6n entre O r d e r s y B o o k s . Estas tablas suelen asociarse con algun tip0 de transacci6n del mundo real.

Tras comentar la arquitectura interna de nuestra base de datos, vamos a examinar la arquitectura externa de un sistema de base de datos Web y a comentar la metodologia para desarrollar un sistema de base de datos Web.

En la figura 7.8 se ilustra el funcionamiento bdsico de un servidor Web. Este sistema consta de dos objetos: un navegador Web y un servidor Web. Para unirlos se necesita una forma de comunicaci6n. Un navegador Web realiza una solicitud a1 servidor. El servidor devuelve una respuesta. Esta arquitectura resulta apropiada para un servidor que devuelva pdginas estdticas. La arquitectura que devuelve resultados de un sitio Web basado en una base de datos resulta un tanto mds complicada.

Navegador

Servidor Web

Figura 7.8. La relacion clientelservidor entre un navegador Web y un servidor Web requiere comunicacion

Las aplicaciones debase de datos Web que desarrollaremos en este libro siguen la estructura general de base de datos Web que se ilustra en la figura 7.9. Gran parte de esta estructura deberia resultarle familiar a estas alturas.
1
Navegador

Servldor Web

2
Motor de PHP

3
Servidor MySQL

Figura 7.9. La arquitectura basica de base de datos Web se compone de un navegador Web, un servidor Web, un motor de secuencia de comandos y un servidor de base de datos

Una transacci6n tipica de base de datos Web se compone de las fases siguientes, numeradas en funci6n de la figura 7.9. Examinaremos estas fases en el context0 del ejemplo Book-0-Rama.

Desarrollo Web con PHP y MySQL

1. El navegador Web de un usuario envia una petici6n HTTP a una pigina Web dada. Por ejemplo, puede tratarse de una busqueda para extraer todos 10s libros escritos por Laura Thomson en Book-0-Rama con ayuda de un formulario HTML. La pigina de resultados de busqueda se denomina results.php. 2. El servidor Web recibe la petici6n de results.php, recupera el archivo y lo pasa a1 motor de PHP para su procesamiento.

3. El motor de PHP comienza a analizar la secuencia de comandos. Dentro de la secuencia de comandos hay un comando que establece la conexi6n a la base de datos y ejecuta una consulta (realiza la busqueda de libros). PHP abre una conexi6n a1 servidor MySQL y remite la consulta pertinente.
4. El servidor MySQL recibe la consulta de la base de datos y la procesa. A continuaci611, envia 10s resultados (una lista de libros) a1 motor de PHP. 5. El motor de PHP termina de ejecutar la secuencia de comandos, lo que suele implicar la aplicaci6n de formato a 10s resultados en HTML. Seguidamente, devuelve el c6digo HTML resultante a1 servidor Web.

6. El servidor Web devuelve el c6digo HTML a1 navegador donde el usuario puede ver la lista de 10s libros solicitados.

El proceso es bisicamente el mismo independientemente del motor de secuencia de comandos o del servidor debase de datos que utilicemos. Por regla general, el software del servidor Web, el motor de PHP y el servidor de la base de datos se ejecutan en el mismo equipo. Sin embargo, tambibn es habitual ejecutar el servidor de la base de datos en un equipo diferente, por razones de seguridad, de una mayor capacidad o de reparto de la carga. Desde el punto de vista de desarrollo, el trabajo serd el mismo, per0 puede presentar algunas ventajas significativas de rendimiento.

Lecturas adicionales
-

En este capitulo, hemos analizado alguna de las directrices para el diseiio debases de datos. Si quiere profundizar en la teoria sobre la que descansan las bases de datos relacionales, puede leer algunas de las obras escritas por expertos en el tema como C.J. Date. Eso si, tenga en cuenta que el material puede resultar bastante te6rico y poco relevante a corto plazo para un desarrollador Web comercial. Las bases de datos Web mis habituales no suelen alcanzar un nivel tan alto de complejidad.

A continuacion
En el siguiente capitulo, comenzaremos a configurar nuestra base de datos MySQL. En primer lugar aprenderd a configurar una base de datos MySQL para la Web y c6mo consultarla y, a continuacih, c6mo consultarla desde PHP.

En este capitulo vamos a comentar c6mo configurar una base MySQL para su uso en un sitio Web. En este capitulo abordaremos 10s siguientes aspectos: Creaci6n de una base de datos Usuarios y privilegios Introducci6n a1 sistemi de privilegios Creaci6n de tablas de base de datos Tipos de colurnna en MySQL En este capitulo, vamos a seguir adelante con la aplicaci6n de la libreria en linea Book-0-Rama comentada en el ~ l t i m capitulo. o A continuaci6n, se recoge el esquema de la aplicaci6n de Book-0-Rama para ayudarle a recordar:
Customers(CustomerID, Name, Address, City) Orders(OrderlD, CustomerID, Amount, Date) Books(Author, Title, Price) Order-Items(OrderID, ISBN, Quantity) -Book-Reviews(ISBN, - Reviews)

Recuerde que las claves principales aparecen subrayadas con una linea continua y las claves secundarias con una linea discontinua.

8. Creacidn de la base de datos W e b

Para utilizar el material de esta seccibn, debe disponer de acceso a MySQL, lo cual significa que Ha completado la instalaci6n bhsica de MySQL en su servidor Web. Esto incluye: Instalar 10s archivos Configurar un usuario para ejecutar MySQL Configurar su ruta Ejecutar mysql -i n s t a l l - d b , si resultara necesario Establecer la configuraci6n del usuario raiz Eliminar el usuario an6nimo y la base d e datos d e prueba Iniciar el servidor de MySQL Si ha realizado todas estas operaciones, puede seguir adelante con la lectura del capitulo. Si no lo ha hecho, en el apendice A encontrarh instrucciones sobre c6mo proceder. Si tiene problemas durante este capitulo, puede que se deba a la configuraci6n de su sistema MySQL. En este caso, revise esta lista y el a p h d i c e A para asegurarse de que la configuraci6n es correcta. Dispone de acceso a MySQL en un equipo de cuya administraci6n no se encarga, como u n servicio de alojamiento Web, un equipo en su lugar d e trabajo, etc. Si este fuera el caso, para poder seguir 10s ejemplos o crear su propia base de datos, deberh pedir a su administrador que configure un usuario y la base de datos para permitirle-trabajar con ella y que le indique el nombre de usuario, la contrasefia y el nombre de la base de datos que se le ha asignado. Puede saltarse las secciones de este capitulo dedicadas a explicar c6mo configurar usuarios y bases de datos o leerlas para explicar mejor lo que necesita su administrador del sistema. Como usuario normal, no podrh ejecutar 10s comandos para crear usuarios y bases de datos. Los ejemplos de este capitulo se han elaborado y probado con la versi6n 3.23.52 de MySQL. Las versiones anteriores disponen d e menor funcionalidad. Deberia instalar o actualizar su versi6n a la mhs reciente, que puede descargar del sitio de MySQL en h t t p : / / m y s q l . corn.

Nota sobre el uso del monitor de MySQL


En este capitulo y en el siguiente, apreciarh que en 10s ejemplos de MySQL cada comando termina en un punto y coma (;). Este simbolo indica a MySQL que ejecute

Desarrollo Web con PHP y MySQL

el comando. Si olvida utilizar el punto y coma, no se aplicarii ninguna acci6n. Se trata de un problema com6n entre 10s nuevos usuarios. Tambi6n significa que puede utilizar nuevas lineas en mitad de un comando. En el libro, hemos utilizado este recurso para facilitar la lectura de 10s ejemplos. Apreciar6 d6nde lo hemos hecho porque MySQL incluye un simbolo de continuaci6n. Se trata de una flecha como la incluida en este fragmento:
mysql> ->
grant select

Este simbolo indica que MySQL espera miis entradas. Mientras no se escriba un punto y coma, obtendrii estos caracteres a1 pulsar Intro. Tenga en cuenta adem6s que las instrucciones de SQL no discriminan entre mayusculas y min6sculas, per0 que las bases de datos y las tablas si pueden hacerlo (este aspecto se ampliarii miis adelante).

Como registrarse en MySQL


Para registrarse, dirijase hasta la interfaz de linea de comandos de su equipo y escriba lo siguiente:
mysql -h nombreciehost -u r i o m b r e d e u s u a r i o -p

El simbolo de comandos puede presentar un aspecto diferente seg6n el sistema operativo y el n6cleo que est6 utilizando. El comando mys ql invoca a1 monitor de MySQL. Se trata de un cliente de linea de comandos que nos permite comunicarnos con el servidor MySQL. El modificador -h se utiliza para especificar el host a1 que establecer la conexibn, es decir, el equipcren etque se estii ejecutando el servidor MySQL. Si ejecuta este comando en el mismo equipo que el servidor MySQL, no necesitarii utilizar el modificador -h ni el pariimetro n o m b r e d e h o s t. De lo contrario, deberii sustituir dicho pariimetro por el nombre del equipo en el que se este ejecutando el servidor MySQL. El modificador -u se utiliza para especificar el n o m b r e d e u s u a r i o con el que desea conectarse. Si no se especifica, se utilizarii el nombre de usuario predeterminado con el que se inici6 la sesi6n en el sistema operativo. Si ha instalado MySQL en su propio equipo o servidor, deberii registrarse como r o o t y crear la base de datos que utilizaremos en esta secci6n. Si ha realizado una instalaci6n limpia, el usuario raiz serii el 6nico usuario del que dispondrii para iniciar la sesi6n. Si estii utilizando MySQL en un equipo administrado por otra persona, utilice el nombre de usuario que se le haya asignado. El modificador -p indica a1 servidor que se desea establecer la conexi6n utilizando una contrasefia. Puede evitar su uso, si no se ha establecido una contrasefia para el usuario utilizado para iniciar la sesibn.

Si se esti iniciando la sesidn como usuario raiz y no se ha establecido una contraseiia para dicho usuario, le recomendamos que consulte el a p h d i c e A de inmediato. Sin una contrasefia para el usuario raiz , su sistema es inseguro. No es necesario que incluya la contraseiia en esta linea. El servidor MySQL se la pediri. De hecho, es mejor no hacerlo. Si introduce la contraseiia en la linea de comandos, se mostrari en la pantalla y otros usuarios podrian verla. Tras introducir el comando anterior, deberia obtener un resultado parecido a1 siguiente:
Enter password:
+ + + +

(Si no funcionase, verifique que el servidor MySQL se esti ejecutando y el comando my s q l aparece en algun lugar de su ruta.) Deberia introducir la contraseiia. Si todo va bien, se mostrari una respuesta parecida a la siguiente:
Welcome t~ the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 5 to server version: 3.23.52-nt Type 'help;' or ' \ h l for help. Type '\c' to clear the buffer mysql>

En su equipo, si no obtiene una respuesta similar, asegurese de haber ejecutado mysql i n s t a l l db, si resultara necesario, de haber establecido la contraseiia del usuarioraiz y de haberla escrito correctamente. Si se trata de otro equipo, asegurese de haber escrito correctamente la contraseiia. Tras ello, deberia aparecer el simbolo de comandos de MySQL listo para crear la base de datos. Si esti utilizando su propio equipo, siga las directrices de la siguiente seccidn. Si esti utilizando el equipo de otra persona, esta fase ya estari completada. Puede saltar a la seccidn ((Us0 de la base de datos corrects,,. Si lo desea, puede leer las secciones intermedias paraampliar sus conocimientos per0 no podri ejecutar 10s comandos indicados en ellas. ( 0 no deberia, a1 menos).

Creacion de bases de datos y usuarios


El sistema debase de datos de MySQL admite una gran cantidad debases de datos diferentes. Por regla general, se utilizari una base de datos por cada aplicacidn, En nuestro ejemplo Book-O-Rama, la base de datos se llamari books.

Creaci6n de la base de datos


gsta es la parte m i s sencilla. Escriba la siguiente secuencia en el simbolo de comandos de MySQL:
mysql>
create database
nombrebd;

Desarrollo W e b con PHP y MySQL

Sustituya el pariimetro nombrebd por el nombre de la base de datos deseado. Para comenzar a crear el ejemplo Book-0-Rama, puede crear una base d e datos llamada
books.

Y eso es todo. Deberia ver aparecer una respuesta como la siguiente:


Q u e r y OK,
1 row

affected

(0.06 s e c )

Esta secuencia indica que todo ha funcionado correctamente. Si no la obtiene, asegurese de incluir el punto y coma a1 final de la linea. Este simbolo indica a MySQL que ha terminado y deberia ejecutar el comando.

Usuarios y privilegios
Un sistema MySQL puede tener muchos usuarios. Como norma deberia utilizarse el usuario raiz para labores administrativas unicamente, por razones de seguridad. Deber6 configurar una cuenta y una contrasefia para cada usuario del sistema . No es necesario que Sean las mismas utilizadas fuera de MySQL (por ejemplo, 10s nombres de usuario y contrasefias de UNIX o NT). Los mismos principios se aplican a1 usuario raiz. Conviene utilizar contrasefias diferentes para el sistema y para MySQL, en especial en el caso de la contrasefia del usuario raiz. No es obligatorio configurar contrasefias para 10s usuarios, per0 si muy aconsejable. A la hora de configurar una base de datos Web, conviene establecer a1 menos un usuario por aplicaci6n Web. Es probable que se este preguntado por quk. La respuesta reside en 10s privilegios.

lntroduccion al sistema de privilegios de MySQL


Una de las mejores funciones de MySQL es su avanzado sistema de privilegios. Un privilegio es el derecho a realizar una acci6n dada sobre u n determinado objeto y se asocia a u n usuario concreto. El concept0 es muy similar a 10s permisos de archivo. A1 crear un usuario dentro de MySQL, se le conceden un conjunto de privilegios en 10s que se especifica lo que puede y no puede hacer dentro del sistema.

Principio de asignacion del privilegio mas bajo


Este principio se puede utilizar para mejorar la seguridad de cualquier sistema informAtico. Se trata de un principio elemental per0 muy importante que se suele pasar por alto a menudo.

8. Creacidn de la base de datos W e b

Su contenido es el siguiente: Un usuario (o proceso) deberia disponer del nivel m6s bajo de privilegio necesario para realizar la tarea que se le asigne. Su aplicacidn debe ir m6s all6 de MySQL. Por ejemplo, para ejecutar consultas desde la Web, un usuario no necesita disponer de todos 10s privilegios asociados a1 usuario raiz. Por lo tanto, deberiamos crear otro usuario que s610 disponga de 10s privilegios necesarios para acceder a la base de datos que acabamos de crear.

Cdmo configurar usuarios: el comando GRANT


Los comandos GRANT y REVOKE se utilizan para conceder y retirar 10s derechos a 10s usuarios de MySQL en cuatro niveles de privilegio. Estos niveles son: Global Base de datos Tabla

En un instante veremos cdmo se aplica cada uno de ellos. El comando GRANT se utiliza para crear usuarios y concederles privilegios. La sintaxis general del comando GRANT es la siguiente:
GRANT p r i v i l e g i o s [ col u m n a s ] ON e l e m e n t o T O n o m b r e - u s u a r i o [ I D E N T I F I E D BY [ W I T H GRANT O P T I O N ]

'contrasefia']

Las cl6usulas incluidas &tre corchetes son opcionales. La sintaxis de este comando incluye varios marcadores de posicidn. El primer lugar, privilegios, equivale a una lista de privilegios separados por comas. MySQL consta de un conjunto definido de ellos, que se describen en la siguiente seccidn. El marcador de posicidn columnas es opcional. Puede utilizarlo para especificar privilegios a cada columna. Puede utilizar el nombre de una sola columna o una lista de nombres de columna separadas por comas. El marcador de posicidn, elemento es la base de datos o tabla a la que se aplican 10s nuevos privilegios. Puede conceder privilegios a todas las bases de datos especificando * . * como elemento. Es lo que se conoce como conceder privilegios globales. T a m b i h puede hacerlo especificando * cnicamente si no va a utilizar ninguna base de datos en concreto. Por regla general, especificar6 todas las tablas de la base de datos como nombrebd. *, una sola tabla de base de datos como nombrebd. n o m b r e t a b l a o columnas especificas indicando nomb r e b d . nombre t a b l a y las columnas deseadas en el marcador de posicidncolumnas. Si estA utilizando una base de datos especi-

Desarrollo Web con PHP y MySQL

fica a1 remitir este comando y s610 se utiliza nomb retabla, se interpretard como una tabla de la base de datos actual. El marcador de posici6n nombre-usuario serd el nombre del usuario con el que desea registrarse en MySQL. Recuerde que no tiene por qu6 ser el mismo que el nombre de registro del sistema. Este pardmetro tambikn puede contener un nombre de host. Puede utilizarlo para distinguir, por ejemplo, entre Laura (interpretado como laura@hostlocal) y 1 aura @ot r os it i o . com. Esta opci6n resulta bastante util porque 10s usuarios pertenecientes a diferentes dominios suelen utilizar 10s mismos nombres. Tambih permite incrementar la seguridad porque se puede especificar desde ddnde se conectan 10s usuarios e incluso a qu6 tablas y datos pueden acceder desde una ubicaci6n dada. El marcador de posici6n contra sen"^ es la contraseiia que deseamos utilizar para iniciar la sesion. Se aplican las reglas habituales para la selecci6n de contraseiias. En una seccidn posterior ampliaremos el tema de la seguridad, per0 las contrasefias no deben resultar sencillas de adivinar. Es aconsejable que contengan un combinaci6n de caracteres en mayusculas y minusculas y caracteres no alfabkticos. La opcion WITH GRANT OPTION, si se especifica, permite que el usuario indicado delegue sus privilegios en otros usuarios. Los privilegios se almacenan en cuatro tablas del sistema, dentro de la base de datos m y s ql. Estas cuatro tablas se denominan m y s q l user, m y s q l db, mysql.tables p r i v y m y s q l . c o l u m n s privyserelacionandirectamentecon 10s cuatro niveles de privilegio mencionados anteriormente. Como alternativa a GRANT, puede alterar estas tablas directamente, como se analizard en un capitulo posterior.

Tipos y niveles de privilegio


Existen tres tipos b6sicos de privilegios en MySQL: 10s privilegios apropiados para su concesi6n a 10s usuarios habituales, 10s privilegios apropiados para su concesi6n a 10s administradores y dos privilegios especiales. Se puede asignar cualquier privilegio a cualquier usuario, per0 es aconsejable restringir 10s privilegios de administrador a 10s administradores, siguiendo el principio de conceder el nivel mds bajo de privilegios. Deberia restringir 10s privilegios concedidos a 10s usuarios para las bases de datos y tablas que necesiten utilizar. No deberia conceder acceso a la base de datos my s ql a nadie a excepcidn de a un administrador. En esta base de datos se almacenan todos 10s usuarios, contrasefias y otros datos. (En un capitulo posterior analizaremos esta base de datos.) Los privilegios para el resto de 10s usuarios deberian establecerse directamente en funcidn de 10s tipos especificos de comandos SQL y si un usuario puede ejecutarlos. En el siguiente capitulo analizaremos en detalle estos comandos. Por el momento, basta con la descripci6n conceptual indicada. En la tabla 8.1 se recogen estos privilegios. En la columna Se aplica a se enumeran 10s objetos a 10s se pueden conceder cada privilegio.

8. Crcocicin dc lo bnsc de dotos Web


Tabla 8.1. Privilegios para usuarios
~.

. - . .
Se aplica a

- - - .---*-----.

- -

.-

Privilegio
SELECT

Descripci6n Perrnite a 10s usuarios seleccionar filas (registros de tablas). Permite a 10s usuarios insertar nuevas filas en las tablas Permite a 10s usuarios modificar valores de filas de tablas existentes. Permite a 10s usuarios eliminar filas de tablas existentes. Permite a 10s usuarios crear y elirninar indices sobre tablas concretas. Perrnite a 10s usuarios alternar la estructura de tablas existentes agregando, por ejernplo, colurnnas, cambiando el nombre de las colurnnas o de las tablas y modificando 10s tipos de datos de las columnas. Permite a 10s usuarios eliminar bases de datos o tablas. Si especifica una base de datos o una tabla dada en el comando GRANT, 10s usuarios solo podran crear dicha base de datos o tabla, lo que significa que tendran que elirninarla prirnero.
.

tablas, colurnnas tablas, columnas tablas, columnas

INSERT

UPDATE

DELETE

tablas tablas

INDEX

ALTER

tablas

CREATE

bases de datos y tablas

DROP

bases de datos y tablas

Perrnite a 10s usuarios elirninar bases de datos o tablas.

La mayor parte d e 10s privilegios para 10s usuarios norrnales son relativarnente inofensivos en t4rminos d e la seguridad del sistema. Se puede utilizar el privilegio ALTER para resolver el sistema de privilegios cambiando el nombre d e las tablas, per0 10s usuarios suelen utilizarlo bastante. La bGsqueda de la seguridad consiste en hallar un equilibrio entre la usabilidad y la protection. Debe tomar una decision con respecto a1 privilegio ALTER,per0 debe saber que se suele conceder a 10s usuarios a menudo. A d e m i s d e 10s privilegios enumerados en la tabla 8.1, existe el privilegio REFERENCES que no se utiliza y el privilegio GRANT que se concede con el parAmetro W I T H GRANT O P T I O N e n lugar d e e n la lista d e prizdegios.

Desnrrollo Web con P H P y M y S Q L

La tabla 8.2 muestra 10s privilegios apropiados para su concesi6n a 10s usuarios administrativos.
Tabla 8.2. Privilegios para administradores
.

- -

. -

Privilegio
RELOAD

Descripcion Permite a un administrador volver a cargar tablas de concesion y elirninacion de privilegios, hosts, registros y tablas. Permite a un administrador cerrar el servidor MySQL. Permite a un administrador ver 10s procesos de servidor y cerrarlos. Permite la lectura de datos en tablas desde archivos y viceversa.

SHUTDOWN
PROCESS
FILE

Estos privilegios se pueden conceder a usuarios que no Sean administradores per0 debe estar muy atento si est.4 considerando dicha posibilidad. El usuario medio no necesita utilizar 10s privilegios RELOAD, SHUTDOPIN y PROCESS. El privilegio FILE es un tanto diferente. La posibilidad de cargar datos desde archivos puede contribuir a ahorrar mucho tiempo a1 volver a introducir 10s datos en la base de datos. Sin embargo, la funci6n de carga de archivos se puede utilizar para cargar cualquier archivo que puede ver el servidor MySQL, ii~cluidas las bases d e datos pertenecientes a otros usuarios y, potencialmente, 10s archivos de contrasefias. Tenga cuidado a1 conceder este privilegio u ofrezca la posibilidad de realizar la carga de 10s usuarios. Existen otros dos privilegios especiales, que se recogen en la tabla 8.3.
Tabla 8.3. Privilegios especiales
r

-- ..
Descripcion

-.

Privilegio
ALL

Concede todos 10s privilegios enumerados en las tablas 8.1 y 8.2. Tarnbien se puede escribir ALL PRIVILEGES en lugar de ALL. No concede ningun privilegio. Este privilegio crea un usuario y le permite registrarse, per0 no se le concede ningun otro privilegio. Por regla general, la concesion de otros privilegios se suele dejar para un momento posterior.

USAGE

Se trata del comando opuesto a1 comando GRANT. Se utiliza para retirar p r i d e gios d e un usuario.

8 . Creacidn de la base de d a b s Web

Su sintaxis es muy similar a la sintaxis de GRANT:


REVOKE privilegios ON elemento FROM nombre-usuari o
[ (

columnas)]

Si se han concedido privilegios con la clhsula WITH GRANT O P T I O N , puede revocarlos de la siguiente forma:
REVOKE GRANT O P T I O N ON elemento FROM nornbre-usuario

Ejemplos de uso de GRANT y REVOKE


Para configurar un administrador, puede escribir:
rnysql>

grant all

-> on -> to red identified by 'mnb123' -> with grant option;

Este ejemplo concede todos 10s privilegios sobre todas las bases de datos a un usuario llamado Fred con la contraseiia mnb123 y le permite traspasar dichos privilegios. No le gustarfi tener un usuario asi en su sistema por lo que conviene revocarlo:
mysql>

revoke all

-> on - > from fred;

Seguidamente vamos a configurar un usuario normal sin privilegios.

mysql>

grant usage -> on books. -> to sally identified by 'magic123';

Hablamos con Sally para determinar que desea hacer y le concedemos 10s privilegios adecuados:
rnysql>

grant select, insert, update, delete, index, alter, create, drop

-> on books. - > to sally;

Fijese en que no necesitamos especificar la contraseiia de Sally para realizar esta tarea. Si decidimos que Sally ha intentado realizar algo no apropiado en la base de datos, podemos reducir sus privilegios:
mysql>

revoke alter, create, drop

-> on books. -> from sally;

Desarrollo Web con PHP y MySQL

Y posteriormente cuando ya no necesite utilizar la base de datos, podemos revocar todos sus privilegios:
rnysql>

revoke all on books. -> from sally;


-\

Como configurar un usuario para la Web


Necesitari configurar un usuario para que sus secuencias de comandos de PHP se conecten a MySQL. Podemos volver a aplicar el principio del privilegio minimo. iQu6 se permitiri a las secuencias de comandos? En la mayor parte de 10s casos, solo se necesita seleccionar, insertar, eliminar y actualizar filas de tablas. Podemos configurar estas tareas de la siguiente forma:
rnysql>

grant select, insert, delete, update

-> on books. *
- > to bookorama identified by 'bookoramal23';

Por razones de seguridad, deberia seleccionar una contraseiia mejor. Si utilizamos un servicio de alojamiento Web, por regla general obtendremos acceso a1 resto de 10s privilegios de tip0 usuario en una base de datos creada para nosotros. Se nos asignari un nombre de usuario y una contraseiia para el uso de la linea de comandos (desde donde crear tablas y realizar otras tareas por el estilo) y para realizar las conexiones de secuencia de comandos Web (para consultar la base de datos). Este sistema resulta un poco menos seguro. Puede configurar un usuario con este nivel de privilegios de la siguiente forma:
rnysql>

grant select, insert, update, delete, index, alter, create, drop

-> on books. * -> to bookorama identified by 'bookoramal23';

Proceda a configurar esta segunda version del usuario ya que es la que utilizaremos en la siguiente seccion.

C6mo cerrar la sesion como administrador


Puede cerrar la sesi6n del monitor de MySQL escribiendo q u i t . Deberia volver a registrarse como usuario Web para comprobar si todo funciona correctamente.

Uso de la base de datos correcta


Si ha llegado hasta aqui, deberia estar registrado en una cuenta de MySQL de nivel de usuario lista para probar el ejemplo de codigo, bien porque acaba de configurarla o porque el administrador del servidor Web se ha encargado de ello.

8. Creacidn de la base de datos W e b

Lo primer0 que necesita hacer a1 iniciar una sesidn es especificar que base de datos desea utiliza. Para ello, puede escribir:
mysql> use nombrebd;

donde nombrebd es el nombre de la base de datos. Como alternativa, puede evitar el comando use especificando la base de datos a1 iniciar la sesidn, de la siguiente forma:
mysql -D nombrebd -h nombrehost - u nombreusuario -p

En este ejemplo, utilizaremos la base de datos de libros:


mysql> use books;

A1 escribir este comando, MySQL deberia devolver una respuesta como la siguiente
Database changed

Si no selecciona una base de datos antes de empezar a trabajar, MySQL devolvera un mensaje de error como el siguiente:
ERROR 1046: No Database Selected

Creacion de tablas de base de datos


El siguiente paso en la configuracidn de la base de datos consiste en crear las tablas. Para ello puede utilizar el comando CREATE TABLE de SQL. Esta instruccidn suele presentar esta forma:
CREATE TABLE
nombretabl a
(

col umnas)

Deberia sustituir el marcadorje posicidn nombretabla con el nombre de la tabla que desea crear y el marcador de posicidn columnas con una lista de columnas separadas por comas en la tabla. Cada columna tendrd un nombre seguido por un tip0 de dato.
Customers(CustomerID, Name, Address, City) Orders(OrderID, CustomerID, Amount, Date) Books(= Author, Title, Price) Order-Items(OrderID, -ISBN, Quantity) Book-Reviews(ISBN, -Review)

El listado 8.1 muestra el cddigo SQL para crear las tablas, asumiendo que ya hayamos creado la base de datos llarnada books. Encontrara el cddigo necesario en el archivo correspondiendo a este capitulo del CD-ROM. Puede ejecutar un archivo SQL existente, como el cargado desde el CD-ROM a traves de MySQL mediante la siguiente secuencia:
> mysql -h host -u bookorama -D books -p < bookorama.sq1

(Recuerde sustituir el host con el nombre de su host.) El uso de la redireccidn de archivos resulta bastante pr6ctico en este caso porque permite editar las secuencias SQL en el editor de texto deseado antes de ejecutarlas.

Desarrollo W e b con PHP y MySQL


Listado 8.1. bookorama.sql. Codigo SQL para crear las tablas de Book-0-Rama
c r e a t e t a b l e customers ( customerid i n t unsigned not n u l l auto-increment name c h a r ( 3 0 ) n o t n u l l , address char(40) not null, c i t y char(20) not null
);

p r i m a r y key,

create table orders ( o r d e r i d i n t u n s i g n e d n o t n u l l a u t o i n c r e m e n t p r i m a r y key, customerid i n t unsigned not n u l l , amount f l o a t ( 6 , 2 ) , date d a t e not n u l l
-

) ;

c r e a t e t a b l e books ( i s b n c h a r ( l 3 ) n o t n u l l primary key, author char(30), t i t l e char(60), price float (4,2)


);

c r e a t e t a b l e order-ifems ( orderid i n t unsigned not n u l l , isbn char(l3) not null, q u a n t i t y t i n y i n t unsigned, primary key
) ;

(orderid, isbn)

c r e a t e t a b l e book-reviews
(

i s b n c h a r ( l 3 ) n o t n u l l p r i m a r y key, review t e x t

Cada tabla se crea con una instruccion CREATE TABLE independiente. Como puede observar hemos creado el esquema con las columnas diseiiadas en el ultimo capitulo. Cada columna tiene un tip0 de dato listado tras su nombre. Algunas columnas tienen otros especificadores.

iCu61 es el significado del resto de las palabras clave?


NOT NULL significa que todas las filas de la tabla deben tener un valor en este atributo. Si no se especifica, el campo puede dejarse en blanco (NULL). AUTO INCREMENT es una funcion especial de MySQL que puede utilizar sobre columnas de tip0 entero. Significa que si dejamos el campo en blanco a1 insertar filas en la tabla, MySQL generara automaticamente un valor de identification exclusivo. Este valor sera una unidad mayor que el valor mdximo incluido en la columna. Solo puede tener una columna de este tip0 por tabla. Las columnas que especifiquen AUTO -INCREMENT deben estar indexadas.

El uso de la palabra clave PRIMARY KEY tras el nombre de una columna determina que la columna se tratara como la clave principal de la tabla. Las entradas de esta columna deben ser exclusivas. MySQL indexari automdticamente esta columna. Fijese en que en el listado anterior a1 utilizarlo con c u s t o m e r i d en la tabla customer se ha hecho con AUTO INCREMENT. La indexaci6n automdtica sobre la clave principal se encarga del indice que necesita AUTO INCREMENT. Si especificamos PRIMARY KEY tras el nombre de una columna, s610 se puede utilizar para claves principales formadas por una sola columna. El uso de la cldusula PRIMARY KEY a1 final de la instrucci6n o r d e r i t e m s es una alternativa. Aqui la hemos utilizado porque la clave principal de esG tabla se compone de dos columnas. La palabra clave UNSIGNED utilizada tras un tipo entero significa que s610 puede tener como valor cero o un numero positivo.

Tipos de columna
Tomemos la primera tabla como ejemplo
create table customers ( customerid i n t unsigned not n u l l a ~ t o ~ i n c r e m e n pt r i m a r y key, name c h a r ( 3 0 ) n o t n u l l , address char(40) not null, c i t y char(20) not null

i;

A1 crear una tabla, deberd tomar una decision con respecto a 10s tipos de columnas. En la tabla customers, tenemos cuatro columnas como se especifica en nuestro esquema. La primera, c u s t o m e r i d es a1 clave principal, que hemos especificado directamente. Hemos decidido que sea de tip0 entero (tipo i n t ) y que 10s ID Sean unsigned. Tambibn hemos aprovechado la funci6n a u t o i n c r e m e n t para que MySQL pueda encargarse de ello automiticamente y evitarnos una preocupaci6n. Las otras dos columnas contendrdn datos de tip0 cadena. En este caso hemos seleccionado c h a r como tip0 de dato. Este tip0 especifica campos de achura fija a travbs de corchetes; por ejemplo, name, puede tener hasta 30 caracteres. Este tip0 de datos asignard siempre 30 caracteres de espacio de almacenamiento para el nombre, aunque no se utilicen todos. MySQL rellenard 10s datos con espacios para asignarles el tamaAo exacto. Como alternativa se puede utilizar el tipo v a r c h a r, que s610 utiliza la cantidad de espacio necesario (mds un byte). El tip0 v a r c h a r absorbe menos espacio per0 resulta m i s lento. Para 10s clientes reales con nombres y direcciones reales, las anchuras seleccionadas para estas columnas son demasiado estrechas. Fijese en que hemos declarado todas las columnas como NOT NULL. Se trata de una pequeiia optimizaci6n que puede realizar cuando resulte posible. En un capitulo posterior trataremos el tema de la optimizaci6n.

Desarrollo W e b con PHP y MySQL

Alguna de las instrucciones CREATE presentan variaciones en cuanto a la sintaxis. Examinemos la tabla o r d e r s :
create table orders ( orderid int unsigned not null auto- increment primary key, customerid int unsigned not null, amount float (6,2), date date not null i;

La columna amount se especifica como numero de coma flotante de tip0 f l o a t . En la mayor parte de 10s tipos de datos de coma flotante, puede especificar la anchura de visualizaci6n y el numero de decimales. En este caso, la cantidad del pedido se establecerii en dblares, por lo que podemos asignar un tamaiio total razonablemente largo (una anchura de seis espacios) y dos decimales para 10s c6ntimos. La columna d a t e lleva asignado el tipo de dato d a t e . En esta tabla concreta, hemos especificado que las columnas puedan definir la cantidad como NOT NULL. ~ P o quk? r Cuando se introduce un pedido en la base de datos, tendremos que crearlo en o r d e r s , agregarle 10s elementos a o r d e r-i t ems y calcular la cantidad. Puede que no sepamos la cantidad a1 crear el pedido, por lo que permitimos que sea NULL. La tabla books presenta algunas caracteristicas similares.
create table books ( isbn char(l3) not null primary key, author char(30), title char(60), price float(4,2)
1;

En este caso, no necesjtamqs generar la clave principal porque 10s ISBN se generan en otra parte. Hemos dejado 10s otros campos como NULL porque una libreria puede conocer el ISBN de un libro antes de conocer su titulo, autor o precio. La tabla o r d e r -i t ems muestra como crear claves principales multicolumna:
create table order items ( orderid int unsigned not null, isbn char(l3) not null, quantity tinyint unsigned,
-

primary key (orderid, isbn)

Hemos especificado la cantidad de un libro como T I N Y I N T UNSIGNED, que equivale a un entero entre 0 y 255. Como se mencion6 anteriormente, las claves principales multicolumna necesitan especificarse con una cliiusula de clave principal. Esta es la que se utiliza aqui. Por ultimo, examine la tabla book -r e v i e w s :

8. Creacidn de la base de datos W e b

create
(

table

book-reviews

isbn char(l3) not null primary key, review text


1;

Esta tabla utiliza un nuevo tip0 de dato, t e x t , que todavia no se ha analizado. Este tip0 se utiliza para texto de gran longitud como un articulo. Existen algunas variantes de este tip0 que se cornentarin en una secci6n posterior. Para comprender mejor el proceso de creaci6n de tablas vamos a analizar 10s nombres de las columnas y 10s identificadores en general, y, a continuaci6n,los tipos de datos que podemos seleccionar para las columnas. Pero en primer lugar, examinaremos la base de datos que hemos creado.

Como examinar la base de datos con SHOW y DESCRIBE


Inicie la sesi6n en el monitor de MySQL y utilice la base de datos books. Para ver las tablas de la base de datos, escriba
mysql> show tables;

MySQL mostrar6 una lista de todas las tablas de la base de datos:

Ibook-reviews 1 books lcustomers lorder l t e m s 1 orders


-

I I I

'I

- -

5 rows in set (0.06 sec)

Tambien puede utilizar la instrucci6n show para ver una lista de bases de datos escribiendo
mysql> show databases;

Puede ver m6s informaci6n sobre una tabla concreta, por ejemplo, libros, utilizando DESCRIBE:
mysql> describe books;

MySQL mostrar6 la informaci6n suministrada a1 crear la base de datos:


l Field
Type Ichar(l3)

l Null

Key

1 Default

I Extra

I
I

I isbn

1 PRI

Desarrollo Web cor, P H P J I MySQL

Estos comandos resultan titiles para recordar un tip0 d e columna o navegar por una base d e datos creada por otra persona.

Identificadores de MySQL
MySQL consta d e cuatro tipos d e identificadores: las bases d e datos, las tablas, las columnas (elementos que ya conocemos) y 10s alias, clue examinaremos en el siguiente capitulo. Las bases d e datos d e MySQL se asignan a directorios en la estructura d e archivos subyacente y las tablas lo hacen a archivos. Este hecho afecta directamente a 10s nombres clue se les puede asignar. Tambien afecta a1 uso de may6sculas y minusculas en dichos nombres. Si su sistema operativo discrimina entre mayusculas y minusculas utilizados en 10s nombres d e 10s directorios o archivos, 10s nombres seleccioi~ados para designar las bases de datos y las tablas tambien lo hartin (por ejemplo, en UNIX) o, en caso contrario, no lo hardn (por ejemplo, en Windows). Los nombres d e columnas y 10s alias no discriminan entre mayusculas y minusculas, per0 no puede utilizar versiones diferentes d e 10s nombres en la misma instrucci6n d e SQL. La ubicaci6ii del directorio y 10s archivos que contengan 10s datos se establece en la configuraci6n. Puede comprarlo e n s u sistema utilizando la instrucci6n m y s q l a d m i n d e la siguiente forma:
!nysi{l,3dmir1v . ? r l a t r l P S

Estamos buscando la variable d a tadi r. En la tabla 8.4 se recoge u n resumen d e 10s posibles identificadores. La unica excepcion adicional es que no se puede utilizar ASCII(O), ASCII(255) ni el caricter d e comillas en 10s identificadores (que es muy probable clue n o utilice).
Tabla 8.4. ldentificadores de MySQL
-

- ~Discriminaentre mayusculas y minthculas? segun el sisterna operativo Caracteres permitidos

Tipo

Longitud

mdxima

Base de datos

64

Todos 10s caracteres perrnitidos por el sistema operativo para el nombre de un directorio a excepcion de 10s caracteres /, \, y . .

Tipo

Longitud mexima

~ D i s c r i m i n aentre mayuscwlas y minQsculas? segun el sisterna operativo

-Caracteres permitidos

Tabla

64

Todos 10s caracteres permitidos por el sistema operativo en un nombre de archivo a excepcion de 10s caracteres / y . . Todos 10s caracteres. Todos 10s caracteres

Columna Alias

64 255

no no

Las reglas son muy abiertas. Desde la versi6n MySQL 3.23.6, se pueden utilizar palabras reservadas y caracteres especiales d e todos 10s tipos en identificadores, la unica limitaci6n es colocar entre comillas inclinadas 10s caracteres extrafios. Por ejemplo:

Las reglas de las versiones d e MySQL (anteriores a la 3.23.6) son mas restrictivas y no lo permiten. Obviamente, conviene aplicar sentido comun a toda esta libertad. El hecho d e poder llamar a una base d e datos 'crear base d e datos' no significa que tengamos que hacerlo. Se aplica el mismo principio aplicado en otros tipos d e programaci6n: utilice identificadores descriptivos.

Tipos d e dato d e colurnna


En MySQL existen tres tipos bAsicos d e columnas: num6ric0, d e fecha y hora, y d e cadena. Cada categoria incluye un gran numero de tipos. En este capitulo 10s resumiremos. En un capitulo posterior se analizaran sus puntos fuertes y sus puntos d6biles. Cada uno d e 10s tres tipos dispone d e varios tamanbs d e almacenamiento. A1 seleccionar un tip0 d e colurnna, el principio general consiste en escoger el tip0 mas pequefio en el que encajen 10s datos. Muchos d e 10s tipos permiten especificar el tamafio maxim0 d e visualizaci6n a1 crear la colurnna. Esta opcidn se identifica en las siguientes tablas con una m. Si resulta opcional se coloca entre corchetes. El valor maximo que se puede especificar para M es 255. En las siguientes descripciones se utilizan 10s corchetes para indicar valores opcionales.

Desnrrollo Web con P H P y MySQL

Los tipos numericos son nameros enteros o de coma flotante. En el caso de 10s nameros de coma flotante, puede especificar el nfimero de lugares decimales. En este Iibro se utiliza D para indicarlo. El valor m6ximo que se puede especificar para D es d e 30 o M-2 (es decir, la longitud mixima d e visualizaci6n menos dos, es decir, un carActer para el punto decimal y uno para la parte entera del ntimero), segan cual sea la menor. Para 10s tipos enteros tambi6n puede especificar si desea que Sean U N S I G N E D , como se muestra en el listado 8.1. En todos 10s tipos num6ricos, tambien puede especificar el atributo ZEROFILL. Cuando se muestran 10s valores de una columna Z E R O F I LL, se rellenarin con ceros a la derecha. Si especifica una columna como Z E R O F I L L , se le asignari automjtican~ente el atributo U N S I GNED. En la tabla 8.5 se muestran 10s tipos integrales. En la columna de rangos se muestran 10s rangos con firma y sin firma en lineas diferentes.
Tabla 8.5. Tipos de datos integrales

Tipo

Rango

Espacio de almacenarniento (bytes)

Descripcion

TINYINT [ (M) ] BIT BOOL SMALLINT [ (M)] MEDIUMINT [ (M)]

Enteros muy pequefios Sinonimo de TINYINT Sinonimo de TINYINT Enteros pequeiios Enteros de tamatio medio
.

4
INTEGER [ (M)] BIGINT [ (M)]

Enteros normales Sinonimo de INT Enteros grandes

En la tabla 8.6 se recogen 10s tipos d e coma flotante.

8. Crcwidn dc In base de dntos Web

Tabla 8.6. Tipos de datos de coma flotante


7 .. .-

Tipo

Rango
IlllGllLW

Descripcidn
\&JyLGV/

FLOAT ( p r e c i s i o n )

depende de la precision

varia

Se puede utilizar para especificar numeros de coma flotante de precision unica o doble. Nurnero de coma flotante de precision unica. Equivale a FLOAT(4), per0 con un ancho de visualizacion y un numero de decimales especificado. Equivale a FLOAT(8) per0 con un ancho de visualizacion dado y con un numero concreto de decimales. Sinonimo de D O U B L E [(MtD)I.

FLOAT [

(M, D) ]

f 1 .I75494351 E-38 f3.402823466E+38

DOUBLE [

(M, D) 1

+I. 7976931 3486231 57E +308 f2.2250738585072OI 4E -308

DOUBLE

P R E C I S ION [ ( M , D ) ]

como arriba Sinonimo de D O U B L E


[ (M, D )

I.

DECIMAL [ ( M [ ,D l ) ]

varia

Numero de coma flotante almacenado corn0 char. El rang0 depende de M, la anchura de visualizacion. Sinonirno de DECIMAL. Sinonimo de DECIMAL.

NUMERIC [ (M, D) ] DEC [

corno arriba corno arriba

(M, D)

T i p s dc fecha y hora
MySQL admite una gran cantidad de tipos de fecha y hora, como se puede observar en la tabla 8.7. Estos tipos permiten recoger datos en formato num4rico o de cadena. Conviene destacar que si se utiliza una colurnna TIMESTAMP se establecera en la fecha y hora correspondiente a la operaci6n mhs reciente realizada sobre la fila si no se establece manualmente. Este comportamiento resulta Otil para el registro de transacciones.

D r s a r r o l l o Web cori P H P y iMySQL


-

Tabla 8.7. Tipos de datos de fecha y hora


-I

-.

. . : -

.-

Tipo
DATE TIME

Rango .

1000-01-01 9999-1 2-3 1 -838:59:59 838:59:59

Una fecha. Se mostrara con formato AAAA-MM-DD. Una hora. Se mostrara con formato H H : ~ SS. : Tenga en cuenta que el rango resulta mucho mas amplio de lo que es probable que necesite. Una fecha y una hora. Se mostraran con el formato YYYY-MM-DD HH:MM: SS. Una marca de tiernpo, que resulta util para la generacion de informes. El formato de visualizacion depende del valor de M (vease la tabla 8.8 situada a continuacion).

DATETIME

TIMESTAMP [ (M)1

Alglin mornento en 2037

La parte superior del rango depende del lirnite de las rnarcas de tiempo de UNIX. Un aiio. Puede especificar un formato de 2 a 4 digitos. Cada uno de estos tiene un rango diferente, como se muestra.

L a tabla 8.8 muestra 10s diferentes tipos de formatos de visualizaci6n T TIMESTAMP.


Tabla 8.8. Tipos de formato de visualizacion de TIMESTAMP
-...

Tipo especificado

C -

-.

--.--

Formato de visualization AAAAMMDDHHMMSS AAAAMMDDHHMMSS AAMMDDHHMMSS AAMMDDHHMM AA44MMDD AAMMDD AAMM PA

TIMESTAMP TIMESTAMP (14) TIMESTAMP (12) TIMESTAMP (10) TIMESTAMP (8) TIMESTAMP (6) TIMESTAMP (4) TIMESTAMP (2)

8. Crencidti de In bnse d e lintos Web

Los tipos d e cadena se clasifican en tres grupos. En primer lugar, estcin las antiguas cadenas planas, es decir, pequeiios fragmentos de texto. Se trata de 10s tipos CHAR (caracter d e longitud fija) y VARCHAR (cardcter d e longitud variable). Puede especificar la anchura d e cada una. Las columnas d e tipo CHAR se rellenarin con espacios hasta cubrir la anchura mixima, independientemente del tamaiio d e 10s datos. (MySQL elimina 10s espacios que sobran a la derecha d e CHARS a1 recuperarlos y d e VARCHARS a1 almacenarlos.) En un capitulo posterior examinaremos las ventajas y desventajas en t6rminos d e espacio y velocidad d e estos dos tipos. En segrindo lugar, estin 10s tipos TEXT y BLOB. Estos tipos disponen de varios tamaiios. Equivalen a texto largo y datos binarios, respectivamente. Los B L O B son objetos largos binarios. Pueden incluir todo lo que se necesite, por ejemplo, imagenes o sonidos. En la practica, las columnas B L O B y T E X T son iguales con la salvedad d e que TEXT discrimina entre may6sculas y m i n ~ s c u l a s , y BLOB no lo hace. Como estos tipos de columna pueden contener grandes cantidades de datos, es necesario tener en cuenta una serie d e consideraciones, como se verd en u n capitulo posterior. El tercer grupo consta d e dos tipos especiales, SET y ENUM. El tipo SET se utiliza para especificar que 10s valores d e esta columna deben proceder d e un conjunto d e valores dados. Los valores d e columna pueden contener m i s d e un valor del conjunto. Cada conjunto especificado puede contener un miximo d e 64 elementos. ENUM es una enumeraci6n. Es muy similar a SET, con la excepci6n d e que las columnas d e este tip0 s610 pueden tener uno de 10s valores especificados o NULL y el mdximo n6mero de elementos de la enumeraci6n s e r i de 65.535. En las tablas 8.9 y 8.10 se recogen 10s tipos d e datos de cadena. La tabla 8.9 muestra 10s tipos d e cadena comunes.
Tabla 8.4. Tipos de cadena habituales

[NATIONAL] CHAR (M) [BINARY]

De 0 a 255 caracteres

Cadena de longitud fija M, donde M se establece entre 0 y 255. Se trata del tipo predeterminado en MySQL, pero se incluye ya que forma parte del estandar ANSI SQL. La palabra clave BINARY espec~ficaque 10s datos deberian tratase como si no dis criminaran entre mayusculas y minusculas. (De manera predeterminada, discrimina entre mayusculas y minusculas.) Sinonimo de CHAR(1) lgual que el anterior, con la excepcion que la longitud es variable.

CHAR

[NATIONAL] VARCHAR (M) De 1 a 255 [BINARY] caracteres

Dcsarrollo Web coil PHP y MySQL

La tabla 8.10 describe 10s tipos TEXT y BLOB. La longitud de un campo TEXT en caracteres e s el tamaiio maximo en bytes d e 10s archivos que yodrian almacenarse en dicho campo.
Tabla 8.10. Tipos TEXT y BLOB
-

Tipo

Longitud mdxima (caracteres)

Descripci6n

TINYBLOB TINYTEXT BLOB TEXT MEDIUMBLOB MEDIUMTEXT LONGBLOB LONGTEXT

28 -1 (es decir, 255) -1 (es decir, 255) 216 -1 (es decir, 65.535)

Un campo BLOB pequefio Un campo TEXT pequefio Un camp0 BLOB de tamatio normal Un campo TEXT de tamafio normal Un campo BLOB de tamatio intermedio U n campo TEXT d e tamatio intermedio

215 -1 (es decir, 65.535)


224-1(es decir, 16.777.215) 224-1((es decir, 16.777.215)

232-1(es decir, 4.294.967.295) Un campo BLOB de tamatio grande 232-1(es decir, 4.294.967.295) Un campo TEXT de tamafio grande

La tabla 8.11 muestra 10s tiyos ENUM y SET.


Tabla 8.1 1. Tipos SET y ENUM

Tipo

Valores mdximos del conjunto

Descripci6n

Las columnas de este tip0 solo pueden contener uno de 10s valores listados o NULL. Las columnas de este tip0 pueden contener un conjunto de valores especificados o NULL.

Si desea obtener miis informaci6n, puede consultar el manual en linea de MySQL para configurar una base de datos e n http: //www .mysql corn/.

8. Creacidn de la base de datos W e b

A continuacion
Ahora que ha aprendido a crear usuarios, bases de datos y tablas, puede concentrarse en interactuar con la base de datos. En el siguiente capitulo, veremos cdmo introducir datos en tablas, c6mo actualizarlos y eliminarlos, y c6mo consultar la base de datos.

En este capitulo vamos a analizar el lenguaje de consulta estructurado (SQL) y su uso para consultar bases de datos. Continuaremos con la base de datos Book-ORama. En concreto, veremos c6mo insertar, eliminar y actualizar datos y c6mo realizar preguntas a la base de datos. En este capitulo se abordar6n 10s siguientes aspectos: Concepto de SQL

Inserci6n de datos en la base de datos Recuperaci6n de datos de la base de datos Combinaci6n de tablas Actualizaci6n de registros desde tablas Modificaci6n de tablas tras su creaci6n Eliminaci6n de registros desde la base de datos Eliminaci6n de tablas Comenzaremos por explicar el significado de SQL y por qu4 resulta titi1 entender el concept0 en el que se basa este lenguaje. Si no ha creado la base de datos de Book-0-Rama, necesitard hacerlo para poder ejecutar las consultas SQL de este capitulo. En un capitulo anterior encontrard las instrucciones.

9. Cdmo trabajar con la base de datos de MySQL

iQuC es SQL?
SQL equivale a lenguaje de consulta estructurado. Se trata del lenguaje estdndar para acceder a 10s sistemas de administraci61-1de base de datos (RDBMS). SQL se utiliza para almacenar y consultar datos desde y hasta una base de datos. Se utiliza en sistemas de base de datos como MySQL, Oracle, PostgreSQL, Sybase y Microsoft SQL Server entre otros. Existe un estdndar ANSI de SQL, y 10s sistemas de bases de datos como MySQL suelen implementarlo. Sin embargo, existen diferencias sutiles entre el SQL estdndar y el SQL de MySQL, que en algunos casos estd previsto integrar en el estdndar y en otros resultan deliberadas. A medida que avancemos, iremos indicando 10s casos mds importantes. En el manual en linea de MySQL se recoge una lista completa de las diferencias entre el SQL de MySQL y el SQL ANSI de cada versibn. Esta pigina se puede encontrar en el siguiente URL asi como en otras muchas direcciones:

Puede que haya oido hablar de 10s lenguajes de definici6n de datos (DDL), utilizados para definir bases de datos, y de 10s lenguajes de manipulaci6n de datos (DML), utilizados para consultar bases de datos. SQL trata estos tipos de bases. En un capitulo anterior, vimos la definici6n de datos (DDL) en SQL, por lo que ya la hemos utilizado. Este lenguaje se utiliza a1 configurar inicialmente una base de datos. Utilizaremos 10s aspectos DML de SQL con mucha mayor frecuencia porque nos servirdn para almacenar y recuperar datos reales de una base de datos.

Insertion de datos en la base de datos -

Para poder trabajar con la base de datos, es necesario almacenar datos en ella. La forma mds habitual de llevar a cab0 esta operaci6n consiste en utilizar la instrucci6n I N S E R T de SQL. Recuerde que 10s RDBMS contienen tablas, que a su vez contienen filas de datos organizados en columnas. Cada fila de una tabla suele describir un objeto o relaci6n del mundo real y 10s valores de las columnas para dichas filas almacenan informacidn sobre el mundo real. Podemos utilizar la instrucci6n I N S E R T para colocar filas de datos dentro de la base de datos. A continuaci611, se recoge la sintaxis habitual de una instrucci6n INSERT:
INSERT [INTO] t a b 1a [ ( col umna 1 , ( valorl, valor2, v a l o r 3 , . .. ) ;

col u m n a 2 ,

col u m n a 3 ,

...) 1

VALUES

Por ejemplo, para insertar un registro dentro de la tabla c u s t o m e r s de Book-0Rama, puede escribir
insert i n t o customers values "25 (NULL, "Julie Smith", Oak Street", "Airport West") ;

Desarrollo Web con P H P y MySQL

Como puede observar, hemos sustituido tabla por el nombre de la tabla en la que queremos colocar 10s datos y 10s valores con valores especificos. Los valores de este ejemplo se encierran enfre comillas dobles. En MySQL, las cadenas deberian encerrarse siempre entre comillas simples o dobles. (En este libro utilizaremos ambas.) Los numeros y las fechas no necesitan comillas. Existen ciertas cosas interesantes en 10s que fijarse en relaci6n a la instrucci6n
INSERT.

Los valores que especificamos se utilizarin para rellenar las columnas de la tabla en orden. Si desea rellenar s610 algunas columnas o si quiere especificarlas en un orden diferente, puede enumerar las deseadas en la parte reservada para las columnas de la instrucci6n. Por ejemplo:
insert into customers (name, city) values ("Melissa Jor~es", "Nar Nar Goon North");

Este enfoque resulta util si s610 se dispone de datos parciales sobre un registro dado o si algunos campos del registro son opcionales. Puede obtener el mismo efecto con la siguiente sintaxis:
insert into customers set narne="Michael Archer", address="12 Adderley Avenue", city="Leeton";

Como puede observar, especificamos un valor NULL para la columna personalizada a1 agregar a Julie Smith e ignoramos dicha columna a1 agregar el resto de 10s clientes. Puede que recuerde que a1 configurar la base de datos, creamos la columna c u s t o m e r i d como clave principal de la tabla c u s t o m e r s por lo que puede que le resulte extraiio. Sin embargo, especificamos el campo como AUTO INCREMENT, lo que significa que si insertamos una fila con un valor NULL o sin niigun valor en este campb, MySQL generarti el siguiente numero en la secuencia de increment0 automatica y la insertarA sin nuestra intervenci61-1, lo cual resulta bastante util. Tambikn puede insertar varias filas dentro de una tabla de una sola vez. Cada fila deberia incluirse en su propio conjunto de corchetes y cada conjunto de corchetes deberia separarse por medio de una coma. Hemos reunido algunos datos de ejemplo para rellenar la base de datos. Se trata de una serie de simples instrucciones I N S E R T que utilizan el enfoque de inserci6n multifila comentado. La secuencia de comandos que realiza esta tarea podrri encontrarla en el CD que se adjunta a1 libro, en el archivo correspondiente a esta carpeta. Tambikn se recoge en el listado 9.1.
Listado 9.1. book-insert.sql. SQL para rellenar las tablas de Book-0-Rarna
use books;

insert into customers values (NULL, "Julie Smith", "25 Oak

Street",

"Airport

West"),

(NULL, "Alan Wong", "1/47 Haines Avenue", "Box Hill"), (NULL, "Michelle Arthur", "357 North Road", "Yarraville"); insert into orders values (NULL, 3, 69.98, "2000-04-02"), (NULL, 1, 49.99, "2000-04-15"), (NULL, 2, 74.98, "2000-04-19"), (NULL, 3, 24.99, "2000-05-01"); insert into books values ("0-672-31697-En, "Michael Morgan", "Java 2 for Professional Developers", 34. 99), ("0-672-31745-I", "Thomas Down", "Installing Debian GNU/Linuxn, 24.991, ("0-672-31509-2", "Pruitt, et al.", "Teach Yourself GIMP in 24 Hours", 24.991, ("0-672-31769-9", "Thomas Schenk", "Caldera OpenLinux System Administration Unleashed", 49.99); insert (1, (2, (3, (3, (4, into order-items "0-672-31697-8", "0-672-31769-9", "0-672-31769-9", "0-67'2-31509-2", "0-672-31745-I",
-

values 2), I), I), I), 3);

insert into book reviews values ("0-672-31697-a", "Morqan's book is clearly written and goes well beyond most of the basic Java books out there.");

Puede ejecutar esta secuencia de comandos a travks de MySQL de la siguiente forma:


>mysql -h host -u bookorama -p < book insert.sq1
-

Recuperaci6n de datos de la base de dato


La mula de carga de SQL es la instrucci6n SELECT. Se utiliza para recuperar datos de una base de datos seleccionando las filas que coinciden con 10s criterios especificados de una tabla. La instrucci6n S E L E C T consta de una gran cantidad de opciones y formas de uso. La forma bfisica de una instrucci6n S E L E C T es 'la siguiente:
SELECT elementos FROM tablas [ WHERE condici6n ] [ GROUP BY tipo-grupo ] [ HAVING definici6n-de-d6nde [ ORDER BY tipo-orden ] [ LIMIT criterios limite ] ;
-

Comentaremos cada una de estas clfiusulas de la instrucci6n. En primer lugar, vamos a examinar una consulta sin ningtin parfimetro opcional que selecciona algu-

Desarrollo W e b con PHP y M y S Q L

nos elementos de una tabla dada. Por regla general, se trata de columnas de la tabla. (Tambien pueden ser 10s resultados de cualquier expresi6n de MySQL. Analizaremos algunos de 10s mds utiles en una secci6n posterior.) La siguiente consulta enumera 10s contenidos de la columna name y c i t y de la tabla c u s t o m e r s :
s e l e c t name, c i t y from c u s t o m e r s ;

Esta consulta devuelve el siguiente resultado, siempre y cuando haya introducido 10s datos de ejemplo del listado 9.1 y las dos instrucciones INSERT de ejemplo:

Como puede observar, tenemos una tabla que contiene 10s elementos seleccionados (name y c i t y ) de la tabla especificada, c u s t o m e r s . Los datos se muestran para todas las filas de la tabla c u s t o m e r s . Puede especificar tantas columnas como desee de una tabla enumerdndolas tras la palabra clave s e l e c t . Tambien puede especificar algunos otros elementos. Uno util es el operador comodin, *, que selecciona todas las columnas de la tabla o tablas especificadas. Por ejemplo, para recuperar todas las columnas y todas las filas de la tabla o r d e r -i t ems, utilizariamos
select * from o r d e r i t e m s ;
-

que devolverd el siguiente resultado:

Recuperacion de datos con criterios especificos


Para poder acceder a un subconjunto de filas de una tabla, necesitamos especificar algunos criterios de selecci6n. Para ello se puede utilizar la c l h s u l a WHERE. Por ejemplo,
select

9. Cdrrio trabajar corr la bose de ifatos de MySQL

seleccionarci todas las columnas d e la tabla d e pedidos pero s61o las filas con
c u s tomerid d e 3.

La cliiusula WHERE especifica 10s criterios utilizados para seleccionar filas concretas. En este caso, henlos seleccionado las filas con un Id. d e cliente d e 3. El signo igual se utiliza para probar la igualdad (tenga en cuenta que es diferente con respecto a PHP y que resulta sencillo confundirlos cuando se utilizan juntos). Adernds d e la igualdad, MySQL adrnite un conjunto completo d e operadores d e comparaci6n y d e expresiones regulares. En la tabla 9.1 se recogen las mas comunes. Tenga en cuenta que n o se trata d e una lista completa (si necesita algun operador no enurnerado, consulte el manual d e MySQL).
Tabla 9.1. Operadores de comparacion utiles para las clausulas WHERE
-

Operador

Nombre (si resulta de aplicacion) igualdad mayor que


customerld importe
=

Descripcion

Comprueba si dos valores son iguales Comprueba si u n valor es mayor que otro Comprueba si u n valor es menor que otro Comprueba si u n valor es mayor o igual que otro Comprueba si u n valor es menor o igual que otro Comprueba si dos valores no son iguales C o m p r u e b a si el campo contiene un valor C o m p r u e b a si el campo no contiene un valor

>

> 60.00

<

menor que

importe

< 60.00

>=

mayor o igual que

i m p o r t e >= 6 0 . 0 0

<=

menor o igual que

i m p o r t e <= 6 0 . 0 0

!=O<>

diferente

cantidad

!= 0

I S NOT N U L L

d i r e c c i o n is not n u l l d i r e c c i o n es n u l l

I S NULL

Desnrrollo Web corr P H P y MySQL


---.
*

-. . - -- - .
-

Operador

Nornbre (si resulta d e aplicacion) nI d

Ejemplo

Descripci6n

BETWEEN

importe between

Comprueba si un valor es mayor o igual que un valor minimo o menor o igual que un valor rnaximo Comprueba si u n valor s e i n c l u y e dentro de un conjunto dado Cornprueba si u n valor no se incluye en un conjunto Comprueba si un valor coincide con un patron utilizando simples patrones d e correspondencia de SQL Comprueba si u n valor n o coincide con un patron Comprueba si un valor coincide con una expresion regular

ciudad in ("Carlton", "Moe")


NOT IN

ciudad in ("Carlton", "Moe") correspondencia de patron nombre like

LIKE

NOT LIKE

correspondencia d e patrones expresion regular


..

nombre not like ("Fred :" ) nombre regexp

REGEXP

Las illtimas tres entradas de la tabla hacen referencia a L I K E y REGEXP. Se trata d e operadores para la blisqueda d e correspondencias en forma d e patr6n. L I K E utiliza correspondencias d e patrcin simples d e SQL. Los patrones pueden consistir en texto normal rnds el carcicter (porcentaje) para indicar una coincidencia con cualquier numero d e caracteres y el carcicter - (gui6n bajo) para sustituir a u n solo car5cter e n la bilsqueda d e correspondencias. La palabra clave R E G E X P se utiliza para las bilsquedas d e correspondencias con expresiones regulares. MySQL utiliza expresiones regulares d e POSIX. En lugar d e REGEXP, puede utilizar R L I K E ya clue son equivalentes. Las expresiones regulares d e POSIX tambikn se utilizan en PHP. Puede leer mds a1 respecto e n u n capitulo anterior. Puede probar una gran cantidad d e criterios d e esta forma y combinar 10s operadores con AND y O R . Por ejemplo:

from orders where customerid

or

customerid=4;

Recuperacih de datos desde varias tablas


A menudo, para responder a una pregunta desde la base de datos, es necesario utilizar datos incluidos en mas de una tabla. Por ejemplo, si quiere saber 10s clientes que realizaron pedidos durante el presente mes, necesitara buscar en la tabla customers y en la tabla Orders. Si ademas quiere saber quk articulos pidieron, necesitara consultar la tabla Order Items. Estos datos se encuentran distribuidos en varias tablas porque hacen referencia a objetos independientes del mundo real. 6ste es uno de 10s principios del buen diseiio de bases de datos comentado en un capitulo anterior. Para reunir esta informaci6n en SQL, debe aplicar una operaci6n denominada combinaci6n. Esta operaci6n consiste en unir dos o mas tablas para seguir la relaci6n entre 10s datos. Por ejemplo, si deseamos ver 10s pedidos realizados por Julie Smith, necesitaremos examinar la tabla us tomers para buscar el identificador de Julie y, a continuaci611, mirar en la tabla Orders para buscar 10s pedidos que tengan dicho identificador. Aunque las combinaciones resultan conceptualmente sencillas, son una de las partes mds sutiles y complejas de SQL. En MySQL se implementan varios tipos diferentes de combinaci6n y cada uno de ellos se utiliza para una finalidad diferente.

Combinaciones sencillas de dos tablas


Comenzaremos por examinar algunas instancias de SQL para consultar la informaci6n sobre Julie Smith de la que acabamos de hablar:
select orders.orderld, orders.amount, orders.date from customers, orders where customers.name = 'Julie Smith' and custarners.customerid = orders.customerid;

El resultado de esta consulta es

Tenemos que fijarnos en varios elementos. En primer lugar, como es necesario obtener informaci6n de las dos tablas para contestar a esta consulta, se han listado ambas. Tambikn se ha especificado el tip0 de combinaci6n, posiblemente sin ser consciente de ello. La coma situada entre 10s nombres de las tablas equivale a escribir INNER JOIN o CROSS JOIN.h e es un tipo de combinaci6n a1 que a veces tambikn

Desarrollo W e b con PHP y MySQL

se hace referencia como combinacibn completa o el product0 cartesiano de tablas. Significa "toma las tablas indicadas y crea otra con ellas; esta tabla deberia constar de una fila para cada combinaci6n posible de filas de cada una de las tablas indicadas, ya tenga sentido o no". En otras palabras, obtenemos otra tabla, que incluye todas las filas de la tabla Customers que se correspondan con cada fila de la tabla Orders, independientemente de si un cliente realiz6 un pedido concreto. En muchas ocasiones el resultado no tiene mucho sentido. Por regla general, lo que queremos es ver las filas coincidentes, es decir, 10s pedidos realizados por un cliente dado y la informacibn correspondiente del cliente. Para lograrlo se utiliza una condicio'n de cornbinacidn en la clausula WHERE.Se trata de un tip0 especial de instrucci6n condicional que explica qu6 atributos muestran la relaci6n entre dos tablas. En este caso, la condicibn de combinaci6n es la siguiente:

que indica a MySQL que ponga filas en la tabla de resultados si el customerId de la tabla customers coincide con el Cus tomerId de la tabla Orders. A 1 agregar esta condici6n de combinacidn en la consulta, hemos creado otro tip0 de combinaci6n llamada cornbinacidn de igualdad. La notaci6n de punto utilizada deja claro a qu6 tabla pertenece una columna dada, es decir, customers customerid hace referencia a la columna cus tome rid de la tabla Customers y order. customerid hace referencia a la columna customerid de la tabla orders. Esta notaci6n es obligatoria si el nombre de una columna resulta ambiguo, es decir, si aparece en mas de una tabla. Tambi6n se puede utilizar para distinguir 10s nombres de columnas utilizados en diferentes bases de datos. En este ejemplo, se ha utilizado la notacibn tabla.columna. Puede especificar la base de datos con una notaci6n basededatos.tabla. columna, por ejemplo, para p r ~ b a una r condicidn como

books.orders.customerid

o t h e r db.orders. customerid

Sin embargo, puede utilizar la notaci6n de punto para todas las referencias de columna de una consulta. Esta opcion es una buena idea, en especial cuando las consultas comienzan a complicarse. Su uso no es obligatorio en MySQL per0 las consultas resultaran mucho mas legibles y sencillas de mantener. Como puede apreciar, hemos utilizado esta convenci6n en el resto de la consulta anterior, por ejemplo, a1 utilizar la condition
customers.name
=

'Julie

Smith'

El nombre de columna s610 tiene lugar en la tabla de clientes por lo que no necesitaremos especificarlo, aunque resultar6 mas claro.

Combinaci6n de varias tablas


Cuando se combinan m6s de dos tablas la operacidn se complica. Como regla general, en las condiciones de combinaci6n se combinan las tablas de dos en dos.

9. Cdmo trabajar con la base de datos de MySQL

Es como seguir las relaciones entre 10s datos de una tabla a otra tabla a otra tabla, etc. Por ejemplo, si queremos saber qu6 clientes han pedido libros sobre Java (por ejemplo, para poder enviarles informaci6n sobre un nuevo libro), necesitaremos rastrear dichas relaciones a trav6s de bastantes tablas. Tendremos que buscar clientes que hayan realizado a1 menos un pedido que incluya un libro de Java. Para acceder a la tabla Order s desde la tabla c u s tome r s podemos utilizar la columna cus tome r i d como hicimos anteriormente. Para acceder a la tabla Order I tems desde la tabla Orders, podemos utilizar la columna o r d e r i d . Para acceder a un libro especifico de la tabla Books desde la tabla Order 1 t e m s , podemos utilizar el ISBN. Tras establecer estos enlaces, podemos buscaribros que incluyan el termino Java en el titulo y recuperar 10s nombres de 10s clientes que hayan comprado alguno de ellos. Examinemos la consulta que realiza estas operaciones.
select customers.name from customers, orders, order items, books where customers.customerid = orders.custornerid and orders.orderid = order items.orderid and order items.isbn = books.isbn and books.title like '%Java%';
-

Esta consulta devuelve el siguiente resultado:

Fijese en que seguimos 10s datos a trav6s de cuatro tablas diferentes y, para hacerlo con una combinaci6n de igyaldad, necesitamos tres condiciones de combinaci6n diferentes. Por regla general, se necesita una condici6n de combination para cada par de tablas que se desee combinar, por lo que el total de condiciones de combinaci6n sera igual a1 n6mero de tablas que se desean combinar menos uno. Esta regla puede resultar 6til para consultas de depuraci6n que no funcionen. Compruebe las condiciones de combinaci6n y asegurese de haber seguido la ruta desde lo que sabe a lo que desea saber.

Busqueda de filas que no coincidan


El segundo tip0 principal de consultas que utilizaremos en MySQL son las combinaciones por la izquierda. En 10s ejemplos anteriores, s610 se han incluido las filas coincidentes entre las tablas. En ocasiones, se necesita recuperar las filas que no coincidan. Por ejemplo, 10s clientes que no hayan realizado nunca un pedido o 10s libros que no se hayan pedido nunca. La forma m i s sencilla de responder a este tip0 de cuesti6n en MySQL es utilizar una combinaci6n por la izquierda. En estas combinaciones se comparan filas a partir

Desarrollo Web con PHP y MySQL

de una condici6n de combinaci6n dada entre dos tablas. Si no existen filas coincidentes en la tabla de la derecha, se agregari una fila a1 resultado que contenga valores N U L L en las columnas de la derecha. Veamos un ejemplo:
select customers.customerid, customers.name, from customers left join orders on custorners.customerid = orders.customerid: orders.orderid

La consulta SQL utiliza una combinaci6n por la izquierda para combinar combination por la izquierda utiliza una sintaxis un tanto diferente en la condici6n de combinaci6n. En este caso, dicha combinaci6n va en una cliiusula O N especial de la instruccidn SQL. El resultado de la consulta es el siguiente:
C u s t o m e r s con O r d e r s . La
l r~ame
+---------------+---------+

1 orderid I
2 3 1 4 NULL NULL 1 1

Smith I \ A l a n Wong I 1 Michelle Arthurl 1 Michelle Arthurl IMelissa Jones I [ M i c h a e l Archer I

l Julie

I
1

I
I

Este resultado muestra que no existen Id. de pedido coincidentes para Melissa Jones y Michael Archer porque dichos Id. son N U L L . Si s610 deseamos ver 10s clientes que no hayan realizado ningun pedido, podemos recuperarlos utilizando dichos valores N U L L en el campo de clave principal de la tabla de la derecha (en este caso o r d e r i d ) .
select customers. customerid, customers. name from customers left join orders using (customerid) where orders. orderid is null;

El resultado serh:

Como observari, hemos utilizado una sintaxis diferente para la condicidn de combinacion en este ejemplo. Las combinaciones por la izquierda admiten la sintaxis O N utilizada en el primer ejemplo o la sintaxis U S I N G del segundo. Tenga en cuenta que la sintaxis U S I N G no especifica la tabla de la que procede el atributo de combinaci6n. Por esta razdn, las columnas de las tablas deben tener el mismo nombre si queremos utilizar U S I N G .

9. Cdmo trnbnjnr con In bnse de dntos de MySQL

A menudo resulta prActico, y a veces necesario, poder utilizar otros nombres para hacer referencia a las tablas. Es lo que se conoce como alias. Los alias se pueden crear a1 principio d e u n a colurnna y utilizarlos a lo largo d e todas ellas. Suelen resultar przicticos por cuestiones d e brevedad. Por ejemplo, examine la consulta q u e escribimos anteriormente pero escrita con alias:

A1 declarar las tablas que vamos a utilizar, agregamos una clziusula AS para establecer el alias asociado a dicha tabla. Tambikn podemos utilizar alias para columnas. Volveremos sobre este tema a1 analizar las funciones d e agregacion. El uso d e alias es obligatorio cuando se trata d e combinar una tabla consigo misma. Suena m i s complicado y extraiio d e lo q u e parece. Resulta Gtil, por ejemplo, si queremos buscar filas d e la misma tabla con valores comunes. Si queremos buscar clientes q u e vivan e n la misma ciudad (por ejemplo, para establecer u n sitio d e lectura) podemos asignar a la tabla ( C U S t o m e r s ) d o s alias diferentes.

Lo q u e estamos haciendo bzisicamente es simular la existencia d e d o s tablas C u s t o m e r s diferentes, cl y c2,y realizar la combinacicin sobre la colurnna c i t y . Como observari tambien necesitamos la segunda condicicin, cl . name ! = c2 . name, para no recuperar todos los clientes por tener el mismo nombre. Rckr~rncn clc lo\ tipo\

dc comhinacicin
-

En la tabla 9.2 se recogen 10s diferentes tipos d e combinaciones vistos. Existen otros, pero 10s incluidos en la tabla son 10s mfis importantes para nuestros propcisitos.
Tabla 9.2. Tipos de combinacion en MySQL
1 1 1 1 1
v -

Nombre
Producto cartesiano

Descripcion
Se combinan todas las filas de todas las tablas. Se utiliza incluyendo una coma entre 10s nombres de las tablas y sin una clausula WHERE. lgual a la anterior

combinacion total

Desnrrollo Web corr PHP

MySQL

Nombre Combinacion cruzada

Descripcion lgual que las anteriores. Tambien se puede utilizar especificando las palabras clave CROSS JOIN entre 10s nombres de las tablas combinadas. Semanticamente, resulta equivalente a la coma. Tambien se puede especificar utilizando las palabras clave INNER JOIN Sin una condicion WHERE resulta equivalente a una combinacion total. Por regla general, se especifica una condicion WHERE para obtener una autentica combinacion interna.

Combinacion interna

combinacion de igualdad Utiliza una expresion condicional con un signo = para buscar filas coincidentes entre las diferentes tablas de la combinacion. En SQL, equivale a una combinacion con una clausula WHERE. combinacion por la izquierda Busca filas coincidentes entre tablas y rellena las filas no coincidentes con valores NULL. En SQL, se utiliza con las palabras clave LEFT JOIN. Se utiliza para buscar valores que falten. Tambien se puede utilizar la combinacion RIGHT JOIN de manera equivalente.

Secilperacirjn de clatos con un orden dado


Si desea m o s t r a r e n un o r d e n concreto las filas recuperadas e n u n a consulta, p u e d e u t i l i z a r l a cl6usula ORDER B Y d e l a instruction S E L E C T . Esta f u n c i 6 n resulta prActic3 p a r a presentar 10s resultados e n un f o r m a t o l e g i b l e para humanos. L a c l 6 u s u l a ORDER B Y se u t i l i z a p a r a o r d e n a r las filas d e u n a o varias c o l u m n a s listadas e n l a clausula S E L E C T . P o r ejemplo,

Esta consulta d e v u e l v e 10s n o m b r e s y las direcciones e n o r d e n alfab6tico p o r e l nombre:

9. Cn'iizo trnbr.rjnr corz ln base d e dntos de MySQL

(A1 utilizar el formato d e nombre y apellido, 10s registros se ordenan por el nombre. Si desea ordenarlos por el apellido, necesitar6 utilizar dos campos diferentes.) El orden predeterminado es ascendente (de la a a la z o numgricamente hacia arriba). Puede especificar este orden mediante la palabra c l a v e ~ s c :

Tambien puede utilizar la palabra clave DESC (descendente) para aplicar el orden inverso:

Puede ordenar 10s registros por m6s d e una columna. Ademss, puede utilizar alias d e columna o incluso sus ndmeros d e posici6n (por ejemplo, 3 es la tercera colurnna d e la tabla) en lugar d e nombres.

Agrupacicin

y agregaci6n cle datos

A menudo nos interesa saber cuintas filas contiene un conjunto dado o el valor promedio d e una colurnna (por ejemplo, el promedio en mettilico por pedido). MySQL incorpora un conjunto d e funciones d e agregaci6n que resultan dtiles para responder a una consulta. Estas funciones d e agregaci6n se pueden aplicar a una tabla en su conjunto o a grupos d e datos dentro d e una tabla. Lo normal es utilizar las listadas en la tabla 9.3.
Tabla 9.3. Funciones de agregacion de MySQL
-. .
I p -

,-

--.-

Nornbre
AVG (columns)

Description

Promedio de 10svalores de la columna especificada Si especifica una colurnna, devolvera el nljrnero de valores que no Sean N U L L de la colurnna. Si agrega la palabra D I S T I N C delante del nombre de la columna, obtendra u n contador de 10s valores diferentes de dicha columna unicamente. Si especifica C O U N T ( * ) , obtendra u n recuento de fila independienternente de 10svalores NULL. Minimo de 10svalores de la columna especificada. Maximo de 10s valores de la columna especificada Desviacion estandar de 10svalores de la colurnna especificada.

COUNT ( e l e m e n t o s )

MIN ( c o l u r n n a )
MAX ( c o l u r n n a )
STD

(columna)

Desnrrollo W e b con P H P y MySQL

Nombre
STDDEV (colurnna)
SUM (colurnna)

Descripcidn
lgual que STD (colurnna) . Suma de 10s valores de la columna especificada.

Vamos a examinar algunos ejemplos, comenzando por el mencionado anteriormente. Podemos calcular la media total de un pedido de la siguiente forma:

El resultado serA el siguiente:

BY. Esta Para obtener informacion detallada, podemos utilizar la c l ~ u s u l GROUP a cliusula nos permite ver la media de pedidos por grupos (por ejemplo, por el numero d e cliente). De esta forma sabremos qu6 clientes realizan 10s mayores pedidos.

A1 utilizar una cl.5usula G R O U P BY con una funci6n de agregacibn, se modifica el comportamiento d e la funcion. En lugar d e obtener la media de las cantidades d e pedidos de toda la tabla, esta consulta recupera la media de las cantidades de pedidos d e cada cliente (0, paw ser mas especifico, para cada customerid):

Antes utilizar la agrupacion y agregacion d e funciones, tenga en cuenta que en ANSI SQL, si utiliza una funci6n de agregacion o la cl6usula G R O U P BY, lo Gnico que puede aparecer en la clausula S E L E C T son las funciones d e agregaci6n y las columnas designadas en la clAusula G R O U P BY. Asi mismo, si quiere utilizar una colurnna en una clausula GROUP BY, debe listarla en la cl6usula SELECT. MySQL brinda una mayor libertad en este sentido ya que admite sintaxis extendida, lo que nos permite dejar elementos fuera d e la clausula SELECT si no 10s deseamos. Ademas d e agrupar y agregar datos, podemos probar 10s resultados d e una operaHAVING. ~ s t se a coloca directamente detras ci6n de agregaci6n utilizando la c l ~ u s u l a

9. Cdmo trabajar con la base de datos de MySQL

de la cliusula GROUP BY y es como una cliusula WHERE aplicada unicamente a grupos y agregados. En nuestro ejemplo anterior, si queremos saber qu6 clientes tienen pedidos cuyo importe medio supere 10s 50 ddlares, podemos utilizar la siguiente consulta:
s e l e c t customerid, avg(amount) from o r d e r s g r o u p by c u s t o m e r i d h a v i n g a v g ( a m o u n t ) > 50;

Fijese en que la cliusula HAVING se aplica a 10s grupos. Esta consulta devolveri el siguiente resultado:

C6mo escoger las filas que recuperar


Una cldusula de la instruccidn SELECT que puede resultar especialmente util en aplicaciones Web es la cliusula LIMIT. Esta cliusula se utiliza para especificar qu6 filas deberian devolverse desde el resultado. Toma dos pardmetros: el numero de fila desde la que empezar y el numero de filas que devolver. La siguiente consulta ilustra el uso de L I M I T :
s e l e c t name from c u s torners l i m i t 2 , 3;

Esta consulta se puede leer cbmo "seleccionar nombre de clientes y devolver tres filas en el resultado, comenzando en la fila numero 2". Fijese en que 10s numeros de fila estdn indexados en cero, es decir, que la primera fila del resultado es la fila n6mero cero. Esto resulta muy util en aplicaciones Web. Por ejemplo, cuando el cliente esti examinando 10s productos de un catilogo y quiere ver 10 por pdgina.

Actualization de registros en la base de datos


Ademds de recuperar datos desde una base de datos, tambi6n resulta normal modificarlos. Por ejemplo, podemos aumentar 10s precios de 10s libros incluidos en la base datos. Para ello, podemos utilizar una instruccidn UPDATE. La forma habitual de una instruccidn UPDATE es la siguiente:
UPDATE n o r n b r e t a h l a SET c o l u r n n a l = e x p r e s i 6 n l , c o l umnaZ=expresidn2,.

Desarrollo Web con P H P y M y S Q L

La idea consiste en actualizar la tabla llamada nombretabla, estableciendo cada columna mencionada a la expresi6.n apropiada. Puede limitar la aplicaci6n de la operaci6n UPDATE a filas concretas mediante una cliiusula WHERE y restringir el nLimero total de filas con una clausula L I M I T . Vamos a examinar algunos ejeinplos. Si desea incrementar 10s precios de todos 10s libros u n 10% puede utilizar una instruccion UPDATE con una clAusula WHERE:

Si quiere cambiar una sola fila (por ejemplo, para actualizar una direccion d e cliente), puede hacerlo d e la siguiente forma:

Alkracion de tablas tras su creaci6n


AdemAs de actualizar filas, podemos alterar la estructura d e las tablas dentro d e una base de datos. Para ello, se puede utilizar la instruccioi~ALTER TABLE. La forma bssica d e esta instrucci6n es la siguiente:

Fijese en que en ANSI,SQls61o puede realizar una alteracidn por cada instrucc ~ ~ ~ A L T TABLE, E R pero MySQL permite realizar todas las que desee. Cada clausu-

la de alteraci6n se puede utilizar para cambiar diferentes aspectos d e la tabla. En la tabla 9.4 se recogen 10s diferentes tipos de alteraci6n que se puede realizar con esta instruccion.
Tabla 9.4. Cambios posibles con la instruccion ALTER TABLE

A D D [COLUMN] d e s c r i p c l o n - c o l umna [FIRST I AFTER colurnna ]

Agrega una nueva columna en la ubicacion especificada. Si no se especifica, la columna ira al final. Fijese en q u e d e s c r i p c i o n columna necesita un nombre y un tipo, como en una instruccion CREATE. Agrega una o varias columnas nuevas a1 final de la tabla.

ADD

[COLUMN] (description-columna, description-columna, . . . )

9 . C h o trabajar con la base de datos de MySQL

sintaxis
ADD INDEX [indice] (columna,

Descrlpcidn

...)

Agrega un indice a la tabla en la colurnna o columnas especificadas. Convierte la colurnna o columnas especificadas en la clave principal de la tabla. Agrega un indice unico a la tabla en una colurnna o columnas especificadas. Agrega o elimina un valor predeterminado de una colurnna dada. Cambia la colurnna llamada columna para que incluya la descripcion. Observe que se puede utilizar para cambiar el nombre de la columns porque descr ipclon-columna incluye un nombre. Similar a C H A N G E . Se puede util~zarpara cambiar tipos de colurnna, no nombres. Elimina columnas con nombre Elimina el indice principal (pero no la columna). Elimina el indice con nombre

ADD

PRIMARY

KEY

(columa,

. ..)

ADD

UNIQUE

[indice]

(columna,

. ..)

A L T E R [COLUMN] c o l u m n a ( S E T DEFAULT v a l o r I DROP D E F A U L T ) CHANGE [ C O L U M N ] c o l u m n a d e s c r l p c i o n n u e v a - c o l umna

MODIFY [COLUMN] d e s c r l p c i o n - c o l umna DROP DROP [COLUMN] PRIMARY

col unma
KEY

DROP

INDEX [AS]

indlce nombre-nuevatabla

RENAME

Cambia el nombre de una tabla

Vamos a examinar algunos usos comunes de ALTER TABLE.Algo que suele ocurrir con frecuencia es darse cuenta de que no se ha asignado el ancho suficiente a una colurnna para albergar 10s datos. Por ejempke, en la tabla c u s t o m e r s , hemos asignado30 caracteres de longitud a 10s nombres. A1 recibir datos, puede que descubramos que algunos nombres son demasiado largos y quedan cortados. Podemos solucionar este problema cambiando 10s tipos de datos de las columnas para aumentar su tamafio a 45 caracteres de largo.

Otra cosa que suele ocurrir de manera habitual es la necesidad de agregar una columna. Imagine que se ha introducido un impuesto local y que Book-O-Rama necesita agregarlo a1 total del pedido y realizar su seguimiento por separado. Podemos agregar una columna para el impuesto en la tabla O r d e r s de la siguiente forma:
a l t e r tah1.e o r d e r s add t a x f h a t (6,>) a f t e r

amaunt;

Otra necesidad que suele surgir de forma habitual es la de eliminar una columna. Podemos suprimir la columna que acabamos de agregar de la siguiente forma:
alter
drap
table
ordcr.~,

tax;

Desarrollo Web con P H P y MySQL

Eliminaci6n de registros de la base de datos


La operaci6n de eliminar filas de la base de datos resulta sencilla. Para ello, puede utilizar la instrucci6n DELETE,que suele presentar este aspecto:
D E L E T E FROM t a b l a [WHERE c o n d i c i b n ] [ L I M I T niirnero]

Si escribe
DELETE FROM t a b l a ;

en solitario, se eliminardn todas las filas de una tabla, por lo que conviene tener cuidado. Lo normal es eliminar filas concretas, para lo cual se pueden especificar en una cliusula WHERE. Por ejemplo, podemos eliminar filas si un libro no estuviera disponible o un cliente concreto llevara mucho tiempo si realizar pedidos y quisiera limpiar un poco la base de datos.
delete from customers where customerid=5;

La cldusula LIMIT se puede utilizar para limitar el numero miximo de filas que se eliminan.

Eliminacicin de tablas
En ocasiones se necesita eliminar una tabla entera. Para ello se puede utilizar la instrucci6n DROP TABLE.Esta operaci6n resulta muy sencilla y presenta este aspecto.
DROP TABLE

tabla:

Esta instrucci6n eliminari todas las filas de la tabla y la propia tabla, por lo que es necesario tener cuidado.

Eliminacicin de una base de datos entera


Podemos ir incluso mis all6 y eliminar una base de datos completa con una instrucci6n DROP DATABASE,que presenta un aspecto parecido a1 siguiente:
DROP DATABASE

base

de

datos;

Esta instrucci6n elimina todas las filas, todos 10s indices y la propia base de datos, por lo no es necesario indicar el cuidado que hay que poner a1 utilizarla.

9. Co'mo trabajar con la base de datos de MySQL

Lecturas adicionales
En este capitulo, hemos pasado revista a 10s elementos mds comunes de SQL que se utilizan a1 interactuar con una base de datos MySQL. En 10s siguientes dos capitulos, examinaremos como conectar MySQL y PHP para poder acceder a su base de datos desde la Web. Tambih exploraremos algunas tecnicas avanzadas de MySQL. Si desea saber mds sobre SQL, puede consultar el estdndar ANSI SQL. Lo encontrard en:

Si desea obtener mds detalles sobre las extensiones de MySQL para ANSI SQL puede consultar el sitio Web MySQL:

A continuacion
En el siguiente capitulo veremos c6mo permitir el acceso a Book-0-Rama desde la Web.

En un capitulo anterior, a1 trabajar con PHP, utilizamos un archivo sin procesar para almacenar y recuperar datos. En dicho capitulo, indicamos que 10s sistemas de base de datos relacionales facilitan enormemente las tareas de almacenamiento y recuperation de datos y resultan mucho m i s eficientes en una aplicaci6n Web. A continuaci6n, tras trabajar con MySQL, podemos comenzar a conectar esta base de datos a una interfaz de usuario basada en la Web. En este capitulo, explicwemos cdmo acceder a la base de datos Book-0-Rama desde la Web utilizando PHP. Aprender6 a leer una base de datos y a escribir en ella, y a filtrar datos de entrada potencialmente peligrosos. A continuacGn, se recogen 10s aspectos b6sicos que se abordarh: Funcionamiento de las arquitecturas de base de datos Pasos b6sicos para consultar una base de datos desde la Web C6mo configurar una conexi6n C6mo obtener informaci6n sobre bases de datos disponibles Selecci6n de una base de datos que utilizar Cdmo consultar una base de datos Recuperaci6n de 10s resultados de consulta Desconexi6n de la base de datos C6mo colocar nueva informaci6n en la base de datos

10. Acceso a la base de datos de MySQL desde la W e b con PHP

Otras funciones utiles de PHP y MySQL Uso de una interfaz generica debase de datos: PEAR DB Otras interfaces debase de datos de PHP

Funcionamiento de las arquitecturas de base de datos


En un capitulo anterior se indicaron las lineas bdsicas del funcionamiento de las arquitecturas de bases de datos Web. A continuaci6n se repiten dichos pasos para ayudarle a recordar:
1. Un usuario de navegador Web envia una petici6n HTTP solicitando una p6gina Web dada. Por ejemplo, el usuario podria solicitar todos 10s libros escritos por Michael Morgan que tenga Book-0-Rama, utilizando un formulario HTML. Los resultados de la b&quedas se almacenan en results.php. 2. El servidor Web recibe la petici6n de results.php, recupera el archivo y lo pasa a1 motor de PHP para su procesamiento.

3. El motor de PHP comienza a analizar la secuencia de comandos. Dentro de la secuencia de comandos hay un comando que establece la conexi6n a la base de datos y ejecuta una consulta (realiza la busqueda de libros). PHP abre una conexi6n a1 servidor MySQL y remite la consulta pertinente.
4. El servidor MySQL recibe la consulta de la base de datos y la procesa. A continuaci611, envia 10s resultados (una lista de libros) a1 motor de PHP.

5. El motor de PHP termina de ejecutar la secuencia de comandos, lo que suele implicar la aplicaci6n de formato a 10s resultados en HTML. Seguidamente, devuelve el c6digo HTML resultante a1 servidor Web.
6. El servidor Web devuelve el c6digo HTML a1 navegador donde el usuario puede ver la lista de 10s libros solicitados.

Ahora tenemos una base de datos MySQL, por lo que podemos escribir el c6digo PHP para realizar 10s pasos anteriores. Comenzaremos por el formulario de busqueda. Se trata de un sencillo formulario escrito en HTML. En el listado 10.1 se recoge su c6digo:
Listado 10.1. search.html. Pagina de b h q u e d a de base de datos de Book-0-Rama
<html> <head> <title>Book-0-Rama Catalog Search</title>

Desnrrollo Web con P H P y MySQL

El c6digo de este forrnulario resulta bastante claro. En la figura 10.1 se muestra el resultado.

I/ Book-0-Rama Catalog Search


Choose Search Type:

IAu(hor_Zl
Enler Search Term:..

! ! E l

Figura 10.1. El forrnulario de busqueda resulta bastante general por lo que se puede buscar un libro a partir de su titulo, autor o ISBN

La secuencia d e comandos que se invocarfi a1 pulsar el b o t h Search es results.php. En el listado 10.2 se incluye el c6digo completo. En este capitulo veremos qu6 realiza esta secuencia de comandos y su funcionamiento.
Listado 10.2. result.php. Esta secuencia de cornandos recupera 10s resultados de nuestra base de datos MySQL y les aplica forrnato para su visualization

10. Acceso a la base de datos de MySQL desde la W e b con P H P

<head> <title>Book-0-Rama Search Results</title> </head> <body> <hl>Book-0-Rama Search Results</hl> <?php / / Cree nombres d e variables cortos $ s e a r c h t y p e = $ H T T P P O S T S s e a r c h t y p e = S H T T P _ P O S T _ V A R S [ ' s e a r c h t y p e ' V A R S [ q ~ e a r ~ h t y p e ' ] ; $searchterm=$HTTP-POSTVARS['searchterm'];

echo 'You have not entered search details.Please g o back and try again. ' ; exit;

@ Sdb = mysql~pconnect('localhost', 'bookorama', 'bookorarnal23');

,if
(

( !

Sdb) Please try again later.';

echo 'Error: Could not connect t o database. exit;

I
rnysql_select~db('books'); $query = "select * from books where ".$searchtype." like .$searchterm."%'";

1 9 "

$result

rnysql-query($query);
=

$nurn-results

mysql nbm r ~ w s ( $ r e s u l t ) ;
-

echo '<p>Number of books found: '.Snum-results.'</p>';

$row echo echo echo echo echo echo echo echo echo

rnysql-fetch-array($result); '<p><strong>'.($i+l).'. Title: ' ; htrnlspecialchars(stripslashes($row['title'])); '</strong><br />Author: ' ; stripslashes ($row[ 'author'I ) ; '<br />ISBN: ' ; stripslashes($row['isbn'l); '<br />Price: ' ; stripslashes($row['price']); '</p>';

I
?>

D r w r r o l l o Wcb corl PHP y MySQL

k h m Edwon Vsr Favonlm Herramenlas Awda

IL

Book-0-Rama Search Results


Number of books found: 1

1. 'l'ille: Java 2 lor Professional Develupe~s Author: Michael Mega


ISBN: 0-672-31697-8 Price: 34.99

Figura 10.2. Los resultados de la busqueda de la base de datos sobre libros de Java se presentan en la pagina Web utilizando la secuencia de comandos results.php

En cualquier secuencia d e comandos utilizada para acceder a una base d e datos desde la Web, se siguen algunos pasos bcisicos:

1. Comprobar y filtrar 10s datos procedentes del usuario. 2. Configurar una conexi6n a la base d e datos pertinente.
3. Consultar la base d e datos.

4. Recuperar 10sresultados.

5. Presentar 10s resultados a1 usuario.


Estos son 10s pasos seguidos en la secuencia d e comandos results.php y vamos a revisar cada uno de ellos por separado.

En primer lugar vamos a eliminar todos 10s espacios en blanco que pudiera haber introducido el usuario d e manera involuntaria a1 principio o a1 final del termino d e bGsqueda. Para ello, aplicamos la funci6n t r i m ( ) a $ s earchterm.

El siguiente paso consiste en verificar que el usuario ha introducido un termino d e btisqueda y un tip0 d e b&.queda. Tenga en cuenta que este paso se realiza tras eliminar 10s espacios en blanco a1 final del termino d e b6squeda. Si hubieramos ordenado

10. Acceso a la base de datos de MySQL desde la W e b con P H P

estas lineas en orden inverso, podria darse el caso de que el usuario hubiera introducido un tdrmino de busqueda formado por espacios en blanco y de esta forma no se generaria un mensaje de error. Por ello, se utiliza la instrucci6n trim ( ) :
if

(!$searchtype

!$searchterm) Please go back and try again.';

t
echo 'You have not entered search details. exit;

Como observar6 hemos comprobado la variable $ sea rchtype aunque en este caso procede de una instrucci6n SELECT de HTML. Se estar6 preguntando por qud preocuparse de comprobar datos que tienen que introducirse. Es importante recordar que puede que exista m6s de una interfaz hasta la base de datos. Por ejemplo, Amazon incluye una gran cantidad de afiliados que utilizan su propia interfaz de busqueda. Ademis, resulta aconsejable filtrar 10s datos para evitar 10s problemas de seguridad que pueden surgir debido a usuarios procedentes de diferentes puntos de entrada. Ademis, cuando se van a utilizar datos introducidos por un usuario, es importante filtrarlos adecuadamente para detectar cualquier car6cter de control. En un capitulo anterior, hablamos de las funciones adds lashes ( ) y stripslashes ( ) . La funci6n adds lashes ( ) se utiliza a1 enviar 10s datos introducidos por el usuario a una base de datos como MySQL y stripslashes ( ) a1 devolver el resultado a1 usuario que ha utilizado caracteres de control. En este caso hemos utilizado addslashes ( ) en 10s tdrminos de busqueda:
Ssearchterm
=

addslashes($searchterm);

Tambidn hemos utilizado sm i p s1as he s ( ) sobre 10s datos procedentes de la base de datos. Ninguno de 10s datos introducidos a mano en la base de datos tenia barras ni caracteres de control. La llamada a la funci6n stripslashes ( ) no tendr6 ningun efecto. A1 desarrollar una interfaz Web para la base de datos, es probable que necesitemos introducir nuevos libros y es posible que alguno de 10s detalles introducidos por 10s usuarios contenga estos caracteres. A1 introducirlos en la base de datos, llamaremos a la funci6n addslashes ( ) ,lo que significa que debemos llamar a la instrucci6n strips1 ashes ( ) a1 extraer 10s datos. Se trata de una costumbre que resulta bastante aconsejable adoptar. Estamos utilizando la funci6n html special chars ( ) para codificar caracteres que tengan significados especiales en HTML. Nuestros datos de prueba actuales no incluyen ningun simbolo ampersand (&), menor que (<), mayor que (>) ni comillas dobles ("), pero hay titulos de libros en 10s que podrian aparecer. Esta funci6n nos permite evitar errores futuros.

Desarrollo W e b con P H P y MySQL

Como configurar de una conexi6n


Utilizaremos la siguiente linea en nuestra secuencia de comandos para establecer una conexi6n a1 servidor de MySQL:
@

$db

mysql~pconnect('loca1host', 'bookorama',

'bookorarnal23');

Hemos utilizado la funci6n m y s q l p c o n n e c t ( ) para establecer una conexi6n a la base de datos. La sintaxis de esta funci6n es la siguiente:
resource mysql -pconnecti [string host [:puertol [:irutasocketl string usuario [ , string contraseAa1 I] ) ;
[,

Por regla general, se le pasa el nombre del host en el que se ejecuta el servidor MySQL, el nombre de usuario utilizado para iniciar la sesi6n y la contrasefia de dicho usuario. Todos estos parfimetros son opcionales y si no se especifican la funci6n utilizarfi 10s predeterminados: el host local para host, el nombre de usuario con el que se procese PHP y una contrasefia en blanco. La funci6n devuelve un identificador de vinculo a la base de datos MySQL en caso de que el intento de conexi6n resulte satisfactorio (que deberia guardar para otras ocasiones) o f a l s e en caso contrario. Es conveniente comprobar el resultado ya que el resto del c6digo no funcionari sin una conexi6n vilida a la base de datos. Para ello, hemos utilizado el siguiente c6digo:
if
I !$db)

t
echo 'Errnr: Could not connect t o database. exit;
1

Please try again later.';

Una funci6n a1ternativ.a qua realiza la misma labor que my s q l -p c o n n e c t ( ) es m y s q l c o n n e c t ( ) . La diferencia esti en que la primera devuelve una conexi6n permaiente a la base de datos. Una conexi6n normal a la base de datos se cerrari cuando la secuencia de comandos termine su ejecuci6n o cuando se llame a la funci6n m y s q l - c l o s e ( ) . Las conexiones permanentes siguen abiertas cuando la secuencia de comandos termina la ejecuci6n y no se pueden cerrar utilizando la funci6n m y s q l - c l o s e ( ) . Es probable que se est6 preguntado para qu6 comprobar si existe una conexi6n permanente. La respuesta esti en que el establecimiento de una conexi6n a una base de datos implica una determinada carga y por lo tanto lleva cierto tiempo. A1 llamar a m y s q l p c o n n e c t ( ) , antes de intentar establecer la conexi6n a la base de datos, se comprieba automiticamente si existe una conexi6n permanente abierta. Si asi fuera, se utilizari dicha conexi6n en lugar de abrir una nueva, con el consiguiente ahorro de tiempo y carga del servidor. Tambikn conviene sefialar que las conexiones permanentes no resultan permanentes si se esti ejecutando PHP como un CGI. (Cada llamada a una secuencia de comandos de PHP inicia una nueva instancia de PHP y la cierra cuando la secuencia

10. Acceso a la base de datos de M y S Q L desde la W e b con PHP

de comandos termina la ejecuci6n. T a m b i h se cierran todas las conexiones permanentes.) Hay que tener en cuenta que el numero de conexiones simultiineas a MySQL es limitado y viene determinado por el pariimetro max c o n n e c t i o n s . El objetivo de este pariimetro y del par6metro MaxClients de Apache es indicarle a1 servidor que rechace las solicitudes de nueva conexi6n en lugar de permitir el uso de todos 10s recursos del equipo en momentos de mucho triifico o cuando se haya producido un error en el software. Los valores predeterminados de estos pariimetros se pueden modificar editando 10s archivos de configuraci6n. Para establecer el pariimetro M a x C l i e n t s de Apache, modifique el archivo h t t p d . conf de su sistema. Para establecer el pariimetro max -c o n n e c t i o n s de MySQL, edite el archivomy. c o n f . Si utiliza conexiones permanentes y priicticamente todas las piiginas del sitio necesitan acceder a la base de datos, es probable que abra una conexi6n permanente para cada proceso de Apache. Esta situaci6n puede dar lugar a un problema si se mantienen 10s valores predeterminados. De manera predeterminada, Apache permite 150 conexiones, per0 MySQL s610 permite 100. En fases de mucho triifico, el numero de conexiones puede resultar insuficiente. Es aconsejable ajustar estos pariimetros en funci6n del hardware de manera que cada proceso de servidor Web disponga de una conexi6n.

Seleccion de una base de datos


Como recordark a1 utilizar MySQL desde un interfaz de linea de comandos, necesitamos indicarle qu6 base de datos tenemos pensado utilizar con la ayuda de un comando como el siguiente:

iuse

books;

Tambi6n necesitamos realizar esta tarea a1 establecer la conexion desde la Web. Desde PHP lo hacemos con una llamada a la funci6n mys q l -s e l e c t -db ( ) , como hemos en el siguiente caso:

La funci6n mys q l -s e 1e c t -db ( ) tiene la siguiente sintaxis:


b o o 1 m y s q l -s e l e c t - d b i s t r i n g

basededatos,

[resource conexidn-basedtdatss]

1;

Este c6digo intentar6 utilizar la base de datos llamada basededatos. Tambien se puede incluir el vinculo de base de datos sobre el que nos gustaria realizar esta operaci6n (en este caso Sdb), per0 si no se especifica, se utilizarii el ultimo vinculo abierto. Si no dispone de un vinculo abierto, se abririi el predeterminado como si hubiera llamada a mysql -c o n n e c t ( ) .

Desnrrollo Web con P H P y M!jSQL

C6mo consulfar la base d e datos


Para realizar una consulta, podemos utilizar la funci6n mysql -q u e r y ( j . Sin embargo, antes de realizar esta tarea, conviene configurar la consulta que se desea ejecutar:

En este caso, buscamos el valor introducido por el usuario ( $ s e a r c h t e r m ) en el campo especificado por el usuario ( S s e a r c h t y p e ) . Como observar5, hemos utilizado el operador l i k e en lugar del signo igual para establecer la busqueda (por regla general, conviene ser tolerante en las busquedas sobre bases de datos).

Tenga en cuenta que no es necesario incluir un punto y coma al final de una consulta enviada a MySQL, a diferencia de las consultas realizadas a traves del monitor de MySQL.

Ahora podemos ejecutar la consulta:


S r e s u l t = roysql .query (Sql~ery ;)

La funci6n mysql -q u e r y

()

tiene la siguiente sintaxis:

Se le pasa la consulta que sedesea ejecutar y, opcionalmente, el vinculo a la base d e datos (nuevamente, $db).Si no se especifica, la funcion utilizar6 el ultimo vinculo abierto. Si no existiese ninguno, la funcion abriria el predeterminado como si hubiera llamado a mys q l c o n n e c t ( ) . Esta funcibn devuelve i n identificador de resultados (que permite recuperar 10s resultados d e la consulta) en caso d e exit0 y f a l s e en caso d e contrario. Deberia almacenarlo (como hemos hecho en este caso en $ r e s u l t ) para poder hacer algo util.

Rccuperacih de resultados

d e consulta

Existe un conjunto de funciones para dividir 10s resultados del identificador de resultados de varias formas. El identificador de resultados es la clave para acceder a las filas devueltas por la consulta. En nuestro ejemplo, hemos utilizado dos funciones d e este tipo: mysql -numrows ( ) y m y s q l - f e t c h - a r r a y 0 .

10. Acceso a la base de datos de MySQL desde la W e b con P H P

La funci6n m y s q l n u m r o w s ( ) indica el nlimero de filas devueltas por la consulta. Deberia pas6rseio a1 identificador de resultados, de la siguiente forma:

Resulta litil saber hacerlo. Si tenemos previsto procesar o mostrar 10s resultados, sabremos cufintos hay y podemos procesarlos en un bucle:
for ($i=O; $i <$nun -results; $it+)

I
/ / procese 10s resultados

En cada iteraci6n de este bucle, llamamos a m y s q l -f e t c h-a r r a y ( ) . El bucle no se ejecutarfi si no se devuelve ninguna fila. Esta funci6n toma cada fila del conjunto de resultados y devuelve la fila como una matriz asociativa, con cada clave en forma de nombre de atributo y cada valor con su valor correspondiente en la matriz:

Dada la matriz asociativa $ r o w , podemos recorrer cada campo y mostrarlos adecuadamente, por ejemplo:
echo '<br />ISBN: ' ; echo stripslashes($row['isbn'l
);

Como se indic6 previamente, hemos llamado a s t r i p s 1a s h e s ( ) para limpiar el valor antes de mostrarlo. Existe una serie de variaciones a la hora de obtener 10s resultados desde un identificador de resultados. En lugar de utilizar una matriz asociativa, podemos recuperar 10s resultados en unamatriz enumerada con m y s q l -f e t c h-r o w ( ) , de la siguiente forma:
$row
=

mysql - fetch-row($result);

Los valores de atributo se enumerarfin en cada uno de 10s valores de matriz


$ r o w [ O ] , $ r o w [ l ] etc.

Tambi6n puede acceder a cada uno de 10s atributos mediante $ r o w - > t i t l e ,


$ r o w - > a u t h o r , etc.

Cada uno de estas opciones recupera una fila por vez. Para ello, debe especificar el nlimero de fila (desde cero a1 numero r o w s [ m s 1 1)asi como el nombre del campo. Por ejemplo:

Puede especificar el nombre del campo como una cadena (en forma de "titulo" o "1ibros.titulo")o en forma de nlimero (como e n m y s q l f e t c h-r o w ( ) ). No deberia usar m y s q l - r e s u l t ( ) con otras funciones de recupe~aci6n.

Desarrollo W e b con PHP y MySQL

Las funciones de recuperaci6n orientadas a filas resultan mucho m6s eficientes que la funci6n m y s q l -f e t c h -r o w ( ) ,por lo que en general deberia utilizar una de aqu6llas.

Desconexion de una base de datos


Puede utilizar
rnysql-close(conexi6n basededatos);

para cerrar una conexi6n debase de datos no permanente. Esta opci6n no resulta estrictamente necesaria porque se cerrar6n de todos modos cuando una secuencia de comandos finalice su ejecuci6n.

C6mo colocar nueva information en la base de datos


La inserci6n de nuevos elementos en la base de datos resulta bastante similar a la obtenci6n de elementos de la base de datos. Los pasos son pr6cticamente iguales: se establece una conexibn, se envia una consulta y se comprueban 10s resultados. En este caso, la consulta enviada serd I N S E R T en lugar de SELECT. Aunque el proceso es similar, a veces resulta util examinar un ejemplo. En la figura 10.3, se ilustra un formulario HMTL sencillo para introducir nuevos libros dentro de la base de datos. El c6digo HMTL de esta p a i n a se incluye en el listado 10.3.
Listado 10.3. newbook.htrnl. Codigo HTML de la pagina de entrada de libros
<htrnl> <head> <title>Book-0-Kama </head>

New

Book

Entry</title>

<body> <hl>Book-0-Rama - New Book Entry</hl>

l o . Acceso n In bnse d e datos de iMySQL desde la W e b corl P H P

k c h r w Edlodn Vsr Farams Herrm-ri3

Apda

Lhremdn

Id hyp i ~ o r r 1 b a n ~ ~ -. . l ' k
~p

*a I F p

J?

81
I'

Book-0-Rama - New Book


ISBN
Author Isfeve L m T~tle l~amba~nleaslled Pr~ce

$ 1 4 9

99

Figura 10.3. El personal de Book-0-Rama puede utilizar esta interfaz para la introduccion de nuevos libros en la base de datos

Los resultados d e este formulario se pasan a i n s e r t b o o k . p h p , una secuencia de comandos clue toma 10s detalles, realiza algunas opeGciones d e validaci6n e intenta escribir 10s datos dentro d e la base d e datos. El c6digo correspondiente a esta secuencia d e comandos se incluye en el listado 10.4.
Listado 10.4. insert-book.php. Esta secuencia de comandos escribe nuevos libros en la base de datos

k l k ~ E i ~ n h n Ver Fawnlor Hsrrmoenlas Apda

~ir-n

1%

~ ~ ~ ~ r ~ h c l - m r j c b c t ~ bz+rrmo ~ l ' n ; . +

-1

I ,

Book-0-Rama Book Entry Results


I book inserted into database

Figura 10.4. La secuencia de comandos se completa satisfactoriamente e indica que el libro se ha agregado a la base de datos

En la figura 10.4 se muestra el resultado cuando se inserta un libro satisfactoriamente. Si examina el codigo de i n s e r t book php, verfi que en gran parte resulta similar a la secuencia d e comandos queescribimos para recuperar datos d e la base de datos. Hemos comprobado que todos 10s campos del formulario se han rellenado y que se les ha aplicado formato correctamente para su inserci6n en la base d e datos conaddslashes ( ) :

Como el precio se ha almacenado en la base d e datos como una variable d e tip0 flotante, no queremos colocar barras en su interior. Para filtrar todos 10s caracteres extraiios que se puedan introducir en este campo numbrico, se puede llamar a la funci6n d o u b l e v a l ( ) , comentada en un capitulo anterior. Tambien se encargarfi d e filtrar 10s simbolos de moneda que pueda haber introducido el usuario en el formulario. Hemos vuelto a establecer la conexion a la base d e datos por medio de mysql p c o n n e c t ( ) ,y hemos configurado una consulta para enviarla a la base de datos. En este caso, la consulta es una instruccion I N S E R T de SQL:
$query = "insert into books values ('".$isbn."', '".$author."', $result = rnysql-queryisquery); '".$title."', '".$price."')";

Gsta se ejecuta sobre la base d e datos d e la forma habitual llamando a mysql-query ( ) . Una diferencia significativa entre utilizar I N S E R T y SELECT estB en el uso de
mysql-affected-rows(): echo mysql-affected-rows()."

*
book inserted into database.";

En la secuencia de comandos anterior, utilizamos mysql num rows ( ) para escribir consultas determinar cuBntas filas devolvia una instruccion SELECT. que cambien la base de datos como INSERT, DELETE y UPDATE, deberia utilizar en su lugarmysql a f f e c t e d rows 0 . Con esto, quedan vistos l & elementos bfisicos del uso de bases de datos MySQL desde PHP. A continuation, examinaremos brevemente algunas otras funciones titiles de las que no hemos hablado todavia.

A 1

Otras funciones dtiles P H P y MySQL


Existen algunas otras funciones de PHP y MySQL utiles, que comentaremos brevemente.

Desarrollo Web con PHP y M y S Q L

Li beracion de recursos
Si tiene problemas de memoria a1 ejecutar una secuencia de comandos, puede utilizar my s q l -f r e e-r e s u l t ( ) , cuya sintaxis es la siguiente:
boo1 rnysql-free result(resnurce r e s u l t a d o ) ;
--

Se llama con un identificador de resultados, como el siguiente:

Este c6digo libera la memoria utilizada para almacenar el resultado. Obviamente no se invoca hasta terminar de trabajar con un conjunto de resultados.

Creaci6n y elirninacion de bases de datos


Para crear una nueva base de datos MySQL desde una secuencia de comandos de PHP, puede utilizar m y s q l c r e a t e d b ( ) y para eliminar una base de datos MySQL existente, puede utilizar m y s q l d r o p d b ( ) . Estas funciones constan de las siguiekes sintaxis:
bool rnysql-create-dbistring b a s e d e d a t o s , [resource c ~ n e x i h n ~ b a s e d e d a t o s )]; bool rnysql_droppdb (string basededa tos, [resource c o n e x i h n - b a s e d e d a t o s ] ) ;

Ambas funciones toman un nombre de base de datos y una conexi6n opcional. Si no se suministra ninguna conexi6n, se abrir6 la ultima. Intentaran crear o eliminar la base de datos cuyo nombre se haya indicado. Ambas funciones devuelven t r u e si el resultado es satisfactorio y f a 1 s e en caso contrario.

Otras interfaces de base de datos y PHP


PHP admite bibliotecas para establecer conexiones a una gran cantidad debases de datos, incluidas Oracle, Microsoft SQL Server, mSQL y PostgreSQL. Por regla general, 10s principios para establecer la conexi6n y consultar cualquiera de las bases de datos son pricticamente 10s mismos. Varian 10s nombres de las funciones individuales y las distintas bases de datos tienen funcionalidades ligeramente diferentes, per0 si puede establecer una conexi6n a MySQL, no le costar6 adaptar esos conocimientos a cualquier situaci6n. Si desea utilizar una base de datos que no tenga una biblioteca especifica disponible en PHP, puede utilizar las funciones ODBC genericas. ODBC equivale a Conectividad de base de datos abierta y es un esthndar para las conexiones a bases de datos. Su funcionalidad es la m6s restrictiva de cualquier conjunto, por razones bastante obvias. Si se necesita una compatibilidad completa, no se pueden explotar funciones especiales.

10. Acceso a la base de datos de MySQL desde la W e b con PHP

Ademhs de las bibliotecas incluidas en PHP, tambidn esthn disponibles clases de abstracci6n debase de datos como Metabase o PEAR::DB, que permiten utilizar 10s mismos nombres de funci6n para cada tip0 de base de datos.

so de una interfaz de base de datos generica: PEAR DB


Vamos a examinar un breve ejemplo del uso de la capa de abstracci6n PEAR DB. Se trata de uno de 10s componentes fundamentales de PEAR y probablemente el mhs utilizado de todos. Si tiene instalado PEAR, ya deberia tener el componente DB. De lo contrario, consulte la secci6n correspondiente del apdndice A. Para permitirle comparar, vamos a ver c6mo hubidramos escrito la secuencia de comandos de resultados de busqueda utilizando DB.
Listado 10.5. results-generic.php. Recupera resultados de bllsqueda desde la base de datos MySQL y les aplica formato para su visualizacion
<html> <head> <title>Book-0-Rarna Search Results</title> </head> <body> <hl>Book-0-Rarna Search Results</hl> <?php / / Cree nornbres d e variables cortos $searchtype=$HTTP-POST-VARS['searchtype']; $s~~~c~~~~~=$HTTP-Pos [ 'searchterm' T-vAR> ] ;

if

!$searchtype I I

!$searchterm)

I
echo 'You have not entered search details.Please go back and try again.'; exit;
1

/ / configuracihn para utilizar PEAR DB require('DB.php1); $user = 'bookorarna'; $pass = 'bookorarnal23'; $host = 'localhost'; $db-name = 'books'; / / configure la cadena d e conexi6n universal o DSN

Desarrollo W e b con PHP y MySQL

/ / establezca una conexidn a la base d e datos Sdb = DB::connecr($dsn, true); / / compruebe s i funciona la conexitn if (DB::isError($db) )

I
echo Sdb->getMessage(); exit;
I

/ / realice ?a consulta $query = "select * from books where ".$searchtype." like rr . Ssearchterm. " % ' " ;

$result = Sdb->query($query); / / compruebe que el resultado es correct0 if (DB::isError($result))

t
echo $db->getMessage(); exit;

I
/ / obtenga el nhrnero de filas devuelto Snurn-results = $result->numRows( 1 ; / / rnuestre cada fila devuelta for ($i=O; $i <$nurn-results; $it+)

I
$row echo echo echo echo echo echo echo echo echo
=

$result->fetchRow(DB-FETCHMODEEASSOC); '<p><strong>'.($i+l).'. Title: ' ; htrnlspecialchars(stripslashes($row['title'])); '</strong><br />Author: ' ; stripslashes(Srow['author']); '<br />ISBN: ' ; stripslashes ($rowrlisbn' ] ) ; '<br /?Price: ' ; stripslashes($row['pricel]);
'</p>';

/ / desconecte d e la base d e datos $db->disconnect ( ) ;


?>

Vamos a examinar 10s elementos nuevos de esta secuencia de comandos. Para establecer la conexion utilizamos la linea
$db
=

DB: :connect (Sdsn, true) ;

Esta funci6n acepta una cadena de conexi6n universal con todos 10s parametros necesarios parar establecer la conexi6n a la base de datos.

10. Acceso a la base de datos de MySQL desde la W e b con PHP

Puede apreciarlo si examina el formato de la cadena de conexi6n:

El segundo partimetro de c o n n e c t ( ) determina si la conexi6n serti permanente o no. El valor t r u e la convertirti en permanente. Tras ello, comprobamos si la conexi6n fa116 con ayuda del metodo i s E r r o r ( ) y, en caso afirmativo, devolvemos un mensaje de error y salimos:

echo $db->getMessage(); exit;

Asumiendo que todo haya salido bien, establecemos una consulta y la ejecutamos de la siguiente forma:

Podemos comprobar el n6mero de filas devueltas:

Recuperamos cada fila de la siguiente forma:

El metodo generic0 fe t c h R o w ( ) permite recuperar una fila con muchos formatos diferentes. El partimetro DB FETCHMODE A S S O C le indica que queremos recuperar la fila en una matriz asociatka. Tras mostrar las filas devueltas, terminamos cerrando la conexi6n a la base de datos:

Como puede apreciar, este ejemplo generic0 resulta muy similar a la primera secuencia de comandos. Las ventajas de usar DB son que s610 necesitamos recordar un conjunto de funciones de base de datos y que el c6digo requerir6 minimos cambios si decidimos modificar el software de nuestra base de datos. Como este libro trata de MySQL, utilizaremos las bibliotecas nativas de MySQL para obtener una mayor velocidad y flexibilidad, per0 si lo desea puede utilizar el paquete DB en sus proyectos dado lo extremadamente titi1 que resulta acudir a el en determinadas ocasiones.

Lecturas adicionales
Si desea obtener m6s informaci6n sobre c6mo combinar MySQL y PHP, puede leer las secciones pertinentes de manuales sobre PHP y MySQL.

Desarrollo W e b con PHP y MySQL

Si desea obtener mas informaci6n sobre ODBC, visite


http://www.webopedia.com/TERM/O/ODBC.html

Metabase esta disponible en


http://phpclasses.upperdesign.com/browse.html/package/2O

En el siguiente capitulo, profundizaremos en el estudio de la administracih de MySQL y veremos formas de optimizar las bases de datos.

En este capitulo, vamos a examinar algunos aspectos avanzados de MySQL como 10s privilegios, la seguridad y la optimizaci6n. En concreto abordaremos 10s siguientes temas: Andlisis detallado del sistema de privilegios Protecci6n de una base de datos MySQL C6mo obtener mds informaci6n sobre la base de datos Agilizaci6n de 10s procesos por medio de indices Sugerencias de optimizaci6n Tipos diferentes de tablas Copias de seguridad y recuperaci6n

Andlisis detallado del sistema de privilegios


En un capitulo anterior vimos c6mo configurar usuarios y concederles privilegios. Para ello, utilizamos el comando GRANT. Si va a administrar una base de datos MySQL, debe entender la funci6n de este comando y su funcionamiento. El uso de la instrucci6n GRANT afecta a las tablas de una base de datos especial llamada mysql. La informaci6n sobre privilegios se almacena en cinco tablas de

11. MySQL Avanzado

esta base de datos. Por lo tanto, a1 conceder privilegios sobre bases de datos, debe tener cuidado a1 otorgar permisos de acceso a la base de datos mys q l . El comando GRANT s610 esta disponible a partir de la versidn 3.22.11 de MySQL. Si desea examinar 10s contenidos de la base de datos mysql, registrese como administrador y escriba
use mysql;

Tras hacerlo, podrA ver las tablas de la base de datos con la instrucci6n
show tables;

como de costumbre. Los resultados presentaran un aspect0 semejante a1 siguiente:

I I I 1 I I

columns priv db func host tables-priv user


-

I
I

I I I

+-----------------+

Cada una de estas tablas, a excepci6n de la tabla func, almacenan informaci6n sobre privilegios. (La tabla f u n c almacena funciones definidas por el usuario.) Tambien se conocen como tablas de permisos. Las funciones especificas de estas tablas varian per0 todas ellas tiene un mismo objetivo general: determinar lo que 10s usuarios pueden y no pueden hacer. Estas tablas contienen dos tipos de campos: 10s campos de Ambito, que-ideaifican a1 usuario, a1 host y a parte de una base de datos; y 10s campos de privilegio, que identifican las acciones que puede realizar el usuario en dicho Ambito. La tabla u s e r se utiliza para decidir si un usuario puede conectarse a1 servidor MySQL y si dispone de privilegios administrativos. Las tablas db y h o s t determinan a qud bases de datos puede acceder el usuario. La tabla t a b l e s p r i v determina qud tablas de una base de datos puede utilizar un usuario y la tabla columns -p r i v establece a qud columnas de la tabla dispone de acceso.

La tabla

de usuario

Esta tabla contiene 10s detalles de 10s privilegios globales de usuario. Determina si un usuario puede conectarse a1 servidor MySQL y si dispone de privilegios globales, es decir, de privilegios que se aplican a toda las bases de datos del sistema. Para ver la estructura de esta tabla, puede utilizar la instrucci6n des c r i b e u s e r ; . En la tabla 11 .I se recoge el esquema de la tabla us e r .

Desarrollo Web COY/ P H P y M y S Q L

Tabla 11.1. Esquema de la tabla user de la base de datos mysql


-

Campo Host User Password

Tipo char(60) char(l6) char(l6)

Reload-priv
S hutdown-priv

enum('N1,'Y') enum('N','Y1)

Cada fila d e esta tabla se corresponde con un conjunto de privilegios para un usuario procedente de un host y registrado con la contraseiia P a s sword. Se trata d e 10s campos de timbito d e esta tabla, ya que describen el dmbito del resto de los campos, llamados campos d e privilegio. Los privilegios enumerados en esta tabla (y en las siguientes) se corresponden con 10s concedidos por medio de la instrucci6n GRANT en un capitulo anterior. Por ejemplo, select p r i v se corresyonde con el privilegio necesario para ejecutar un comando s ELECT Si un usuario tiene un privilegio concreto, el valor d e dicha columna ser6 Y. Por el contrario, si a un usuario no se le ha concedido dicho privilegio, el valor serfi N. Los privilegios listados en la tabla d e usuarios son globales, lo que quiere decir que se aplican a todas las bases de datos del sistema (incluida la base de datosmysql). Los administradores tendr6n varios valores Y per0 la mayoria de 10s usuarios deberian tener todos N. Los usuarios normales deberian disponer de derechos para acceder a determinadas bases d e dates, per0 no a todas las tablas.

Las tahlas dh y host


La mayor parte d e 10s privilegios d e 10s usuarios se almacenan en las tablas d b y
host.

La tabla db determina qu6 usuarios pueden acceder, a qu6 bases de datos y desde que hosts. Los privilegios listados en esta tabla se aplican a cualquier base d e datos designada en una fila dada. La tabla h o s t cornplementa a la tabla db. Si un usuario va a conectarse a una base de datos desde varios hosts, no se enumerari ningun host para dicho usuario en la tabla. En su lugar, se incluir6 un conjunto d e entradas en la tabla h o s t para especificar 10s privilegios correspondientes a cada combinaci6n de usuario y host. En las tablas 11.2 y 11.3se recogen 10s esquemas d e estas dos tablas, respectivamente.
Tabla 11.2. Esquema de la tabla db de la base de datos mysql
. 7

--

.-

.-

. . ..

- .-

Tipo Host Db User Select-priv Insert-priv Update-priv Delete-priv Create-priv Drop-priv Grant-priv

Tabla 11.3. Esquema de la tabla host de la base de datos mysql

Campo Host Db

Tipo

Desnrrollo Web con PUP y MySQL


-

Campo Select-priv Insert-priv Update-priv Delete-pr~v Create-priv Drop-priv Grant-priv References-priv Index-priv Alter-priv

Tipo enum('N1,'Y') enum('N','Y') enum('Nt,'Y') enum('Nt,'Y') enum('N','Y1) enum('N','Yt) enum('N','Y1) enum('N','Y1) enum('N','Y1) enum ('N','Y')

Estas dos tablas se u t i l i z a n para almacenar privilegios d e n i v e l d e tabla y d e n i v e l de columna, respectivamente. Funcionan como l a tabla db, con la diferencia de que suministran privilegios para las tablas d e u n a base d e datos dada y p a r a las columnas d e u n a tabla concreta, respectivamente. Estas tablas constan d e u n a estructura ligeramente diferente a las tablas u s e r , db y h o s t . E n l a tabla 11.4 y 11.5 se incluyen 10s esquemas de las tablas t a b l e s -p r i v y columns-priv, respectivamente.

Tabla 11.4. ~ s ~ u e h deala tabla tables-priv de la base de datos mysql

Host Db User Table-name Grantor Timestamp Table-priv Column-priv char(77) timestamp(l4) set('Selectl, 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter') set ('Select', 'Insert', 'Update', 'References')

11. MySQL Avanzado

Tabla 11.5. Esquema de la tabla columns-priv de la base de datos mysql

Campo Host Db User Table-name Column-name Timestamp Column-priv char(60) char(64) char(l6) char(64) char(64) timestamp(l4) set('Selectl, 'Insert', 'Update', 'References')

La columna Grantor de la tabla tables p r i v almacena el usuario que concedi6 el privilegio a este usuario. La columna Times tarnp d e ambas tablas almacena la fecha y la hora en la que se concedi6 el privilegio.

Control de acceso: icomo utiliza MvSQL las tablas cle concesi6n de privilegios?
MySQL utiliza las tablas grant para determinar qu6 puede hacer un usuario en un proceso d e dos fases:
1. Verificaci6n de conexi6n. En esta fase, MySQL comprueba si disponemos de permiso para establecer una conexi6n en funci6n de la informaci6n de la tabla d e usuario, como se indic6 anteriormente. Para realizar esta operaci6n, se utiliza el nombre d e usuario, el nombre d e host y la contraseiia. Si se deja en blanco un nombre d e usuario, equivaldrfi a todos 10s usuarios. Los nombres d e host se pueden especificar mediante el uso d e u n carficter comodin ( G ) . Se puede utilizar en forma de campo completo (es decir, que '1; equivalga a todos 10s hosts) o como parte d e un nombre d e host, por ejemplo, B tangledweb. corn.au, que equivale a todos 10s hosts que terminen en tangledweb. corn.au . Si se deja en blanco el campo de contraseiia, no s e r i necesario utilizar una contraseiia. Sin embargo, no conviene utilizar usuarios en blanco, comodines en hosts ni usuarios sin contrasefias por cuestiones d e seguridad.

2. Verificaci6n de la solicitud. Cada vez que se introduce una solicitud, tras establecer una conexi6n, MySQL comprueba si disponemos del nivel necesario de privilegios para realizar dicha petici6n. En primer lugar, el sistema comprueba 10s privilegios globales (en la tabla u s e r ) y si no resultan suficientes, comprueba las tablas db y host. Si no se dispone d e 10s privilegios

Desarrollo Web con P H P y MySQL

necesarios en dicho nivel, MySQL examinard la tabla t a b l e s -p r i v y, si no son bastan, examinard la tabla colums-p r i v .

Actualization de privilegios: icuando surten efecto


10s cambios?
El servidor MySQL lee automdticamente las tablas de privilegios a1 iniciarse y a1 aplicar las instrucciones GRANT y REVOKE. Sin embargo, ahora que ya sabemos d6nde y c6mo se almacenan dichos privilegios, podemos alterarlos manualmente. A1 actualizarlos manualmente, el servidor MySQL no notarg que han cambiado. Es necesario indicarle a1 servidor que se ha producido un cambio y existen tres formas de hacerlo. Puede escribir
FLUSH P R I V I L E G E S ;

en la linea de comandos de MySQL (necesitard haber iniciado la sesi6n como administrador). gsta es la forma mds habitual de actualizar 10s privilegios. Tambikn puede ejecutar
rnysqladrnin f l u s h - p r i v i l e g e s

rnysqladrnin

reload

desde el sistema operativo. Tras ello, se comprobardn 10s privilegios globales cuando un usuario se conecte, 10s privilegios de base de datos en la siguiente instrucci6n de uso y 10s privilegios de tabla y columna en la 5igui;nte petici6n de usuario.

Como proteger la bases de datos MySQL


La seguridad es importante, en especial a1 establecer la conexi6n entre la base de datos MySQL y el sitio Web. En esta seccibn, vamos a repasar las precauciones que se deberian adoptar para proteger una base de datos.

MySQL desde el punto de vista del sistema


operativo
Noes aconsejable ejecutar el servidor MySQL (mysqld) como usuario raiz si estd utilizando un sistema operativo de tip0 UNIX ya que permitiria a un usuario de MySQL con un conjunto completo de privilegios leery escribir archivos en cualquier

11. MySQL Avanzado

parte del sistema operativo. Es importante tener en cuenta esta circunstancia ya que se suele pasar ficilmente por alto y ya ha sido utilizada para piratear sitios Web basados en Apache. (Afortunadamente, se trataba de piratas buenos y lo unico que hicieron fue reforzar la seguridad). Es aconsejable configurar un usuario de MySQL de manera especifica para ejecutar mysqld. AdemBs puede configurar 10s directorios (donde se almacenan 10s datos fisicamente) para limitar el acceso a dicho usuario. En muchas instalaciones, el servidor se configura para ejecutarse como userid mysql, en el grupo mysql. Tambien deberia colocar su servidor MySQL tras un cortafuegos. De esta forma podrB evitar conexiones procedentes de equipos no autorizados. Compruebe si puede conectarse desde el exterior a su servidor a traves del puerto numero 3306; se trata del puerto predeterminado en el que se ejecuta MySQL y deberia estar cerrado en el cortafuegos.

Contrasenas
Asegurese de que todos 10s usuarios tienen contrasefias (en especial el usuario raiz) y que estBn bien elegidas y se cambian peribdicamente, como en el caso de las contrasefias de sistemas operativos. Recuerde que no conviene utilizar contrasefias que contengan palabras o estBn formadas por palabras de un diccionario. Lo mejor es utilizar combinaciones de letras y numeros. Si va a almacenar contrasefias en archivos de secuencias de comandos, asegurese de que s610 el usuario cuya contrasefia este almacenada puede verlos. Los dos lugares principales en 10s puede suceder son:
1. En la secuencia de comandos m y s q l . s e r v e r , es probable que necesite utilizar la contrasefia raiz de UNIX. Si asi fuera, asegurese de que s610 el usuario raiz puede leer esta secuencia de comandos. 2. En las secuencias decomandos de PHP que se utilizan para establecer una conexi6n a la base de datos, necesitar6 almacenar la contrasefia para dicho usuario. Esta operaci6n se puede realizar de forma segura colocando el nombre de usuario y la contrasefia en un archivo llamado, por ejemplo, d b c o n n e c t . php, que puede situar donde lo necesite. Esta secuencia de comandos se puede almacenar fuera de Brbol de documentos Web y configurarla para que s610 resulte accesible a1 usuario adecuado. Recuerde que si coloca estos detalles en un archivo i n c o en cualquier otra extensi6n de archivo en el Brbol Web, tend14 que asegurese de comprobar que el servidor Web sabe que dichos archivos deben interpretarse como PHP, para que 10s detalles no puedan verse en un navegador Web. No almacene contrasefias en forma de texto dentro de la base de datos. Las contrasefias de MySQL no se almacenan de esa forma, per0 resulta habitual en aplicaciones Web en las que se desea almacenar 10s nombres de usuario y contrasefias de 10s miembros del sitio. Puede cifrar las contrasefias utilizando las funciones PASSWORD ( ) o MD5 de MySQL. Recuerde que si inserta una contrasefia con el comando INSERT utilizando una de estas funciones, a1

Desarrollo W e b con PHP y MySQL

ejecutar una selecci6n (para registrar un usuario), tendrd que utilizar la misma funci6n de nuevo para comprobar la contraseiia utilizada por el usuario. En la parte dedicada a la implementaci6n de proyectos utilizaremos esta funcionalidad.

Privilegios de usuario
Asegurese de tener claro el sistema de privilegios de MySQL y las consecuencias de la concesi6n de 10s distintos privilegios. No conceda mas privilegios a un usuario de 10s necesarios. Para verificarlos, examine las tablas de concesidn de privilegios. En concreto, no conceda 10s privilegios PROCESS, FILE, SHUTDOWN y RELOAD a ningun usuario que no sea un administrador a menos que resulte completamente necesario. El privilegio PROCESS se puede utilizar para ver qu6 estdn haciendo o escribiendo otros usuarios, incluidas sus contrasefias. El privilegio F I L E se puede utilizar para leer y escribir archivos desde y hasta el sistema operativo (incluyendo, por ejemplo, el archivo / et c/pas sword en un sistema UNIX). El privilegio GRANT deberia concederse con precauci6n ya que permite a 10s usuarios compartir sus privilegios con otros usuarios. Asegurese de que a1 configurar 10s usuarios, s61o les concede acceso desde 10s hosts que utilizan para conectarse. El usuario j ane @localhos t es correct0 per0 el usuario j ane es bastante comun y podria registrarse desde cualquier lugar (y puede que no se trate de la persona que esta pensando). Evite utilizar comodines en 10s nombres de host por razones similares. Puede'aumentar mds la seguridad utilizando direcciones IP en lugar de nombres de dominio en la tabla host.Esta medida evita errores o intrusos en su DNS. Para ello, inicie el demonio de MySQL con la opcidn -s kip-name-resolve,que exige que todos 10s valores de columna de host Sean una direcci6n IP o un host local. Como alternativa puede iniciar mysqld con la opci6n -secure. Esta opci6n comprueba las IP resueltas para determinar si se corresponden con 10s nombres de host suministrados. (Esta opcion s61o estd activada de manera predeterminada desde la versi6n 3.22 en adelante). No deberia permitir que 10s usuarios no administrativos dispongan de acceso a1 programa mysqladmin en el servidor Web. Este programa se ejecuta desde la linea de comandos por lo que su acceso se convierte en una aspect0 relacionado con 10s privilegios del sistema operativo.

Aspectos relacionados con la Web


A 1 conectar la base de datos MySQL a la Web, surgen una serie de temas de seguridad especiales. Conviene, en primer lugar, configurar un usuario especial para las operaciones relacionadas con las conexiones Web. Puede concederle 10s privilegios minimos necesario excluyendo, DROP, ALTER o CREATE. Puede concederle el privilegio SELECT so10 sobre las tablas de catdlogos y el privilegio I N S E R T sobre las tablas de pedidos.

Se trata de un nuevo ejemplo de la aplicaci6n del principio de concesicin de la menor cantidad posible de privilegios.
_ _ C I C . _ _ -

- .

Advertencia
En el ultimo capitulo hablamos del uso de las funciones a d d s l a s h e s ( ) y s t r i p s l a s h e s ( ) para eliminar caracteres problematicos en cadenas. Es importante no olvidarse de aplicar estas funciones y de limpiar 10s datos antes de enviar nada a MySQL. Como recordara, utilizamos la funciondoubleval ( ) para comprobarque losdatos numericos eran numericos. Resulta habitual pasar por alto esta comprobacion.
Deberia comprobar siempre todos 10s datos procedentes de un usuario. Aunque el formulario HTML est6 formado de cuadros de selecci6n y botones de option, alguien podria haber modificado el URL para piratear la secuencia de comandos. Tambien conviene comprobar el tamafio d e 10s datos entrantes. Si 10s usuarios escriben contrasefias o datos confidenciales para su almacenamiento en la base de datos, recuerde que se transmitirhn como texto sin procesar desde el navegador a1 servidor a menos que utilice SSL (del ingl6s Secure Sockets Layer, Nivel d e sockets seguro). En una secci6n posterior se ampliar5 este tema.

Por el momento, hemos utilisado SHOW y DESCRIBE para determinar las tablas que incluye la base d e datos y las columnas de las tablas. A continuaci6n, vamos a analizar otras formas d e utilizar estas instrucciones asi como la instrucci6n EXPLAIN para obtener m5s informaci6n sobre c6mo se realiza una operaci6n d e selection.

C6mo obtener inforrnacibn con SHOW


Antes hemos utilizado

para obtener una lista de tablas d e la base de datos La instruccion

muestra una lista d e bases d e datos disponibles.

D e s n r r o l l o W e b coil PHP y MySQL

A continuaci6n puede utilizar la instrucci6n SHOW TABLES para ver la lista de tablas d e una d e esas bases d e datos:

Si se aplica la instrucci6n SHOW TABLES sin especificar una base d e datos, se utilizari la base d e datos actual d e manera predeterminada. Si sabe cuiles son las tablas, puede obtener una lista d e las columnas:

Si no activa el parimetro correspondiente a la base d e datos, la instrucci6n SHOb7 COLUMNS utilizari la base d e datos actual. Tambien puede utilizar la notacicin tabla.columna:

Existe una variaci6n d e la instrucci6n SHOb7 para ver 10s privilegios que tiene un usuario. Por ejemplo, si ejecutamos la siguiente instrucci6n, obtendremos el resultad o ilustrado en la figura 11.1.

Las instrucciones GRANT que se muestran no son necesariamente las que se ejecutaron para conceder privilegios a un usuario dado, sin0 mAs bien instrucciones d e resumen equivalentes que generan el nivel actual d e privilegios del usuario.
*.......................................................................................... ; Grants f o r bookorana8%
+ +

+.. .......................................................................................... :GRAMT U S A G E O H ' : TO ' b o o k o r a m a ' @ ' % ' I D E N T I F I E D B Y PASSia;DRD ' 6 a 8 7 b 6 8 1 0 c b 0 7 3 d e ' i G R A H T S E L E C T , I R S E R T , U P D A T E , D E L E T E , C R E A T E , D R O P , I N D E X , A L T E R OH b o o k s . ' TO ' b o o k o r a r a ' P ' % '

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

Figura 11.1: El rkultado de la instruccion SHOW GRANTS


-

Nota
La instruccion SHOW GRANTS se agrego en la version 3.23.4 de MySQL. Si su version es inferior no funcionara. Existen muchas variantes d e la instrucci6n SHOW. En la tabla 11.6 se recoge un resumen d e todas ellas.
Tabla 11.6. Sintaxis de la instruccion SHOW
r.- ~

Variante
SHOW DATABASES [LIKE base-de-datos]

Descripci6n Enumera todas las bases de datos. Puede sustituir el parametro base-de-datos por sus nombres.

Variante
SHOW TABLES [FROM base-deda tos] [LIKE tabla]

Descripcibn Enumera las tablas de la base de datos utilizada actualmente o de la base de datos llamada base-de-datos si se especifica. Puede sustituir tabla por el nombre de tablas.

SHOW COLUMNS FROM Enurnera todas las columnas de una tabla de la base de tabla [FROM base-de- datos actualmente en uso o de una base de datos especida tos] [LIKE colunula] ficada. Puede sustituir colurnna por nombres de colurnna. Puede utilizar SHOW FIELDS en lugar de SHOW COLUMNS. SHOW INDEX FROM tabla Muestra 10s detalles de todos 10s indices de una tabla dada [FROM base-de-da tos] de la base de datos actualmente en uso o de otra base de datos llamada base-de-datos si se especifica. Tambien puede utilizar SHOW KEYS en su lugar. SHOW STATUS [LIKE es tado-elemento]

Devuelve inforrnacion sobre una serie de elementos del sistema, como el numero de subprocesos que se estan ejecutando. La clausula LIKE se utiliza para buscar coincidencias en 10s nombres de estos elementos; por ejemplo, '~hread%'recupera 10s elementos 'Threads-cached ' , 'Threads-connected' Y ' T h r e a d ~ ~ r u n n i n g ' . Muestra 10s nombres y 10s valores de las variables del sistema MySQL, como el numero de version. La clausula LIKE se puede utilizar para buscar correspondencias de forma similar a SHOW STATUS. Muestra todos 10s procesos que se estan ejecutando en el sistema. L a mayor parte d e 10s usuarios veran sus subprocesos per0 si disponen del privilegio PROCESS tambien veran 10s procesos de todos 10s demas usuarios, incluigas sus contrasetias si aparecen en las consultas. Las consultas se dividen en secciones de 100 caracteres de manera predeterminada. La palabra clave FULL muestra las consultas completas. Muestra inforrnacion sobre cada una de las tablas de la base de datos actualmente en uso o de la base de datos llarnada base-de-datos si se especifica, con la posibilidad de buscar coincidencias con cornodines. Entre la inforrnacion se incluye el tip0 de tabla y cuando se actualize por ultima vez. Muestra la instruccion GRANT requerida para recuperar el nivel actual de privilegio asociado al usuario.

SHOW VARIABLES [LIKE nombre-de-variabl el

SHOW [FULL] PROCESSLIST

SHOW TABLE STATUS [FROM base-de-da tos] [LIKE base-de-da tos]

SHOW GRANTS FOR usudrio

Como alternativa a la instrucci6n SHOW COLUMNS, se puede utilizar la instrucci6n D E S C R I B E , que es similar a la instrucci6n D E S C R I B E de Oracle (otro RDBMS).

Desarrollo W e b con PHP y MySQL

Su sintaxis bdsica es
DESCRIBE tabla [columna];

Esta instrucci6n devolverd informacidn sobre todas las columnas de la tabla o sobre una columna dada. Puede utilizar comodines en el nombre de la columna.

Compresion del funcionamiento de las consultas con EXPLAIN


La instrucci6n EXPLAIN se puede utilizar de dos formas. En primer lugar, puede utilizar
EXPLAIN
tabla;

El resultado de esta instruccion es bastante similar a1 devuelto por las instruccionesDESCRIBE tablaoSHOW COLUMNS FROM t a b l a . La segunda forma de utilizar EXPLAIN es mucho mds interesante ya que permite ver c6mo evalua MySQL una consulta SELECT. Para utilizarla de esta forma, basta con poner la palabra e x p l a i n delante de una instrucci6n SELECT. Puede utilizar la instrucci6n EXPLAIN cuando est6 intentando probar una consulta compleja y el resultado no es el esperado o si tarda mds de lo esperado en completarse. Si estd escribiendo una consulta compleja, puede probarla antes ejecutando el comando EXPLAIN. Con el resultado obtenido, puede modificar la consulta para optimizarla si resultara necesario. Se trata tambi6n de una prdctica herramienta de aprendizaje. Por ejemplo, intente ejecutar la siguiente consulta sobre la base de datos Book-ORama. El resultado se rec-oge an la figura 11.2.
explain select customers.name from customers, orders, order items, books where customers.customerid = orders.customerid and orders.orderid = order items.orderid and order-items.isbn = books.isbn and books.title like '%Java%';
+ .............+........+...............+.........
t.

: type t .............+........ : orders I ALL 1 order-items I ref : c u s t o m e r s I ALL


I
table

........+..................+......+.............
key-len

+
+

+...............+.........+.........+..................+......+.............

possible-keys

key

ref

:rows 1 4

Extra

1
I I

+ ............. + ........+...............+.........

books

eq-ref

PRIMARY PRIMARY PRIMARY PRIMARY

I I

NULL PRIMARY ) NULL I PRIMARY

,
1

+.........+..................+......+.............

NULL I 4 j NULL I 13 1

NULL orders.orderid NULL order_items.isbn

1 1 3 1

:
;

Using index where used I where used j

Figura 11.2. El resultado de la instruccion EXPLAIN

El resultado puede parecer confuso a1 principio per0 resulta muy util. Vamos a examinar las columnas de esta tabla por separado.

La primera columna, t a b l e , enumera simplemente las tablas utilizadas para responder a la consulta. Cada fila del resultado ofrece informacidn sobre c6mo se ha utilizado dicha tabla en la consulta. En este caso, las tablas utilizadas son o r d e r s ,
o r d e r items, customers y books. La columna t y p e explica como se est6 utilizando la tabla en las combinaciones de

la consulta. En la tabla 11.7 se recogen 10s distintos valores que puede tener esta colurnna. Estos valores se enumeran del m6s ra'pido a1 ma's lento en terminos d e ejecucidn d e la consulta y proporciona una idea d e la cantidad d e filas que es necesario leer d e cada tabla para ejecutar una consulta.
Tabla 11.7. Posibles tipos de combinaciones mostradas por EXPLAIN
1
- -

Tipo

-7

Descripcibn La tabla se lee una sola vez. Esto ocurre cuando la tabla consta d e una sola fila. El tip0 s y s t e m s e utiliza cuando se trata de una tabla del sistema y el tipo c o n s t en el resto de 10s casos. Para cada conjunto de filas del resto de tablas de la combinacion, leemos una fila de esta tabla. Este tipo se utiliza cuando la combinacion usa todas las partes del indice d e la tabla y el indice es exclusivo o es la clave principal. Para cada conjunto de filas del resto d e tablas d e la combinacion, leemos un conjunto de filas de esta tabla que coinciden en su totalidad. Este tip0 se utiliza cuando la combinacion no puede seleccionar una unica fila en funcion de la condicion de combinacion, es decir, si solo se utiliza parte d e la clave en la combinacion o si no es exclusiva o una clavebrincipal Para cada conjunto completo d e filas del resto de las tablas de la combinacion, se lee un conjunto de filas de esta tabla , incluidas en un rango dado. Se examina el indice completo Se examinan todas las filas de la tabla.

const Osystem

eq-ref

ref

range

index
ALL

En el ejemplo anterior, puede ver que una d e las tablas se combina con e q r e f ( b o o k s ) ,que otra utiliza el tip0 r e f ( o r d e r i tems 1 y que las otras dos ( o r d e r s y c u s t o m e r s ) se combinan con ALL; es d e z r , examinando todas las filas d e la tablas. La columna rows confirina estas combinaciones: lista aproximadamente el numero de filas d e cada tabla que deben examinarse para realizar la combinacion. Si multiplica estos valores, obtendrh el numero total d e H a s que se examinan a1 llevar a cabo una consulta. Estos numeros se multiplican porque una combinaci6n es como el product0 d e las filas d e diferentes tablas (si desea obtener m6s detalles a1

Desavrollo W e b con P H P y MySQL

respecto, consulte un capitulo anterior). Recuerde que se trata del n6mero de filas examinado, no el numero d e filas devuelto y es una estimaci6n. MySQL no puede saber el n6mero exacto sin llevar a cabo la consulta. Obviamente, cuanto m6s pequel'io sea este numero mejor. En estos momentos el conjunto d e datos d e nuestra base d e datos resulta insignificante, per0 cuando empiece a crecer, el tiempo d e ejecuci6n se disparard. Volveremos sobre este tema en un instante. La columna p o s s i b l e k e y s recoge las claves que MySQL podria utilizar para combinar la tabla. En estecaso, se trata d e las claves principales. La columna k e y es la clave desde la que se utiliza la tabla MySQL o N U L L si no se ha utilizado ninguna clave. Como observari, aunque las tablas o r d e r s y c u s t o m e r s incluyen claves principales, no se utilizan en esta consulta. Veremos c6mo resolver este problema en un instante. La columna k e y l e n indica la longitud de la clave utilizada. Puede utilizarla para determinar si s610 se est6 utilizando parte de una clave, lo cual resulta pertinente cuando s e tienen claves compuestas d e varias columnas. En este caso, se utilizan las claves completas alli donde se utilizan claves ( o r d e r i t e m s y b o o k s ) . La columna r e f muestra las columnas utilizadas con la claveal seleccionar filas d e la tabla. Por ultimo, la columna E x t r a indica cualquier otra informaci6n sobre c6mo se establece la combinaci6n. En la tabla 11.8 se recogen 10s valores posibles que pueden aparecer en esta columna.
Tabla 11.8. Los valores posibles de la colurnna devueltos por la instruccion EXPLAIN
r=.

Valor

~ -. Significado

--.

--

Not exists Range checked for each record Using filesort Using index Using temporary WHERE used

La~onsulta se ha optirnizado para utilizar LEFT

JOIN.

lntenta buscar el rnejor indice, si existiese, para cada fila del conjunto de filas del resto de las tablas de la cornbinacion. Seran necesarias dos barridos para ordenar 10s datos. (Por lo tanto, la operacion resultara el doble de larga). Toda la inforrnacion de la tabla procede del indice, es decir, no se examinan las filas. Se utiliza una clausula WHERE para seleccionar las filas.

Existen varias formas d e solucionar 10s problemas descubiertos por E X P L A I N . En primer lugar, compruebe 10s tipos de columnas y aseg6rese de que son iguales. En concreto, fijese en el ancho de las columnas. Los ind.ices no se pueden utilizar para comparar columnas si tienen diferentes anchos. Para resolver este problema, cambie 10s tipos de columna de forma que coincidan o integrelos en su diseiio desde el principio.

11. MySQL Avanzado

En segundo lugar, puede pedirle a1 optimizador de combinaciones que examine las distribuciones de clave y que optimice las combinaciones de forma miis eficaz por medio de la utilidad my i s amchk. Para invocarla, escriba
rnyisarnchk -analyze

ruta-a-1

a-base-de-da

tos-mysql/tabla

Puede comprobar varias tablas si las incluye todjls en la linea de comandos o si utiliza
rnyisarnchk -analyze

ruts-a-la-base-de-da t o s - ~ m y s q l / *. M Y I

Puede comprobar todas las tablas de todas las bases de datos ejecutando la siguiente linea, lo que generarii el resultado ilustrado en la figura 11.3:
rnyisamchk analyze

r u ta-al-la

directorio-de-da

tos-mysql

/*,I*

.>lYI

.............+........+...............+.........+.........
table

I
+

.............+........+...............+.........+.........+.....................+......+.........................
books arder-ltems arders c~stamsrs

type

I I I I

I
I

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

I
t

+ I NULL 1 NULL ALL I PRIMARY 4 1 where used NULL lndex I PRIMARY 5 1 where used; Uslng index I 1 7 1 NULL I PRIMARY eq-ref I PRIMARY 4 1 ordsr_ltem~.~rderld I PRIMARY 1 eq-ref PRIMARY 4 1 0rders.customerld I PAIMARY 1 ........+...............+.........+.........+.....................+......+......................... +

possible_keys

key

: : : :

key-len

........ .............+......+......................... ref ________________: r a w s Extra

: : :
:

Figura 11.3. Resultado devuelto por EXPLAIN tras ejecutar myisamchk

Como observar6, la forma en la que se evalua la consulta ha variado bastante. Ahora s610 utilizamos todas las filas de una de las tablas (books). En concreto, utilizamos e q r e f para dos de las tablas e i n d e x para las otras. MySQL tambien utiliza ahora 1 ; clave completa para o r d e r -i t e m s (17 caracteres en lugar de 10s 4 que utilizaba antes). Tambien ha aumentado el numero de filas utilizado, lo que probablemente se debe a que la base de datos incluye pocos datos. Recuerde que el numero de filas indicado no es miis que una estimacidn. Pu'ede realizar la consulta y comprobar si coinciden. Si sugiere utilizar una combinaci6n 10s ntimeros varian mucho, el manual de ' M ~ S Q L directa y enumerar las tablas en la cliiusula FROM en orden diferente. En tercer lugar, podemos considerar la posibilidad de agregar un nuevo indice a la tabla, si la consulta es a) lenta y b) comun. Si se trata de una consulta especial que es probable que no vuelva a utilizar, no merecerii la pena el esfuerzo ya que ralentizarii otros procesos. En la siguiente secci6n veremos c6mo agilizar las consultas.

Como agilizar consultas con indices


Si se encuentra en una situaci6n como la descrita anteriormente, en la que la columna p o s s i b l e k e y s devuelta por una instrucci6n EXPLAIN contiene valores NULL,podria mejorar su rendimiento si agrega un indice a la tabla en cuesti6n. Si la columna que estd utilizando en la c l i i u s u l a w resulta ~ ~ ~ ~ id6nea para su indexacibn,

Desarrollo Web con P H P y MySQL

puede crear un nuevo indice para ella con ayuda de la i n s t r u c c i 6 n ~ TABLE ~ ~ ~ de ~ la siguiente forma:
ALTER TABLE tabla ADD INDEX ( c o l u r n n a );

Trucos de optimizaci6n general


Ademis de 10s trucos vistos antes para la optimizaci6n de consultas, existen otros que permiten incrementar el rendimiento de las bases de datos MySQL.

Optimizacion del diseno


Es aconsejable que todos 10s elementos de la base de datos tengan el menor tamaiio posible. Para ello, se debe minimizar la redundancia en la fase de diseiio. Tambikn se puede lograr el mismo objetivo asignando 10s tipos de datos mis pequeiios a las columnas. Tambikn deberia reducir a1 minimo 10s valores NULL y seleccionar una clave principal que sea lo m6s corta posible. Evite el uso de columnas de longitud variable siempre que pueda (como VARCHAR, TEXT Y BLOB). Si sus tablas tienen campos de longitud fija, resultarin m6s ripidas de utilizar aunque absorban un poco m i s de espacio.

Permisos
Ademis de aplicar las sugerencias propuestas en la secci6n dedicada a EXPLAIN, puede mejorar la velocidad delas consultas simplificando 10s permisos. Ya indicamos anteriormente la forma en la que se comprueban las consultas con el sistema de permisos antes de su ejecuci6n. Cuanto m6s sencillo resulte este proceso, mis ripido se ejecutard la consulta.

Optimizacicin de tablas
Si lleva utilizando una tabla durante un period0 largo de tiempo, 10s datos pueden fragmentarse a1 procesar las actualizaciones y las eliminaciones. Como consecuencia, el proceso de busqueda puede alargarse. Para solucionar este problema puede utilizar la instrucci6n
O P T l M I Z E T A B L E nombre-de-tabla;

o escribir
myisarnchk
-r

table

en la linea de comandos.

11. MySQL Avanzado

Tambikn puede recurrir a la utilidadmyisamch k para ordenar un indice de tabla y 10s datos en funci6n de dicho indice, de la siguiente forma:
myisamchk sort-index sort-records=l r u t a - a 1 - l a - d i r e c t o r i o - d e - d a t o s -m y s q l / * / * . M Y I

Uso de indices
Utilice indices siempre que lo necesite para aumentar la velocidad de las consultas. Intente que resulten sencillos y no Cree indices que sus consultas no vayan a utilizar. Para comprobar 10s indices que se est6n utilizando ejecute la instrucci6n EXPLAIN como se indic6 anteriormente.

Uso de valores predeterminados


Siempre que le resulte posible, utilice valores predeterminados e inserte unicamente 10s datos si difieren de 10s predeterminados. De esta forma, se reducir6 el tiempo que tarda la instrucci6n I N S E R T en ejecutarse.

Uso de conexione permanentes


Este consejo resulta especialmente de aplicaci6n para las bases de datos Web. Nuestra intenci6n aqui es recod6rselo ya que se coment6 en una secci6n anterior

Otras suplerencias
Existen muchos otros trucos que puede aplicar para mejorar el rendimiento en situaciones concretas y paEa rezolver necesidades particulares. En el sitio Web de MySQL encontrar6 una gran cantidad de ellos. Dirijase a

Tipos diferentes de tabla


Antes de terminar con el estudio de MySQL, es necesario analizar 10s distintos tipos de tablas. Para seleccionar el tip0 de tabla a1 crearla utilice
CREATE TABLE t a b l a T Y P E = t l p o

. . ..

Los posibles tipos de tabla son


MY I SAM. Cste es el tip0 predeterminado y el que hemos estado utilizando hasta que equivale en inglks a Mktodo de acceso secuencial ahora. Se basa en I SAM,

indexado, un mktodo estAndar para almacenar 10s registros y 10s archivos.

Desarrollo W e b con PHP y MySQL


1S A M . Descrito arriba.
HEAP. Las tablas de este tipo se almacenan en memoria y sus indices se cifran. Como resultado las tablas HEAP son extremadamente rfipidas per0 presentan el inconveniente de que si tiene lugar un fa110 en el sistema, 10s datos se perderfin. Las tablas HEAP resultan ideales para almacenar datos temporales. Es aconsejable especificar el numero mfiximo de filas en la instrucci6n CREATE TABLE o las tablas pueden absorber toda la memoria. Por ultimo, las tablas HEAP no pueden incluir columnas de tipo BLOB, TEXT o AUTO INCREMENT. BDB. Estas tablas garantizan la seguridad de las transacciones, es decir, incluyen las funciones COMMIT y ROLLBACK. Son mfis lentas que las tablas MyISAM, per0 proporcionan todas las ventajas del uso de transacciones. Estas tablas se basan en Berkeley DB.

InnoBD. Estas tablas tambien garantizan la seguridad de las transacciones y se les aplican 10s mismos comentarios de las tabas BDB. Estos tipos de tablas pueden resultar utiles cuando se necesita una mayor velocidad o garantizar la seguridad de las transacciones. Si desea utilizar 10s tipos BDB o InnoDB, deberia seleccionar el tip0 binario MySQL-Max que se incluye en la distribuci6n de MySQL, en lugar del tip0 binario MySQL normal.

Carga de atos desde un archivo


Una funci6n util de MySQL de la que todavia no hemos hablado es la instrucci6n
LOAD DATA INFILE.

Esta instruccih se puede utilizar para cargar datos en la tabla procedentes de un archivo. Se ejecuta de forma muy riipida. Se trata de un comando flexible con muchas opciones, per0 se suele utilizar de la siguiente forma:
LOAD DATA I N F I L E "newbooks.txt" I N T O T A B L E b o o k s ;

Esta instrucci6n lee las filas del archivo newbooks.txt dentro de la tabla books. De manera predeterminada, 10s campos de datos del archivo deben separarse mediante tabuladores y encerrarse en comillas simples y cada fila debe separarse mediante un carficter de nueva linea (\n). Los caracteres especiales deben marcarse con la barra inclinada (\). Todas estas caracteristicas se puede configurar mediante varias opciones de la instrucci6n LOAD (si desea obtener mfis detalles consulte el manual de MySQL). Para usar la instrucci6n LOAD DATA INFI LE, es necesario disponer del privilegio F I L E comentado anteriormente.

11. MySQL Avanzado

Como realizar una copia de seguridad de la base de datos MySQL


MySQL incorpora dos formas de realizar una copia de seguridad. La primera consiste en bloquear las tablas mientras se copian 10s archivos fisicos, utilizando el comando LOCK TABLES. Su sintaxis es la siguiente.
LOCK TABLES tabl a tipo-de-bl oqueo
[

tabl a tipo-de-bl oqueo . . . ]

El parametro tabla deberia sustituirse por el nombre de una tabla y el tipo-de-bloqueo deberia ser READ o WRITE. Para realizar una copia de seguridad s610 se necesita un bloqueo READ. Los usuarios y las secuencias de comandos pueden ejecutar consultas de s610 lectura durante el volcado. Si tiene un conjunto razonable de consultas que alteren la base de datos, como pedidos de cliente, esta soluci6n no resulta prtictica. El segundo metodo es mtis avanzado y utiliza el comando m y s q l -dump. Se suele utilizar de la siguiente forma:
rnysqldump o p t all-databases

>

all.sql

Este comando volcarti un conjunto de todo el SQL necesario para volver a construir la base de datos en el archivo a l l . s q l . A continuation, deberia detener el proceso my s q l d durante un instante y volver areiniciarlo con la o p c i 6 n - l o g - u p d a t e [ = a r c h i v o -d e-r e g i s t r o ] . Las actualizaciones almacenadas en el archivo de registro indicartin 10s cambios realizados desde la realizaci6n del volcado. (Obviamente, deberia volcar 10s archivos de registros en un archivo de copia de seguridad normal.)

Restablecimiento de la base de datos MySQL


Si necesita restablecer una base de datos MySQL, dispondri nuevamente de dos opciones. Si el problema es una tabla de datos daiiada, puede ejecutar myi s amchk con la opci6n - r (reparar). Si ha utilizado el primer metodo de volcado de seguridad, puede copiar 10s archivos de datos en la misma ubicaci6n dentro de una nueva instalacidn de MySQL. Si ha utilizado el segundo metodo de volcado, el proceso de restablecimiento constarti de dos fases. En primer lugar, tendrti que ejecutar las consultas en el archivo de volcado para reconstruir la base de datos hasta el punto de volcado del archivo. En segundo lugar, deberti actualizar la base de datos desde el punto almacenado en 10s archivos de registro. En UNIX puede ejecutar un comando como el siguiente:
1s -1 -t -r hostname.[O-Ql*

xargs

cat

mysql

para procesar 10s archivos de registro en el orden correcto.

Desarrollo Web con PHP y M y S Q L

Si desea obtener mds informacidn sobre el proceso de volcado y recuperaci6n de MySQL, consulte el sitio Web de MySQL en:
http://www.mysql.org

Lecturas adicionales
En estos capitulos sobre MySQL, nos hemos centrado en 10s usos y las partes del sistema mds relevantes para el desarrollo Web y en la combinacidn de MySQL con PHP. Si desea saber mds a1 respecto, en especial en relaci6n a aplicaciones que no Sean Web, o sobre la administraci6n de MySQL, puede visitar el sitio Web de MySQL en

A continuacion
Ya hemos analizado 10s conceptos bdsicos de PHP y MySQL. En el siguiente capitulo examinaremos 10s aspectos de seguridad y comercio electrdnico relacionados con la configuracidn de sitios Web basados en bases de datos.

En este capitulo se presentan algunos aspectos relacionados con la especificaci6n, diseiio, construcci6n y mantenimiento de un sitio Web de comercio electr6nico de manera eficaz. Examinaremos el plan, 10s posibles riesgos y varias formas de lograr que un sitio Web resulte autosuficiente. Examinaremos 10s siguientes aspectos:
0 0

Que se puede consegqir c m un sitio de comercio electr6nico Tipos de sitios Web comerciales Riesgos y amenazas Por qu6 estrategia optar

iCudl es nuestro objetivo?


Antes analizar 10s detalles de implementaci6n de su sitio Web, deberia tener claro sus objetivos y disponer de un plan razonablemente pormenorizado para alcanzarlos. En este libro, partimos del supuesto de que est6 desarrollando un sitio Web comercial y que, por lo tanto, uno de sus objetivos es ganar dinero. Existen muchos enfoques comerciales aplicables a Internet. Puede que desee anunciar sus servicios tradicionales o vender en linea un product0 del mundo real.

12. Creacidn de u n sitio Web de comercio electrdnico

QuizAs tenga un product0 que se puede vender y distribuir por la red. 0 puede que no tenga intention de utilizar el sitio Web para generar ingresos, sin0 como medio para fomentar las actividades fuera de linea o como una alternativa menos costosa a las actividades presentes.

Tipos de sitios Web comerciales


Los sitios Web comerciales realizan una o varias de las actividades siguientes: Publicar informaci6n sobre la compafiia a trav6s de folletos en linea Recoger pedidos de articulos o servicios Suministrar servicios o articulos digitales Afiadir valor a 10s articulos o servicios Reducir costes Las secciones de muchos sitios Web encajan en varias categorias. A continuaci6n, se incluye una descripci6n de cada una de ellas y la forma habitual en la que generan ingresos u obtienen otros beneficios para una organizaci6n. La intenci6n de esta secci6n del libro es ayudarle a formular sus objetos. iPor qu6 quiere un sitio Web? ~ C O va ~ aO contribuir cada funci6n de su sitio Web a1 negocio?

Medios publicitarios en Iinea


PrActicamente todos 10s sitios Web comerciales de principios de 10s afios 90 no eran m6s que una folleto ek linTa o una herramienta de venta. Este tip0 de sitios sigue siendo la forma mAs habitual adoptada por 10s sitios Web comerciales. Ya sea como incursi6n en la Web o como ejercicio de publicidad de bajo coste, este tip0 de sitios siguen teniendo su 16gica para muchos negocios. La presencia publicitaria en Internet puede adoptar distintas formas, desde una tarjeta de visita convertida en pAgina Web a una colecci6n de informaci6n publicitaria. En cualquier caso, el objetivo del sitio y la raz6n financiera de su existencia es atraer a 10s clientes para que entren en contact0 con nuestro negocio. Este tip0 de sitios no genera ningun ingreso directamente, per0 puede contribuir a 10s beneficios obtenidos a trav6s de 10s medios tradicionales. El desarrollo de un sitio de este tip0 presenta pocos retos t6cnicos. Los aspectos sobre 10s que centrarse son similares a 10s de otros ejercicios de publicidad. Entre 10s errores mds habituales que se suelen cometer a1 desarrollar este tip0 de sitios se incluyen 10s siguientes: No suministrar informaci6n importante

Desarrollo W e b con PHP y MySQL

No responder a la informaci6n generada por el sitio No actualizar el sitio No rastrear el 4xito del sitio

N o suministrar informacidn importante


iQu4 es lo que buscan 10s visitantes que acuden a su sitio? Todo depende de lo que ya sepan. Puede que busquen informaci6n t4cnica detallada sobre el product0 o informaci6n muy b6sica como datos de contacto. La informaci6n que suministran muchos sitios Web no resulta util o no incluyen 10s datos m6s importantes. Como minimo, el sitio debe indicar a 10s visitantes a qu4 nos dedicamos, en qu4 Areas geogr6ficas del mundo se proporcionan nuestros servicios y c6mo pueden ponerse en contacto con nosotros.

Mala presentacidn
En Internet, una empresa pequeiia puede parecer de mayor tamaiio y resultar muy llamativa y, a1 contrario, una empresa de gran tamafio puede parecer pequeiia, poco profesional y poco llamativa si el sitio Web no est6 bien diseiiado. Con independencia del tamaiio que tenga su empresa, asegurese de que su sitio Web sea de calidad. El texto debe estar escrito y revisado por alguien con un buen conocimiento del lenguaje correcto. Los grtificos deben estar limpios, deben ser claros y deben tardar poco tiempo en descargarse. En un sitio comercial, deberia tener cuidado a1 elegir 10s gr6ficos y 10s colores de manera que encajen con la imagen que se desea transmitir. Si utiliza efectos de animaci6n y sonido procure hacerlo con cuidado. Aunque no lograrti que su sitio se genere de la misma forma en todos 10s equipos, sistemas operativos y navggadores, asegurese de que se visualiza y de que no produzca errores generalczados.

N o responder a la informacidn generada por el sitio Web


En la Web, un buen servicio de asistencia a1 cliente resulta tan importante para atraer y mantener clientes como en el mundo exterior. Las compafiias, ya Sean pequeiias o grandes, son responsables de colocar una direcci6n de correo electr6nico en una p6gina Web y de no examinar o responder a 10s mensajes de correo riipidamente. La gente suele tener diferentes expectativas sobrelos tiempos de respuesta a 10s mensajes de correo electr6nico con respecto a1 correo postal. Si no examina y responde a1 correo diariamente, 10s usuarios creer6n que no se concede la importancia necesaria a sus consultas. Las direcciones que se incluyen en piginas Web deberian ser genericas e ir dirigidas a un puesto o departamento en lugar de a una persona concreta. iQue ocurrir6 con el correo enviado a fred.smith@ejemplo . com cuando se vaya su titular? Es mas probable que el correo dirigido a ventas @ej empl o .com pase a su

12. Creacidn de u n sitio Web de cornercio electrdnico

sucesor. Tambikn podria distribuirse a un grupo de personas, lo que contribuiria a garantizar su pronta contestaci6n.

No actualizar el sitio
Debe procurar que su sitio Web estk actualizado. Para ello, es necesario cambiar 10s contenidos peribdicamente. Los cambios en la organizaci6n deben reflejarse en el sitio. Un sitio Web con telaraiias desanimar6 a 10s visitantes a volver y contribuir6 a hacerles creer que gran parte de la informaci6n podria ser incorrecta. Una forma de evitar que un sitio parezca obsoleto consiste en actualizar sus piginas manualmente. Tambien puede utilizar un lenguaje de secuencia de comandos como PHP para crear piginas dinimicas. Si su secuencia de comandos dispone de acceso a informaci6n actualizada, podrh generar p6ginas que esten a1 dia de manera constante.

No realirar el seguimiento del exito del sitio


Crear un sitio Web es muy buena idea, per0 jc6m0 justificar el esfuerzo y el gasto? Llegar6 un momento, en especial si se trata del sitio de una gran compafiia, en el que se le pedir6 que demuestre o cuantifique su valor para la organizacibn. En las campafias de marketing tradicionales, las grandes organizaciones invierten mucho dinero en estudios de mercado, antes y despuks de lanzar la campafia, para comprobar su eficacia. En funci6n de la escala y del presupuesto asignado a la iniciativa Web, estos indicadores podrian resultar igualmente apropiados para el disefio del sitio o para cuantificar su valor. Entre las opciones disponibles, m6s caras o m6s baratas, se incluyen las siguientes:

Examinar 10s registros del servidor: 10s servidores Web almacenan una gran cantidad de datos sobre cada petici6n realizada a1 servidor. Gran parte de estos datos resultande pika utilidad y su formato sin procesar tampoco es de gran ayuda. Para destilar 10s archivos de registros y obtener un resumen significativo de 10s datos, es necesario utilizar un analizador de archivos de registros. Dos de 10s m6s conocidos y gratuitos son Analog, disponible en la h t t p : / / w w w . s t a t s l a b . cam. a c . u k / - s r e t l / a n a l o g , y Webalizer, disponible en h t t p : //www.mrunix. n e t / w e b a l i z e r / . Tambikn existen programas comerciales como summary, disponible en h t t p : / / summary n e t , que podrian resultar m6s completos. Los analizadores muestran c6mo varia el tr6fico de un sitio Web con el tiempo y quk paginas se ven.

Monitorizaci6n de las ventas: el objetivo de 10s sitios Web con funciones publicitarias es generar ventas. Deberia poder estimar el efecto sobre las ventas compar6ndolo con 10s niveles de ventas antes del lanzamiento del sitio. Esta operaci6n se complica si se han aplicado otras acciones de marketing en el mismo periodo. Solicitar informacidn a 10s usuarios: si pregunta a sus usuarios, kstos le dir6n lo que piensan del sitio. Puede obtener informaci6n 6til mediante un formula-

Desarrollo Web con PHP y MySQL

rio o una direcci6n de correo electr6nico con la que recoger 10s comentarios de 10s usuarios. Para animar a 10s usuarios a enviar informaci6n puede incluir un incentivo, como la participaci6n en un sorteo. Analisis de usuarios representativos: la creaci6n de grupos de opinion puede convertirse en una t6cnica eficaz para evaluar un sitio o incluso en un prototipo del sitio previsto. Para dirigir un grupo de opini6n s610 necesitarii reunir algunos voluntarios, animarles a valorar el sitio y entrevistarles para obtener y registrar sus opiniones. Los grupos de opini6n pueden resultar caros si su direcci6n se delega en moderadores profesionales encargados d e valorar y filtrar a 10s participantes con el objetivo de garantizar una representaci6n demogriifica y de personalidad exacta dentro de una comunidad amplia y , a continuac%n, entrevistar hiibilmente a 10s participantes. Pero el coste d e 10s grupos de opini6n tambi6n puede ser nulo, si su direcci6n se deja en manos d e un amateur y si se utiliza u n conjunto de personas cuya relevancia con respecto a1 mercado d e destino sea desconocida. Una forma de obtener u n grupo de opini6n bien dirigido consiste en recurrir a 10s servicios de una compaiiia especializada en investigaciones de mercado, per0 no es la 6nica. Si dirige su propio grupo d e opinibn, procure seleccionar un moderador hiibil. Se deben valorar especialmente sus cualidades de comunicaci6n e imparcialidad ante 10s resultados. Limite el tamaiio d e 10s grupos a conjuntos d e entre seis y diez personas. El moderador deberia estar apoyado por una persona encargada de registrar 10s datos o por una secretaria que le permita centrarse en la entrevista. La validez de 10s resultados obtenidos de 10s grupos se corresponderii con a1 muestra de gente utilizada. Si utiliza a amigos o a 10s familiares de sus empleados para valorar el producto, es poco probable que representen a la comunidad general.

Recogida de pedjdos de articulos y servicios


Si la publicidad del sitio resulta atrayente, el siguiente paso 16gico consistira en permitir que sus clientes realicen el pedido por Internet. Los profesionales de las ventas saben que es importante lograr que 10s clientes tomen una decisi6n de manera inmediata. Cuanto miis tiempo se conceda a1 cliente para reconsiderar la decisi6n de compra, mayor serii la probabilidad de que mire otras ofertas y cambie de opini6n. Si un cliente quiere su producto, la mejor estrategia es permitirle realizar la compra de la forma miis fiicil y riipida posible. Si obligamos a la gente a desconectar el m6dem para llamar por tel6fono y realizar un pedido o a acudir a una tienda, lo que estaremos haciendo es poner obstiiculos a la compra. Si la publicidad en linea ha convencido a un visitante a comprar un producto, permitale que realice la compra de inmediato sin abandonar el sitio Web. La recogida de pedidos a travds de un sitio Web es una buena idea para muchas iniciativas comerciales. Todos 10s negocios quieren pedidos. La posibilidad de realizar pedidos en linea permite aumentar las ventas o reducir la carga sobre el personal de ventas. Obviamente, tambi6n se incurririi en unos costes. La construcci6n de un

12. Creacidn de u n sitio Web de comercio electrdnico

sitio Web dinfimico, la organizaci6n de la infraestructura de pago y el suministro de un servicio de atenci6n a1 cliente suponen gastos. Intente determinar si sus productos resultan adecuados para su comercializaci6n a trav& de un sitio de comercio electrbnico. Entre 10s productos que se suelen comprar a traves de Internet se incluyen libros y revistas, programas y equipos informhticos, musica, ropa, viajes y entradas a eventos de entretenimiento. Si su producto no se incluye en ninguna de estas categorias, no desespere. Estas categorias estfin atestadas de marcas establecidas. Sin embargo, resulta aconsejable considerar alguno de 10s factores que explican por qu6 estos productos se venden tan bien por Internet. De manera ideal, 10s productos que se venden en un comercio electr6nico son imperecederos, sencillos de transportar y lo suficientemente caros como para que 10s gastos de envios resultan razonables aunque no demasiado caros como para que el comprador sienta la necesidad de examinarlos fisicamente antes de comprarlos. Los mejores productos para su comercializaci6n a traves de un comercio electr6nico son 10s bienes de consumo. Si quiere comprar un aguacate, es probable que desee examinarlo visualmente antes e incluso tocarlo. No todos 10s aguacates son iguales. La copia de un libro, de un CD o de un programa informhtico suele ser idhtica a otras copias con el mismo titulo. Los compradores no necesitan ver el articulo concreto antes de comprarlo. Ademfis, 10s productos comercializados a traves de comercios electr6nicos deben atraer a la gente que utiliza Internet. En el momento de escribir este libro, esta audiencia se compone fundamentalmente de adultos con empleo, j6venes, con ingresos medios altos y asentados en zonas urbanas. Con el tiempo, sin embargo, 10s usuarios de Internet abarcarhn a toda la poblaci6n. Algunos productos nunca aparecerhn reflejados en 10s estudios sobre ventas por Internet, per0 son un 6xito. Si tiene un producto que atrae unicamente a un nicho del mercado, Internet puede se? un medio fantfistico para obtener comparadores. Algunos productos tienen pocas probabilidades de convertirse en categorias de comercio electr6nico. Los articulos baratos y perecederos, como 10s comestibles, son una mala opci6n, aunque esto no ha disuadido a las compafiias a intentarlo, aunque sin mucho exito. Existen categorias que encajan perfectamente en sitios publicitarios per0 que resultan dptimas para su venta en linea. Por ejemplo, articu10s grandes y caros, como vehiculos o propiedades inmobiliarias que requieren mucha investigaci6n antes de su compra, per0 que resultan demasiado caros para servirlos en forma de pedidos y dificiles de transportar. Existen varios obstficulos para convencer a un comprador potencial de que rellene un pedido. A saber: Preguntas sin respuesta Confianza Facilidad de uso Compatibilidad

Desarrollo W e b con PHP y MySQL

Si un usuario se ve frustrado por cualquiera de estos obstdculos, es probable que abandone el sitio sin comprar.

Preguntas sin respuesta


Si un usuario potencial no encuentra una respuesta inmediata a una pregunta, es probable que abandone el sitio. Este hecho trae consigo una serie de implicaciones. AsegGrese de que el sitio estd bien organizado. ~Resulta sencillo buscar lo que se desea cuando se visita el sitio por primera vez? Asegtirese de que el sitio resulta completo per0 sin abrumar a 10s visitantes. En la Web, 10s usuarios suelen examinar rdpidamente el contenido en lugar de leerlo atentamente, por lo que es aconsejable ser conciso. En la mayor parte de 10s medios publicitarios, existen limites priicticos en cuanto a la cantidad de informaci6n que se puede incluir. No ocurre asi en el caso de un sitio Web. En este caso, 10s dos limites principales son el coste de crear y actualizar la informaci6n y las restricciones impuestas por la capacidad para organizar, distribuir y conectar la informaci6n sin abrumar a 10s visitantes. Resulta tentador imaginar un sitio Web como un comercial que recoge 10s pedidos automdticamente, que nunca duerme y que no reciben ningGn salario. Sin embargo, el servicio de asistencia a1 cliente sigue siendo importante. Anime a 10s visitantes a formular preguntas. Intente suministrar respuestas inmediatas o prdcticamente inmediatas por tel6fon0, por correo electr6nico o a trav6s de cualquier otro medio oportuno.

Confianra
Si un visitante no estd familiarizado con una marca, ipor qu6 deberia fiarse de nosotros? Todo el mundo puede crear un sitio Web. La gente no tiene por qu6 fiarse de lo escrito en el sitio Web y la realizaci6n de un pedido requiere una determinada confianza. iC6m0 distingue eLvisitante entre una organizaci6n con buena reputaci6n o una empresa sin eskipulos? A la gente le preocupa una serie de cosas a1 comprar en la red: i Q ~ se 6 va a hacer con su informaci6n personal? iSe va a vender a otros, se va a utilizar para enviar enormes cantidades de publicidad o se va almacenar en un lugar poco seguro para que otros puedan acceder a ella? Es importante indicar a la gente qu6 es lo que se va a hacer con sus datos. Es lo que se conoce como politica de privacidad y deberia resultar fdcil de acceder a ella. ~ S negocio U es respetable? Si su empresa estd registrada en una entidad con autoridad relevante, tiene una direcci6n fisica y un nGmero de tel6fon0, y lleva varios afios funcionando, es menos probable que se trate de un engafio que un negocio compuesto tinicamente por un sitio Web y quizds una direccidn postal. Asegtirese de mostrar estos detalles. iQu6 ocurre si un comprador no estd satisfecho con su compra? iEn qu6 circunstancias se procederd a realizar un reembolso? iQui6n se hace cargo de 10s gastos de envio? Tradicionalmente, las empresas dedicadas a la venta por

12. Creacidn de u n sitio W e b de comercio electrdnico

correo aplican politicas de reembolso rnis liberales que 10s establecimientos tradicionales. Muchos ofrecen una garantia de satisfacci6n sin condiciones. Tenga en cuenta 10s costes de las devoluciones con respecto a1 aumento de las ventas que generari una politica general de devoluci6n. En cualquier caso, asegurese de indicar la politica aplicada en el sitio. ~Deberian 10s clientes confiarle la informaci6n de sus tarjetas de credito? El aspect0 rnis importante relacionado con la confianza de 10s compradores de Internet es el temor a enviar 10s datos de su tarjeta de credit0 por la red. Por esta raz6n, debe administrar la informaci6n sobre tarjetas de credit0 de manera segura y recalcar su preocupaci6n a1 respecto. Esto significa que, como minimo, deberia aplicar el sistema SSL (Secure Sockets Layer) para transmitir 10s detalles desde el navegador del usuario a1 servidor Web y asegurarse de que su servidor Web esti administrado de manera competente y segura. En una secci6n posterior ampliaremos estos temas.

Facilidad de uso
Los consumidores varian enormemente en cuanto a su experiencia con 10s ordenadores, idioma, nivel de alfabetizacibn, memoria y visi6n. Debe intentar que su sitio resulte lo rnis sencillo posible de utilizar. Aunque existe una gran cantidad de libros dedicados a1 disefio de la interfaz de usuario, a continuaci6n se recogen varias directrices:

Intente mantener la sencillez del sitio a1 mdximo. Cuantas m i s opciones, anuncios o elementos de distracci6n se incluyan en la pantalla, mds probable seri confundir a1 usuario. Intente que el texto resulte claro. Utilice fuentes claras y sencillas. No utilice tamafios demasiado ~ e d w i d o y s tenga en cuenta que en cada equipo se representari con tamafios diferentes. Aseglirese de simplificar a1 mdximo el proceso de realizacih de pedidos. La intuici6n y las pruebas disponibles avalan la idea de que cuantos rnis clics del rat6n tenga que aplicar el usuario para realizar un pedido mayor seri la posibilidad de que no complete el proceso. Intente reducir a1 minimo lo pasos, per0 tenga en cuenta que Amazon.com tiene la patente en EEUU sobre un proceso que utiliza un unico clic, denominado 1-Click. Esta patente es impugnada energicamente por muchos propietarios de sitios Web. Procure que 10s usuarios no se pierdan. Incluya puntos de referencia y pistas de navegaci6n para indicar a 10s usuarios d6nde se encuentran. Por ejemplo, si un usuario se encuentra dentro de una subsecci6n del sitio, resalte la seiial de navegaci6n correspondiente a dicho sitio.
Si esti utilizando la metifora del carro de la compra en la que se suministra un contenedor en el que 10s clientes pueden acumular sus compras antes de finalizar la venta, mantenga un vinculo visible a1 carro en la pantalla constantemente.

Desarroilo W e b con PHP y MySQL

Compatibilidad
Asegurese de probar su sitio en varios navegadores y sistemas operativos. Si el sitio no funciona en un navegador o sistema operativo extendido, el sitio pareceri poco profesional y perderi un porcentaje importante del mercado. Si su sitio ya es operativo, 10s registros de su servidor Web pueden indicar quk navegadores utilizan sus visitantes. Como regla general, si prueba su sitio en las dos ultimas versiones de Microsoft Internet Explorer y Netscape / Mozilla en un PC que ejecute Microsoft Windows, en las dos tiltimas versiones de Netscape/Mozilla en un Apple Mac, la versi6n actual de Netscape / Mozilla de Linux y un navegador de s610 texto como Lynx, su sitio resultara visible para la mayor parte de 10s usuarios. Intente evitar funciones y mecanismos nuevos, a menos que le apetezca escribir y mantener varias versiones del sitio.

Suministro de servicios y articulos digitales


Muchos productos y servicios se puede vender a traves de la Web y enviar a 10s clientes por correo. Sin embargo, existen servicios que se pueden entregar de manera inmediata a traves de Internet. Si un servicio o articulo se puede trasmitir hasta un m6dem, se podri pedir, pagar y entregar de manera instantinea, sin interacci6n humana. El servicio de este tip0 m i s obvio es la informaci6n. En ocasiones la informacidn resulta completamente gratuita o se alimenta de publicidad. En algunos casos la informaci6n se suministra a traves de una suscripci6n o se paga por unidades. Entre 10s articulos digitales de este tip0 se incluyen libros electr6nicos y musica en formato electr6nico como MP3. Las bibliotecas de imigenes se pueden digitalizar y descargar. El software mforifiitico no tiene por que incluirse siempre en CD. Se puede comprimir y descargar. Entre 10s servicios que se pueden vender de esta forma se incluyen el acceso a Internet o servicios de alojamiento Web asi como servicios profesionales que se pueden sustituir por un sistema experto. El envio fisico de un articulo solicitado desde un sitio Web presenta ventajas e inconvenientes sobre 10s articulos y servicios digitales. El envio de un articulo fisicamente tiene un coste mientras que las descargas digitales son pricticamente gratuitas. Esto significa que si tiene algo que se pueda duplicar y vender digitalmente, el coste para su sitio sera el mismo si vende un unidad que si vende mil. Por supuesto, existen limites: si el nivel de ventas y el trifico aumenta, se verA obligado a invertir en hardware o ancho de banda. Los productos o servicios digitales se pueden vender con facilidad como articulos inmediatos. Si una persona realiza un pedido de un articulo fisico tendra que esperar uno o varios dias para recibirlo. Las descargas se suelen medir en segundos o minutos. La inmediatez puede convertirse en una carga para 10s comerciantes. Si distribuye un product0 digitalmente, tendra que hacerlo de inmediato. No puede supervisar

12. Creacidn de u n sitio W e b de comercio electrdnico

el proceso manualmente ni distribuir 10s picos de actividad durante el dia. Los sistemas de distribuci6n inmediata resultan por tanto mds proclives a1 fraude y suponen una carga sobre 10s recursos informiticos. Los articulos y 10s servicios digitales son ideales para el comercio electr6nico pero, como es obvio, el abanico de productos que se puede distribuir de esta forma es limitado.

C6mo aiiadir valor a 10s articulos y servicios


Algunas secciones de sitios Web comerciales no venden ningun articulo ni servicio. Los servicios de seguimientos que incorporan las compaiiias de mensajeria (UPS en www. u p s . corn o Fedex en www. f edex corn) no estdn disefiados para generar ingresos directamente. Afiaden valor a 10s servicios existentes ofrecidos por la organizaci6n. Las compafiias obtienen una ventaja competitiva a1 permitir que 10s clientes puedan saber donde se encuentra su paquete o acceder a sus cuentas bancarias. Dentro de esta categoria se incluyen 10s foros de ayuda. Existen fundadas razones comerciales para ofrecer a 10s clientes un Area de debate en la que compartir sugerencias para resolver problemas sobre 10s productos de su compaiiia. Los clientes pueden resolver sus problemas consultando las soluciones dadas a otros, 10s clientes internacionales puede obtener ayuda sin tener que realizar llamadas internacionales y pueden responder a preguntas de otros clientes fuera de 10s horarios de oficina. Este tip0 de servicios puede contribuir a aumentar la satisfacci6n de 10s clientes con un coste muy bajo.

Recorte de costes
Internet se suele utilizai. parzrecortar costes. El ahorro puede proceder de la distribuci6n de la informaci6n en linea, de la facilidad para el establecimiento de la comunicaci6n, de la sustituci6n de servicios o de la centralizaci6n de operaciones. Si necesita distribuir informaci6n a una gran cantidad de usuarios, probablemente pueda realizar la misma tarea a traves de un sitio Web de manera mEis econ6mica. Independientemente de que se trate de suministrar listas de precios, catAlogos, procedimientos documentados, especificaciones tecnicas o cualquier otra informaci6n, es probable que resulte m6s barato colocar la informaci6n en la Web que imprimirla y distribuirla en papel, en especial si la informaci6n cambia de manera regular. El resultado es el mismo, ya se trate de distribuir ofertas y responder a ellas rgpidamente o de facilitar la comunicaci6n directa de cliente con el mayorista o el fabricante, eliminando intermediarios: 10s precios b a j a r h o 10s ingresos crecerh. La sustituci6n de servicios que supongan un gasto por su versi6n electr6nica puede reducir 10s costes. Un buen ejemplo es el de Egghead.com. Los responsables de esta empresa decidieron cerrar sus almacenes de ordenadores y centrarse en actividades de comercio electr6nico. Aunque la construcci6n de un sitio de comercio electr6nico de cierta entidad cuesta dinero, el coste de mantener una cadena de mds de 70 tiendas

Desarrollo Web con PHP y MySQL

es mucho mayor. La sustituci6n de un servicio existente tiene sus riesgos. Entre ellos, la pkrdida de clientes que no utilicen Internet. La centralizaci6n tambien puede contribuir a reducir costes. El mantenimiento de una gran cantidad de sedes fisicas requiere el pago de rentas y gastos indirectos, el personal que trabaja en ellas y 10s costes del mantenimiento de inventario en cada sede. Un negocio en Internet puede situarse en un unico punto y resultar accesible a todo el mundo.

Riesgos y amenazas
Todos 10s negocios deben hacer frente a riesgos, competidores, robos, cambios en las preferencias del public0 y a desastres naturales, entre otros. La lista es interminable. Sin embargo, muchos de 10s riesgos a 10s que deben hacer frente las compaiiias de comercio electronic0 son muy inferiores o resultan irrelevantes con respecto a otras iniciativas. Estos riesgos incluyen: Piratas inform~ticos Fracaso en la atraccion de suficiente negocio Fallos de hardware Fallos de alimentacion, de comunicacion y de red Fiabilidad de 10s servicios de distribucion Competencia Errores de softwareCambios en las politicas e impuestos gubernamentales Limites de la capacidad sistema

Pi ratas informhticos
Las amenazas mas conocidas para 10s sitios de comercio electronic0 proceden de 10s usuarios de ordenadores malintencionados conocidos como piratas informaticos. Todos 10s negocios corren el riesgo de convertirse en el objetivo de 10s criminales, per0 no hay duda de que 10s comercios electr6nicos atraen la atencion de 10s piratas informaticos con una variedad de intenciones y habilidades. Los piratas pueden atacar por el desafio o la fama que supone sabotear un sitio, para robar o para obtener articulos y servicios gratuitos. La protection de un sitio implica una combination de tareas: Mantener copias de seguridad de la information importante

12. Creacidn de u n sitio W e b de comercio electrdnico

Aplicar politicas de contratacion que atraigan a personal honesto y mantener su fidelidad (10s ataques rnis peligrosos proceden del interior) Adoptar precauciones basadas en software, como seleccionar software seguro o actualizarlo Formar a1 personal para identificar objetivos y puntos d6biles Auditar y registrar las actividades para detectar las intrusiones o 10s intentos de intrusi6n Los ataques rnis efectivos sobre sistemas informiticos aprovechan puntos d6biles conocidos, como contraseiias ficiles d e averiguar, malas configuraciones y versiones antiguas de software. La adopci6n de unas cuantas medidas puede desanimar a 10s atacantes con poca experiencia y garantizar la disponibilidad de una copia de seguridad si ocurre lo peor.

Fracaso en la atraccion de suficiente negocio


Aunque 10s ataques de 10s piratas informiticos son muy temidos, la raz6n de la mayor parte de 10s fracasos en el imbito de 10s comercios electr6nicos viene determinado por factores econ6micos tradicionales. La creaci6n y comercializaci6n de un sitio de comercio electr6nico de gran tamaiio exige fuertes inversiones. Las compaiiias aceptan la p6rdida de dinero a corto plazo si ello conlleva un refuerzo de la marca en el mercado y un increment0 de clientes e ingresos futuros. En el momento de escribir estas lineas, Amazon.com, que es con pocas dudas el establecimiento minorista rnis conocido de la Web, lleva perdiendo dinero durante cinco afios consecutivos (las perdidas en el primer trimestre de 2000 ascienden a 99 millones de d6lares). En la larga lista de fracasos sonados destaca la empresa europea boo. corn, que agot6 sus fondos y fue absorbida tras invertir mas 120 millones de d6lares en seis meses. No es que Boo no vendiera, sin0 que gastaban mucho rnis de lo que obtenia.

Fallos de hardware
No hace falta decir que si su negocio depende de un sitio Web y falla una parte esencial de uno de 10s equipos, el resultado se veri afectado. En 10s sitios Web con mucho trifico o cuyo mantenimiento activo resulte esencia1 esta justificada la existencia de sistemas redundantes para que el fa110 de uno afecte a1 funcionamiento de todo el sistema. Como con todas las amenazas, debe determinar si la posibilidad de desactivar su sitio Web por un dia a la espera de que se realicen las reparaciones pertinentes justifica 10s gastos en equipo redundante.

Desarrollo W e b con PHP y MySQL

Fallos de alimentacion, comunicacion, red y distri bucion


Internet se basa en una compleja red de proveedores de servicios. Si su conexidn con el resto del mundo falla, no podr6 hacer mucho m6s que esperar a que el proveedor vuelva a instalar el servicio. Otro tanto se puede decir con respecto a las cortes del fluido elktrico, a las huelgas y a otro tip0 de parones relacionados con las compafiias de reparto. Existe una soluci6n que depende del presupuesto y consiste en contratar varios servicios a proveedores distintos. El coste se incrementar6 pero si uno de 10s proveedores falla, pod& recurrir a otro. Los cortes breves de suministro elkctrico se pueden superar invirtiendo en generadores.

Com petencia
Si va a abrir una tienda en una calle, no le costar6 mucho hacer un estudio exacto sobre la competencia con la que se va a enfrentar. Sus competidores ser6n principalmente negocios que vendan articulos similares y que e s t h situados en 10s alrededores. Adem6s surgir6n otros. En el Ambito del comercio electr6nic0, el terreno es m6s incierto. Los competidores dependerin de 10s costes de envio y pueden encontrarse en cualquier parte del mundo. Ademas, estar6n sujetos a las fluctuaciones de las divisas y a 10s costes de la mano de obra. En Internet la competencia es encarnizada y cambia a gran velocidad. Si trabaja en una categoria popular, puedemparecer competidores todos 10s dias. No hay mucho que pueda hacer para eliminar el riesgo de la competencia, per0 si se mantiene a1 tanto de 10s nuevos desarrollos, puede estar seguro de que su iniciativa resultar6 competitiva.

Errores de software
Los negocios basados en software resultan vulnerables a 10s errores de las aplicaciones informhticas. Para reducir la probabilidad de errores vitales, seleccione software que resulte fiable, asigne tiempo suficiente para probarlo tras cambiar partes de su sistema, disponga de un proceso de prueba formal y no permita que se realicen cambios en el sistema activo sin probarlos antes en otra parte. Para reducir la gravedad de 10s resultados, realice copias de seguridad actualizadas de todos 10s datos, mantenga configuraciones operativas de software a1 realizar un cambio y supervise el funcionamiento del sistema para detectar problemas r6pidamente.

12. Creacio'n de un sitio W e b de comercio electro'nico

Cambios en las politicas e impuestos gubernamentales


La legislaci6n sobre las empresas basadas en Internet varia segun 10s paises. Las posibilidades van desde que no exista legislaci6n alguna a que se encuentre en fase de desarrollo o que est6 suficientemente desarrollada. Esta situation es poco probable que continue asi. Como resultado, algunos modelos empresariales podrian verse amenazados, regulados o eliminados por la legislacion futura. Ademis, surgiran impuestos. No hay forma de evitar estas cuestiones. La unica soluci6n consiste en estar atento a la nueva legislaci6n y mantener el sitio dentro de la ley. Considere la posibilidad de integrarse en un grupo de presi6n cuando vayan surgiendo estas cuestiones.

Limites de la capacidad del sistema


Una cuestion que deberia tener presente a1 diseiiar su sistema es el crecimiento. Lo normal es que su sistema reciba cada vez mas trafico por lo que deberia diseiiarse de forma se pueda escalar para hacer frente a la nueva demanda. Si el crecimiento es limitado puede incrementar la capacidad del sistema adquiriendo hardware mas ripido. Pero 10s equipos tienen un limite en cuanto a la velocidad. ~ E s t d escrito su software para que a1 alcanzar ese punto, se puedan separar sus partes para compartir la carga entre varios sistemas? ~ P u e d e su base de datos procesar varias peticiones simultaneas procedentes de diferentes equipos? Hay muy pocos sistemas que puedan hacer frente a un crecimiento ingente si esfuerzos, per0 si disefia su sistema teniendo en cuenta el factor de la escalabilidad, podra identificar y eliminar loscuellos de botella cuando crezca su base de clientes.

Por quC estrategia optar


Algunos creen que Internet cambia demasiado rapid0 como para poder realizar planes que resulten eficaces. Pero esa mutabilidad convierte en fundamental la labor de planificacibn. Si no establece metas y selecciona una estrategia, se verd obligado a improvisar ante 10s cambios en lugar de anticiparse a ellos. Tras examinar algunos de 10s objetivos tipicos de un sitio Web comercial y algunas de las amenazas principales a las que hacer frente, es probable que ya tenga pensada alguna estrategia para el suyo. Esta estrategia debe identificar un modelo de negocios. En general, el modelo de negocios suele ser una iniciativa cuyo funcionamiento ya se ha probado, per0 en ocasiones puede tratarse de una idea en la que tenga fe. ~Adaptard su modelo de negocios actual a la Web, imitard a un competidor o creard un servicio pionero?

Desarrollo W e b con PHP y MySQL

A continuacion
En el siguiente capitulo, abordaremos el tema de la seguridad en el comercio electr6nico y suministraremos una descripci6n general de 10s terminos, amenazas y t&nicas de seguridad.

En este capitulo se analiza el papel de la seguridad en el comercio electr6nico. Veremos qui6n puede estar interesado en nuestra informaci6n y c6mo podrian obtenerla, 10s principios irnplicados en la creacidn de una politica para evitar este tip0 de problemas y algunas tecnologias disponibles para salvaguardar la seguridad de u n sitio Web incluida la criptografia, la autenticaci6n y el rastreo. En este capitulo se examinarin 10s siguientes aspectos: Importancia de la i n f o f m a c h Arnenazas contra la seguridad Creaci6n de una politica de seguridad Equilibrio entre usabilidad, rendimiento, coste y seguridad Principios de autenticacidn Uso de autenticacion Fundamentos de la criptografia Criptografia de clave publica Firmas digitales Certificados digitales Servidores Web seguros Auditorias y registros

13. Aspectos de seguridad relacionados con el comercio electrdnico

Cortafuegos Copia de seguridad de datos Seguridad fisica

lmportancia de la informacion
A 1 analizar el tema de la seguridad, lo primer0 que tenemos que valorar es la importancia de 10s datos que estamos protegiendo, tanto para nosotros como para 10s atacantes potenciales. Puede resultar tentador creer que siempre deberia aplicarse el nivel mas alto seguridad a todos 10s sitios, per0 la protecci6n tiene un coste. Antes de decidir el esfuerzo o 10s gastos que se desean invertir en el sistema de seguridad, es necesario determinar el valor de la informaci6n. El valor de la informacion almacenada en el equip0 de un usuario que utilice su ordenador para divertirse, el de una empresa, el de un banco y el de una organizaci6n militar es diferente, a1 igual que varian 10s esfuerzos que invertir6 un atacante para obtener acceso a dicha informaci6n. Tenemos que determinar el valor que tienen 10s contenidos almacenados en nuestros equipos para un visitante malintencionado. Los usuarios que utilizan el ordenador como pasatiempo dispondran de tiempo limitado para profundizar en el tema de la seguridad de sus sistemas o en aumentarla. Como la informaci6n que almacenardn en sus equipos es poco probable que interese a otros usuarios, 10s ataques seran poco frecuentes y el esfuerzo invertido en ellos serd limitado. Sin embargo, todos 10s usuarios de equipos con conexi6n a la red deberian tomar una serie dz precauciones ya que incluso 10s equipos con 10s datos menos interesantes pueden utilizarse como plataformas para lanzar ataques a otros sistemas. Los equipos militares son un objetivo obvio tanto para individuos como para gobiernos extranjeros. Para atacar a 10s gobiernos es necesario disponer de muchos medios, por lo que resulta aconsejable invertir en personal y otro tip0 de recursos para garantizar la aplicaci6n de todas las precauciones posibles. Si es responsable de un sitio de comercio electr6nic0, su atractivo para 10s piratas informdticos se situara entre estos dos extremos.

Amenazas contra la seguridad


iCuAles son 10s riesgos que se ciernen sobre su sitio? iQu6 amenazas existen? En un capitulo anterior se analizaron algunas de las amenazas a las que se expone un comercio electr6nico. Muchas de ellas estan relacionadas con la seguridad.

Desarrollo Web con P H P y MySQL

Las amenazas variartin en funci6n del tip0 de sitio Web per0 se pueden citar las siguientes:
'0

Exposici6n de datos confidenciales Pkrdida o destruccidn de datos Modificaci6n de datos Denegaci6n de servicio Errores en el software Repudio

En las siguientes secciones se analiza cada una de ellas.

Exposicion de datos confidenciales


La informaci6n almacenada en 10s equipos, o la transmitida de un equipo a otro, puede ser confidencial. Podria tratarse de informaci6n destinada unicamente a determinadas personas, como listas de precios de mayoristas, informacidn suministrada por un cliente, como su contraseiia, datos de contact0 o el numero de una tarjeta de crkdito. No deberia guardar la informacidn que no desee compartir en su servidor Web. Los servidores Web no son el lugar m6s aconsejable en el que guardar informaci6n secreta. Si almacena 10s datos sobre su n6mina o su plan para la dominaci6n del mundo en un ordenador, procure que no sea el mismo que el utilizado como servidor Web. Los servidores Web son equipos diseiiados para su acceso publico por lo que s610 deberian contener informaci6n que se ofrezca publicamente o que se acabe de recoger del publico. Para reducir el riesgo de h exposici6n de datos, debe limitar 10s mktodos de acceso a la information y 10s usuarios que disponen de dicho acceso, lo cual implica desarrollar las labores de diseiio teniendo presente la seguridad, configurar el servidor y el software de manera correcta, programar con atencibn, realizar pruebas exhaustivas, eliminar 10s servicios innecesarios del servidor Web y exigir autenticaci6n. Diseiie, configure, codifique y pruebe atentamente su sitio Web para reducir 10s riesgos de un ataque y, lo que es m6s importante, para reducir la probabilidad de que un error exponga accidentalmente la informaci6n. Suprima 10s servicios innecesarios de su servidor Web para reducir el numero de puntos dkbiles potenciales. Cada servicio que estk ejecutando puede resultar vulnerable. Es necesario mantener todos 10s servicios actualizados para eliminar 10s puntos vulnerables conocidos. Los servicios no utilizados pueden resultar peligrosos. Si no utiliza el comando rcp, ,porquk tenerlo instalado? Si indica a1 instalador que su equipo es un host de red, las distribuciones mds importantes de Linux y Windows NT instalardn una gran cantidad de servicios que no necesita y que deberia eliminar.

13. Aspectos de seguridnd relncior~ndoscon el corncrcio electrdnico

La autenticacion implica solicitar a 10s usuarios que demuestren su identidad. Cuando un sistema sabe q u i h realiza una petition, puede decidir si dicha persona dispone de acceso. Existen varios m6todos d e autenticacion d e 10s cuales s61o se utilizan dos de forma generalizada: las contrasefias y las firmas digitales. Los analizaremos m i s adelante. CD Universe ofrece un buen ejemplo del coste, tanto en dinero como en reputation, clue supone permitir la exposici6n de information confidencial. A finales de 1999, un pirata informitico, que se hacia llamar Maxus, se puso en contacto con CD Universe para indicarles clue disponia d e 300.000 n6meros d e tarjetas d e cr6dito clue habia sustraido su sitio Web. Por la destruccion d e esta informacion pedi6 una recompensa que CD Universe se neg6 a pagar. Como resultado, CD Universe acabo en las primeras pdginas d e todos 10s peri6dicos d e mayor tirada cuando Maxus comenz6 a hacer p6blicos 10s numeros d e las tarjetas d e credit0 d e sus usuarios. Los datos tambien corren el riesgo d e exposici6n e n sus trayectos por la red. Las redes TCP/ IP incoryoran una gran cantidad de funciones clue han contribuido a convertirlas en el estandar d e facto para la conexi611 de diversas redes como Internet. Sin embargo, la seguridad no se incluye entre ellas. Los protocolos TCPJIP dividen 10s datos en paquetes y 10s reenvian de equipo en ecluipo hasta que alcanzan su destino. Por lo tanto, 10s datos pasaran a trav6s de una gran cantidad de ordenadores hasta llegar a su destinatario, como se ilustra en la figura 13.1, y cualquiera de ellas puede ver 10s datos en su transito.

Figura 13.1. Los datos enviados a traves de lnternet recorren una gran cantidad de equipos potencialrnente inseguros

Para ver la ruta que siguen 10s datos desde un equipo hasta el equipo d e destino, puede utilizar el comando t r a c e r o u t e (en un equipo UNIX). Este comando devuelve las direcciones de 10s ecluipos a travt;s d e 10s cuales han yasado 10s datos para alcanzar el host de destino. Si 10s datos van dirigidos a un ecluipo d e su propio pais, podrian atravesar una decena d e ecpipos diferentes. Si fueran destinados a un equipo situado fuera del pais, el numero de intermediarim podria superar la veintena. Si

Desarrollo Web can PHP y MySQL

su organizaci6n es de gran tamafio y consta de una red compleja, 10s datos podrian recorrer hasta cinco equipos antes de abandonar el edificio. Para proteger la informaci6n confidencial, puede cifrar 10s datos antes de enviarlos a travks de una red y descifrarlos en el otro extremo. Los servidores Web suelen utilizar el sistema SSL (Secure Socket Layer), desarrollado por Netscape para realizar esta tarea mientras 10s datos navegan entre 10s servidores Web y 10s navegadores. Se trata de una forma bastante barata en terminos de costes y de esfuerzos de proteger las transmisiones, per0 como el servidor necesita cifrar y descifrar 10s datos en lugar de enviarlos y recibirlos simplemente, el numero de visitantes por segundo a1 que puede dar servicio el equipo se reduce dristicamente.

Pbrdida o destruccion de datos


La perdida de datos puede resultar mis costosa que su apropiaci6n indebida. Si lleva meses construyendo su sitio, recogiendo informaci6n sobre usuarios y pedidos, iseria capaz de determinar el coste, en tiempo, reputaci6n y dinero, resultante de perder toda esa informaci6n? Si no ha realizado ninguna copia de seguridad de esos datos, se veri obligado a volver a escribir el sitio Web y a comenzar desde cero. Un pirata informitico podria colarse en su sistema y formatear su disco duro. Tambikn podria ocurrir que un programador o un administrador poco atento eliminen el disco sin querer o que un disco se estropee. Los discos duros giran miles de veces por minuto y en ocasiones fallan. Segun la ley de Murphy, fallarii el disco m6s importante y mucho despues de realizar una copia de seguridad. Puede adoptar varias medidas para reducir la probabilidad de perder datos. Proteja sus servidores contra ataques informiticos. Reduzca a1 minimo 10s empleados con acceso a su equipo. Contrate unicamente personal competente y atento. Compre discos duros de calidad. Utilice la arquitectura RAID para permitir el uso de varios discos duros cqmo un disco miis ripido fiable. Independientemente del causante de las perdidas de datos 6 1 0 hay una forma de protecci6n real: las copias de seguridad. La realizaci6n de copias de seguridad no es exactamente una tarea divertida y con suerte no necesitarii recurrir a ellas, per0 su funci6n es vital. Asegurese de volcar sus datos de manera peri6dica y de probar el procedimiento para asegurarse de que resultan recuperables. Asegurese de almacenar las copias de seguridad lejos de 10s equipos habituales. Aunque es poco probable que 10s locales de su empresa se quemen o sufran alguna otra catistrofe, el almacenamiento de una copia de seguridad fuera de ellos es una medida de seguridad barata y eficaz.

Modificacion de 10s datos


Aunque la perdida de 10s datos puede causar muchos daiios, su modificaci6n puede resultar aun peor. iQu6 ocurriria si alguien logra acceder a sus datos y 10s modifica? La eliminaci6n completa de 10s datos no tardaria mucho tiempo en detectarse, per0 preguntese cu6nto tiempo llevaria detectar su modificaci6n.

13. Aspectos de seguridad relacionados con el comercio electrdnico

Entre las formas de modificaci6n se incluyen cambios en 10s archivos de datos o ejecutables. La intenci6n de un pirata informtitico puede ser modificar el aspect0 de la Web u obtener beneficios fraudulentos. Mediante la sustituci6n de archivos ejecutables con versiones saboteadas, un pirata informatic0 que haya logrado entrar una vez en el sistema podria crear una puerta trasera secreta para futuras visitas. Puede proteger 10s datos contra su modificaci6n a1 viajar por la red mediante una firma. Esta tdcnica no impide la modificaci6n de 10s datos pero, si el receptor comprueba que la firma coincide a1 recibir 10s archivos, sabr6 que el archivo no se ha modificado. Si cifra 10s datos para protegerlos contra la visualizaci6n no autorizada, resultartin muy dificiles de modificar durante el trayecto sin su detecci6n. La protecci6n de 10s archivos almacenados en un servidor frente a su modificaci6n exige el uso de las funciones de permisos de acceso a archivos que incorpore su sistema operativo y protege el sistema de accesos no autorizados. La aplicaci6n de permisos de archivos permite autorizar el uso del sistema, pero no modificar 10s archivos del sistema ni de otros usuarios. La falta de un sistema de permisos es una de las razones que convertian a 10s sistemas operativos Windows 95 y Windows 98 en poco aptos para su uso con servidores. Detectar las modificaciones puede resultar dificil. Si descubrimos que alguien ha penetrado en nuestro sistema de seguridad jc6m0 podremos saber si se han modificad0 archivos importantes? Algunos archivos, como 10s archivos de datos que se almacenan en una base de datos, est6n ideados para cambiar con el paso del tiempo. Sin embargo, la intenci6n de otros es permanecer invariables desde su instalaci6n a menos que se actualicen deliberadamente. La modificaci6n de programas y datos puede resultar engafiosa, y aunque 10s programas puedan reinstalarse si se sospecha que han sido modificados, puede que no sepa qu6 versi6n de 10s datos estd "intacta". Existen aplicaciones que permiten comprobar la integridad de 10s archivos, como Tripware. Esta aplicaci6n regist& informaci6n sobre archivos en un estado seguro, probablemente inmediatamente despu6s de la instalacibn, y permite utilizarla en un momento posterior para verificar si 10s archivos han variado. Puede descargar la versi6n comercial o gratuita de

Errores en el software
Es posible que el software que haya comprado, obtenido o escrito incluya errores graves. Dado 10s cortos plazos de desarrollo asignados a 10s proyectos Web, es muy probable que el software incluya errores. Todas las iniciativas comerciales basadas en procesos inform6ticos resultan vulnerable~ a software con errores. Los errores en el software pueden causar todo tipo de comportamientos impredecibles incluida la indisponibilidad del servicio, lagunas de seguridad, perdidas financieras y servicios deficientes.

Desarrollo W e b con P H P y MySQL

Entre las causas habituales de 10s errores se pueden citar las malas especificaciones tbcnicas, suposiciones err6neas realizadas por 10s desarrolladores y pruebas incompletas.

Malas especificaciones t6cnicas


Cuanto mds escasa y ambigua resulte su documentaci6n de disefio, mds probable es que el product0 final incluya errores. Aunque puede que resulte obvio especificar la anulaci6n de un pedido si se rechaza la tarjeta de crbdito de un cliente, puedo hablarles de un sitio con un alto presupuesto que incluia este error. Cuanta menos experiencia tengan 10s desarrolladores con el tip0 de sistemas con el que estdn trabajando, mds precisas deberian ser las especificaciones tbcnicas.

Suposiciones erroneas hechas por 10s desarrolladores


Los disefiadores y 10s programadores de un sistema necesitan realizar una gran cantidad de suposiciones. Es de esperar que las documenten y que resulten acertadas. Sin embargo, las suposiciones pueden resultar err6neas. Por ejemplo, un desarrollador podria asumir que 10s datos de entrada serdn viilidos, que no incluiriin caracteres inusuales o que la cantidad de caracteres introducidos serii inferior a un tamafio dado. Tambibn podria asumir que no tendriin lugar dos acciones simultiineas que entren en conflict0 o que una tarea de procesamiento compleja lleve mds tiempo que una tarea sencilla. Suposiciones como bsta se pueden deslizar porque suelen ser ciertas. Un pirata informiitico puede aprovecharse de un desbordamiento de bufer generado por una suposicidn hecha por un programador con respecto a la longitud mdxima de 10s datos de entrada o un usuario legitimo puede obtener mensajes de error confusos o abandonar la visita porque a 10s desarrolladores no se les ocurri6 prever que el nombre de una persona pueda incluir un ap6strofe. Este tip0 de errores se pueden detectar y solucionar mepiante una combinaci6n de pruebas y revisi6n detallada del cbdigo. Histbricamente, el sistema operativo o las debilidades del nivel de aplicaci6n explotadas por 10s piratas informiitica se relacionan con 10s desbordamientos de b6fer o con 10s errores de sincronizaci6n.

Pruebas incompletas
Resulta priicticamente imposible verificar todas las posibles entradas de 10s usuarios en todos dispositivos de hardware existentes, con todos 10s sistemas operativos posibles y utilizando todos 10s pariimetros de usuario disponibles. Esto es especialmente cierto en el caso de 10s sistemas basados en la Web. Es necesario implementar un plan de pruebas bien disefiado que verifique todas las funciones del software en un conjunto representativo de equipos. Un conjunto de pruebas bien planeado deberia probar todas las lineas de c6digo del proyecto a1 menos una vez. De manera ideal, estas pruebas deberian automatizarse para poder ejecutarlas en 10s equipos seleccionados con muy poco esfuerzo.

13. Aspectos de seguridad relacionados con el comercio electrdnico

El problema m6s importante de esta operation es que se trata de un trabajo repetitivo muy poco atractivo. Aunque hay gente a la que le gusta romper cosas, hay muy pocas a las que le guste romper la misma cosa una y otra vez. Es importante que en este proceso participen otras personas adem6s de 10s desarrolladores originales. Uno de 10s objetivos principales de las pruebas es detectar las suposiciones erroneas realizadas por 10s desarrolladores. Es probable que una persona no implicada realice suposiciones diferentes. Ademgs, 10s profesionales no suelen mostrarse muy inclinados a buscar errores dentro de su trabajo.

Repudio
El ultimo riesgo que considerar es el repudio. El repudio tiene lugar cuando una parte implicada en una transaccion niega haber tomado parte en ella. En el comercio electronico puede tratarse de una persona que realice un pedido a travks del sitio Web y que rechace la autorizacion para realizar el cargo sobre su tarjeta de crkdito, o una persona que acepte algo procedente del correo electronic0 y que despuks afirme que alguien falsific6 dicho correo. De manera ideal, las transacciones financieras deberian garantizar la seguridad de que ninguna d e las partes las repudiar6. Ninguna parte podria denegar su participaci6n en una transaccion o, para ser m6s exacto, ambas partes podrian demostrar de manera terminante las acciones realizadas por la otra parte ante un tercero, como por ejemplo un tribunal. En la practica, esto no suele ocurrir. La autenticacion ofrece ciertas garantias sobre la parte con la que se esta tratando. Los certificados digitales d e autenticacion emitidos por una organization d e confianza brindan una gran fiabilidad. Tambikn deberian poder certificarse 10s contenidos d e lo mensajes enviados por cualquiera d e las partes. No sirve de mucho poder demostrar que Corp Pty Ltd nos ha enviado un mensaje si no p d e m o s probar que hemos recibido exactamente 10s que 10s han enviado. Como se indico anteriormente, la firma o el cifrado de 10s mensajes dificulta su alteracion de manera subrepticia. Para las transacciones entre las partes con una relacion ya establecida, 10s certificados digitales y el uso de comunicaciones cifradas o firmadas proporcionan una forma efectiva de limitar el repudio. Si las transacciones son aisladas, como el contact0 inicial entre un sitio d e comercio electronico y un usuario que utilice una tarjeta de crkdito, esta opci6n no resulta tan practica. Las compafiias de comercio electronico deben estar dispuestas a probar su identidad y a contratar 10s servicios de una autoridad de certification como VeriSign ( h t t p : //www.verisign. com/)oThawte(http: / / w w w . t h a w t e . com/)paragarantizar la autenticidad de la compafiia. iEstar6 dispuesta esa misma compafiia a rechazar a todos 10s clientes que no estkn dispuestos a adoptar la misma medida para demostrar su identidad? En las pequeiias transacciones, 10s comerciantes est6n dispuestos a admitir un determinado nivel de fraude o riesgo de repudio a cambio de mantener el nivel de transacciones.

Desarrollo Web con P H P y MySQL

Desde 1997 existe una alianza entre VISA, un determinado numero de organizaciones financieras y compaiiias de software para promover un estindar llamado SET (del ingl6s Secure Electronic Transaction, Transaccion electr6nica segura). Este sistema permite a 10s titulares de tarjetas de credit0 obtener certificados digitales de 10s emisores de sus tarjetas. Si esta iniciativa sigue adelante, podria reducirse el riesgo de repudio asi como otros tipos de fraude en las transacciones por Internet. Por desgracia, aunque la especificacion lleva en pie desde hace muchos aiios, parece que 10s bancos no se animan a emitir certificados compatibles con SET a 10s titulares de tarjetas. Los comerciantes no parecen dispuestos a rechazar a 10s clientes sin software SET y 10s usuarios muestran poco entusiasmo en adoptarlo. No hay muchas razones que obliguen a 10s clientes a hacer cola en sus bancos y a instalar el monedero digital en sus equipos si 10s comerciantes no van a rechazarlo si no lo utilizan.

Equilibrio entre usabilidad, rendimiento, coste y seguridad


Por su propia naturaleza, la Web es un lugar peligroso. Este medio est6 diseiiado para permitir que numerosos usuarios soliciten servicios desde sus equipos. La mayor parte de estas peticiones realizan peticiones de p6ginas Web perfectamente legitimas, per0 a1 conectar sus equipos a Internet tambi6n existe la posibilidad de que la gente realice otros tipos de conexiones. Aunque resulta tentador asumir que es apropiado establecer el nivel de seguridad m6s alto, no suele ser asi. Si desea estar completamente protegido, tendr6 que colocar todos 10s equipos en una caja fuerte sin conexi6n a la red. Para que 10s equipos resulten accesibles y se puedan utilizar, es necesario rebajar el nivel de seguridad de alguna manera. Debemos buscar un equilibrio entre la seguridad, la usabilidad, el coste y el rendimiento. Si aumentamos la seguridad de un servicio podemos reducir su capacidad de uso, por ejemplo, a1 limitar lo que puede hacer la gente o pedir que se identifiquen. El increment0 de la seguridad tambi6n puede reducir el nivel de rendimiento de sus equipos. La ejecuci6n de software para lograr que el sistema resulte m6s seguro (corno sistemas de encriptaci6n y detecci6n de intrusos, escaneres de virus y operaciones de registro de usuarios) absorbe recursos. Se necesita mucho m6s potencial de procesamiento para suministrar una sesi6n cifrada, como una conexi6n SSL a un sitio Web, que una sesion normal. La p6rdida de rendimiento se puede compensar con la adquisici6n de equipos o hardware m6s r6pido que est6 especialmente diseiiado para operaciones de encriptaci6n. El rendimiento, la usabilidad, el coste y la seguridad se pueden considerar como objetivos contrapuestos. Deber6 examinar 10s pros y 10s contras de cada opci6n y tomar una decisi6n que logre un compromiso en funci6n del valor de la informaci6n, del presupuesto, de la cantidad de visitas esperadas y de 10s obst6culos que considere que aceptar6n 10s usuarios legitimos.

13. Aspectos de seguridad relacionados con el cornercio electro'nico

Creaci6n de una politica de seguridad


Una politica de seguridad es un documento que describe La filosofia general sobre seguridad en su organizaci6n Quk se debe proteger: software, hardware y datos Quikn es responsable de la protecci6n de estos elementos Estindares de seguridad e indicadores para medir el cumplimiento de dichos est6ndares
A la hora de desarrollar la politica de seguridad se pueden aplicar las mismas reglas utilizadas para escribir un conjunto de requisitos de software. En esta politica no deberia hablarse de implementaciones o soluciones, sin0 de requisitos de seguridad y de objetivos dentro del entorno. Y no deberia actualizarse a menudo. Deberia crear un documento en el que se establezcan las directrices utilizadas para medir el cumplimiento de la politica de seguridad en un entorno dado. Puede establecer directrices diferentes para las distintas partes de la organizaci6n. Seria como un documento de diseiio o un procedimiento manual en el que se recoja quk se est6 haciendo para garantizar el nivel de seguridad requerido.

Principios de autenticacion
El objetivo de la autenticaci6n es demostrar que alguien es quikn dice ser. Existen muchas formas de suministrar autenticaci6n per0 como en el caso de muchas medidas de seguridad, cuanto m6s seguros son 10s mktodos m6s problem6ticos resultan de utilizar. Las tkcnicas de autenticaci61-1 incluyen el uso de contraseiias, firmas digitales, medidas biomktricas mediante esc6neres de huellas y medidas que implican el uso de hardware como tarjetas inteligentes. En la Web s610 se utilizan dos de manera extendida: las contraseiias y las firmas digitales. Las medidas biomktricas y la mayor parte de las soluciones de hardware implican el uso de dispositivos de entrada especiales, lo que limitaria el acceso a aquellos usuarios autorizados con ordenadores equipados. Esta opci6n podria resultar aceptable o incluso deseable para obtener acceso a 10s sistemas internos de una organizacibn, per0 reduce gran parte de las ventajas de permitir el acceso a1 sistema en la Web. Las contraseiias resultan f6ciles de implementar, sencillas de utilizar y no requieren el uso de dispositivos de entrada especiales. Suministran un determinado nivel de autenticaci61-1 per0 es posible que resulten insuficientes para sistemas de alta seguridad. El concept0 de una contraseiia es sencillo. El usuario y el sistema conocen la contraseiia. Si otro visitante afirma ser un usuario y conoce su contraseiia, el sistema

Desarrollo Web con P H P y MySQL

lo aceptard. Este sistema resulta seguro siempre y cuando nadie m i s sepa o pueda adivinar la contrasefia. Las contrasefias presentan en si mismas varios puntos dbbiles y no suministran autenticaci6n segura. Muchas contrasefias resultan f6ciles de averipar. Si permite que 10s usuarios seleccionen sus propias contrasefias, un 50% escogerd contrasefias fdciles de descubrir, como vocablos de un diccionario o el nombre de usuario. Puede obligar a 10s usuarios a incluir numeros o signos de puntuaci6n en sus contrasefias, aunque esta medida afectari a la usabilidad ya que 10s usuarios tendr6n dificultades para recordarlas. Otra opci6n consiste en mostrar a 10s usuarios c6mo seleccionar mejores contrasefias per0 de todas maneras el 25% de ellos seguir6 utilizando contrasefias sencillas de adivinar. Puede implementar politicas de contrasefias que impidan a 10s usuarios seleccionar combinaciones ficiles comparando las contrasefias introducidas con un s signos de puntuaci6n o una combinaci6n diccionario o exigiendo el uso de n ~ m e r o o de letras en mayusculas y minusculas. El peligro de una politica de este tip0 es que 10s usuarios legitimos no logren recordar las contraseiias escogidas. Las contrasefias dificiles de recordar aumentan la probabilidad de que 10s usuarios realicen una acci6n poco segura como escribirlas en una nota y pegarla en sus monitores. Es necesario educar a 10s usuarios para que no escriban sus contrasefias ni las comuniquen por telbfono a alguien que afirme estar trabajando en el sistema. Las contrasefias s610 deberian capturarse electrbnicamente. Meditante el uso de programas para capturar pulsaciones del teclado en una terminal o la informaci6n que circula por la red, 10s piratas informdticos pueden capturar pares de nombres de usuario y contrasefias. Puede limitar las oportunidades de capturar contrasefias cifrando el trafico de red. A pesar de sus defectos potenciales, las contraseiias son una forma sencilla y relativamente efectiva de autenticar usuarios. Puede que el nivel de anonimato no resulte adecuado para la seguridad nacional, per0 son una soluci6n perfecta para comprobar el estado del pedido de un cliente.

a autenticacion
P

La mayor parte de 10s navegadores y servidores Web incorporan mecanismos de autenticaci6n. Los servidores Web se pueden configurar para solicitar un nombre de usuario y una contrasefia para permitir el acceso a 10s archivos de determinados directorios del servidor. Cuando se necesite introducir u n numero de usuario y una contrasefia, el navegador presentard un cuadro de diilogo parecido a1 de la figura 13.2. Tanto Apache como el servidor IIS de Microsoft permiten proteger de manera sencilla una parte del sitio o el sitio en su totalidad de esta forma. PHP y MySQL incorporan muchas otras formas de lograr el mismo objetivo. MySQL resulta m6s r6pido que la autenticaci6n integrada. PHP suministra una autenticaci6n rnis flexible o presenta la solicitud de forma rnis atractiva.

Figura 13.2. Los navegadores Web solicitan a 10s usuarios que se autentiquen al

intentar visitar u n directorio de acceso restringido en u n servidor Web En u n capitulo posterior veremos algunos ejernplos d e autenticaci6n.

Un algoritmo cle e n c r i p t a c i h es un proceso matemfitico que transforma informacion en una cadena aparentemente aleatoria d e datos. Los datos d e 10s que se parte so11 texto sin procesar, aunque es importante para el proceso que represente la informaci6n (que se trate d e texto o d e otro tipo d e datos). La inforrnacion cifrada se conoce corno texto encriptado, aunque se parezca poco a un texto e n la mayor parte d e los casos. La figura 13.3 muestra el proceso d e encriptado e n forrna d e diagrama d e flujo. El texto que se desea cifrar se introduce en u n motor d e encriptacion, que podria ser un dispositivo mecinico, como 10s equipos Enigma d e la segunda guerra mundial, auque e n la actualidad presenta prficticamente siernpre el aspecto d e un programa informitico. El motor devuelve el texto encriptado. . -

Algor~tmo procesar encr~ptac~dn

Texto c~frado

Figura 13.3. La encriptacion toma texto sin procesar y lo transforma en texto encriptado

Para crear el directorio protegido cuya solicitud d e autenticaci6n se muestra e n la figura 13.2, utilizamos el tipo d e autenticacion mds bdsica d e Apache. (En el siguiente capitulo le mostraremos ccirno utilizarlo). Este metodo cifra las contraseiias antes d e almacenarlas. Creamos un usuario con la contrasefia p a s s w o r d . 6sta se cifro y se almacenci como aWDuA3X3H. mc2.Como puede observar, el texto d e partida y la cadena cifrada n o se parecen en nada. Este sistema d e cifrado no es reversible. Muchas contrasefias se almacenan utilizando un algoritmo d e encriptaci61-1d e una sola direction. Para pocler determinar si una contraseiia introducida results correcta, no es necesario descifrar la contraseiia

Desarrollo W e b con P H P y MySQL

almacenada. En su lugar, bastar5 con cifrar la contraseiia introducida y compararla con la versi6n almacenada. Muchos procesos de encriptacion se pueden invertir, aunque no todos. El proceso inverso a1 encriptaci6n se conoce como decriptar. La figura 13.4 muestra un proceso de encriptacion de doble sentido.

Texto sin procesar

Algoritrno de encriptacibn

de 4 sin + cifrado +decriptacibn procesar

Texto

Algorltrno

Texto

Figura 13.4. El proceso de encriptacion toma texto sin procesar y lo transforma en texto cifrado con aspect0 aleatorio. El proceso de decriptado toma el texto encriptado y lo transforma en el texto de partida

La criptografia tiene unos 4000 afios de antigiiedad, per0 alcanz6 la mayoria de edad en la segunda guerra mundial. Su crecimiento desde entonces ha seguido de cerca a1 desarrollo de las redes de ordenadores. En un principio s610 era utilizada por las instituciones militares y organizaciones financieras. En 10s aiios 70 se extendi6 su uso y en 10s aiios 90 se hizo omnipresente. En 10s ultimos aiios, la encriptacih ha pasado de ser un concept0 que la gente s610 conocia por las peliculas de espias y de la segunda guerra mundial a convertirse en algo de lo que se habla en 10s peri6dicos y se utiliza cada vez que se compra algo a trav6s de navegadores Web. Existen muchos algoritmos de encriptaci6n disponibles. Algunos, como DES, utilizan una clave secreta o privada; otros, como RSA, utilizan una clave publica y una clave privada distinta.

Encriptacion de clave privada


La encriptaci6n de clave privada se basa en usuarios autorizados que conocen o disponen de acceso a una clave. Esta clave debe mantenerse en secret0 ya que de lo contrario 10s mensajes cifrados podrian ser leidos por personas no autorizadas. Como se muestra en la figura 13.4, tanto el remitente (la persona que cifra el mensaje) como el receptor (el que descifra el mensaje) tienen la misma clave. El algoritmo de clave secreta mris utilizado es DES (del ingl6s Data Encryptation Standard, Est6ndar de encriptaci6n de datos). Este m6todo fue desarrollado por IBM en 10s afios 70 y fue adoptado como el esthdar americano para comunicacionescomerciales y gubernamentales no clasificadas. La velocidad de 10s ordenadores ha aumentado enormemente desde entonces y DES ha quedado obsoleto desde a1 menos 1998. Otros sistemas de claves secretas conkidos son RC2, RC4, RC5, triple DES e IDEA. El sistema triple DES resulta bastante seguro. Utiliza el mismo algoritmo que DES, per0 se aplica tres veces con hasta tres claves diferentes. El mensaje de texto se cifra con la primera clave, se descifra con la segunda y se vuelve a cifrar con la tercera.

13. Aspectos de seguridad relacionados con el comercio electrdnico

Uno de 10s defectos de la encriptacion con clave secreta es que para enviar un mensaje seguro a alguien, es necesario disponer de un forma segura de poderles enviar la clave secreta. Si dispone de una forma segura de enviar una clave, ipor qu6 no utilizarla para enviar el mensaje? Afortunadamente, en 1976 se produjo un avance significativo cuando Diffie y Hellman publicaron el primer m6todo de clave pfiblica.

Encriptacion de clave pu blica


La encriptacion de clave publica se basa en dos claves, una clave publica y una clave privada. Como se ilustra en la figura 13.5, la clave publica se utiliza para cifrar mensajes y la clave privada para descifrarlos. La ventaja de este sistema es que la clave publica, como su nombre indica, se puede distribuir pGblicamente. Todo el mundo a1 que le entreguemos nuestra clave publica puede enviarnos un mensaje seguro. Mientras mantengamos en secret0 nuestra clave privada, s610 nosotros podremos descifrar el mensaje.

privada

Texto sin procesar

de +encriptacibn

Algoritmo

Texto cifrado

Texto Algoritmo de ) sin decriptacibn procesar

Figura 13.5. La encriptacion de clave publica utiliza claves distintas para cifrar y descifrar rnensajes

El algoritmo de clave pGblica mds utilizado es RSA, desarrollado por Rivest, Shamir

y Adelman en MIT y publicado en 1978. RSA era un sistema propietario per0 la patente vencid en septiembre de 2000. La capacidad para transmitir una clave ptiblica de forma abierta y sin necesidad de preocuparse por que resulte visible para una tercera parte supone una gran ventaja. Un sistema de clave publica se utiliza para transmitir la clave para un sistema de clave secreta que se utilizard durante el resto de una comunicacidn de sesidn. Esta complejidad aiiadida resulta tolerable porque 10s sistemas de clave secreta son unas 1000 veces mds rdpidos que 10s sistemas de clave publica.

Firmas dieitales
Las firmas digitales estdn relacionados con la criptografia de clave publica, per0 invierten 10s papeles de las claves publicas y privadas. Un remitente puede cifrar y

Desarrollo Web con P H P y MySQL

firmar digitalmente un mensaje con su clave secreta. Cuando se recibe el mensaje, el receptor puede descifrarlo con la clave secreta del remitente. Como el remitente es la unica persona con acceso a la clave secreta, el receptor puede estar bastante seguro de la procedencia del mensaje y de que no se ha alterado. Las firmas digitales resultan muy 6tiles. Garantizan la procedencia de 10s mensajes y dificultan el rechazo del envio por parte del remitente. De todos modos, es importante tener en cuenta que aunque el mensaje se ha cifrado, cualquier persona que tenga la clave ptiblica puede leerlo. Si bien se utilizan las mismas tecnicas y claves, la finalidad del uso de la encriptaci6n en este caso es impedir la modificaci6n de 10s mensajes y su repudio, no su lectura. Como el cifrado de clave p6blica resulta bastante lento en el caso de mensajes de gran tamaiio, se suele utilizar otro tip0 de algoritmo, llamado funci6n hash, para mejorar la eficacia. La funcion hash calcula un mensaje implicito o valor hash para cualquier mensaje que se le indique. El valor generado por el algoritmo no es importante. Lo importante es que el resultado sea fijo, es decir, que sea el mismo cada vez que se utiliza una entrada dada, que sea pequeiio y que el algoritmo sea ri5pido. Las funciones hash m6s habituales son MD5 y SHA. Una funci6n hash genera un mensaje implicito que coincide con un mensaje dado. Si disponemos de ambos mensajes, podremos verificar si el texto se ha variado, siempre y cuando estemos seguros de que no se ha tocado el mensaje implicito. La forma mas habitual de crear una firma digital consiste en crear un mensaje implicito para todo el mensaje utilizando una funci6n hash ri5pida y, a continuacibn, cifrar unicamente el mensaje implicito utilizando una algoritmo de clave publica. Seguidamente se puede enviar la firma con el mensaje a traves de cualquier metodo normal no seguro. Cuando se recibe un mensaje, se puede realizar su comprobaci6n. La firma se descifrarii utilizando la clave ~ u b l i c a del remitente. Se genera un valor hash para el mensaje utilizando el misko metodo utilizado por el remitente. Si el valor hash descifrado coincide con el valor hash generado, podemos estar seguros de que el mensaje procede del remitente y no se ha alterado.

Certificados digitales
La posibilidad de verificar que un mensaje no se ha alterado y que procede de un usuario o de un equipo dado es un gran avance. Para las interacciones comerciales, resultaria incluso mejor disponer de la posibilidad de vincular a dicho usuario o servidor a una entidad legal real como una persona o compaiiia. Un certificado digital combina una clave p6blica con 10s detalles de una organizaci6n o individuo en un formato digital firmado. En un certificado, nosotros tenemos la clave publica de la otra parte, por si queremos enviar un mensaje cifrado y tendremos 10s detalles de la otra parte, que podemos estar seguros de que no se han alterado.

El problema en este caso es que la fiabilidad de la informaci6n depende de lo fiable que sea el remitente ya que todo el mundo puede generar y firmar u11 certificado utilizando otra identidad. En las transacciones comerciales, resulta iltil utilizar una tercera parte d e confianza que acredite la identidad d e 10s participantes y 10s detalles d e s u s certificados. Estas terceras partes se conocen como CA (del inglks Certifying Authorities, Autoridades de certificacicin). Las autoridades de certificacion expiden certificados digitales a individuos y compafiias sujetas a una serie de comprobaciones de identidad. Las dos CA mAs conocidas son VeriSign ( h t t p : / / w w w . v e r i s i g n corn/) y Thawte ( h t t p : //www. t h a w t e . corn/), pero existen otras. VeriSign y Thawte pertenecen a la misma compariia y hay muy poca diferencia entre ambas. Algunas menos conocidas, como Equifax Secure (www .e q u i fa x s e c u r e . corn), resultan bastante m6s baratas. Las autoridades firman un certificado para acreditar que se ha comprobado la identidad d e una persona o compaiiia. Tenga en cuenta que el certificado no es una referencia ni una declaracion d e solvencia. No garantiza que se estA tratando con una entidad fiable. Lo Gnico clue garantiza es que en caso d e que nos engaiien, es probable que obtengamos una direccion fisica y una entidad o persona contra la que dirigir la demanda. Los certificados suministran una estructura d e confianza. Si confiamos en la CA, podemos confiar en aquellas partes en las que confia la CA y a su vez en aquellas partes e n las que confia la parte certificada. En la figura 13.6 se ilustra la ruta d e certificados que muestra Internet Explorer para un certificado concreto. En ella, pued e observar que www e q u i fa x s e c u r e . corn tiene un certificado emitido por Equifax Secure E-Business Certifying Authority. Esta CA, a s u vez, dispone d e un certificado emitido por Thawte Server Certifying Authority.

Figura 13.6. La ruta de certificados de www.equifaxsecure.com muestra la estructura de

confianza que perrnite confiar en este sitio

Desarrollo Web con PHP y MySQL

Los certificados digitales se suelen utilizar para conferir un aire de respetabilidad a1 sitio Web de un comercio electrhico. Con un certificado emitido por una CA conocida, 10s navegadores Web pueden establecer conexiones SSL a nuestro sitio sin generar cuadros de dialogo de advertencia. Los servidores Web que permite conexiones SSL se suelen llamar servidores Web seguros.

Servidores Web segu ros


Puede utilizar el servidor Web Apache, el servidor IIS de Microsoft o cualquier otro servidor Web comercial para establecer comunicaciones seguras con navegadores a travbs de SSL. Apache permite utilizar un sistema operativo de tip0 UNIX, que suelen resultar mas fiables per0 m i s dificiles de configurar que 11s. El servidor Apache se puede utilizar en una plataforma Windows. El uso de SSL sobre IIS implica sencillamente instalar IIS, generar un par de claves e instalar el certificado. El uso de SSL en Apache requiere la instalacibn de tres paquetes diferentes: Apache, Mod-SSL y OpenSSL. Tambibn puede obtener lo mejor de 10s dos mundos comprando Stronghold. Stronghold es un producto comercial disponible desde www. c2 n e t por unos 1000 dblares. Esti basado en Apache per0 tiene forma de archivo binario autoinstalable y lleva preconfigurado el sistema SSL. De esta forma, se obtiene la fiabilidad de UNIX asi como un producto de facil instalacibn con asistencia tecnica del proveedor. Las instrucciones de instalacibn para 10s dos servidores Web m i s populares, Apache e IIS, se incluyen en el apbndice A. Puede comenzar a utilizar SSL de forma inmediata si genera sus propios certificados digitales per0 10s visitantes que acudan a su sitio recibirin una advertencia de sus navegadores indicandoles que hemos firmado nuestros propios-certi%cados. Para poder utilizar SSL con eficacia, necesitara un certificado publicado por una autoridad de certificacibn. El proceso exacto para lograrlo varia segun la autoridad de certificacibn, per0 por regla general deberi demostrar que su empresa esti reconocida legalmente, que consta de una direcci6n fisica y que es el titular del nombre de dominio pertinente. Necesitari generar una solicitud de firma de certificado. El proceso para lograrlo varia de un servidor a otro. Encontrari las instrucciones en 10s sitios Web de las autoridades de certificacibn. Stronghold e IIS incorporan un proceso basado en cuadros de dialogo mientras que Apache requiere la introduccibn de comandos. Sin embargo, el proceso es esencialmente el mismo para todos 10s servidores. El resultad0 final es una solicitud de firma de certificado (CSR) cifrada. Las CSR presentan un aspect0 parecido a1 siguiente:

B E G I N NEW CERTIFICATE REQIJEST--MIIBuwIBAAKBqQCLnlXX8faMtit~tzStp9wY6BVTPuEU9~pMmt~rb6vqaNZy4dTe6VS P4p7wGepq5CQ]fOL4Hjdatq12~~t08~~BkCDO98Xq9qP6CY45HZk+q6GyGOLZSOD 8cQHwhio~JP65s5Tz0180FB~pI3bHxfO6aYe~WYz~DiFKplBrUd~~at~~K4SQIVAPLH

13. Aspectos de seguridad relacionados con el comercio electrdnico

Tras adquirir la CSR, pagar la cuota correspondiente, conseguir la documentaci6n que prueba nuestra existencia y verificar que el nombre de dominio que estamos utilizando es el mismo que el incluido en la documentaci6n corporativa, estari en disposici6n de firmar un certificado con una autoridad de certificacibn. Cuando la autoridad de certificados emita el suyo, deberi almacenarlo en su sistema e indicarle a su servidor Web d6nde encontrarlo. El certificado finales un archivo de texto parecido a1 CSR mostrado anteriormente.

Auditorias y registros
Su sistema operativo le permitiri registrar todo tip0 de eventos. Los eventos en 10s que puede estar interesado desde el punto de vista de la seguridad incluyen errores de red, acceso a archivos de datos concretos como 10s de configuraci6n o el registro de NT y llamadas a programas como su (que se utiliza para convertirse en otro usuario, por regla general el usuario raiz, en un sistema UNIX). Los archivos de registro pueden servir de ayuda para detectar comportamientos err6neos o malintencionados cuando tienen lugar. Tambikn se puede utilizar para determinar c6mo tuvo lugar un problema o una intrusidn si se examina tras observar problemas. Los archivos de registro presentan dos problemas principales: el tamafio y la veracidad. Si establece 10s criterios para detectar y registrar problemas en el nivel de mayor paranoia, terminari obteniendo registros gigantescos que resultan muy dificiles de examinar. Para trabajar con archivos de registro de gran tamafio, tendri que recurrir a una herramienta existente o derivar algunas secuencias d e comandos de la politica de seguridad establecida para realizar bdsquedas de eventos "interesantes" dentro de 10s registros. El proceso de auditar 10s registros puede realizarse en tiempo real o de manera peribdica. Los archivos de registros resultan vulnerables a ataques. Si un intruso dispone de acceso de usuario raiz o de administrador a nuestro sistema, podri alterar 10s archivos de registros para borrar sus huellas. Unix permite registrar eventos en un equipo diferente, lo que implica que el intruso deberi acceder a dos equipos a1 menos para cubrir sus huellas. NT dispone de funcionalidad similar, per0 no resulta tan sencilla de implementar. El administrador de sistema puede realizar auditorias peri6dicas, per0 ademis, podriamos contratar un servicio de auditorias externo para que controlara el comportamiento de 10s administradores.

Desarrollo Web con P H P y MySQL

Cortafuegos
El objetivo de 10s cortafuegos es alejar una red del mundo exterior. De la misma forma que 10s cortafuegos de un edificio o de un coche impiden que el fuego se extienda a otros compartimentos, 10s cortafuegos de red impiden que el caos se extienda por una red. Los cortafuegos estin disefiados para proteger 10s equipos de una red del mundo exterior. Filtran y rechazan el trifico que no cumple las reglas establecidas en ellos. Restringe las actividades de la gente y de 10s equipo situados fuera del cortafuegos. En ocasiones, 10s cortafuegos tambien se pueden utilizar para restringir Tas actividades de 10s equipos incluidos en su interior. Un cortafuegos puede limitar 10s protocolos de red que se pueden utilizar, 10s hosts a 10s que se pueden conectar o forzar el uso de un servidor proxy para reducir costes en terminos de ancho de banda. Un contrafuegos puede ser un dispositivo de hardware, como un enrutador con reglas de filtrado o u n programa de software que se ejecute en un equipo. En cualquier caso, el cortafuegos necesita interfaces para las dos redes y un conjunto de reglas. Su misi6n consiste en supervisar todo el trifico que intenta pasar de una red a otra. Si el trifico cumple las reglas establecidas, serd dirigido a otra red; de lo contrario, se detendri o se rechazard. Los paquetes se pueden filtrar por su tipo, direcci6n de origen, direcci6n de destino o puerto. En algunos casos, 10s paquetes pueden rechazarse simplemente y en otros pueden desencadenar entradas en el registro o activar alarmas.

Copia de seguridad de 10s datos


*

No se puede subestimar la importancia de las copias de seguridad en n i n g ~ n plan de recuperaci6n de desastres. El hardware y 10s inmuebles se puede asegurar y sustituir, o 10s sitios alojados en cualquier host, per0 si su software Web personal desaparece, ninguna entidad aseguradora podri sustituirlo. Debe hacer una copia de seguridad de todos 10s componentes de su sitio Web (pdginas estdticas, secuencias de comandos y bases de datos) peribdicamente. La frecuencia depende del dinamismo del sitio. Si se trata de un sitio completamente estitico, bastari con hacer una copia cuando se modifique. Sin embargo, el tip0 de sitios que estamos tratando en este libro es probable que cambien con frecuencia, en especial si se reciben pedidos en linea. La mayor parte de 10s sitios con un tamafio razonable deben alojarse en un servidor con sistema RAID (del ingles Redundant Array of Inexpensive Disks, Matriz redundante de discos independientes) que admiten funciones de replica. De esta forma, queda cubierta la probabilidad de que ocurra un fa110 en el disco duro. Considere, sin embargo, qu6 ocurriria en una situaci6n que afecta a la matriz, a1 equipo o a1 edificio entero.

13. Aspectos de seguridad relacionados con el cornercio electrdnico

La frecuencia con la que realizar 10s volcados de seguridad deberia corresponderse con el volumen de actualizaci6n. Estas copias de seguridad deberian almacenarse en un soporte diferente y a ser posible en un lugar distinto y seguro contra incendios, robos o desastres naturales. Existen muchas aplicaciones para realizar funciones de copia de seguridad y recuperaciones. En nuestro caso, nos centraremos en c6mo volcar un sitio construido con PHP y equipado de una base de datos MySQL.

Copia de seguridad de 10s archivos generales


Los volcados de archivos HTML, PHP, imigenes y otros archivos que no Sean de base de datos se puede realizar con facilidad en la mayor parte de 10s sistemas utilizando software para la realizaci6n de copias de seguridad. Entre las herramientas gratuitas mas utilizadas se puede mencionar AMANDA desarrollada por la University of Maryland. Esta utilidad se incorpora en la mayor parte de las distribuciones de UNIX y tambien se puede utilizar para realizar copias de seguridad en equipos Windows a traves de SAMBA. Si desea saber mas sobre AMANDA, dirijase a

Copia de seguridad y restauracion de bases de datos

YSQL
El proceso de volcado de seguridad de una base de datos en funcionamiento resulta mas complicado ya que no queremos copiar ningfin dato mientras la base de datos se estA modificando. En un capitulo anterio;encontrar~ instrucciones sobre c6mo volcar y restaurar una base de datos MySQL.

eguridad fisica
Las amenazas de seguridad consideradas hasta el momento hacen referencia a elementos intangibles como el software, per0 no deberia descuidar la seguridad fisica de su sistema. Debe prever u n sistema de aire acondicionado y sistemas de protecci6n contra el fuego, personas (torpes o criminales), fallos en el suministro electric0 y fallos en la red. Su sistema deberia estar protegido bajo llave en un lugar seguro. El lugar concreto dependerd de cada caso per0 puede ser una habitacibn, una jaula o un armario. S610 se deberia conceder permiso de acceso a esta habitaci6n a1 personal pertinente. El personal no autorizado podria, voluntaria o involuntariamente, desconectar 10s cables o intentar eludir 10s mecanismos de seguridad utilizando un disco de reinicio.

Desarrollo Web con PHP y MySQL

Los rociadores de agua pueden causar tanto dafio a 10s componentes electr6nicos como el fuego. En el pasado, se utilizaron sistemas de extinci6n de incendios alimentados por gas hal6n para evitar este problema per0 en la actualidad la producci6n de este gas est6 prohibida por el Protocolo de Montreal sobre sustancias que reducen la capa de ozono, por lo que 10s sistemas para la extinci6n de incendios deben utilizar otras alternativas menos dafiinas como el gas arg6n o el di6xido de carbono. Puede leer m6s a1 respecto en

En determinados lugares, se producen breves cortes de fluido electr6nico de manera habitual. En sitios con climatologias extremas o cables enterrados se suelen producir cortes de fluido de larga duraci6n. Si el funcionamiento continuo del sistema es un factor importante deberia invertir en un SAI (sistema de alimentaci6n ininterrumpido). El coste de un SAI capaz de mantener el fluido electric0 para un equipo durante 10 minutos asciende a nos 300 d6lares. Si se necesita un sistema para cubrir cortes de suministro m i s largos o mas equipos, el coste se elevar6. Los cortes de suministro de larga duraci6n requieren un generador que alimente el sistema de refrigeration y 10s equipos. A1 igual que 10s fallos de suministro elkctrico, 10s fallos de red, que pueden durar minutos o horas, quedan fuera de nuestro control y se producen irremediablemente de tiempo en tiempo. Si el mantenimiento de la red es vital, es aconsejable contratar 10s servicios de varios proveedores de servicios. El coste ser6 superior, per0 en caso de fallo, su sitio seguir6 siendo visible, aunque se vea afectada su capacidad. Este tip0 de cuestiones podrian llevarle a considerar la opci6n de ubicar sus equipos dentro de una infraestructura dedicada. En u n negocio de tamafio medio puede que no resulte justificable el uso de u n SAI que mantenga el fluido electrico durante varios minutos, varias conexiones de red redundantes y sistemas antiincendios. Sin embargo, en una infraestructqa de calidad en la que se alojen cientos de equipos similares si resultaria justificable.

En el siguiente capitulo, nos centraremos de manera especifica en la autenticaci6n, funci6n que permite a 10s usuarios acreditar su identidad. Examinaremos varios metodos diferentes, incluido el uso de PHP y MySQL para autenticar a nuestros visitantes.

En este capitulo veremos c6mo implementar varias tdcnicas de PHP y MySQL para autenticar a un usuario. Entre 10s aspectos que analizaremos se incluyen 10s siguientes: Identificaci6n de visitantes Jmplementaci6n del control de acceso Autenticaci6n b6sica

Uso de la autenticaci6n b6sica de PHP Uso de la autenticaci6n b6sica .htaccess de Apache Uso de la autenticaci6n b6sica con IIS Uso de la autenticaci6n con mod-a u t h -mysql Creaci6n de procesos de autenticaci61-1 personalizados

Identificaci6n de visitantes
La Web es un medio relativamente an6nim0, per0 a menudo resulta util saber quidn est6 visitando nuestro sitio. Afortunadamente para la privacidad de 10s visitantes, 10s datos que se pueden obtener sin su colaboraci6n son bastante escasos.

14. Implementacidn de la autenticacidn con PHP y MySQL

Con un poco de trabajo, 10s servidores pueden averiguar bastantes datos sobre 10s equipos y las redes que se conectan a ellos. Los navegadores suelen identificarse, para lo cual indican a1 servidor qu6 navegador, versi6n y sistema operativo se est6 utilizando. Se puede determinar qu6 resolucidn y profundidad de color est6 utilizando el visitante en su pantalla asi como el tamaiio asignado a la ventana del navegador Web. Cada equipo que se conecta a Internet tiene una direcci6n IP exclusiva. Esta direcci6n permite deducir algunos datos sobre el visitante. Se puede determinar a qui6n pertenece la IP y, aproximadamente, la ubicaci6n geogrifica del visitante. Algunas direcciones resultan m6s 6tiles que otras. Por regla general, 10s usuarios con conexiones permanentes a Internet tendr6n una direcci6n permanente. A 10s clientes que llamen a un proveedor de acceso a Internet se les suelen asignar direcciones para su uso temporal. Si vuelve a ver dicha direcci6n es probable que est6 siendo utilizada por un equipo distinto y si vuelve a encontrar a1 visitante es probable que est6 utilizando una direcci6n IP diferente. Por suerte para 10s usuarios Web, ninguno de 10s datos que ofrece el navegador sirve para identificarles. Si desea saber el nombre u otra informaci6n sobre un visitante, tendrd que preguntarles. Muchos sitios Web utilizan razones convincentes para obtener datos de 10s usuarios. El New York Times (ht tp : //www. nyt i m e s . corn) ofrece su contenido gratis per0 s610 a aquellas personas que est6n dispuestas a suministrar datos como su nombre, sex0 e ingresos. El sitio Slashdot (http : / / www. slashdot. org) permite a 10s usuarios registrados participar en 10s debates con un apodo y personalizar la interfaz que ven. La mayor parte de 10s sitios de comercio electr6nico registran informaci6n sobre sus usuarios cuando realizan el primer pedido. De esta forma no tendr6n que volver a hacerlo en 10s pedidos siguientes. Tras solicitar y recabarinfor'maci6n de 10s visitantes, necesitamos una forma de asociar dicha informacidn con sus usuarios correspondientes cuando vuelvan a visitarnos. Si partimos del supuesto de que cada persona visitar6 su sitio desde una cuenta determinada y desde un equipo dado, y que cada visitante utiliza 6nicamente un equipo, podemos almacenar una cookie en el equipo del usuario para identificarle. Sin embargo, no ocurre siempre es asi. Con frecuencia, la gente comparte un equipo y muchos usuarios utilizan varios equipos para navegar. Por lo tanto, no quedar6 m6s remedio que preguntar a1 visitante qui6n es de nuevo. Ademis de solicitar que se identifique, tendr6 que pedirle alguna prueba que confirme que es qui6n dice ser. Como se indicd en un capitulo anterior el proceso de pedir a 10s usuarios que demuestren su identidad se conoce como autenticaci6n. El metodo habitual de autenticaci6n utilizado en 10s sitios Web consiste en pedir a 10s usuarios que introduzcan un nombre de usuario y una contraseiia. El proceso de autenticaci6n se suele utilizar para conceder o rechazar el acceso a p6ginas o recursos concretos, per0 puede resultar adecuado o 6til para otros fines como la personalizaci6n.

Desnrrdlo Web con PHP y MySQL

Un control de acceso sencillo no resulta dificil de implementar. El codigo incluido en el listado 14.1 devuelve tres posibles resultados. Si el archivo se carga sin parimetros, mostrari un formulario HMTL solicitando un nombre de usuario y una contrasetia. En la figura 14.1 se muestra este tip0 d e formulario.

Archm Ediabn Ver Favorms .Herramienbs Ayuda ~~~~

-.

O~reccibn

(a n~p-l~~~t.

c ~ ~ s : i i i ~ ~ : ~ ~ ~ l ~ / s ~ r , c ~

Please Log In

Figura 14.1. Nuestro formulario HTML pide a 10s visitantes que introduzcan un nombre de usuario y una contrasetia para poder acceder

Si se han introducido 10s par6metros pero no son correctos, se mostrari un mensaje de error. En a1 figura 14.2 se muestra dicho mensaje.

Figura 14.2. Cuando 10s usuarios introducen inforrnacion incorrecta, tenernos que devolver un mensaje de error

Si 10s parimetros se han introducido y son correctos, se mostrari el contenido secreto, coino se ilustra en la figura 14.3.

El c6digo para crear la funcionalidad ilustrada en las figuras 14.1, 14.2 y 14.3 se muestra en el listado 14.1.

Archwu Ed1u6n Ver Fsvonloe Herrarn~entas A p d a


Dmmbn k 1 h m / / W ~ S C I Y C ~ / Cll ~ 4 / ~ u eoh2 1

.I

Here it is!
I bet you are glad you can see this secret page

Figura 14.3. Cuando se introducen 10s detalles correctos, la secuencia de comandos muestra el contenido. Listado 14.1. secret.php. Codigo PHP y HTML para proporcionar un sencillo mecanismo de autenticacion

Desarrollo W e b con PHP y MySQL


1 else if($name=='user'&&$password=='pass')

t
/ / el nombre y la contrasetia del visitante son correctos echo '<hl>Here it is!</hl>'; echo 'I bet you are glad you can see this secret page.';

I
else i / I el nombre y la contrasetia del visitante no son correctos echo '<hl>Go Away!</hl>'; echo 'You are not authorized to view this resource.';

I
?>

El codigo del listado 14.1 constituye un sencillo mecanismo de autenticacion para conceder acceso a una piigina a 10s usuarios autorizados, per0 presenta algunos problemas importantes. Esta secuencia de comandos Incluye un nombre de usuario y una contraseiia en su interior Almacena la contraseiia en forma de texto sin procesar S610 protege una piigina Transmite la contraseiia en forma de texto sin procesar Estas cuestiones se pueden resolver con diferentes grados de esfuerzo y exito.

Almacenamiento de contrasenas
Existen muchos lugares en 10s que almacenar nombres de usuario y contraseiias mejores que dentro de urta sehencia de comandos. Los datos introducidos dentro de una secuencia de comandos resultan dificiles de modificar. Se podria escribir una secuencia de comandos que se modificara a si misma per0 no es una buena idea ya que supondria tener una secuencia de comandos en el servidor, que se ejecutaria en 6 1 per0 que otros podrian modificar o escribir sobre ella. Si almacenamos 10s datos en otro archivo dentro del servidor resultarii miis sencillo escribir un programa para agregar y eliminar usuarios y alterar contraseiias. El uso de secuencias de comandos u otros archivos de datos con funciones de almacenamiento presenta un limite en cuanto a1 numero de usuarios que se pueden incluir sin que se vea afectada la velocidad de la secuencia de comandos. Si tiene previsto almacenar y realizar busquedas en un archivo con una gran cantidad de elementos, deberia considerar la opci6n de utilizar una base de datos, como se coment6 anteriormente. Como regla, si el numero de elementos que necesita almacenar y buscar supera 10s 100, utilice una base de datos en lugar de un archivo. El uso de una base de datos para almacenar nombres de usuario y contraseiias complicarii la secuencia de comandos, per0 a cambio permitirii autenticar a muchos

14. Implementacio'n de la autenticacidn con PHP y M y S Q L

usuarios riipidamente. Tambikn permitirii escribir con facilidad una secuencia de comandos para agregar nuevos usuarios, para eliminar usuarios y para permitir que 10s usuarios cambien sus contrasefias. En el listado 14.2 se incluye una secuencia de comandos para autenticar visitantes utilizando una base de datos.
Listado 14.2. secretdb.php. Hemos utilizado MySQL para mejorar nuestro sencillo

mecanismo de autenticacion
<?php

if(!isset($HTTP~POST~VARS['r1ame'])&&!isset($l4TTP-POST-VARS['password'])) i
//El
?>

v i s i t a n t e t i e n e q u e i n t r o d u c i r un nornbre y una c o n t r a s e A a

< h l > P l e a s e Lcy Ini/hl> T h i s page i s s e c r e t . <form rnethod="postn a c t i o n = " s e c r e t d b . p h p " > ' <table border="lW> <tr> i t h > Usernarne < / t h > < t d > < i n p u t t y p e = " t e x t n name-"namew> < / t d > </tr> <tr> < t h > Password < / t h > < t d > < i n p u t t y p e = " p a s s w o r d " narne="password"> < / t d > </tr> <tr> < t d colspan="2" a l i g n = " c e n t e r W > < i n p u t type="subrnit" value="Log In"> </td> </tr> </table>

t
else

I
/ / e s t a b l e z c a c o n e x i h n a rnysql Srnysql = rnysql -c o n n e c t ( ' l o c a l h o s t ' , i f ( !$rnysql)
echo 'Cannot connect t o d a t a b a s e . ' ; exit; 'webauth', 'webauth'
);

I
seleccione l a base de datos pertinente 'auth' ); Srnysql = r n y s q l - s e l e c t - d b ( i f ( ! Srnysql)

//

i
echo 'Cannot s e l e c t d a t a b a s e . ' ; exit;

I
/ / c o n s u l t e l a b a s e d e d a t o s p a r a d e t e r r n i n a r s i e v i s t e un r e g i s t r o q u e //coincida

Desnrrollo W e b con PHP y MySQL


$query = "select count ( * ) name = '$nameT and pass = '$password'"; $result = mysql i f ( ! $result) from auth where

1
echo 'Cannot exit;

1
$count if
(
=

mysql_result( $result, 0, 0
)

);

$count > 0

1
/ / el nombre y la contrasefia del visitante son correctos echo '<hl>Here it is!</hl>'; echo 'I bet you are glad you can see this secret page.';
else

1
/ / el nombre y la contrasefia del visitante no snn correctos echo '<hl>Go Away!</hl>'; echo 'You are not authorized to view this resource.';

I
I
?>

La base de datos que estamos utilizando se puede crear conectando a MySQL como usuario raiz de MySQL y ejecutando 10s contenidos del listado 14.3.
Listado 14.3. createauthdb.sql. Estas consultas MySQL crean la base de datos auth, la tabla auth y dos usuarios de ejemplo

create database auth; use auth; create table auth ( name varchar(l0) not null, pass varchar(30) rlot null, primary key (name)
);

insert into ('user',

auth values 'pass');

insert ir,to auth values ( 'testuser', password('testl23') grant select, insert, update, delete on a ~ t h . ~ to webauth@localhost identified by 'webauth' ;

);

14. Implementacidn de la autenticacio'n con PHP y MySQL

Cifrado de contraseiias
Independientemente de d6nde almacenemos las contraseiias (en una base de datos o en un archivo), no conviene hacerlo como texto sin procesar porque corremos un riesgo innecesario. Podemos utilizar un algoritmo de comprobacidn aleatoria (hash) de una direcci6n para obtener una mayor seguridad con muy poco esfuerzo. La funci6n de PHP c r y p t ( ) proporciona una funcidn de comprobaci6n aleatoria de una direcci6n. Su sintaxis es la siguiente:
string crypt (string

str

[,

string

salt])

Dada la cadena s t r, la funci6n devolveri una cadena pseudoaleatoria. Por ejemplo, dada la cadena "pass" y el parimetro salt "xx", la funcidn c r y p t ( ) devolverti "xxkTlrnYjlikoI1".Esta cadena no se puede descifrar y convertir en "pass" ni siquiera por su creador, lo que puede que no resulte de gran utilidad a primera vista. Lo que hace que la funci6n c r y p t ( ) resulte util es que su resultado es siempre el mismo. Por lo tanto, si utilizamos la misma cadena y el mismo partimetro s a 1t , la funci6n c r y p t ( ) devolveri el mismo resultado siempre que se ejecute. En lugar de utilizar el siguiente cddigo de PHP
i f ( Susername
==

'user'

&&

Spassword

==

'pass'

1
//Aceptado, l a s contrasefias coinciden

podemos utilizar c6digo como &te


if (
)

Susernarne

==

'user'

&&

1
//Aceptado,
\

l a s c o n t r a s e ~ a sc o i n c i d e n

crypt($password,'xx')

==

'xxkTlmYjlikoI1'

No necesitamos saber qu6 aspect0 presenta "xxkTlmYjlikoI1"antes de aplicarle la funcidn c r y p t ( ) . Tan s610 necesitamos saber si la contraseiia escrita coincide como la cifrada inicialmente con la funci6n c r y p t ( ) . Como se mencion6 anteriormente, no conviene incluir 10s nombres de usuario y las contraseiias en una secuencia de comandos de manera expresa. Utilizaremos un archivo independiente o una base de datos para almacenar esta informaci6n. Si estamos utilizando una base de datos MySQL para almacenar 10s datos de autenticacibn, podemos utilizar la funci6n c r y p t ( ) de PHP o la funci6n PASSWORD ( ) de MySQL. Estas funciones no generan el mismo resultado, per0 estin diseiiadas con el mismo fin. Ambas toman una cadena y aplican un algoritmo de comprobaci6n aleatoria no reversible. Para utilizar P A S S W O R D ( ) , podriamos escribir la consulta SQL del listado 14.2 como
select count ( * I from auth where

Desarrollo Web con PHP y MySQL


name pass '$name1 and password ( 'Spassword'

= =

La consulta contari el ntimero de filas de la tabla auth que tengan un nombre igual a 10s contenidos de $name y un valor p a s s igual a1 resultado producido por PASSWORD ( ) aplicado a 10s contenidos de $ p a s s w o r d . Si 10s usuarios deben utilizar nombres de usuario tinicos, el resultado de esta consulta seri 0 o 1. Si examina de nuevo el listado 14.3, observari que hemos creado un usuario ('user') con una contraseiia sin cifrar y otro usuario con una contraseiia cifrada ('testuser') para ilustrar estos dos enfoques.

Protecci6n de piginas multiples


La tarea de crear una secuencia de comandos como esta para proteger rnis de una pigina resulta un poco rnis complicada. Como HTTP no tiene estado, no existe un enlace o asociaci6n automitica entre las solicitudes consecutivas de un mismo usuario. Este hecho dificulta la tarea de mantener datos de una pigina a otra, como la informaci6n de autenticaci6n introducida por un usuario. La forma rnis sencilla de proteger varias piginas consiste en utilizar 10s mecanismos de control de acceso incorporados en su servidor Web, como veremos en breve. Si queremos crear esta funcionalidad, podemos incluir partes de la secuencia de comandos ilustrada en el Listado 14.1 dentro de las piginas que queremos proteger. Utilizando a u t o p r e p e n d f i l e y a u t o a p p e n d f i l e , podemos adjuntar a1 principio o despu& el &dig: requerido para cada archivo en directorios concretos. El uso de estos directorios se analiz6 en un capitulo anterior. Si utilizamos este enfoque, iqu6 ocurriri cuando nuestros visitantes recorran varias paginas de nuestro sitio? No podemos obligarles a volver a introducir sus nombres y contraseiias para c3da pigina que deseen ver. Podemos adjuntar 10s detalles introducidos a cada hipervinculo de la pigina. Como 10s nombres de usuario pueden incluir espacios u otros caracteres no permitidos en 10s URL, deberiamos utilizar la funci6n u r l e n c o d e ( ) para codificar de forma segura estos caracteres. Sin embargo, este enfoque presenta todavia algunos problemas. Como 10s datos se incluira'n en piginas Web enviadas a1 usuario asi como 10s URL que visiten, las piginas protegidas que visiten resultarin visibles para todos 10s usuarios que utilicen el mismo equipo y retrocedan por las pa'ginas almacenadas en cache o examinen el historial del navegador. La contraseiia se envia entre el navegador y el servidor cada vez que se solicita una pigina, lo cual no resulta muy recomendable. Existen dos buenas formas de resolver estos problemas: la autenticaci6n bisica de HTTP y las sesiones. La autenticacibn ba'sica resuelve el problema de las piginas almacenadas en cache, per0 el navegador seguira' enviando la contraseiia a1 servidor con cada petici6n. El control de sesiones resuelve ambos problemas. En primer lugar examinaremos el proceso de autenticaci6n bisica de HTTP y dejaremos para capitulos posteriores el anilisis del control de sesi6n.

Autenticacion basica
La autenticacidn de usuarios es una tarea habitual, de ahi que HTTP incorpore funciones que se ocupan de ello. Las secuencias de comandos o 10s servidores Web pueden solicitar autenticacidn desde un navegador Web. El navegador Web se encargar6 de mostrar un cuadro de di6logo o un elemento similar para obtener la informacidn necesaria del usuario. Aunque el servidor Web solicite nuevos detalles de autenticacidn para cada peticidn del usuario, el navegador Web no necesitard pedir 10s detalles del usuario para cada p6gina. Por regla general el navegador almacena esta informacidn mientras el usuario tenga una ventana del navegador abierta y la reenvia autom6ticamente a1 servidor Web cuando 6ste la solicite sin interaccidn con el usuario. Esta funcidn de HTTP se denomina autenticacidn b6sica. Puede desencadenarla utilizando PHP o mecanismos incorporados a1 servidor Web. Examinaremos el metodo utilizado por PHP, por Apache y por 11s. El proceso de autenticacidn b6sica transmite el nombre de usuario y la contraseiia de un usuario en forma de texto sin procesar, por lo que no resulta muy seguro. HTTP 1.1 contiene un metodo algo m6s seguro conocido como autenticacidn de texto implicita, que utiliza un algoritmo de comprobacidn aleatoria (habitualmente MD5) para disfrazar 10s detalles de la transaccidn. Muchos servidores Web admiten la autenticacidn de texto implicita, per0 no ocurre asi con un n6mero significativo de navegadores Web. Microsoft Internet Explorer admite la autenticacidn de texto implicita desde su versidn 5.0. En el momento de escribir estas lineas, ni Netscape ni Mozilla la admiten. Adem6s del problema de compatibilidad con 10s navegadores Web, la autenticacidn de texto implicita resulta todavia poco segura. Tanto la autenticacidn bdsica como su variante por medio de res6menes ofrecen un bajo nivel de seguridad. Ninguna garantiza a 10s usuario3 que se est6 interactuando con el equipo deseado. Ambas permiten que un pirata inform6tico pueda reproducir la misma peticidn en el servidor. Como la autenticacidn b6sica transmite la contrasefia del usuario en forma de texto sin procesar, cualquier pirata informitico podria capturar paquetes y suplantar a1 usuario para realizar una peticidn. La autenticacidn b6sica ofrece un nivel bajo de seguridad similar a1 de las conexiones a traves de telnet o ftp, ya que las contraseiias se transmiten en forma de texto sin procesar. La autenticacidn de texto implicita results un poco m6s segura, ya que cifra las contraseiias antes de transmitirlas. Para proteger todas las partes de una transaccidn Web de forma segura se puede utilizar SSL y 10s certificados digitales. Consulte el siguiente capitulo, si desea implementar un sistema de proteccidn seguro. Sin embargo, en muchas ocasiones, resulta apropiado utilizar un sistema r6pido aunque relativamente inseguro, como la autenticacidn b6sica. La autenticacidn bdsica protege un dominio con nombre y exige el uso de un nornbre de usuario y una contraseiia v6lidas. Los dominios reciben nombres para poder alojar m6s de uno en el mismo servidor. Se puede dar el caso de que distintos

Desarrollo W e b con PHP y MySQL

archivos o directorios del mismo directorio formen parte de distintos dominios y que cada uno de ellos est6 protegido por un conjunto diferente de nombres y contrasefias. Los dominios con nombre tambi6n permiten agrupar varios directorios en un host fisico o virtual como dominio y utilizar una contraseiia para protegerlos todos.

Uso de la autenticacih b6sica en PHP


Por regla general, las secuencias de comandos son multiplataforma per0 el uso de la autenticaci6n bisica se basa en variables de entorno establecidas por el servidor. Para que una secuencia de comandos HTTP se pueda ejecutar en Apache utilizando PHP, en forma de m6dulo Apache o en IIS utilizando PHP como mddulo ISAPI, es necesario detectar el tip0 de servidor y comportarse de forma ligeramente diferente. La secuencia de comandos del Listado 14.4 se ejecutari en ambos servidores, per0 a diferencia de la mayor parte de las secuencias de comandos utilizadas eneste libro, es necesario que el parsmetro r e g i s t e r-g l o b l a s del archivo php.ini est6 activado.
Listado 14.4. PHP puede desencadenar autenticacion HTTP basica

/ / Si el usuario estd utilizando IIS, necesitamos establecer SPHP-ALITH-USER / / y $FHP-AUTH-PW if (substr($SERVER-SOFTWARE, 0, 9 ) == 'Microsoft' & & !isset($PHP-AUTH-USER) & & ! isset (SPHP-AUTH-PW) & & substr($HTTP~AUTHORIZATION, 0, 6 ) == 'Basic ' 1

list ($PHP-AUTH-USER, $PHP-AUTH-PW) = explode(':', base64 -decode(substr(SHTTP~AUTHORIZATION, 6 )1 ) ;

I
/ / Sustituya esto si se trata 3 e una instrucci6n con una base d e //dates o similar if (SPHP-AUTH-USER ! = 'user' I I SPWP-AUTH-PW ! = 'pass')
/ / el visitante no ha introducido sus datos o su / / nombre y contraseRa no son correctos header('WWW-Authenticate: Basic realm="Realm-Name"'); if (substr($SERVER_SOFTWARE, 0, 9 ) == 'Microsoft') header('Status: 401 Unauthorized'); else headerilHTTP/l.O 401 Unauthorized');

echo '<hl>Go Away!</hl>'; echo 'You are not authorized to view this resource.';

14. Irnplemmtncidn de la auter~ticacidncon P H P y MySQL

El c6digo del listado 14.4 actua de forma muy similar a la de 10s listados anteriores del capitulo. Si un usuario no ha introducido la informaci6n de actualizaci6n, se le pedira. Si 10s datos introducidos son incorrectos, se devolverh un mensaje rechazindolos. Si incluye un nombre d e usuario y una contraseba correctos, se devolverhn 10s contenidos d e la phgina. El usuario verh una interfaz algo diferente a la devuelta por 10s listados anteriores. No suminislramos un formulario HTML para la informacih de inicio d e sesi6n. El navegador del usuario mostrarfi un cuadro d e dislogo. Para algunas personas, ser$ una mejora mientras que otros preferirh disponer de control completo sobre 10s aspectos visuales de la interfaz. En la figura 14.4 se presenta el cuadro de didogo de inicio de sesi6n que devuelve Internet Explorer.

k h m Edlclon Ver Fmiunlos Herram~entasAyudn


Dlrsmon

1@J

hhllp//wcbw~vei/~bplril4/~t~I11led

.. .. . .

. $ lr

Figura 14.4. El navegador del usuario se encarga de la apariencia del cuadro de dialog0 al utilizar la autenticacion HTTP

Como el proceso d e autenticaci6n se delega en las funciones integradas en el navegador, 6ste opta por ejercer cierta discretion a1 procesar 10s intentos d e autorizaci6n fallidos. Internet Explorer permite a1 usuario realizar la autenticaci6n tres veces antes de mostrar la pigina d e rechazo. Netscape permitirfi que el usuario intente autenticarse las veces que lo desee (entre 10s distintos intentos, mostrarh una cuadro de didogo indicando que la autorizaci6n ha fallado y preguntarti a1 usuario si desea intentarlo de nuevo). Netscape scilo muestra la phgina de rechazo si el usuario hace clic en Cancelar.

Desarrollo W e b con PHP y MySQL

Como en el caso del c6digo de 10s listados 14.1 y 14.2, podemos incluir el c6digo del listado 14.4 en las paginas que deseemos proteger o adjuntarlos a1 principio de todos 10s archivos de un directorio.

Uso de la autenticacibn bisica con 10s archivos .htaccess de Apache


Podemos obtener resultados muy similares a 10s de la secuencia de comandos anterior sin escribir una secuencia de comandos de PHP. El servidor Web Apache incorpora una gran cantidad de m6dulos de autenticaci6n diferentes que se pueden utilizar para determinar la validez de 10s datos introducidos por un servidor. El mas sencillo de utilizar es mod a u t h , que compara pares de nombre y contraseiia con las lineas de un archivo d e texto incluido en el servidor. Para lograr el mismo resultado de la secuencia de comandos anterior, necesitamos crear dos archivos HMLT distintos, uno para el contenido y otro para la pagina de rechazo. En 10s ejemplos anteriores nos saltamos algunos elementos de HTML, entre ellos las etiquetas <html>y <body>,que deberiamos incluir a1 generar HTML. El listado 14.5 recoge el contenido que ven 10s usuarios autorizados. Hemos llamado a este archivo c o n t e n t . html. El listado 14.6 recoge la pagina de error, que hemos llamado r e j e c t i o n . h t m l . La visualizacidn de esta pagina es opcional, pero incorpora un toque profesional si se incluye informaci6n util en ella. Como la pigina se mostrara cuando un usuario intente entrar en un area protegida, el contenido util podria incluir instrucciones sobre c6mo registrarse para obtener una contrasefia o c6mo recuperarla y que nos la envien por correo electr6nico si la hemos olvidado.

Listado 14.5. content.html. Contenido de ejemplo


<htrnl><body> < h l > H e r e ~t i s ! < / h l > < p > I b e t you a r e g l a d you c a n s e e t h i s s e c r e t p a g e . < / p > </body></htrnl>

Listado 14.6. rejection.htrnl. Pagina de error de ejemplo


<titrnl><body> < h l > G o Away! < / h l > <p>You a r e n o t authorized t o v i e w t h i s r e s o u r c e . < / p > </body></htrnl>

Estos archivos no contienen nada nuevo. El codigo verdaderamente interesante para este ejemplo se recoge en el listado 14.7. Este archivo se puede denominar .htaccess y controlar6 el acceso a 10s archivos y a todos 10s subdirectorios incluidos dentro de su directorio.

14. Implementacidn de la autenticacidn con PHP y MySQL


Listado 14.7. .htaccess. Un archivo .htaccess puede establecer rnuchos pararnetros de configuracion de Apache, incluyendo la activacion del proceso de autenticacion
ErrorDocument 4 0 1 /chapterl4/rejection.html AuthUserFile /home/book/.htpass AuthGroupFile /dev/null AuthName "Realm-Name" AuthType Basic require valid-user

El listado 14.7 es un archivo .htaccess para activar un proceso de autenticacidn bisico en un directorio. En un archivo .htaccess se pueden configurar muchos parimetros, per0 las seis lineas del utilizado en este ejemplo se relacionan con el proceso de autenticacidn. La primera linea
ErrorDocument 401
/chapterl4/rejection.html

indica a Apache qu6 documento mostrar para aquellos visitantes que no logren autenticarse. o cumen t para suministrar piginas Puede utilizar otras directivas E r r o r D personalizadas para otros errores HTTP como el 404. Su sintaxis es la siguiente:
ErrorDocument ndrnero-de-error

URL

Para que una pigina procese el error 401, es importante que el URL dado est6 disponible publicamente. No resulta muy util suministrar una pigina de error personalizada para indicar a 10s usuarios que ha fallado su autorizacidn si la pigina esti bloqueada en un directorio en el que necesitan autenticarse para poder verlo. La linea
AuthUserFile /home/book/.;tpass

indica a Apache ddnde encontrar el archivo que contiene las contrasefias autorizadas de 10s usuarios. Este archivo se suele denominar h t p a s s per0 puede asignarle el nombre que desee. Lo importante no es el nombre sino el lugar utilizado para almacenarlo. No deberia almacenarse dentro del irbol Web ya que se podria descargar a travks del servidor Web. En el listado 14.8 se recoge el archivo .htpass de ejemplo. Ademis de especificar 10s usuarios individuales que estin autorizados, es posible especificar que s610 aquellos autorizados que se incluyan en determinados grupos dispongan de acceso a 10s recursos. En nuestro caso no lo hemos hecho, por lo que la linea

AuthGroupFile

/dev/null

establece que el a r c h i v o ~ u t h ~ r o ~ u pi l apunte e a / d e v / n u l l , un archivo especial de 10s sistemas Unix cuyo valor queda garantizado como nulo.

Desarrollo Web con P H P y MySQL

Como el ejemplo PHP, para utilizar autenticacidn HTTP, necesitamos aplicar un nombre a nuestro dominio de la siguiente forma:
AuthName "Nombre-Dominio"

Puede seleccionar el nombre de dominio que desee, per0 recuerde que este nombre se mostrard a 10s visitantes. Como se admiten varios metodos de autenticacidn, necesitamos especificar el que estamos utilizando. Vamos a utilizar la autenticacidn de tipo Basic como se especifica en la siguiente directiva:
AuthType B a s i c

Necesitamos especificar quien dispone de acceso. Podemos especificar usuarios o grupos concretos, o como hemos hecho, todos 10s accesos de usuarios autenticados. La linea
require valid-user

especifica que se conceda acceso a cualquier usuario vdlido.


Listado 14.8. htpass. El archivo de contraseiias almacena nombres de usuarios y la contraseia cifrada de cada usuario
u s e r l : 0nRp9M80GS7zM user2:nC13sOTOhp.ow u s e r 3 : yjQMCPWjXFTzU u s e r 4 :LOrnlMEi/hArne2

Cada linea del archivo .htpass contiene un nombre de usuario, dos puntos y la contrasefia cifrada del usuario, Los contenidos exactos del archivo . htpass variardn. Para crearlo, se utiliza un pequefio programa llamado htpas swd que se incluye en la distribucidn de Apache. El programa htpasswd se utiliza de una de las siguientes formas:
htpasswd
[ -cmdps

I a r c h i vo-de-co t r a s e f i a s nornbre d e- u s u a r i o
-

h t p a s s w d -b [ c r n d p s l

a r c h i vo-de-cotraseiias

nornbre-de-usuario

constreriia

El unico modificador que necesita utilizar es -c. Este modificador indica a htpasswd que Cree el archivo. Debe utilizarlo para el primer usuario que agregue. Debe tener cuidado de no utilizarlo para el resto de 10s usuarios porque si el archivo existiese, htpasswd lo eliminaria y crearia uno nuevo. Los modificadores opcionales m, d,p o s se pueden utilizar si desea especificar el algoritmo de cifrado que desea utilizar (incluida la opcidn de no utilizar cifrado alguno). El modificador b indica a1 programa que espere la contrasefia como pardmetro, en lugar de solicitarla, lo cual resulta 6til si desea llamar a htpasswd de forma no

14. lmplementacidn de la autenticacidn can P H P y MySQL

interactiva como parte de un proceso por lotes, per0 no deberia utilizarse si esti llamando a htpasswd desde la linea de comandos. Los siguientes comandos crean el archivo que se muestra en el listado 14.8:
htpasswd htpasswd htpasswd htpasswd -bc /horne/buok/.htpass user1 pass1 - b /horne/book/.htpass user2 pass2 -b /horne/book/.htpass user4 pass3 - b /horne/book/.htpass user4 pass4

Este tip0 de autenticaci6n resulta sencillo de configurar, per0 el uso de un archivo htacces s de esta forma plantea una serie de problemas. Los usuarios y las contraseiias se almacenan en un archivo de texto. Cada vez que un navegador solicita un archivo protegido por el archivo htacces s el servidor debe analizar dicho archivo y, a continuaci611, el archivo de contraseiias, para determinar la coincidencia del nombre de usuario y la contraseiia. En lugar de utilizar un archivo .ht a c ce s s, podriamos especificar las mismas acciones en el archivo httpd . conf,el archivo de configuraci6n principal para el servidor Web. Cada vez que se solicita un archivo se analiza un archivo .htacces s.El archivo httpd conf s610 se analiza cuando el servidor se abre inicialmente. Este m6todo resulta mds ripido per0 obliga a detener y reiniciar el servidor si necesita realizar cambios. Independientemente de d6nde almacene las directivas de servidor, seri necesario comprobar la contraseiia en el archivo de contrasefias de cada petici6n. Esta t&cnica, como en el caso de las vistas anteriormente en las que se utiliza un archivo sin procesar, no resulta adecuada cuando se manejan cientos o miles de usuarios.

Autenticacion b h i c a con IIS


Como Apache, IIS admite autenticaci6n HTTP. Apache utiliza el enfoque de UNIX y se controla mediante la edici6n de archivos de texto. En el caso de IIS, la configuraci6n se realiza a traves de cuadrbs de diilogo. Windows 2000 permite cambiar la configuraci6n de Internet Information Server 5 (IIS5)utilizando el Administrador de servicios de Internet. Esta utilidad se incluye dentro de la secci6n Herramientas administrativas del Panel de control. El Administrador de servicios de Internet presenta un aspect0 parecido a1 que se recoge en la figura 14.5. El control de drbol situado en la parte izquierda muestra que el servidor windows - se rve r incluye varios servicios. En el que estamos interesados es el sitio Web predeterminado. Dentro de estos sitio Web, tenemos un directorio llamado protected.Dentro de este directorio hay un archivo llamado content. html. Para agregar autenticaci61-1 bdsica a1 directorio protected,haga clic con el b o t h derecho del rat6n sobre 61 y seleccione Propiedades en el mend contextual. El cuadro de diilogo Propiedades permite cambiar una gran cantidad de parimetros del directorio. Las dos fichas en las que estamos interesados son Seguridad de directorios y Errores personalizados. Una de las opciones de la ficha de Seguridad de directorios es Control de autenticacion y acceso anonimo. Si hace clic sobre el b o t h Modificar se abriri el cuadro de diilogo que se muestra en la figura 14.6.

Desnrrollo W e b cor~P H P y MySQL

Fisura 14.5. La consola de administracion de Microsoft permite configurar Internet Information Server 5

Figura 14.6. llS5 permite el acceso anonimo de manera predeterminada, per0 nos permite activar la autenticacion

14. Implernentncidr~dr ln nutrtzticncidr~corz P H P y MySQL

Dentro d e este cuadro d e didogo, podemos deshabilitar el acceso anonimo y activar la autenticacion bdsica. Con 10s parfimetros que se muestran en la figura 14.6, so10 aquellos usuarios que suministren un nombre y una contrasefia adecuados pueden ver 10s archivos d e este directorio. Para poder duplicar el comportamiento d e 10s ejemplos anteriores, incluiremos una piigina para indicar a 10s usuarios que sus detalles d e autenticaci6n no son correctos. A1 cerrar el cuadro cie didlogo de 10s rnktodos d e autenticacibn podrernos seleccionar la ficha Errores personalizados. La ficha Errores personalizados, ilustrada en la figura 14.7, asocia errores con mensajes d e error. En este caso, hernos almacenado el rnismo archivo d e rechazo utilizado anteriorrnente, r e j e c t i o n . h t m l , ilustrado el listado 14.6.11s perrnite incluir mensajes d e error m6s especificos que 10s que permite Apache, con el c6digo de error HTTP que tuvo lugar y una explicaci6n. Podemos incluir diferentes mensajes para cada caso, per0 en nuestro ejemplo hernos optado por sustituir 10s dos que van a tener lugar en este ejemplo con nuestra pdgina d e error. Esto es todo lo que necesitamos hacer para implernentar la autenticacion d e este directorio utilizando IIS5. Como ocurre con gran parte del software d e Windows, resulta mds sencillo d e configurar que el software paralelo d e UNIX, per0 mds dificil d e copiar d e un equipo a otro o d e un directorio a otro. Tarnbikn resulta mds sencillo equivocarse a1 configurarlo y hacer que el equipo resulte inseguro. El peor defect0 de IIS es que para autenticar a 10s usuarios Web cornpara 10s datos d e registro con cuentas incluidas en el equipo. Si queremos perrnitir que el usuario " j o h n " se registre con la contrasefia " p a s s w o r d " , necesitamos crear una cuenta d e usuario en el equipo o en un dominio con su nornbre y contrasefia. Es necesario poner rnucha atencion a1 crear cuentas para procesos de autenticacion Web de forrna que 10s usuarios dispongan unicamente d e 10s derechos de cuenta que necesiten para ver pdginas Web y ningun otro derecho como acceso telnet.

Figura 14.7. La ficha Errores personalizados permite asociar paginas de error con eventos de error

Desnrrollo W e b con PHP y MySQL

Uso de la autenticacion mod auth mvsal


Como ya se ha indicado, el uso de mod a u t h con Apache es un metodo sencillo de configurar y eficaz. Sin embargo, como almacena 10s sitios en un archivo de texto, no resulta practico para sitios con trafico que reciban la visita de una gran cantidad de usuarios. Afortunadamente, puede disfrutar de la misma facilidad de uso que mod a u t h y de la velocidad de una base de datos utilizando mod a u t h m y s q l . Este Gddulo funciona priicticamente igual que mod a u t h , per0 como utilTza una base de datos MySQL en lugar de un archivo de t e x t ~ , ~ e r m ibuscar te sobre una larga lista de usuarios rapidamente. Para utilizar este mddulo, es necesario compilarlo e instalarlo en su sistema o pedirle a su administrador de sistema que lo instale.

Instalacion de mod auth mvsal


Para poder utilizar mod a u t h m y s q l , necesitarh configurar Apache y MySQL siguiendo las instrucciones incluidas en el Apbndice A con una serie de pasos adicionales. Las instrucciones de 10s archivos README y USAGE de esta distribucidn resultan bastante buenas. A continuacidn, incluimos un resumen de las mismas. 1. Obtenga el archivo de distribucidn correspondiente a1 modulo. Se encuentra incluido en el CD-ROM que se adjunta a1 libro, per0 puede obtener la ultima versidn de
h t t p : //www.rnysql. c o r n / d o c / e n / C o n t r i b . htrnl

o de

h t t - p : //www. r n y s q l . c o m / D o w n l o a d s / C o r ~ t r i b /

2. Descomprima el cddigo fuente.

3. Cambie a1 directorio mod a u t h m y s q l y ejecute c o n f i g u r e . Necesitarfi indicarle ddnde encontrarla instalacidn MySQL y el c6digo fuente de Apache. Por ejemplo:

per0 puede ser diferente.

4. Ejecute make y, a continuacidn, ma ke i n s t a 1 1. Necesitara agregar


a 10s parametros indicados en c o n f i g u r e a1 configurar Apache. Por ejemplo:

14. Implementacidn de la autenticacidn con P H P y MySQL

5. Tras aplicar el resto de 10s pasos del a p h d i c e A, tendri que crear una base de datos y una tabla en MySQL para incluir la informaci6n de autenticaci6n. No tiene por qu6 tratarse de una base de datos o tabla diferente; puede utilizar una tabla existente como la base de datos a u t h del ejemplo utilizado anteriormente.
6. Agregue una linea a1 archivo h t t p d . c o n f para suministrar a1 m6dulo mod a u t h my s ql 10s parimetros que necesita para establecer la conexi6n a M ~ S Q L~ .~directiv presentarfi a este aspecto:
AuthpMySQLpInfo hostname user password

La forma m i s sencilla de comprobar si la compilaci6n funciona es ver si se inicia el servidor Apache. Para iniciar Apache, escriba lo siguiente en caso de incorporar compatibilidad SSL:
/usr/local/apache/bir~/apachectl

startssl

Si no incorpora compatibilidad SSL, escriba


/usr/local/apache/birl/apachectl

start

Si se inicia con la directiva ~ u t -h M ~ S Q L~ n f en o el archivo h t t p d c o n f , el m6dulo mod -a u t h -my s ql se agregarfi satisfactoriamente.

Uso de mod-auth-niysql
Tras instalar el m6dul0, su uso resultari m i s cornplicado que utilizar mod-a u t h. El listado 14.9 muestra un ejemplo del archivo h t a c c e s s que autenticari usuarios con contrasefias cifradas almacenadas en la base de datos creada anteriormente en este capitulo.

Listado 14.9. El archivo .htaccess autentica usuarios utilizando una base de datos MySQL
ErrorDocument 401 /chapterl4/rej ectior~. html

AllthName "Realm Name" AuthType Basic Auth-MySQL-DB auth Auth-MySQL-Encryption-Types MySQL AuthpMySQLpPasswordpTable auth

Desarrollo W e b con PHP y MySQL


Auth-MySQL-Username --Field Auth-MySQLpPasswurdpField require valid-user
name pass

Como puede observar la mayor parte del listado 14.9 es igual a la del listado 14.7. Queda por especificar un documento de error para cuando falla la autenticacion (error 401). Tambien especificamos autenticacion basica y el nombre del dominio. Como ocurre con el listado 14.7, permitimos el acceso d e cualquier usuario valido y autenticado. Como estamos utilizando el m6dulo mod a u t h mys q l y no queremos utilizar todos 10s pardmetros predeterminados, disp%emosde algunas directivas para especificar c6mo deberia funcionar.~uthMySQL D B , Auth MySQL Pas sword Table, Auth MySQL Username ~ i e l Y d ~ i t M~SQL h password F i e l d esp& cifican el nombre de la base de datos, la tabla, elcamPo de nombre d e usuario y el campo de contrasefia, respectivamente. Hemos incluido la directiva Auth MySQL E n c r y p t i o n Types para especificar que queremos utilizar el cifrado d e contraseiias MySQL. Los valores aceptables s o n p l a i n t e x t , C r y p t DES oMySQL. C r y p t DES (elpredeterminado), queutiliza el sistema de contrasFfias cifradas DES e s t ~ n d a de r UNIX. Desde la perspectiva del usuario, este ejemplo del m6dulo mod a u t h mys q l funciona exactamente igual que el ejemplo mod a u t h . ~l navegadorWeb :1 presentard un cuadro de didlogo. Si la autenticaci6n resilta satisfactoria, se mostrard el contenido. Si la autenticacih falla, se devolverd la pdgina de error. Para muchos sitios Web, el modulo mod a u t h mysql es ideal. Es r5pid0, relativamente sencillo de implementar y permite~tiliza~cualquier mecanismo que resulte prdctico para agregar entradas debase de datos para nuevos usuarios. Para obtener mds flexibilidad y la posibilidad de lograr un control m5s exhaustivo sobre secciones de las pdginas, puede implementar su propio sistema de autenticaci6n utilizando PHP y MySQL.

Creacion de su propio sistema de autenticacion


Hemos visto c6mo crear nuestros propios metodos de autenticaci6n incluyendo algunos defectos y exige ciertos compromisos, y hemos utilizado metodos de autenticaci6n incorporados, que resultan menos flexibles que escribir nuestro propio c6digo. En un capitulo posterior, cuando abordemos el tema del control de sesiones, podremos escribir nuestro propio sistema de autenticaci6n con menos compromisos que en este capitulo. En un capitulo posterior, desarrollaremos un sistema de autenticaci6n simple de usuario que evite algunos de 10s problemas vistos aqui utilizando sesiones para realizar el seguimiento de variables entre pdginas. En otro capitulo posterior, aplicaremos este enfoque a un proyecto del mundo real y veremos c6mo se puede utilizar para implementar un sistema de autenticaci6n m5s exhaustivo.

14. lmplementacidn de la autenticacidn con PHP y MySQL

Lecturas adicionales
Los detalles de la autenticaci6n HTTP se especifican en la RCF 2617, que esti disponible en

bisica en Apache, La documentaci6n de mod -au t h, que controla la autenticaci61-1 puede encontrarla en

La documentaci61-1 del m6dulo mod a u t h mysql se incluye en el archivo de descarga. El tamafio de este archivo es ieque$, por lo que merece la pena descargarlo.

A continuacion
En el siguiente capitulo se explica c6mo salvaguardar 10s datos en todas las fases de procesamiento, desde su entrada, hasta su transmisi6n y almacenamiento. Incluye el uso de SSL, certificados digitales y cifrado.

En este capitulo, vamos a explicar como tratar de forma segura 10s datos de usuario desde la introducci6n y transmisi6n hasta la fase de almacenamiento, lo que nos permitir6 implementar una transacci6n entre nosotros y un usuario de forma segura de extremo a extremo. En este capitulo nos centraremos en 10s siguientes aspectos: C6mo suministrar transacciones seguras Uso de SSL (Secure Sockets Layer, Capa de sockets segura) Almacenamiento seguro Por qu6 almacenar nLimeros de tarjeta de credit0 Uso de la encriptaci6n en PHP

C6mo suministrar transacciones seguras


Para garantizar el suministro de transacciones seguras a travbs de Internet es necesario examinar el flujo de informaci6n de nuestro sistema y garantizar la seguridad de la informaci6n en cada punto. En el tema de la seguridad de Internet, no hay conceptos absolutos. NingLin sistema tiene garantizada su impenetrabilidad para siempre. El termino seguro indica que el nivel de esfuerzo aplicado a un sistema o transmisi6n es alto comparado con el valor de la informaci6n.

Si queremos dirigir nuestros esfuerzos de seguridad de manera eficaz, necesitamos examinar el flujo de la informaci6n a traves de todos las partes del sistema. En la figura 15.1 se ilustra el flujo que sigue la informaci6n de usuario en una aplicaci6n tipica escrita utilizando PHP y MySQL.

Figura 15.1. La inforrnacion de usuario es alrnacenada o procesada por 10s siguientes elementos de un entorno de aplicacion Web tipico.

Los detalles de cada transacci6n que tengan lugar en su sistema pueden variar en funci6n del diseiio, de 10s datos del usuario y de las acciones que desencadenaron la transacci6n. Puede examinar todos estos elementos de una manera similar. Cada transacci6n entre una aplicaci6n Web y un usuario comienza con el envio de una solicitud desde el navegador del usuario a traves de Internet hasta el servidor Web. Si la p6gina es una secuencia de comandos de PHP, el servidor Web delegar6 el procesamiento de la p6gina en el motor PHP. La secuencia de comandos de PHP puede leer y escribir datos en el disco. Tambien puede incluir o requerir otros archivos de PHP o HTML. Asi mismo puede enviar consultas de SQL a1 demonio de MySQL y recibir respuestas. El motor de MySQL es responsable de leer y escribir sus propios datos en el disco. Este sistema tiene tres partes fundamentales: El equipo del usuario Internet El sistema A continuaci6n, analizaremos 10s aspectos de seguridad relacionados con cada una de estas partes de manera separada, pero obviamente el equipo del usuario e Internet son las que quedan m6s lejos de nuestro control.

El equipo del usuario


Desde nuestro punto de vista, el equipo del usuario ejecuta un navegador Web. No disponemos de control sobre factores como la seguridad aplicada a1 equipo. Debemos

Desarrollo Web con PHP y MySQL

tener en cuenta que el equipo puede resultar muy poco seguro o que se trate de un terminal compartida en una biblioteca, escuela o cafe. Existen muchos navegadores diferentes en el mercado y cada uno de ellos incorpora funciones diferentes. Si consideremos unicamente las versiones mas recientes de 10s dos navegadores mas populares, las innumerables diferencias entre ellos afectaran a la forma de generar y representar el c6digo HTML, a lo que hay que afiadir las cuestiones de seguridad y funcionalidad. Debemos tener en cuenta que muchos usuarios deshabilitaran funciones que consideren como un riesgo para su seguridad o privacidad, como las funciones de Java, las cookies o JavaScript. Si utilizamos estas funciones, deberiamos comprobar que nuestra aplicaci6n no pierde demasiado atractivo para 10s usuarios sin ellas o considerar el uso de una interfaz menos completa que les permita utilizar nuestro sitio. Los usuarios situados fuera de 10s EEUU y Canada puede que utilicen navegadores que s610 admitan un sistema de encriptaci6n de 40 bits. Aunque el gobierno de 10s EEUU ha cambiado la ley en enero de 2002 para permitir la exportaci6n de encriptaci6n segura (excluyendo a aquellos paises sobre 10s que pese un embargo) y las versiones de 128 bits ya estan disponibles para la mayoria de 10s usuarios, es probable que muchos no hayan actualizado sus sistemas. Si no incluye garantias de seguridad a 10s usuarios de manera textual en su sitio, este hecho no deberia ser motivo de preocupaci6n para 10s desarrolladores Web ya que SSL se encargar2 de procesar automaticamente el nivel de seguridad mas alto que pueda establecer entre el servidor y el navegador del usuario. No podemos estar seguros de que la conexi6n a nuestro sitio Web se produzca desde un navegador Web utilizando la interfaz desarrollada para tal efecto. Las peticiones que llegan a nuestro sitio pueden proceder de otro sitio que est6 utilizando imageries o contenidos sin permiso de su propietario, o de una persona que est6 utilizando software como CURLpara evitar las medidas de seguridad. En un capitulo posterior examinaremos la biblioteca de CURL,que se puede utilizar para simular conexiones de3de un navegador. Como desarrolladores, esta biblioteca nos resulta de utilidad per0 recuerde que se puede utilizar de manera malintencionada. Aunque no podemos cambiar o controlar la forma en la que estan configurados 10s equipos de nuestros usuarios, debemos tenerlos en cuenta. La variedad de equipos utilizados por 10s usuarios para conectarse a Internet puede convertirse en un factor importante a la hora de decidir cuanta funcionalidad suministrar a traves de secuencias de comandos del lado del servidor (corno PHP) y cuanta a trav6s de secuencias de comandos del lado del cliente (corno JavaScript). La funcionalidad suministrada por PHP puede ser compatible con el navegador de todos 10s usuarios ya que el resultado final no es mas que una pagina HMTL. El uso de cualquier otro elemento que no sea c6digo JavaScript basico exigira tener en cuenta las diferentes funciones de cada versi6n de 10s navegadores. Desde la perspectiva de la seguridad, conviene utilizar secuencias de comandos del lado del servidor para operaciones como la validation de datos porque, de esta forma, nuestro c6digo fuente no resultara visible para el usuario. Si validamos 10s datos en JavaScript, 10s usuarios podran ver el c6digo y quizas evitarlo.

15. Implementacidn de transacciones seguras con P H P y MySQL

Los datos que resulte necesario guardar podemos almacenarlos en nuestros propios equipos, como archivos o registros de base de datos o en 10s equipos de nuestros usuarios en forma de cookies. En un capitulo posterior veremos c6mo utilizar cookies para almacenar datos restringidos (como una clave de sesi6n). La mayor parte de 10s datos que almacenamos deberian alojarse en el servidor Web o en nuestra base de datos. Existen buenas razones para almacenar la menor cantidad posible de datos en el equipo del usuario. Si la informaci6n no se almacena en nuestro equipo, no dispondremos de control sobre la seguridad de su almacenamiento, no podremos estar seguros de que el usuario no la eliminar6 ni podremos impedir que la modifique para intentar confundir a1 sistema.

Internet
A1 igual que ocurre con el equipo del usuario, tenemos muy poco control sobre las caracteristicas de Internet, per0 eso no significa que tengamos que ignorarlas a1 disefiar el sistema. Internet incorpora una gran cantidad de funciones interesantes, per0 es un lugar inseguro d e manera inherente. A1 enviar informaci6n desde un punto a otro, es necesario tener en cuenta que otros podrian verla o alterarla, como se coment6 en un capitulo anterior. Con esto en mente, puede decidir qu6 acci6n tomar. Podria optar por: Transmitir la informaci6n de todas formas, sabiendo que podria leerse. Cifrar o firmar la informaci6n antes de transmitirla para mantener su privacidad o protegerla ante posibles manipulaciones. Decidir que la informaci6n es demasiado valiosa para arriesgarse a divulgarla y buscar otra forma de dis2ribuirla. Internet es tambi6n un medio bastante an6nimo. Resulta dificil determinar si una persona con la que mantiene relaci6n resulta ser qui6n dice ser. Incluso en el caso de que podamos asegurarnos de que un usuario es qui6n dice ser, resultaria dificil demostrarlo sin ninguna duda en un for0 public0 como un tribunal, lo que puede dar lugar a problemas como el del repudio, visto en un capitulo anterior. En definitiva, las transacciones en Internet presentan dos problemas fundamentales, la privacidad y el repudio. Existen a1 menos dos formas diferentes de garantizar el flujo de la informaci6n desde nuestro servidor Web hasta Internet y viceversa: SSL (Capa segura de sockets) S-HTTP (Protocolo de transferencia de hipertexto seguro) Ambas tecnologias ofrecen mensajes privados y no manipulables, y autenticaci611, per0 SSL estii miis extendido y resulta m5s sencillo de implementar mientras que SHTTP no acaba de calar. En este capitulo examinaremos SSL.

Desarrollo Web con PHP y MySQL

Su sistema
La parte del universo sobre la que disponemos de control es nuestro sistema. Nuestro sistema viene representado por 10s componentes que se incluyen dentro del cuadro ilustrado en la figura 15.1. Estos componentes pueden estar separados fisicamente en una red o incluirse en un 6nico equipo fisico. Resulta bastante seguro despreocuparse de la seguridad de la informaci6n si delegamos esta tarea en productos de terceros. Es probable que 10s autores de estas aplicaciones hayan dedicado m6s tiempo a1 tema que nosotros. Mientras utilice una versi6n actualizada de un product0 reconocido, podr6 descubrir cualquier problema conocido mediante la acertada aplicaci6n de Google o su motor de busqueda preferido. Deberia asignar m6xima prioridad a la tarea de mantener esta informacion a1 dia. Si es responsable de 10s procesos de instalaci6n y configuraci6n, deberi preocuparse por la forma de instalar y configurar el software. Muchos errores de seguridad surgen como resultado de no seguir las advertencias de la documentaci6n o implican aspectos relativos a la administraci6n general del sistema. C6mprese un buen libro sobre la administraci6n del sistema operativo que tenga la intenci6n de utilizar o contrate 10s servicios de un administrador de sistema con experiencia. A1 instalar PHP deberia tener en cuenta que resulta m i s seguro y m6s eficiente hacerlo en forma de un m6dulo SAP1 para el servidor Web que ejecutarlo a trav6s de la interfaz CGI. Un aspect0 que debe considerar es qu6 pueden hacer sus secuencias de comandos. Preguntese qu6 datos potencialmente delicados trasmite su aplicaci6n a1 usuario a traves de Internet y qu6 datos estamos pidiendo a nuestros usuarios que nos envien. Si estamos transmitiendo informaci6n entre nosotros y nuestros usuarios cuya privacidad debamos garantizar o cuya manipulaci6n debamos dificultar, deberiamos considerar la opci6nde utilizar SSL. Ya hemos hablado del uso de SSL entre el equipo del usuario y el servidor. Tambien deberiamos prever la situaci6n en la que se transmitan datos desde un componente de nuestro sistema a otro a trav6s de la red. Un ejemplo tipico seria si nuestra base de datos estuviera alojada en un equipo diferente a nuestro servidor Web. PHP se conectaria a1 servidor MySQL a trav6s de TCPIIP y esta conexi6n no estaria encriptada. Si 10s equipos estuvieran en una red de Area local privada, deberia asegurarse de que la red es segura. Si 10s equipos se conectan a trav6s de Internet, el sistema probablemente resulte lento y necesite tratar la conexi6n de la misma forma que otras conexiones sobre Internet. Es importante asegurarse de que cuando 10s usuarios crean estar interactuando con nosotros que asi sea. La obtenci6n de un certificado digital proteger6 a nuestros visitantes contra pricticas de personificaci6n y nos permitiri utilizar SSL sin que 10s usuarios vean aparecer un mensaje de aviso adem6s de aportar u n aire de respetabilidad a nuestra aventura en linea. ~Comprueban minuciosamente nuestras secuencias de comandos 10s datos introducidos por 10s usuarios?

15. Implementacidn de transacciones seguras con PHP y MySQL

~Tenemos cuidado de almacenar la informacibn de manera segura? En las siguientes secciones responderernos a estas preguntas.

Us0 SSL
El protocolo SSL fue disefiado originalmente por Netscape para facilitar la seguridad de las comunicaciones entre servidores y navegadores Web. Desde entonces ha sido adoptado como el metodo e s t k d a r de manera no oficial por 10s navegadores y servidores para intercambiar informacibn delicada. Existe una amplia compatibilidad para la versibn 2 y 3 de SSL. La mayor parte de 10s servidores Web incluyen funcionalidad SSL o pueden aceptarla como mbdulo complementario. Internet Explorer y Netscape incorporan compatibilidad SSL desde la versi6n 3. Los protocolos de red y el software que 10s implemente se suelen organizar en forma de pila de capas. Cada capa puede pasar datos a la capa superior e inferior, y solicitar servicios de la capa situada por encima o por debajo. La figura 15.2 muestra una pila de protocolos.
...
TCPIUDP IP
Var~os

Capa de aplicacion Capa de transporte C a ~ de a red Capa de host a red

Figura 15.2. L a pila de protocolos utilizada por u n protocolo de capa de aplicacion como

el Protocolo de transferencia de hipertexto Cuando se utiliza HTTP para transferir informacibn, el protocolo HTTP llama a1 Protocolo de control de triTnsrn?sibn (TCP) que a su vez se basa en el Protocolo de Internet. Este protocolo necesita un protocolo adecuado para que el hardware de red pueda utilizarse para tomar paquetes de datos y enviarlos como sefial electrica a nuestro destino. HTTP es un protocolo de capa de aplicacibn. Existen muchos otros protocolos de capa de aplicacibn, como FTP, SMTP y telnet (corno se muestra en la figura) y otros como POP e IMAP. TCP es uno de 10s dos protocolos de capa de transporte utilizados en redes TCPIIP. IP es el protocolo de la capa de red. El host hasta la capa de red es responsable de conectar nuestro host (equipo) a una red. La pila de protocolos TCP/IP no especifica 10s protocolos utilizados para esta capa, ya que necesitamos diferentes protocolos para 10s diferentes tipos de redes. A1 enviar datos, &tos se dirigen a travbs de la pila desde una aplicacibn a un dispositivo fisico de red. A1 recibir 10s datos, 6stos se dirigen desde la red fisica, a traves de la pila, hasta la aplicacibn. El uso de SSL agrega una capa transparente adicional a este modelo. La capa SSL existe entre la capa de transporte y la capa de aplicacibn, como se ilustra en la figura 15.3. La capa SSL modifica 10s datos desde nuestra aplicacibn HTTP antes de pasar10s a la capa de transporte para enviarlos a su destino.

Desarrollo W e b con PHP y MySQL

Capa de aplicaci6n Protowlo de registro SSL TCP IP Host a red Capa SSL Capa de transporte C a ~ de a red C a ~ de a host a red

Figura 15.3. SSL agrega una capa adicional a la pila de protocolos asi corno protocolos de capa de aplicacion para controlar sus propias operaciones

SSL es tedricamente capaz de crear un entorno de transmisidn seguro para otros protocolos aparte de HTTP, pero se suele utilizar para HTTP. Se pueden utilizar otros protocolos porque la capa SSL es basicamente transparente. Esta capa proporciona la misma interfaz a 10s protocolos situados por encima que la capa de transporte subyacente. A continuacidn se encarga, de forma transparente, de 10s saludos, de la encriptacidn y de la decriptacidn. Cuando un navegador Web se conecta a un servidor Web seguro a trav6s de HTTP, 10s dos necesitan seguir un protocolo de saludo para llegar a un acuerdo sobre elementos como la autenticacibn y la encriptacidn. La secuencia de saludo implica 10s siguientes pasos:

1. El navegador se conecta a un servidor con SSL habilitado y solicita que se autentique.


2. El servidor envia su certificado digital. 3. El servidor puede solicitar opcionalmente (aunque no suele ser lo normal) a1 navegador que se autentique.
4. El navegador presenta una lista con 10s algoritmos de encriptacidn y funciones hash que admite. El servidor selecciona la encriptacidn mas segura que admite.

5. El navegador y el servidh generan claves de sesidn:


5.1. El navegador obtiene la clave publica desde su certificado digital y la utiliza para encriptar un numero generado de forma aleatoria.
5.2. El servidor responde con mas datos aleatorios en forma de texto sin procesar (a menos que el navegador haya suministrado un certificado digital en la solicitud del servidor en cuyo caso el servidor utiliza la clave publica del navegador). 5.3. Las claves de encriptacidn para la sesidn se generan a partir de estos datos aleatorios utilizando funciones hash.

El proceso de saludo no es instantaneo porque la generacidn de datos aleatorios de calidad, la decriptacidn de 10s certificados digitales, la generacidn de las claves y el uso de la criptografia de clave publica lleva su tiempo. Afortunadamente, 10s resultados se guardan en cach6, de manera que si el mismo navegador y servidor desean intercambiar varios mensajes seguros, el proceso de saludo y el tiempo de procesamiento requerido s610 tendran lugar una vez.

15. Implementacidn de transacciones seguras con PHP y MySQL

Cuando 10s datos se envian a traves de una conexi6n SSL, tienen lugar 10s siguientes pasos:

1. Se dividen en paquetes que resulten sencillos de procesar. 2. Cada paquete se comprime (opcionalmente).
3. Cada paquete lleva asignado un c6digo de autenticaci6n de mensaje (MAC) calculado utilizando un algoritmo hash.
4. El c6digo MAC y 10s datos comprimidos se combinan y se encriptan. 5. Los paquetes encriptados se combinan con informaci6n de cabecera y se envian a la red. En la figura 15.4 se ilustra todo el proceso. Como observarA en el diagrama, el encabezado TCP se agrega tras encriptar 10s datos, lo que significa que la informaci6n dirigida podria manipularse y aunque 10s husmeadores no puedan ver la informaci6n que estamos intercambiando si podrian ver quien lo estd haciendo. La raz6n por la que SSL realiza la compresi6n antes de la encriptaci6n responde a que, aunque el trdfico de red pueda (como ocurre a menudo) comprimirse antes de transmitirse por una red, 10s datos encriptados no se comprimen bien.
Nuestros datos <html><head><title><MyPage<nitle>...

/
Paquetes de datos

F $
I

&F ']
Cornprimir

Datos cornprirnidos

Codigo de rnensaje de autenticac~on

Paquetes encriptados

Paquetes TCP

Figura 15.4. SSL divide, comprirne, aplica una funcion hash a 10s datos y 10s encripta antes de enviarlos

Los sistemas de compresi6n se basan en la identificaci6n de repeticiones o patrones dentro de 10s datos. El intento de aplicar un algoritmo de compresi6n tras convertir 10s datos en un conjunto aleatorio de bits mediante un proceso de encriptaci6n no

Desarrollo Web con PHP y MySQL

tiene mucho sentido. Seria una pena si SSL, que fue diseiiado para incrementar la seguridad de la red, tuviera el efecto secundario de incrementar el trifico de red. Aunque SSL es relativamente complejo, 10s usuarios y 10s desarrolladores resultar i n ajenos a gran parte de lo que ocurre, ya que sus interfaces externas simulan protocolos existentes. En el futuro, SSL 3.0 podria ser sustituido por TLS 1.0 (Seguridad de capa de transporte) per0 en el momento de escribir estas lineas, TLS se encuentra todavia en la fase de estindar de borrador y no resulta compatible con la mayoria de 10s servidores y navegadores. La intencidn de TLS es la de convertirse en un verdadero estAndar abierto, en lugar de un estindar definido por una organizacidn que se ha puesto a disposicidn de otras. TLS se basa directamente en SSL 3.0 per0 contiene mejoras pensadas para superar 10s puntos debiles de SSL.

Filtrado de la entrada de 10s usuarios


Uno de 10s principios de la construccidn de una aplicacidn Web segura es que no se debe confiar nunca en la informacidn introducida por el usuario. Filtre siempre 10s datos introducidos por el usuario antes de colocarlos en un archivo o base de datos, o de pasarlos a travks de un comando de ejecucidn del sistema. A lo largo de este libro hemos hablado varias veces de las t6cnicas que se pueden utilizar para filtrar las entradas de 10s usuarios. A continuacidn, 10s recogemos brevemente para recordarlas. La funcidn addslashes ( ) deberia utilizarse para filtrar 10s datos del usuario antes de pasarlos a una base de datos. Esta funcidn evitari todos 10s caracteres especiales que podrian presentar problemas en una base de datos. Puede utilizar la funcidn stripsl_as hr+s ( ) para devolver 10s datos a su forma original. Comillas mdgicas. Puede activar las directivas magic quotes-gpc y magic quotes-runtime en su archivo php.ini. Estas dirictivas agregan y quitanias barras invertidas automAticamente. La directiva magic quotes gpc aplicari este formato a las variables GET, POST y cookies entrantes y la directiva magic quotes-runtime lo aplicari a 10s datos dirigidos o procedentes de bases de datos. La funcidn escapeshell cmd ( ) deberia utilizarse a1 pasar datos del usuario a llamadas s ys tem ( ) o exec ( ) o a apdstrofes invertidos. Esta funcidn evitarA todos 10s metacaracteres que se puedan utilizar para obligar a1 sistema a ejecutar comandos arbitrarios introducidos por un usuario malintencionado. Puede utilizar la funcidn strip tags ( ) para limpiar de etiquetas HTML y PHP una cadena. Esta funcidn eiitari que 10s usuarios introduzcan secuencias de comandos malintencionados en 10s datos que puedan representarse en el navegador.

15. Implementacidn de transacciones seguras con PHP y M y S Q L

Puede utilizar la funci6n htmlspecialchars ( ) ,que convierte 10s caracteres en sus equivalentes de entidad HTML. Por ejemplo, < se convertirA en &It ;. Esta funci6n convierte todas las etiquetas de secuencia de comandos en caracteres inofensivos.

Suministro de un almacenamiento seguro


Los tres tipos diferentes de datos almacenados (archivos HTML o PHP, datos relacionados con secuencias de comandos y datos MySQL) se almacenarin en Areas diferentes del mismo disco, aunque se muestran de forma separada en la figura 15.1. Cada tip0 de almacenamiento requiere adoptar distintas precauciones y se examinar6 de manera individual. El tip0 de datos miis peligroso que almacenaremos es el contenido ejecutable. En un sitio Web, suelen adoptar la forma de secuencias de comandos. Es necesario poner mucho cuidado a1 establecer 10s permisos de archivo dentro de la jerarquia Web. En concreto, el iirbol de directorios cuyo primer elemento es htdocs en un servidor Apache y inetpub en un servidor 11s. Otros necesitan disponer de permisos para leer nuestras secuencias de comandos para poder ver su salida, per0 no deberian tener permiso para escribir o editarlos. La misma advertencia se aplica a 10s directorios incluidos dentro de la jerarquia Web. S610 nosotros deberiamos disponer de permiso para escribir en dichos directorios. Otros usuarios, incluido el usuario utilizado por el servidor Web para ejecutarse, no deberian disponer de permiso para escribir o crear nuevos archivos en directorios que se puedan cargar desde el servidor Web. Si permite que otros escriban archivos en este punto, podrian crear una secuencia de comandos malintencionada y ejecutarla a1 cargarla a trav6s del servidor Web. Si sus secuencias de cornandm necesitan disponer de permiso para escribir en 10s archivos, Cree un directorio fuera del iirbol Web para ello, en especial si se trata de secuencias de comandos para la carga de archivos en el servidor. No deberian mezclarse las secuencias de comandos y 10s datos que escriben. A1 escribir datos delicados, es probable que se vea tentado a encriptarlos como primer paso. En este enfoque, sin embargo, no resultar6 de mucho valor. Veamos por qu6: si tememos un archivo llamado numeros ta j etascredito . txt en nuestro servidor Web y un pirata informitico obtiene acceso a nuestro servidor y logra leerlo, iqu6 podria leer? Para poder encriptar y decriptar 10s datos necesitamos un programa que 10s cifre y un programa que 10s descifre, y uno o varios archivos de claves. Si el pirata puede leer 10s datos, nada le impedirA, con toda probabilidad, leer 10s archivos de clave asi como otros archivos. La encriptaci6n de 10s datos puede resultar valiosa en un servidor Web, per0 s610 si el software y las claves para decriptar 10s datos no se almacenan en el servidor Web sin0 en otro equipo. Una forma de tratar datos delicados de forma segura seria encriptarlos en el servidor y transmitirlos a otro equipo, por correo electr6nic0, por ejemplo.

Desarrollo Web con PHP y M y S Q L

Los datos de la base de datos son similares a 10s archivos de datos. Si se configura MySQL de manera correcta, s610 MyQSL podrti escribir en sus archivos de datos, lo cual significa que s610 necesitamos preocuparnos por 10s accesos de 10s usuarios dentro de MySQL. Ya se ha comentado el sistema de permisos de MySQL, que asigna derechos concretos a nombres de usuarios concretos en hosts concretos. Tambikn hay que destacar el hecho de que a menudo necesitaremos escribir una contraseiia de MySQL en una secuencia de comandos de PHP. Por regla general, las secuencias de comandos de PHP se pueden cargar publicamente. Este hecho no es tan peligroso como pudiera parecer a primera vista ya que si no se penetra en la configuraci6n del servidor Web, el c6digo PHP no resultarti visible desde el exterior. Si el servidor Web se configura para analizar archivos con la extension .php usando el intQprete de PHP, no se podrti ver desde fuera el c6digo sin interpretar. Sin embargo, conviene tener cuidado a1 utilizar otras extensiones. Si coloca archivos .inc en sus directorios Web, cualquier persona que 10s solicite recibir6 el c6digo sin analizar. Por lo tanto, serti necesario colocar 10s archivos de inclusi6n fuera del tirbol Web, configurar el servidor para que entregue archivos en esta extension o utilizar .php tambikn como extensidn en kstos. ~i esta compartiendo un servidor Web con otros, las contraseiias de MySQL podrian resultar visibles a otros usuarios del mismo equipo que puedan ejecutar secuencias de comandos a travks del mismo servidor Web. Esta situaci6n puede resultar inevitable en funci6n de la configuraci6n del sistema. Para evitarla, puede configurar el servidor Web de manera que ejecute secuencias de comandos como usuarios individuales o que cada usuario ejecute su propia instancia del servidor Web. Si no es el administrador del servidor Web (corno ocurrirti con toda probabilidad si comparte un servidor), es aconsejable que comente esta situaci6n con el administrador y busque opciones de seguridad.

#or que almacenar numeros de tarjeta de credito?


Tras comentar el tema del almacenamiento seguro de datos delicados, debemos detenernos en un tip0 de datos que merece especial atenci6n. Los usuarios de Internet esttin especialmente preocupados por sus numeros de tarjeta de crkdito. Si va a almacenar estos numeros, debe prestar especial cuidado. Preguntese para quk 10s necesita y si resulta verdaderamente necesario almacenarlos. iQuk va hacer con un numero de tarjeta? Si el tip0 de transacciones con el usuario va a ser esportidico y su sistema realiza el procesamiento de tarjetas en tiempo real, convendria aceptar el numero de tarjeta del cliente y enviarlo directamente a la pasarela de procesamiento de transacciones sin almacenarlo. Si necesita aplicar cargos cada cierto tiempo, por ejemplo aplicar una cantidad mensual a cada tarjeta por una suscripci6n, esta opci6n puede que no resulte la mtis acertada. En este caso, deberia considerar la posibilidad de almacenar 10s numeros en algun lugar distinto a1 servidor Web.

15. Implementacidn de transacciones seguras con P H P y MySQL

Si va a almacenar grandes cantidades de detalles relativos a las tarjetas de clientes, asegurese de que el administrador del sistema tenga experiencia en el tema y que disponga de tiempo para comprobar las actualizaciones de la informaci6n de seguridad del sistema operativo y de otros productos que utilice.

Uso de encriptacion en PHP


Una acci6n sencilla per0 util a la que podemos recurrir para demostrar el uso de la encriptacih es enviar un mensaje de correo electr6nico cifrado. El estandar de facto utilizado para encriptar correos electr6nicos durante muchos aiios ha sido PGP, que equivale a Pretty Good Privacy (Privacidad bastante buena). Este estandar fue escrito por Philip R. Zimmermann especialmente para agregar privacidad a1 correo electronico. Existen versiones gratuitas de PGP, per0 debe tener en cuenta que no se trata de software gratuito. La versi6n gratuita s610 se puede utilizar de manera legal con fines no comerciales. Para obtener una licencia de PGP fuera de 10s EEUU y Canada, consulte la lista de sitios de descarga internacional en la pigina de PGP: h t t p : / /www . p g p i .o r g . Recientemente ha surgido una alternativa de c6digo abierto a PGP. GPG (Gnu Privacy Guard) no contiene algoritmos patentados y se puede utilizar comercialmente sin restricci6n. Ambos productos realizan la misma tarea de forma similar. Si tiene pensado utilizar herramientas de linea de comandos, la elecci6n no importa, per0 cada una incorpora interfaces diferentes como complementos para programas de correo electr6nico que descifran 10s mensajes recibidos automhticamente. GPG esta disponible en h t t p : / /www.gnupg . o r g . Puede utilizar 10s dos productos de manera conjunta. Por ejemplo, puede crear un mensaje encriptado con GPG y dirigirlo a alguien que utilice PGP (siempre que sea una versi6n reciente) para descifrarlo. Como nosotros estamos interesados en la creaci6n de mensajes en el servidor Web, vamos a ver un ejemplo del uso de GPG. Si se utiliza PGP, la operaci6n no requerira muchos cambios. Como en el caso de otros ejemplos de este libro, necesitara disponer de GPG para que el c6digo funcione. Puede que ya tenga instalada esta herramienta en su sistema. De no ser asi, no se inquiete, ya que el procedimiento de instalaci6n resulta sencillo (aunque la configuraci6n puede complicarse).

Instalaci6n de GPG
Para agregar GPG a nuestro equipo de Linux, descargamos el archivo pertinente de www .gnupg .o r g . Necesitaremos utilizar gun z i p y t a r o extraer 10s archivos del archivo comprimido, dependiendo de su tipo, .tar.gz o .tar.bz2. Para compilar e instalar el programa, utilice 10s mismos comandos que en la mayor parte de las versiones de Linux:
configure (or ./configurar en funci6n de su sistema)

Desarrollo Web con PHP y MySQL


make make i n s t a l l

Si no es el usuario raiz, tendrfi que configurar la secuencia de comandos con la opci6n -prefix de la siguiente forma:
./configure p r e f ix=/path/tu/you~~/directory

ya que 10s usuarios distintos a1 usuario raiz no disponen de acceso a1 directorio predeterminado de GPG. Si todo discurre satisfactoriamente, GPG se compilara y el ejecutable se copiarfi en /usr / 1 ocal /bin/ gpg o en el directorio que especifiquemos. Puede cambiar muchas opciones. Consulte la documentation de GPG si desea obtener mfis detalles. Para un servidor Windows, el proceso resulta incluso mfis sencillo. Descargue el archivo zip, descomprimalo y coloque el archivo gpg.exe en algun punto de su PATH. (C:\ Windows \, por ejemplo).Cree un directorio en C: \ gnupg. Abra el simbolo de comandos y escriba gpg. Tambikn necesitamos instalar GPG o PGP y generar un par de claves en el sistema desde las que tengamos previsto comprobar el correo. En el servidor Web, existen muy pocas diferencias entre las versiones de linea de comandos de GPG y PGP, por lo que podemos utilizar GPG ya que resulta gratuito. En el equipo desde el que leer el correo, puede que prefiera utilizar una versi6n comercial de PGP por el complemento de interfaz grfifico que incorpora a1 lector de correo electrhico. Si no tiene un par de claves, genkrelas en el equipo en el que vaya a leer el correo electr6nico. Recuerde que un par de claves se compone de una clave publica que otros usuarios (asi como su secuencia de comandos de PHP) utilizarfin para encriptar el correo antes de enviirnoslo y una clave privada que se utilizar5 para descifrar 10s mensajes recibidos o firmar e l ~ o r r e o saliente. Es importante que el proceso de generaci6n de claves se realice en el equipo en el que se va a leer el correo y no en el servidor Web ya que la clave privada no debe almacenarse en el servidor Web. Si est6 utilizando la versi6n de linea de comandos de GPG para generar las claves, introduzca el siguiente comando:
gpg --gen-key

Debera responder a una serie de preguntas. La mayor parte de ellas incluyen una respuesta predeterminada que puede aceptar. Ademfis, se le pedirfi su nombre real, una direcci6n de correo electr6nico y un comentario, que se utilizari para designar a la clave. Por ejemplo, 'Luke Welling <luke@tangledweb. corn. au>'. Como puede apreciar el patr6n resulta claro. Si se incluyera un comentario, se colocaria entre el nombre y la direcci6n. Para exportar la clave publica del par de claves, puede utilizar el comando:
gpg -export

>

nornbredearchi v o

15. Implementacidn de transacciones seguras con P H P y MySQL

Como resultado se generard un archivo binario para su importaci6n en el archivo de claves de GPG o PGP en otro equipo. Si quiere enviar por correo electr6nico esta clave a otros usuarios, para que puedan importarla en sus propios archivos de claves, puede crear una versi6n ASCII como la siguiente:
qpq export a

>

nombrdearchivo

Tras extraer la clave p~blica, puede cargar el archivo en su cuenta en el servidor Web. Para ello, puede utilizar FTP. Los siguientes comandos asumen que estamos utilizando UNIX. Los pasos son 10s mismos que para Windows, per0 10s nombres de 10s directorios y 10s comandos del sistema serdn diferentes. Registrese en el servidor con su cuenta y cambie 10s permisos sobre el archivo para que 10s usuarios puedan leerlo. Escriba:
chrnod 6 4 4 nornbredear-chi vo

Necesitard crear un archivo de claves para que el usuario utilizado para ejecutar las secuencias de comandos de PHP pueda usar GPG. Este usuario dependerd de c6mo est6 configurado el servidor. A menudo suele ser el usuario "nobody", per0 puede ser cualquier otro. Cambie a1 usuario del servidor Web. Necesitard disponer de acceso de usuario raiz para ello. En la mayor parte de 10s sistemas, el servidor Web se ejecuta como nobody. En 10s siguientes ejemplos partiremos de este supuesto. (Puede cambiarlo por el usuario adecuado en su sistema.) Si este fuera en caso en su sistema, escriba:
su r o o t su nobody

Cree un directorio para el usuario n o b o d y y almacene el archivo de claves y otra informaci6n de configuraci6n..Este archivo deberia incluirse en el directorio raiz del usuario nobody. El directorio raiz de cada usuario se especifica en / e t c/p a s s wd. En muchos sistemas Linux, el directorio del usuario nobody es el directorio predeterminado / , sobre el que dicho usuario no tiene permiso para escribir. En muchos sistemas BSD, el directorio predeterminado para el usuario nobody es / n o e x i s t e n t e, que como no existe, no se puede escribir en 61. En nuestro sistema, el usuario n o b o d y se ha asignado a1 directorio raiz / tmp. Deberemos asegurarnos de que el usuario de servidor Web dispone de un directorio raiz sobre el que tenga permiso para escribir. Escriba
cd rnkdir

.q n u p g

El usuario n o b o d y necesitard una clave de firma propia. Para crearla, ejecute el siguiente comando de nuevo:

Desarrollo Web con PHP y MySQL

Como el usuario nobody es probable que no reciba ningun correo personal, podemos crear una clave de s610 firma. El 6nico objetivo de esta clave es permitirnos confiar en la clave piiblica extraida anteriormente. Para importar la clave publica exportada anteriormente, utilice el siguiente c6digo:
gpg -import nombredearchivo

Para indicarle a GPG que queremos confiar en esta clave, necesitamos editar sus propiedades de la siguiente forma:
gpg -edit-key 'Luke Welling <luke@tangledweb.com.au>'

En esta linea, el texto entre comillas es el nombre de la clave. Obviamente, el nombre de la clave no seri 'Luke Welling <luke@tangledweb.com.au>', sin0 una combinaci6n del nombre, el comentario y la direccion de correo electr6nico suministrada a1 generarlo. Este programa incluye la opci6n h e l p , que describiri 10s comandos disponibles t r u s t , s i g n y save. Escriba t r u s t para indicarle a GPG que confia en la clave completamente. Escriba sign para firmar esta clave publica utilizando la clave privada del usuario
nobody.

Finalmente, utilice save para salir del programa manteniendo 10s cambios.

C6mo probar GPG


Ya tenemos configurado GPG y listo para su uso. La creaci6n de un archivo que contenga alguna sec~encia de texto y su almacenamiento como test.txt nos permitiri utilizarlo para guardarlo. Escriba el siguiente comando (modificado para utilizar el nombre de su clave).

gpg - a r e c i p i e n t test.txt

'Luke

Welling

<luke@tangledweb.com.au>'

-encrypt

deberia devolver la siguiente advertencia


gpg: Warning: using insecure memory!

y crear un archivo llamado test.txt.asc. Si abre este archivo, deberia ver un mensaje encriptado como el siguiente:
--BEGIN PGP MESSAGE--Verslon: GriuPG v1.0.3 (GNU/Linux) Comment: For info see http://www.gnupq.org

15. lmplementacidn de transacciones seguras con PHP y MySQL

Deberia poder transferir este archivo a1 sistema en que gener6 la clave inicialmente y ejecutar
gpg test.txt.asc

para ver el texto original de nuevo. Para colocar el texto en un archivo, en lugar de mostrarlo en la pantalla, puede utilizar el modificador -0 y especificar un archivo de salida de la siguiente forma:
qpq d o test.out test.txt.asc

Si tiene configurado GPG para que el usuario utilizado para ejecutar las secuencias de comandos PHP pueda usarlo desde a1 linea de comandos. Si no funcionara, consulte a su administrador del sistema o la documentaci6n de GPG. El listado 15.1 y 15.2 permite enviar correo electr6nico encriptado utilizando PHP para llamar a GPG.
Listado 15.1. private-mail.php.
Nuestro formulario HTML para enviar correo electronico encriptado

<html> <body> <hl>Send Me Private Mail</hl>

* <?php / / puede que necesite cambiar esta linea, si no utiliza //los puertos predeterminados; 8 0 para el trifico normal y 443 para SSL if($HTTP-SERVER-VARS['SERVER-P0RT1]!=443) echo '<p><font color="redW> WARNING: you have not connected to this page using SSL. Your messaqe could be read by others.</font></p>';
?>

<form method="postV action="send -private mail.phpn><br / > Your email address:<br / > <input type="textW name="fromW sizeN="38"><br / > Subject :<br / > <input type="textW name="titleN size="38"><br / > Your message:<br / > <textarea name="bodyM cols="30" rows="lOW> </textarea><br / > <input type="submitN value="Send!"> </form> </body> </html>
-

Desarrollo Web con PHP y MySQL


Listado 15.2. send-private-rnail.php. Nuestra secuencia de comandos de PHP para llamar a G P G y enviar correos electronicos encriptados
<?php //cree $from $title $body

nombres d e variables cortos $HTTP-POST-VARS['~~~~'~; = S~~~~-Pos~-vARs[~title']; = SHTTP-POST-VARS['body'l;


=

/ / Indique a gpg ddnde encontrar el archivo d e claves / / En este sistema, el directorio raiz del usuario nobody putenv('GNUPGHOME=/tmp/.gnupg');

es

/tmp/

//cree un nombre d e archivo 6nico Sinfile = ternpnami", 'pgp'); $outfile = $infile.'.asc'; //escriba el texto del usuario $fp = fopen (Sinfile, 'w' ) ; fwrite($fp, $body); f c l o s e ( $ f p ); en el archivo

//configure el comando $command ="/usr/local/bin/gpg -a \ \ -recipient 'Luke Welling <luke@tangledweb.com.au>' e n c r y p t -o $outfile Sinfile"; / / ejecute el comando gpg system($command, $ r e s u l t ) ; //elimine el archivo unlink($infile); temporal no encriptado

\\

else 1 //lea el archivo encriptado $contents = fread (Sfp, filesize ($outfile) 1; //elimine el archivo temporal encriptado unlink($outfile); mail($to-email, $title, $contents, "From: echo '<hl>Message Sent</hl> <p>Your message was encrypted and <p>Thank you.'</p>'; $from\nM); sent.i/p>

15. lmplementacidn de transacciones seguras con P H P y MySQL

echo

'<hl>Error:</hl> <p>Your message could not be encrypted, s o has not been sent.</p> <p>Scrry. </p>' ;

I
?>

Para que este c6digo funcione, necesitara cambiar algunos elementos. El correo electronic0 se enviara a la direcci6n incluida en $to-email. Tendrd que modificar la linea

para reflejar la ubicaci6n del archivo de claves GPG. En nuestro sistema, el servidor Web se ejecutari como usuario nobody y el directorio raiz sera / tmp/. Estamos utilizando la funci6n tmpnam ( ) para crear un nombre de archivo temporal unico. Puede especificar el directorio y un prefijo de nombre de archivo. Vamos a crear y a eliminar estos archivos en un segundo, por lo que no resulta muy importante c6mo 10s llamemos. Vamos a especificar el prefijo 'pgp', per0 vamos a permitir que PHP utilice el directorio temporal del usuario. La instrucci6n
$command
=

'/usr/local/bin/gpg -a ' . '-recipient 'Luke Welling <luke@tangledweb.com.au>' '-encrypt -o $outfile Sinfile';

'.

configura el comando y 10s parametros que se utilizardn para llamar a gpg. Debera modificarlo para adaptarlo a sus necesidades. A1 utilizarlo en la linea de comandos tendra que indicar a GPG qu6 clave utilizar para encriptar el mensaje. La instrucci6n

ejecuta 10s comandos almacenados en $command y almacena el valor devuelto en $ result.Podemos ignorar el valor devuelto, per0 nos permite tener una instruccion if e indicar a1 usuario que algo ha ido mal. Cuando hayamos terminado con 10s archivos temporales utilizados, 10s eliminamos con la funci6n unlink ( ) . Por lo tanto, el correo no encriptado del usuario se almacenard muy poco tiempo en el servidor. Y si el servidor fallara durante la ejecucion, el archivo podria quedarse en el servidor. A1 considerar la seguridad de nuestra secuencia de comandos, es importante tener en cuenta todos 10s flujos de informaci6n dentro del sistema. GPG encriptara nuestra secuencia de comandos y permitira que nuestro destinatario la descifre, per0 cabe preguntarse c6mo lleg6 la informaci6n originalmente desde el remitente. Si suministramos una interfaz Web para enviar correos GPG encriptados, el flujo de la informaci6n seguiria la ruta ilustrada en la figura 15.5.

Desnrrollo Web con P H P y MySQL

1 Navegador del Remtente

N Sewidor
Web

ewdor de correo del desl~nalario

, -

Clbenle

de c07w del

aes~matar 9

Figura 15.5. En nuestra aplicacion de correo electronico cifrado, el mensaje s e envia a

traves de Internet tres veces En esta figura, cada flecha representa el mensaje enviado desde u n equipo a otro. Cada vez que se envia el mensaje, viaja a trav4s d e Internet y puede pasar por una gran cantidad d e redes y equipos intermedios. La secuencia d e comandos que estamos examinando aqui existe e n el equipo denominado Servidor Web en el diagrama. En el servidor Web, el mensaje se encriptari utilizando la clave publica del destinatario. A continuaci6n se enviar5 a trav6s de SMPT al servidor d e correo del destinatario. Este se conectarii a s u servidor d e correo electr6nic0, utilizando POP o IMAP probablemente, y descargarfi el mensaje utilizand o un lector d e correo. En este punto descifraremos el mensaje utilizando su clave privada. Los datos transferidos en la figura 15.5 se etiquetan como 1 , 2 y 3. Para las fases 2 y 3, la i n f o r m a c i h transmitida es u n mensaje GPG encriptado y no tienen ningun valor para nadie clue no tenga la clave privada. Para la transferencia 1, el mensaje transmitido e s el texto que el remitente introduce en el formulario. Si nuestra informaci6n e s lo suficientemente importante como para encriptarla e n la segunda y tercera etapa del viaje, es u n poco tonto enviarla sin encriptar en la primera fase. Por lo tanto, esta secuencia d e comandos pertenece a u n servidor que utiliza SSL. Si conectainos a nuestra secuencia d e comandos utilizando u n puerto distinto a1 443, se generarti una advertencia. Este puerto es el puerto utilizado por SSL d e manera predeterminada. Si su servidor utiliza u n puerto distinto para SSL, necrsitard mo* dificar este c6digo. En lugar d e suministrar un mensaje d e error, podemos procesar esta situacion d e otras formas. Podemos redirigir a1 usuario a1 mismo URL a trav4s d e una conexi611 SSL. Podemos optar por ignorarlo porque por regla general no resulta importante si el formulario se entrega utilizando una conexion segura. Lo clue si suele ser importante es clue 10s detalles que el usuario ha introducido e n el formulario se nos envien de forma segura. Bastaria con indicar 1111 URL completo como acci6n en nuestro formulario. En la actualidad, la etiqueta d e apertura del formulario presenta este aspecto:

Podriamos modificarla para enviar datos a trav6s d e SSL incluso si el usuario se conecta sin SSL, d e la siguiente forma:

Si codificamos d e manera especifica el URL completo de esta forma, nus aseguraremos d e que 10s datos del visitante se envien utilizado SSL, per0 necesitaremos mo-

15. lmplementacidn de transacciones seguras con PHP y MySQL

dificar el codigo cada vez que lo utilicemos en otro servidor o incluso en otro directorio. Aunque en este caso y en muchos otros, no es importante enviar el formulario a1 usuario a travds de SSL, resulta una buena idea hacerlo asi. Si aparece el simbolo de un candado en la barra de estado de sus navegadores, 10s usuarios podrin estar seguros de que la informaci6n se est5 enviando de forma segura. No necesitarin examinar el cddigo HTML para determinar el atributo de accibn.

Lecturas adicionales
La especificacion de la versi6n 3 de SSL podri encontrarla en Netscape:
http://horne.netscape.corn/eng/ss13/

Si desea saber mis sobre c6mo funcionan las redes y 10s protocolos de redes, puede consultar un texto de introducci6n ya clisico Computer Networks de Andrew S. Tanenbaum.

Con esto terminamos el anilisis de 10s aspectos relacionados con el comercio electronic~ y la seguridad. En la siguiente seccibn, examinaremos tdcnicas m i s avanzadas de PHP, como la interacci6n con otros equipos en Internet, la generation de imigenes de forma instantinea y el uso del control de sesi6n.

En un capitulo anterior, vimos c6mo leer y escribir datos en archivos del servidor Web. En este capitulo, vamos a examinar otras funciones de PHP que nos permiten interactuar con el sistema de archivos en el servidor Web. En este capitulo analizaremos 10s siguientes aspectos: Carga de archivos con PHP Uso de funciones de directwrio Interacci6n con archivos en el servidor Ejecuci6n de programas en el servidor Uso de las variables de entorno de servidor Para analizar 10s usos de estas funciones, examinaremos un ejemplo. Suponga que queremos permitir que nuestros clientes puedan actualizar parte de 10s contenidos de un sitio Web, por ejemplo, las noticias sobre nuestra compafiia. (0que queremos incorporar una interfaz m6s sencilla que la de FTP para su USO.) Una posibilidad podria consistir en permitir a 10s clientes que carguen archivos de contenido en forma de texto sin procesar. Estos archivos estarian disponibles en el sitio, a travks de una plantilla disefiada con PHP, como hicimos en un capitulo anterior. Antes de profundizar en las funciones del sistema de archivos, vamos a examinar brevemente el funcionamiento de la carga de archivos.

16. lrzteraccidr~corr cl sisternn d t n r c l ~ i v o s y el scrvidor

PHP incorpora una funcionalidad de gran utilidad que permite realizar cargas HTTP. En lugar de recorrer el camino del servidor a1 navegador utilizando HTTP, 10s archivos realizan el trayecto contrario, es decir, van desde el navegador a1 servidor. Por regla general, esta funci6n se implements mediante una interfaz d e formulario HTML. En la figura 16.1 se ilustra la que utilizaremos en nuestro ejemplo.

1 Upload new news files


11
Upload U x Bc

9 1

FI

1 I

Figura 16.1. El formulario HTML utilizado para la carga de este archivo consta de campos y tipos de campos diferentes de 10s incluidos en u n formulario HMTL normal Como puede ver, el formulario incluye un cuadro en el que el usuario puede introducir un nombre de archivo o hacer clic sobre el b o t h Browse para examinar 10s archivos disponibles localinente. Es posible que no haya visto un formulario de carga antes. En un instante veremos c61no implementarlo. Tras introducir un nombre de archivo, el usuario puede hacer clic sobre Send File para cargar el archivo en el servidor, donde le espera una secuencia de comandos de PHP.

MTM? oara la cawga de archivos


Para poder implementar la carga de archivos, necesitamos utilizar sintaxis d e HTML disponible para dicho fin. En el listado 16.1 se recoge el c6digo HMTL correspondiente a este formulario.
Listado 16.1. upload.html. Formulario HTML para la carga de archivos

Desarrollo W e b con PHP y MySQL


<input Upload <input \/form> . /body> </html> type="hiddenV name="MAX-FILE-SIZE" this file: <input name="userfilen type="submit" value="Send File"> value="1000000"> type="fi1ew>

Fijese en que este formulario utiliza POST. Las cargas de archivo tambien se pueden realizar con el metodo PUT admitido por Netscape Composer y Amaya. No funcionan con GET. Las funciones adicionales de este formulario son las siguientes: En la etiqueta <form>,debemos establecer el atributo enctype="multipart/ form-data " para permitir que el servidor sepa que viene un archivo con la informaci6n habitual del formulario. Debemos incluir un campo de formulario que establezca el archivo de tamaiio mdximo que se puede cargar. Se trata de un campo oculto y se muestra a continuation:

El nombre de este campo de formulario debe ser MAX F I L E SIZE. El valor es el tamaiio mdximo (en bytes) de archivos que per&tiremos que se carguen. Por el momento lo hemos establecido en 1000000 bytes (aproximadamente un megabyte). Puede aumentar o disminuir este tamaiio en funci6n de su aplicaci6n. Necesitamos una entrada para el archivo de tipo, que en el ejemplo se corresponden con la linea
<input name="userfile" type="file">

Puede seleccionar el nombre que desee para el archivo, per0 tengalo en cuenta cuando vaya a utilizarlo para acceder a su archivo desde la secuencia de comandos PHP de recepci6n.

U n inciso sobre seguridad


Antes de seguir adelante, conviene recordar que algunas versiones de PHP presentan ciertos puntos debiles en el c6digo para la carga de archivos. Si decide utilizar la funci6n de carga de archivos en u n servidor de producci6n, es aconsejable que utilice la versi6n mds actual de PHP y que se mantenga atento a 10s posibles parches que puedan surgir. Este hecho no deberia disuadirle de utilizar una tecnologia tan buena. Basta con poner atenci6n a1 escribir el c6digo y considerar la posibilidad de restringir el acceso a la funci6n de carga de archivos a 10s administradores del sitio y a 10s encargados de administrar el contenido, por ejemplo.

16. Interaccidn con el sistema de archivos y el servidor

Codigo PHP para procesar la tarea de carga del archivo


La tarea de escribir PHP para capturar el archivo resulta bastante sencilla. A1 cargar un archivo, se incluiri en una ubicaci6n temporal en el servidor Web. Se trata del directorio temporal predeterminado del servidor Web. Si no mueve o cambia el nombre del archivo antes de que termine la ejecucidn de la secuencia de comandos, se eliminari. Como nuestro formulario HTML consta de un campo llamado us e r f i l e , pasaremos cinco variables a PHP. Existen varias formas de acceder a estas variables. Puede utilizar la matriz superglobal $ FILES, disponible en PHP 4.1.0. gste es el m4todo recomendado. T a m b i h puede acceder a las variables a trav4s de la matriz $HTTP POST F I L E S o, si tiene activado el parimetro r e g i s t e r -g l o b a l s , puede accedera e1la;directamente. Sin embargo, 4ste es el dmbito en el que resulta m6s importante mantener desactivado el pardmetro r e g i s t e r -g l o b a l s , por lo que le recomendamos acceder a las variables de la siguiente forma: El valor almacenado e n $ F I L E [ ' u s e r f i l e l ] [ ' t m p - n a m e ' ] o $HTTP POST F I L E S [ ' u s e r f i l e l ] [ ' t m p n a m e ' ] e s e l l u g a r e n e l q u e e l archivo-se haalmacenado temporalmente e n e l servidor Web. El valor almacenado en $ F I L E [ ' u s e r f i l e ' ] [ 'name1 ] o $HTTP POST F I L E S [ u s e r f i1 e ] [ 'name ' ] es el nombre del archivo en el sistema del usuario. Elvaloralmacenadoen$ F I L E [ ' u s e r f i l e l ] [ ' s i z e ' ] o$HTTP POST F I L E S [ ' u s e r f i l e ] [ l J i z e l ] es el tip0 MIME del archivo, por ejemplo t e x t / p l a i n o imaqe/gif. Elvaloralmacenadoen$ F I L E [ ' u s e r f i l e ' ] [ ' e r r o r ' ] o $HTTP POST F I L E S [ ' u s e r f i l e ' ] ;[ e r r o r ' ] devolverd cualquier c6digo de error asoy ciado con la carga de archivos. Este se afiadi6 en PHP 4.2.0. En el ejemplo de este capitulo vamos a utilizar SHTTP POST F I L E S para garantizar la compatibilidad con versiones anteriores, per0 tenga e;cuenta que si tiene previsto utilizar la funcidn de carga de archivos en su servidor Web, deberia utilizar la versi6n m i s actualizada de PHP. Como sabemos d6nde se encuentra el archivo y c6mo se llama, podemos copiarlo en cualquier ubicaci6n que nos resulte util. A1 final de la ejecuci6n de la secuencia de comandos, se eliminara el archivo temporal. Por lo tanto, debe trasladarlo de ubicaci6n o asignarle otro nombre si desea guardarlo. En nuestro ejemplo, vamos a utilizar 10s archivos cargados como articulos de noticias recientes para eliminar todas las etiquetas que puede incluir y a trasladarlo a un directorio m i s util. En el listado 16.2 se recoge una secuencia de comandos que realiza esta operaci6n.

Desarrollo Web con PHP y MySQL


Listado 16.2. upload.php. PHP para capturar archivos desde el formulario HTML
<html? <head> <title>Uploading . . . </title> </head> <body> <hl>Uploading file . . . </hl> <?php / / $userfile es donde s e coloch el archivc? en el servidor Web $userfile = SHTTP-POST-FILES['userfilerj['tmp-name']; / / Suserfile-rlame es el r.ombre original dcl archivo $userfile n a m e = SHTTF-POST-FILES['userfile'] [ ' n a m e ' ] ;
-

/ / $userfile-sire es el tamaAo en bytes Suserfile-size = SHTTP-POST FILES['userfile'] ['size'];


-

/ / $userfile-type es el tipo mime, por ejernplo irnage/qif $userfile -type = SHTTP POST FILES['userfile'] ['type'];
-

/ / $userfile-error es cualquier error encontrado Suserfile error = SHTTP-POST-FILES['userfilet] [ l e r r ~ ~ r ' j ;


-

/ / userfile error s e introdujo en PHP 4.2.0 / / use este cidigo con versiones nuevas if [Suserfile -error > 0 )
-

i
echo 'Problem: ' ; switch ($userfile error)
-

case case case case exit;

1: 2: 3: 4:

echo echo echo echo

'File exceeded upliiad max-filesize'; break; 'File exceeded max file-size'; break; 'File h n l y partially uploaded'; break; ' N o file uploaded'; break;
-

/ / final del chdigo para la versihn 4.2.0

/ / Fara las versiones anteriores a la 4.2.0 use la compri~bacihnrnanual d e //errores cnmo se rnuestra a / / continuacihn
/ k

if ($userfile=='nonel)

i
echo 'Problem: no file uploaded'; exit;

I
if ($userfile size-=0)
-

i
echo 'Problem: uploaded file is zero length'; exit;

*/
//
final de la comprobacihn de errores para las versiones antiguas

/ / una comprobacihn m6s: ;lleva asignado el archivo el tipo MIME correcto?


if (Suserfile type ! = 'text/plain') i echo 'Problem: file is not plain text'; exit;
-

I
/ / coloque el archivo donde desee Supfile = '/uploads/'.$userfile name;
-

/ / is-uploaded-file y move-uploaded-file if ( i s ~ u p l o a d e d ~ f i l e ( S u s e r f i 1 e ) )

se agregaron en la versihn 4.0.3

i
echo 'Problem: Could not move file to destination directory'; exit;

I
else i echo 'Problem: Possible file upload attack. Filename: exit;

f userffile-name;

/ / chdigo para versiones antiguas seghn recomienda el manual d e PHP /* function is_uploaded~file(Sfilename) { if (!$tmp-file = get cfg vari'upload tmp d i r t ) ) { $tmp - file = dirname(tempnam(", ' I ) ) ;
-

Stmp-file .= ' / ' . basename(Sfi1ename); / / El usuario podria llevar una barra inclinada a1 final en php.ini . . . return (ereg-replace('/+', ' / I , Stmp-file) == $filename);

if (is-uploaded-file(Suserfi1e))
{ }

copy ($userfile, Supfile); else echo 'Problem: Possible file upload attack. Filename: '.$userfile-name';

t
J

*/
/ / final del chdigo para la versihn antigua
echo 'File uploaded successfully<br / X b r
/ > I ;

//

volver a aplicar formato a 10s contenidos $fp = fopeniSupfile, 'r'); $contents = fread (Sfp, filesize (Supfile));

del

archivo

fclose

(Sfp);

$ c o n t e n t s = s t r i p-t a g s ( $ c o n t e n t s ) ; S f p = f o p e n ( $ u p f i l e , 'w' ) ; fwrite($fp, $contents); f c l o s e ( $ f p );

//

m o s t r a r que s e ha c a r g a d o echo 'Prevlew of uploaded f l l e c o n t e n t s : < b r / > < h r / , ' ; echo $ c o n t e n t s ; echo ' < b r / > < h r / / I ;

Llama la atenci6n que la mayor parte del c6digo de esta secuencia de comandos est6 dirigido a la comprobaci6n de errores. La carga de archivos implica riesgos potenciales de seguridad que deben evitarse siempre que resulte posible. Necesitamos validar el archivo cargado con mucho cuidado para asegurarnos de que resulta seguro distribuirlo a nuestros visitantes. Vamos a examinar las partes fundamentales de esta secuencia de comandos. Comencemos por la comprobacidn del c6digo d e error devuelto por SHTTP POST FILES [ ' u s e r f i l e ' ] [ ' e r r o r ' ] . Este c6digo de error se introdqo en FHP4.2.0. Desde PHP 4.3 tambi6n existe una constante asociada a cada uno de estos cbdigos. Las constantes y 10s valores posibles son 10s siguientes:
0

UPLOAD-ERROR-OK,valor 0, significa que no se produjo ningiin error. UPLOAD ERR IN1 SIZE,valor 1,significa que el tamafio del archivo cargado supera el mfi;imo\alor especificado en el archivo php.ini con la directiva u p l o a d -max-f i l e s i ~ . UPLOAD-ERR-FORM SIZE,valor 2, significa que el tamafio del archivo cargado supera el valor m2ximo especificado en el formulario HTML del elemento MAX -FILE-SIZE. UPLOAD ERR-PARTIAL,valor 3, significa que el archivo se ha cargado parcialmenG. UPLOAD-ERR-NO-FILE,valor 4, significa que nose ha cargado ning6n archivo.

Si estfi utilizando una versi6n antigua de PHP, puede crear una versi6n manual de estas comprobaciones como se indica a continuaci6n. Puede comprobar si S u s e r f i l e es "none". gste es el valor establecido por PHP si no se cargd ning6n archivo. Tambi6n probamos si el archivo tiene contenido (para ello, verificamos si S u s e r f i l e sizeesmayorque0). Por 6ltimo e independientemente de la versibn, decidimos que s610 queremos que se carguen archivos de texto por lo que probamos el tip0 MIME verificando S u s e r f i l e-t y p e .

16. Intr>rnccici,l corl r l sistcr,rn dr nrchivos y

1.1

seroidor

Seguidamente, comprobamos q u e el archivo que estamos intentando abrir se ha cargado y no se trata d e un archivo local corno / e tc/passwd. Volveremos sobre este tema en u n instante. Si todo esto funciona, copiamos el archivo e n nuestro directorio d e inclusi6n. En este ejemplo, h e n ~ o s utilizado /uploads/, q u e se encuentra fuera del drbol d e documentos Web y resulta, por lo tanto, u n buen lugar e n q u e almacenar 10s archivos q u e deban dirigirse a otras ubicac~ones. A continuaci611, abrimos el archivo, limpiamos las etiquetas d e HTML o PHP q u e puedan haber q u e d a d o con la func16n s trlp tags ( ) y volvemos a guardarlo. Por Liltimo, mostramos 10s contenidos delarchivo para q u e el usuario pueda ver que se ha cargado satisfactoriamente. En la figura 16.2 se rnuestran 10s resultados d e la ejecuci6n (satisfactoria) d e esta secuencia d e comandos.

Prcvlcw ofuploaded We cmttntr

2nd July. 1000 - M d ~ Cnearanoo t today amountrd Lhev fonhcoh d hbbc C,Rim2 .knalgns am confidrot Ihc campmy's i h c r should icdp on h e Lsl day m Wgl lt o f rrccnt drJr mlh NASA

Figura 16.2. Tras copiar el archivo y aplicarle formato, se muestra el archivo cargado para indicar al usuario que la operacion de carga se ha realizado correctamente

En septiembre d e 2000, se anuncio que u n pirata informatico podia hacer q u e la secuencia d e comandos para la m r g a d e archivos procesara un archivo local corno si se hubiera cargado en el servidor. Este hecho se document6 en la lista d e correo BUGTRAQ. Si lo desea, puede consultar 10s documentos sobre seguridad oficiales e n u n o d e 10s muchos compendios BUGTRAQ, corno h t t p : / / l l s t s . i n s e c u r e . o r g / b u g t r a q / 2 0 0 0 / S e p / 0237.html. En nuestro caso hemos utilizado las funciones i s-uploaded - file ( ) y move-uploaded- flle ( ) para asegurarnos d e q u e el archivo q u e estamos proces a n d o se ha cargado y q u e no se trata d e u n archivo local corno /etc/passwd.Esta funcicin est5 disponible a partir d e la versi6n 4.0.3 d e PHP. Hemos incluido c6digo d e ejemplo por si e s t u l ~ i e r a utilizando una versi6n anterior con funcionalidad equivalente (indicada e n el c6digo por medio d e comentarios). Si no se escribe con cuidado la secuencia d e comandos para procesar la carga d e archivos, u n visitante malintencionado podria utilizar un nombre d e archivo temporal y convencer a la secuencia d e comandos para clue procese dicho archivo corno si se tratara d e u n archivo cargado.

Desarrollo W e b con PHP y MySQL

Como muchas secuencias de comandos para la carga de archivos devuelven 10s datos cargados a1 usuario o 10s almacenan en algun lugar desde 10s que puedan cargarse, se podria lograr acceder a cualquier archivo que el servidor Web pueda leer, como 10s archivos del directorio / e t c / p a s swd y c6digo fuente de PHP, incluidas las contrasehas de la base de datos.

Problemas habituales
A1 realizar cargas de archivo en un servidor es necesario tener en cuenta una serie de aspectos. En el ejemplo anterior se asume que 10s usuarios han sido autenticados en algun momento. No es aconsejable permitir que todo el mundo pueda cargar archivos en un sitio. Si va a permitir que 10s usuarios no autenticados o no fiables carguen archivos en el servidor, conviene examinar exhaustivamente su contenido para evitar que se cargue o ejecute una secuencia de comandos malintencionada. Deberia estar atento, no s610 a1 tip0 y a 10s contenidos del archivo, sin0 tambien a1 nombre del archivo en si mismo. Es aconsejable cambiar el nombre a 10s archivos cargados utilizando instancias que resulten seguras. Si esti utilizando un equipo basado en Windows, asegurese de que utilizar \ \ o / en lugar de \ en las rutas de archivo. Si el proceso de carga no funciona, compruebe el archivo p h p . i n i . Verifique que la directiva u p l o a d tmp d i r apunta a algun directorio a1 que disponga de acceso. Puede que t a ; b i & necesite ajustar la directiva memory l i m i t para cargar archivos de mayor tamaiio. Esta directiva determina eltamaho miximo de 10s archivosque puede cargar. Si se est6 ejecutando PHP en mod0 seguro, obtendri un mensaje de error indicando que no se puede acceder a1 archivo temporal. Para solucionar problema, s610 se puede desactivar el mod0 seguro o escribir una secuencia de comandos qbe no sea de PHP para que copie el archivo en una ubicaci6n accesible. Tras ello, puede ejecutar esta secuencia de comandos desde la secuencia de comandos de PHP. A1 final del capitulo, analizaremos c6mo ejecutar programas en el servidor desde PHP.

Uso de las funciones de directorio


Una vez cargados 10s archivos, resultar6 iitil permitir ver lo que se ha cargado y manipular 10s archivos de contenido. PHP consta de una serie de funciones de sistema de archivos y directorios que resultan de utilidad a1 respecto.

16. lnteraccidn con el sistema de archivos y el servidor

Lectura desde directorios


En primer lugar, implementaremos una secuencia de comandos que permita examinar el contenido cargado. La operaci6n de examinar directorios resulta muy sencilla en PHP. En el listado 16.3, se incluye una sencilla secuencia de comandos que se puede utilizar con este fin.
Listado 16.3. browserdir.php. Un listado de directorios de 10s archivos cargados

echo "Upload directory is $current-dircbr / > " ; echo 'Directory Listing:<br /><hr /><br / > I ; while ($file = readdir($dir)) i echo "$file<br / > " ;

i
echo 'ihr /><br closedir($dir);
?>
/ > I ;

</body> </html>

Esta secuencia de comandos utiliza las funciones o p e n d i r


readdir ( ) .

La funci6n opendi r ( ) se utiliza para abrir un directorio para su lectura. Su uso es muy similar a1 de fopen ( ) para leer desde archivos. En lugar de pasarle un nombre de archivo, deberia pasarle un nombre de directorio:

( ), c l o s e d i r ( )

La funci6n devuelve un indicador de directorio, de la misma forma que fopen ( ) devuelve un indicador de archivo. Cuando el directorio est5 abierto, puede leer un nombre de archivo desde 61 llamando a r e a d d i r ( $ d i r ) ,como se muestra en el ejemplo. Este elemento devuelve f a l s e cuando no hay archivos que leer. (Tenga en cuenta que tambikn devolver5 f a 1 s e si lee un archivo llamado " 0 ";conviene verificarlos si es probable que ocurra.) Los archivos no se ordenan en ningiin orden concreto, por lo que si necesita una lista ordenada, deberia leerlos en una matriz y ordenarlos despuks. Cuando haya terminado d e leer desde u n directorio, debera llamar a c l o s e d i r ( $ d i r ) para terminar. De nuevo, la operaci6n es similar a f c l o s e ( ) para un archivo.

Desarrollo Web con PHP y M!ySQL

El resultado d e ejemplo d e la secuencia d e comandos d e exploraci6n d e directorios se muestra e n la figura 16.3.

Figura 16.3. El listado de directorio muestra todos 10s archivos del directorio seleccionado, incluidos el directorio . (directorio actual) y el directorio . . (el directorio de nivel superior). Puede filtrarlos si lo desea

Si e s t i utilizando este mecanismo para permitir que el usuario examine 10s directorios, es aconsejable lilnitar 10s directorios que se pueden explorar para evitar el acceso a areas normalmente restringidas. Una funci6n asociada que resulta d e utilidad en ocasiones es la funci6n r e w i n d d i r ( $ d i r ) . Esta funci6n restablece la lectura d e 10s nombres d e archivo a1 principio del directorio. Como alternativa a estas funciones, puede utilizar la clase d i r d e PHP. ~ s t consa ta d e las propiedades h a n d l e y p a t h , y d e 10s mt5todos r e a d ( ) , c l o s e ( ) y rewind ( ) , que funcionan igual clue las alternativas no incluidas en clases.

Podemos obtener informacidn adicional utilizando u m ruta a u n archivo. Las funciones d i r n a m e ( $ p a t h ) y b a s e n a m e ( $ p a t h ) devuelven la parte d e una ruta y la parte d e un archivo d e nombre d e la ruta, respectivamente. Esto podria resultar Litil para nuestro explorador d e directorios, en especial si comenzamos a construir una estructura compleja d e directorios d e contenido basada e n nombres d e directorios y nombres d e archivos descriptivos. T a m b i h podemos agregar a1 listado d e directorios una indicaci6n del espacio libre para cargas d e archivos con la funci6n d i s k f r e e s p a c e ( $ p a t h ) .Si pasamos una ruta a u n directorio, devolverj el nlimero dgbytes rbres en el disco (Windows) o el sistema d e archivos (UNIX) e n el que se encuentra el directorio.

Ademas d e leer d e manera pasiva la informacidn sobre directorios, podemos utilizar las funciones m k d i r ( ) y r m d i r ( ) para crear y eliminar directorios. S610

16. lnteraccidn con el sistema de archivos y el servidor

podrfi crear y eliminar directorios en rutas a las que disponga de acceso el usuario utilizado para ejecutar la secuencia de comandos. El uso de la funci6nmkdi r ( ) resulta mfis complicado de lo que podria parecer a primera vista. Esta funci6n toma dos parfimetros, la ruta a1 directorio deseado (incluyendo el nuevo nombre de directorio) y el permiso que le gustaria que tuviera dicho directorio, por ejemplo: Sin embargo, 10s permisos que se enumeren no tienen por qu6 ser 10s permisos que vaya a obtener. La funci6n umas k actual serfi ANDed (como resta) con este valor para obtener 10s permisos actuales. Por ejemplo, si la funci6n umas k es 022, obtendremos el permiso 0755. Si lo desea puede restablecer la uma s k antes de crear un directorio para sustituir este efecto mediante el siguiente c6digo:

Este c6digo utiliza la funci6n umas k ( ) , que se puede utilizar para comprobar y cambiar la umas k actual. Se sustituirfi la umas k por el valor pasado y se devolverfi la umas k antigua o, si se llama sin parfimetros, se devolverfi tinicamente la umas k actual. Tenga en cuenta que la funci6n umas k ( ) no tiene ningun efecto en 10s sistemas Windows. La funci6n rmdi r ( ) elimina un directorio. Por ejemplo:

El directorio que se desee elisinar debe estar vacio.

lnteracci6n con el sistema de archivos


Ademfis de ver y obtener informaci6n sobre directorios, podemos interactuar y obtener informaci6n sobre archivos incluidos en el servidor Web. Ya hemos visto c6mo escribir y leer archivos, per0 existen muchas otras funciones de archivo disponibles.

Como obtener informacion de archivo


Podemos alterar la parte de la secuencia de comandos para explorar directorios que leen archivos de la siguiente forma:
while ($file
=

Sdir->read() )

Desarrollo Web con P H P y MySQL


echo '<a href="filedetails.php?file='.$file."'>' .$file. '</a><br

/ > I ;

Podemos crear la secuencia de comandos filedetaihphp para suministrar informacion adicional sobre un archivo. En el listado 16.4 se muestran 10s contenidos de este archivo. Tenga en cuenta que parte de las funciones utilizadas aqui no son compatibles con Windows, entre las que se incluyen posix -g e t p w u i d o , f i l e o w n e r ( ) y f ilegroup ( ) , o su compatibilidad no es fiable.
Listado 16.4. filedetails.php. Las funciones de estado de archivo y sus resultados
~<html> <head> <title>File Details</titlei </head> <body> <?php Scurrent dir = '/uploads/'; $file = basename($file); / / filtrar la informaci6n d e directorio //por seguridad
-

echo 'chl>Details o f file: $file = $current-dir.$file;

'.%file.'</hl>';

echo '<hZ>File data</h2>'; echo 'File last accessed: '.date('j F Y echo 'File last modified: '.date('j F Y
-

H:i', H:i',

fileatime(Sfi1e)).'<br filemtime($file)). '<br

/ > I ;

/ > I ;

$user = posix getpwuid(fileowner($file)); echo 'File owner: '.$user['name'].'<br / > I ; $group = posix qetgrgid(filegroup($file)); echo 'File group: ' .$gro&['name1]. 'ibr / > I ;
-

echo 'File permissions: ' .decoct (fileperms ($file)) echo 'File type: '.filetype($file).'<br
/ > I ;

. '<br

/ > I ;

echo 'File size: '.filesize(Sfile).' bytes<br

!>I;

echo 'ch2>File tests</hZ>'; echo echo echo echo echo echo 'true' : 'false').'<br / > I ; 'is dir: . s i r $ f i l e ? 'is executable: '.(is-executable($file)? 'true' : 'falset).'<br / > I ; 'is-file: '.(is file($file)? 'true' : 'false').'<br / > I ; 'is-link: '.(is-link($fjle)? 'true' : 'falsel).'<br / > I ; 'is-readable: '.(is-readableisfile)? 'true' : 'false').'<br / > I ; 'iswritable: '.(is-writable($file)? 'true' : 'falsel).'<br / > I ;
~-

16. Irrtcrncocir~rorr el sistcirrn dr n r c h ~ u o s y cl seroidor

En la figura 16.4 se muestran 10s resultados d e ejecutar el listado 16.4.

1
11

Details of file: ipatxt


File data
Flr last accessed 23 July2000 0 1 4 8 F+ hn rno&rd 23 j ~ I 20013 g 01 49 Fllc ownrr Mvrarwr Fde p q , nopSrcup

Fde pmnraonr 100755 N ! typr Bt


Fllr n r c 206 bnrs

Figura 16.4. La vista de 10s detalles de archivo rnuestra inforrnacion del sistema de archivos sobre un archivo. Como puede observar 10s permisos se muestra en formato octal

Vamos a analizar qu6 hace cada una d e las funciones utilizada en el listado 16.4. Como se mencion6 anteriorniente, la funci6n b a s e n a m e ( ) obtiene el nombre del archivo sin el directorio. ( T a m b i h puede utilizar la funcicin d i r n a m e ( ) para obtener el nombre del directorio sin el nombre d e archivo). Las funciones f i l e a t i m e ( ) y f i l e m t i m e ( ) devuelven la marca d e tiempo indicando el momento en el que seaccedi6 pnr 6ltima vez al archivo y la ultima vez que se modific6, respectivamente. Hemos moditicado el formato d e la marca d e tiempo con la funcicin d a t e ( ) para que resulte mcis legible. Estas funciones devolvercin el misino valor en algunos sisternas operativos (como en el ejemplo) segun qu4 informaci611 almacene el sistema. Las funcioncs f i l e o w n e r ( ) y f i l e g r o u p ( ) devuelven el Id. del usuario ( u i d ) y el Id. d e g r u p o ( g i d ) del archivo. J h o s se pueden convertir en nombres utilizando las funciones p o s i x -g e t p w u i d ( ) y p o s i x -g e t g r g i d ( ) para q u e resulten mas sencillos d e leer. Estas funciones toman el u i d o g i d como parametro y devuelven una matriz asociativa d e informaci6n sobre el usuario o grupo, incluido sus nombres, con10 hemos hecho en esta secuencia d e comandos. La funcion f i l e p e r m s ( ) devuelve 10s permisos sobre el archivo. Les hemos aplicado un nuevo forrnato utilizando la tuncion d e c o c t ( ) para que resulte rnds familiar a 10s usuarios d e UNIX. La funci6n f i l e t y p e ( ) devuelve informacion sobre el tipo d e archivo que se va a examinar. Los resultados posibles son f i f o , c h a r , d i r , b l o c k , l i n k , f i l e y unknown.

Desarrollo W e b con P H P y MySQL

La funci6n f i l e s i z e ( ) devuelve el tamafio del archivo en bytes. Elsegundoconjuntodefunciones(is d i r 0, is-executable (), i s - f i l e ( ) , i s l i n k 0, i s r e a d a b l e ( ) y i s w r y t a b l e ( ) ) prueba el atributo con nombre d e u n archivo devuelve t r u e o f a y s e . Tambi6n podriamos utilizar la funcion s t a t ( ) para recopilar una gran cantidad de informaci6n del mismo tipo. A1 pasar un archivo, devuelve una matriz que contiene datos similares a 10s de estas funciones. La funci6n 1 st a t ( ) es similar per0 para su uso con vinculos simb6licos. Las funciones de estado de archivo tardan mucho tiempo en procesarse. Por esta razon, sus resultados se almacenan en cach6. Si desea comprobar informaci6n sobre el archivo antes o despu6s de un cambio, deberi llamar a
clearstatcache ( ) ;

para poder vaciar 10s resultados anteriores. Si desea utilizar la secuencia de comandos previa antes o despu6s de cambiar datos del archivo, deberia llamar a esta funci6n como primer paso para asegurarse de que 10s datos generados estin actualizados.

C6mo cambiar las propiedades


Ademis de ver las propiedades de archivo, podemos alterarlas. Las funciones c h g r p ( a r c h i v o , g r u p o ) , chmod ( a r c h i v o , p e r m i s o ) y chown ( a r c h i v o , u s u a r i o ) se comportan de forma similar a sus equivalentes de UNIX. Ninguna de ellas funcionari en 10s sistemas basados en Windows, aunque chown ( ) se ejecutari y devolveri siempre t r u e . La funci6n c h g r p ( ) se utiliza para cambiar el grupo de un archivo. S61o se puede utilizar para cambiar el grupo a1 que pertenece el usuario, a menos que se trate del usuario raiz. La funci6n chmod ( ) se utiliza para cambiar 10s permisos sobre un archivo. Los permisos se pasan con la forma chmod habitual de UNIX (debe anteponerles un " 0" para indicar que su formato es octal, por ejemplo). La funci6n chown ( ) se utiliza para cambiar el titular de un archivo. S610 se puede utilizar si la secuencia de comandos se esti ejecutando como raiz, lo que no deberia ocurrir nunca.

Creacion, elirninacion y despl

ienta de ar

Puede utilizar las funciones de sistema de archivos para crear, trasladar y eliminar archivos. En primer lugar, y de forma sencilla, puede crear un archivo o cambiar la hora de la ultima modification utilizando la funci6n t o u c h ( ) . Su funcionamiento es similar a1 comando t o u c h de UNIX. Su sintaxis es la siguiente:
int touch (string

archivo,

lint

hora

[,

int

horall)

16. lnteraccidn con el sistema de archivos y el servidor

Si el archivo ya existiese, su hora de modificaci6n se sustituiria por la actual o por la indicada en el segundo pargmetro si se especifica. Si desea utilizar esta ultima opcibn, deberia incluirse en formato de marca de tiempo. Si el archivo no existiese se crearia. La hora de acceso del archivo tambien se modificaria: de manera predeterminada la hora del sistema actual o la marca de tiempo especificada en partimetro opcional. Puede eliminar archivos utilizando la funcidn u n l i n k ( ) . (Tenga en cuenta que esta funci6n no se llama d e l e t e : no existe dicha funci6n.) Se utiliza de la siguiente forma:

Esta funci6n no resulta operativa con las versiones antiguas de Windows. Si este fuera su caso, puede utilizar la siguiente funci6n para eliminar u n archivo en Windows:

Puede copiar y mover archivos con las funciones copy ( guiente forma:
coP~(Sso~r~2-patS hd , e s t l n a t i o n-p a t h ) ; renarne($oldfile, $newfile);

y rename

()

de la si-

Como puede haber observado, hemos utilizado la funci6n copy ( ) en el listado 16.2. La funcidn rename ( ) se encarga tambien de la tarea de trasladar archivos de un lugar a otro porque PHP no consta de la funcidn move. La posibilidad de mover archivos entre sistemas de archivos y la de sobrescribir archivos con rename ( ) depende del sistema operativo, por lo que debe comprobar 10s efectos en su servidor. Asi mismo, tenga cuidado con la ruta que utilizarti hasta el nombre de archivo. Si fuera relativa, lo seria con respecto a la ubicaci6n de la secuencia de comandos, no a1 archivo original.

Uso de funciones de ejecuci6n de programas


A continuacibn, dejaremos a un lado las funciones relacionadas con el sistema de archivos y pasaremos a examinar las funciones disponibles para ejecutar comandos en el servidor. Estas funciones resultan utiles cuando se quiere suministrar una interfaz de usuario basada en la Web a un sistema existente basado en linea de comandos. Por ejemplo, hemos utilizado estos comandos para crear una interfaz de comandos para el administrador de listas de correos e zmlm. Volveremos a utilizarlas en capitu10s posteriores.

Desarrollo Web con P H P y MySQL

Existen cuatro tgcnicas principales para ejecutar un comando en el servidor Web. Aunque son bastante parecidas, presentan pequefias diferencias.
1. e x e ( )

La funci6n e x e c ( ) tiene la siguiente sintaxis:


string

exec

(string

cornando

[,

array

resul tado

[,

int

~ a l o r ~ d e v ut e o l] ]

Se le pasa el comando que le gustaria que se ejecutase, por ejemplo,


exec ( " 1 s
-la") ;

La funci6n e x e c ( ) no genera un resultado directo. Devuelve la ultima linea del resultado del comando. Si se pasa en una variable como resultado, se obtendrfi un matriz de cadenas que representa cada linea del resultado. Si se pasa e n una variable como v a l o r -d e v u e l t o , se obtendrfi el c6digo de devoluci6n.
2. p a s s t h r u
()

La funci6n p a s s t h r u
void passthru

()

tiene la siguiente sintaxis:


i n t valor devueltcl i

( s t r i n g cornando [ ,

La funci6n p a s s t h r u ( ) repite el resultado en el navegador, lo cual resulta util si el resultado es binario (por ejemplo, datos de una imagen). No devuelve nada. Los parfimetros funcionan de la misma forma que 10s de la funci6n e x e c ( ) . La funci6n s y s t e m ( ) iiene la siguiente sintaxis:
string system (string

cornando

[,

int

valor-devuelto] 1

Esta funci6n repite el resultado del comando en el navegador. Se diferencia de la funci6n anterior en que intenta eliminar el resultado tras cada linea (si se ejecuta PHP como m6dulo de servidor). Devuelve la 6ltima linea de resultado (si tiene gxito) o f a l s e (en caso de fallo). Sus parfimetros funcionan de la misma forma que 10s parfimetros de las funciones anteriores.
4. Ap6strofes invertidos

Se trata de operadores de ejecuci6n como ya se indic6 en un capitulo anterior. No pueden tener una salida directa. El resultado de ejecutar el comando se devuelve en una cadena, que se puede dirigir a un dispositivo o utilizar para realizar cualquier otra operaci6n deseada.

16. Interaccidn con el sistema de archivos y el servidor

Si sus necesidades resultan mas complicadas, puede utilizar p o p e n ( ) , p r o c o p e n ( ) y p r o c c l o s e ( ) . Estas funciones se utilizan para bifurcar procesos externos y enviar d z o s entre ellos. Las 6ltimas dos funciones se agregaron en la versi6n 4.3 de PHP. La secuencia de comandos que se recoge en el listado 16.5 ilustra c6mo utilizar las cuatro tecnicas de forma equivalente.
Listado 16.5. Funciones de estado de archivo y sus resultados

/ / / / / versiSn exec echa 'ipre\';

/ / unis eseci'ls -la', $result); / / windows / / exec('dir', $result); foreach (Srzsult as $line) echa "$line\n";

/ / / / / verslhn passthru echo '<pre>'; / / unix passthru('1s -la'); / / windows / / passthru('dirl);

echo '</pre>'; echo '<br /><hr /><br / > ' ;

/////

versihn

system

echo '<pre>'; / / unix $result = system('1s -la'); / / windows / / $result = system('dir'); echo '</pre>'; echo '<br /><hr /><br / > I ; /////versihn con aphstrofes invertidos echo '<pre>'; / / unix $result = '1s -all; / / windows / / $result = ' d l r ' ;

Desarrollo Web con PHP y MySQL


echo S r e s u l t ; echo ' < / p r e > ' ;

Podriamos haber utilizado estos enfoques como alternativa a la secuencia de comandos de exploracidn de directorios escrita anteriormente. Uno de 10s efectos secundarios del uso de funciones externas queda ampliamente demostrado aqui: su cddigo dejar6 de ser portable. En este caso hemos utilizado comandos de Unix y el cddigo no se ejecutard en Windows. Si tiene previsto incluir datos enviados por el usuario como parte del comando que va a ejecutar, deberia ejecutarlos siempre a trav6s de la funcidn escapeshellcmd ( ) en primer lugar. De esta forma evitarfi que 10s usuarios puedan ejecutar comandos malintencionados en su equipo. Puede llamar a esta funci6n de la siguiente forma:

Tambi6n deberia utilizar esta funcidn para convertir cualquier argument0 especial que tenga previsto pasar a su comando de nticleo.

Interaction con el entorno: getenv() y putenv()


Antes de dar por concluida esta seccidn, vamos a ver cdmo podemos utilizar variables de entorno desde PHP. Para ello, disponemos de dos funciones: getenv ( ) ,que permite recuperar variables de entorno y putenv ( ) que permite establecer variables de entorno. Tenga en cuenta que estamos hablando del entorno en el que PHP se ejecuta en el servidor. Puede obtener una lish de'todas las variables de entorno de PHP ejecutando
phpinf o ( )

Algunas resultan mfis titiles que otras, por ejemplo

devolverfi el URL de la pfigina desde la que el usuario llegd hasta la pfigina actual. Tambi6n puede establecer las variables de entorno como desee con putenv ( ) , por ejemplo,
$home = " / h o m e / n o b o d y " ; putenv (" HOME=$home " ) ;

Si fuera un administrador de sistemas y quisiera limitar las variables de entorno que pueden establecer 10s programadores, podria utilizar la directiva safe mode allowed env va rs de php.ini. Cuando PHP se ejecuta en mod0 seguro, 1 s ; usua: rios sdlo Fueden establecer las variables de entorno cuyos prefijos se enumeran en esta directiva.

16. lnteraccibn con el sistema de archivos y el servidor

Si desea obtener informacidn adicional sobre qu6 representan las variables de entorno, puede consultar la especificacidn de CGI.
http://hoohaa.ncsa.uiuc.edu/cgi/env.htrnl

Lecturas adicionales
La mayor parte de las funciones de sistemas de archivo de PHP est6n asociadas con las funciones subyacentes de 10s sistemas operativos. Si esta utilizando UNIX y desea obtener mhs informacidn, consulte las phginas man.

A continuacion
En el siguiente capitulo, veremos c6mo utilizar las funciones de red y protocolo de PHP para interactuar con sistemas distintos a 10s de nuestro servidor Web, lo cual contribuir6 a ampliar el horizonte de posibilidades para nuestras secuencias de comandos.

En este capitulo, examinaremos las funciones orientadas a la red de PHP que permiten a nuestras secuencias de comandos interactuar con el resto de Internet. En Internet, encontrar6 una ingente cantidad de recursos y una gran variedad de protocolos para su uso. En esta seccidn examinaremos 10s siguientes aspectos: Una descripcidn general de 10s protocolos disponibles Envio y lectura de correo electr6nico Uso de otros sitios Web a travks de HTTP Uso de funciones de busqueda de red Usode FTP Uso de comunicaciones de red genkricas con CURL

Description general de protocolos


Los protocolos son reglas de comunicaci6n para una situacidn dada. Por ejemplo, ya conocemos el protocolo que hay que seguir cuando nos encontramos a alguien. Decimos hola, estrechamos la mano y decimos adi6s. Los protocolos de red son similares. Como en el caso de 10s protocolos humanos, se utilizan diferentes protocolos informaticos para cada situaci6n y aplicaciones. Por ejemplo, utilizamos HTTP (Pro-

17. Uso de funciones de red y de protocolo

tocolo de transferencia de hipertexto) para enviar y recibir p6ginas Web. Es probable que tambikn haya utilizado FTP (Protocolo de transferencia de archivos) para transferir archivos entre equipos de una red. Existen muchos otros. Los protocolos, asi como otros est6ndares de Internet, se describen en las RFC (Solicitudes de comentarios). Estos protocolos son definidos por el IETF (Grupo de trabajo de ingenieria de Internet). En Internet existen muchos lugares en 10s que encontrar RFC. La fuente bdsica es el editor de RCF situado en

Si tiene problemas a1 trabajar con un protocolo dado, las RFC son la fuente oficial

y suelen resultar titiles para solucionar 10s problemas con el c6digo. Sin embargo, la
cantidad de detalles es muy grande y suelen incluir cientos de pdginas. Entre las RFC m6s conocidas se puede citar la RFC2616, que describe el protocolo HTTP/ 1.1 y la RFC822, que describe el formato de 10s mensajes de correo electr6nico por Internet. En este capitulo, vamos a examinar 10s aspectos de PHP que utilizan algunos protocolos. Especificamente, veremos c6mo enviar correo con SMTP, c6mo leer correo con POP e IMAP, c6mo conectar con otros servidores Web a travks de HTTP y HTTPS, y c6mo transferir archivos con FTP.

Envio v r e c e ~ c i o n de correos electronicos


La forma principal de enviar correos electr6nico en PHP consiste en utilizar la funcion mail ( ) ,ya comentadazn un capitulo anterior. Esta funci6n utiliza el protocol~ SMTP (Protocolo sikple para la transferencia de correo) para enviar correo electr6nico. Es posible utilizar toda una variedad de clases gratuitas para aiiadir funcionalidad a mail ( ) . En un capitulo posterior, utilizaremos una clase complementaria para enviar archivos adjuntos HTML en un mensaje de correo. SMTP s610 se utiliza para enviar correos. Los protocolos IMAP (Protocolo de acceso a mensajes de Internet, descrito en la RFC2060) y POP (Protocolo de oficina de correos, descrito en la RFC1939 o STD0053) se utilizan para leer el correo de un servidor de correos. Estos protocolos no pueden enviar correo. IMAP se utiliza para leer y manipular mensajes de correo almacenados en un servidor y es m6s avanzado que POP, el cual se suele utilizar para descargar mensajes de correo electr6nico a un cliente y eliminarlos del servidor. PHP incorpora una biblioteca IMAP. Esta biblioteca tambikn se puede utilizar para realizar conexiones POP, NNTP (Protocolo de transferencia de noticias de red) e IMAP. Examinaremos con detenimiento el uso de la biblioteca IMAP en el proyecto incluido en un capitulo posterior.

Desarrollo Web con PHP y MySQL

Uso de otro sitio Web


La Web permite utilizar, modificar e incrustar servicios e informacibn existente en nuestras propias pfiginas. PHP convierte esta tarea en algo muy sencillo, corno se ilustra en el ejemplo que se comenta a continuacibn. Imagine que la compaiiia para la que trabaja quiere mostrar en la pfigina principal el precio de sus acciones. Esta informacidn est6 disponible en varios sitios dedicados a temas bursiitiles, per0 jcbmo acceder a ella? Tenemos que empezar por buscar un URL en el que se incluya esta informacibn de primera mano. Tras ello, cuando un usuario se dirija a nuestra piigina principal, abriremos una conexibn a dicho URL para recuperar la piigina y extraer la informacibn deseada. Como ejemplo, hemos creado una secuencia de comandos que recupera y aplica formato a la cotizacibn extraida del sitio Web de AMEX. En concreto, recuperaremos el precio de cotizacibn de las acciones de Amazon. (Puede incluir otra informacibn ya que el principio es el mismo.) En el listado 17.1 se recoge la secuencia de comandos.
Listado 17.1. lookup.php. Secuencia de comandos que recupera la cotizacion de una accion del NASDAQ con el simbolo listado en $symbol
<html> <head> < t i t l e > S t o c k Quote from NASDAQ</title> </head> <body> <?php / / s e l e c c i o n e qu6 a c c i 6 n exarninar $symbol='AMZN1; echo "<hliStock Quote for-$symbol</hl>";

e c h o ' C o u l d not. o p e n URL'; exit;

I
Scorltents = f r e a d (Sfp, 1000000) ; fclose [Sf?);

/ / b u s q u e l a p a r t e d e l a p i g i n a d e s e a d a y d e v u e l v a l a corno
//resultado S p a t t e r n = " [ \ \ \ $ [ O - 9 lt\\.[O-91t)"; i f (eregi[Spattern, $contents, $quote) ) I

17. Uso defurrciones de red y de protocolo

En la figura 17.1 se recoge el resultado del listado 17.1.

Stock Quote for PuMZN

7
111

Figura 17.1. Esta secuencia de comandos utiliza una expresion regular para extraer la cotizacion de una accion de la inforrnacion recuperada de la bolsa de valores

La secuencia de comandos resulta bastante clara. De hecho, no utiliza ninguna funcicin nueva, s610 nuevas aplicaciones de dichas funciones. Puede que recuerde de un capitulo anterior que podemos utilizar las funciones de archivo para leer desde un URL. Eso es lo que hemos hecho en este caso. La llamada a fopen ( )

devuelve un punter0 a1 inicio de pigina del URL suministrado. A partir de ahi se trata simplemente de leer el URL desde la pigina y cerrarlo de nuevo.

Como observark el numero utilizado para indicarle a PHP cuAnto leer del archivo es muy alto. Si se tratara d e un archivo en el servidor, lo normal seria utilizar fi l e s i z e ( $ f i l e )per0 esta funci6n no se puede utilizar con un URL. Tras ello, tenemos todo el texto de la pigina Web de dicho URL almacenado en la variable $contents.

Desarrollo Web con PHP y MySQL

Seguidamente, podemos utilizarlo como expresi6n regular y recurrir a la funci6n eregi ( ) para buscar la parte de la pfigina deseada:
Spattern = " (\\\$[0-9 I+\\. LO-91+)"; if (eregilspattern, $contents, $quote))

1
echo "$symbol was last sold at: "; echo $quote[l];
1

Y eso es todo. Podemos utilizar esta tecnica parar realizar otras tareas. Por ejemplo, podemos recuperar la informacidn meteorol6gica local e incluirla en nuestra pfigina. El mejor uso de esta tecnica consiste en combinar informaci6n procedente de varias fu